#!/usr/local/bin/python import logging import util from M2Crypto import SSL from M2Crypto.m2xmlrpclib import SSL_Transport from xmlrpclib import ServerProxy, dumps, loads, Fault, Error, Binary from M2Crypto.SSL import SSLError from M2Crypto.BIO import BIOError from socket import error as socket_error from socket import sslerror import httplib from federation.util import fedd_ssl_context from federation import service_error class emulab_segment: def __init__(self, boss, cert): self.ctxt = fedd_ssl_context(my_cert=cert) self.ctxt.set_verify(SSL.verify_none, 10) self.boss = boss self.null = """ set ns [new Simulator] source tb_compat.tcl set a [$ns node] $ns rtproto Session $ns run """ self.log = getattr(self, 'log', None) self.debug = getattr(self, 'debug', False) def emulab_call(self, method, params): VERSION = 0.1 try: transport = SSL_Transport(self.ctxt) port = ServerProxy(self.boss, transport=transport) remote_method = getattr(port, method, None) if remote_method is not None: resp = remote_method(VERSION, params) else: raise service_error(service_error.internal, "Bad method: %s" % method) except socket_error, e: raise service_error(service_error.connect, "Cannot connect" % e) raise e except BIOError, e: if self.log: self.log.warn("BIO error: %s" % e) raise e except sslerror, e: if self.log: self.log.warn("SSL (socket) error: %s" % e) raise e except SSLError, e: if self.log: self.log.warn("SSL error: %s" % e) raise e except httplib.HTTPException, e: if self.log: self.log.warn("HTTP error: %s" % e) raise e except Fault, f: raise service_error(service_error.protocol, "Remote XMLRPC Fault: %s" % f) except Error, e: raise service_error(service_error.protocol, "Remote XMLRPC Fault: %s" % e) code = resp.get('code', -1) if code ==0: return (code, resp.get('value', None)) else: return (code, resp.get('output', None)) def get_state(self, pid, eid): """ Return the state of the experiment as reported by emulab """ if self.debug: state = 'swapped' else: params = { 'proj': pid, 'exp': eid } code, state = self.emulab_call('experiment.state', params) if code != 0: state = 'none' if self.log: self.log.debug("State is %s" % state) return state def make_null_experiment(self, pid, eid, tmpdir): """ Create a null copy of the experiment so that we capture any logs there if the modify fails. Emulab software discards the logs from a failed startexp. """ if self.debug: if self.log: self.log.debug("[make_null_experiment]: (debug) Creating experiment") return True else: params = { 'proj': pid, 'exp': eid, 'nsfilestr': self.null, 'batch': False, 'idleswap': 0, 'noidleswap_reason': 'Federated experiment', 'noswapin': True, 'wait': True } if self.log: self.log.info("[make_null_experiment]: Creating experiment") print params code, value = self.emulab_call('experiment.startexp', params) if self.log: if code == 0: self.log.info('[make_null_experiment]: Create succeeded') else: self.log.error('[make_null_experiment]: Create failed: %s' \ % value) return code == 0 def swap_exp(self, pid, eid, direction='out', wait=True): """ Swap experiment in. """ if self.debug: if self.log: self.log.info("[swap_exp]: (debug) Swapping %s %s" % \ (eid, direction)) return True else: if self.log: self.log.info("[swap_exp]: Swapping %s %s" % (eid, direction)) params = { 'proj': pid, 'exp': eid, 'direction': direction, 'wait': wait, } code, value = self.emulab_call('experiment.swapexp', params) if self.log: if code == 0: self.log.info('[swap_exp]: Swap succeeded') else: self.log.error('[swap_exp]: Swap failed: %s' % value) return code == 0 def modify_exp(self, pid, eid, tcl, wait=True): if self.debug: self.log.info("[modify_exp]: (debug) Modifying %s" % eid) return True else: self.log.info("[modify_exp]: Modifying %s" % eid) params = { 'proj': pid, 'exp': eid, 'nsfilestr': tcl, 'wait': wait, 'reboot': True, 'restart_eventsys': True, } code, value = self.emulab_call('experiment.modify', params) if self.log: if code == 0: self.log.info('[modify_exp]: Modify succeeded') else: self.log.error('[modify_exp]: Modify failed: %s' \ % value) return code == 0 def get_mapping(self, pid, eid): """ Get the physical to virtual mapping from the expinfo command and save it in the self.map member. """ if self.debug: if self.log: self.log.info("[get_mapping] (debug) Generating mapping") return True else: if self.log: self.log.info("[get_mapping] Generating mapping") params = { 'proj': pid, 'exp': eid, 'aspect': 'mapping' } code, nodes = self.emulab_call('experiment.info', params) if code ==0: for k, v in nodes.items(): if v.get('erole', False) and 'pnode' in v: self.node[k] = v['pnode'] if self.log: self.log.info("Mapping complete") return True else: raise service_error(service_error.internal, "Cannot get node mapping of segment:%s/%s" % (pid, eid))