def initialize(self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Resource Orchestration Sublayer...") self.orchestrator = ResourceOrchestrator(self) if self._nffg_file: try: service_request = self._read_data_from_file(self._nffg_file) service_request = NFFG.parse(service_request) dov = self.orchestrator.virtualizerManager.dov self.__proceed_instantiation( nffg=service_request, resource_view=dov.get_resource_info()) except (ValueError, IOError, TypeError) as e: log.error("Can't load service request from file because of: " + str(e)) quit_with_error(msg=str(e), logger=log) else: log.info("Graph representation is loaded successfully!") # Initiate ROS REST-API if needed if self._agent or self._rosapi: self._initiate_ros_api() log.info("Resource Orchestration Sublayer has been initialized!") if self._agent: log.warning( "In AGENT mode Service Layer is not going to be initialized!")
def build (self, topo=None): """ Initialize network. 1. If the additional ``topology`` is given then using that for init. 2. If TOPO is not given, search topology description in CONFIG with the \ name 'TOPO'. 3. If TOPO not found or an Exception was raised, search for the fallback \ topo with the name ``FALLBACK-TOPO``. 4. If FALLBACK-TOPO not found raise an exception or run a bare Mininet \ object if the run_dry attribute is set :param topo: optional topology representation :type topo: :any:`NFFG` or :any:`AbstractTopology` or ``None`` :return: object representing the emulated network :rtype: :any:`ESCAPENetworkBridge` """ log.debug("Init emulated topology based on Mininet v%s" % MNVERSION) # Load topology try: if topo is None: log.info("Get Topology description from CONFIG...") self.__init_from_CONFIG() elif isinstance(topo, NFFG): log.info("Get Topology description from given NFFG...") self.__init_from_NFFG(nffg=topo) elif isinstance(topo, basestring) and topo.startswith('/'): log.info("Get Topology description from given file...") self.__init_from_file(path=topo) elif isinstance(topo, AbstractTopology): log.info("Get Topology description based on Topology class...") self.__init_from_AbstractTopology(topo_class=topo) else: raise TopologyBuilderException( "Unsupported topology format: %s - %s" % (type(topo), topo)) return self.get_network() except SystemExit as e: quit_with_error(msg="Mininet exited unexpectedly!", logger=log, exception=e) except TopologyBuilderException: if self.fallback: # Search for fallback topology fallback = CONFIG.get_fallback_topology() if fallback: log.info("Load topo from fallback topology description...") self.__init_from_AbstractTopology(fallback) return self.get_network() # fallback topo is not found or set if self.run_dry: # Return with the bare Mininet object log.warning("Topology description is not found! Running dry...") return self.get_network() else: # Re-raise the exception raise except KeyboardInterrupt: quit_with_error( msg="Assembly of Mininet network was interrupted by user!", logger=log)
def start_network(self): """ Start network. :return: None """ log.debug("Starting Mininet network...") if self.__mininet is not None: if not self.started: try: self.__mininet.start() except SystemExit: quit_with_error( msg="Mininet emulation requires root privileges!", logger=LAYER_NAME) except KeyboardInterrupt: quit_with_error( msg= "Initiation of Mininet network was interrupted by user!", logger=log) self.started = True log.debug("Mininet network has been started!") self.runXTerms() else: log.warning( "Mininet network has already started! Skipping start task..." ) else: log.error("Missing topology! Skipping emulation...")
def __init__(self, layer_API, with_infr=False): """ Initialize Controller adapter. For domain components the ControllerAdapter checks the CONFIG first. :param layer_API: layer API instance :type layer_API: :any:`ControllerAdaptationAPI` :param with_infr: using emulated infrastructure (default: False) :type with_infr: bool """ log.debug("Init ControllerAdapter - with IL: %s" % with_infr) super(ControllerAdapter, self).__init__() # Set a weak reference to avoid circular dependencies self._layer_API = weakref.proxy(layer_API) self._with_infr = with_infr # Set virtualizer-related components self.DoVManager = GlobalResourceManager() self.domains = ComponentConfigurator(self) try: if with_infr: # Init internal domain manager if Infrastructure Layer is started self.domains.load_local_domain_mgr() # Init default domain managers self.domains.load_default_mgrs() except (ImportError, AttributeError, ConfigurationError) as e: from escape.util.misc import quit_with_error quit_with_error( msg="Shutting down ESCAPEv2 due to an unexpected error!", logger=log, exception=e) # Here every domainManager is up and running # Notify the remote visualizer about collected data if it's needed notify_remote_visualizer(data=self.DoVManager.dov.get_resource_info(), id=LAYER_NAME)
def initialize(self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Service Layer...") self.__sid = CONFIG.get_service_layer_id() if self.__sid is not None: log.debug("Setup ID for Service Layer: %s" % self.__sid) else: self.__sid = self.LAYER_ID log.error( "Missing ID of Service Layer from config. Using default value: %s" % self.__sid) # Set element manager self.elementManager = ClickManager() # Init central object of Service layer self.service_orchestrator = ServiceOrchestrator(self) # Read input from file if it's given and initiate SG if self._sg_file: try: stats.init_request_measurement(request_id=self._sg_file) service_request = self._read_data_from_file(self._sg_file) log.info("Graph representation is loaded successfully!") if service_request.startswith('{'): log.debug( "Detected format: JSON - Parsing from NFFG format...") nffg = NFFG.parse(raw_data=service_request) elif service_request.startswith('<'): log.debug( "Detected format: XML - Parsing from Virtualizer format..." ) converter = NFFGConverter(domain="INTERNAL", logger=log) nffg = converter.parse_from_Virtualizer( vdata=service_request) else: log.warning("Detected unexpected format...") return if nffg.mode is not None: log.info('Detected mapping mode in NFFG: %s' % nffg.mode) else: nffg.mode = NFFG.MODE_ADD log.info("No mapping mode has been detected in NFFG! " "Set default mode: %s" % nffg.mode) log.info("Schedule service request delayed by %d seconds..." % SCHEDULED_SERVICE_REQUEST_DELAY) stats.set_request_id(request_id=nffg.id) self.api_sas_sg_request_delayed(service_nffg=nffg) except (ValueError, IOError, TypeError) as e: log.error("Can't load service request from file because of: " + str(e)) quit_with_error(msg=str(e), logger=log) else: # Init REST-API if no input file is given self._initiate_rest_api() # Init GUI if self._gui: self._initiate_gui() log.info("Service Layer has been initialized!")
def _all_dependencies_met(self): """ Called when every component on which depends are initialized on POX core. Contain dependency relevant initialization. :return: None """ try: self.initialize() # With fully event-driven communication between the layers the dependency # handling takes care by listen_to_dependencies() run into a dead-lock. # The root of this problem is the bidirectional or cyclic dependency # between the components, so basically the layers will always wait to each # other to be registered on core. To avoid this situation the naming # convention of event handlers on which the dependency checking based is # not followed (a.k.a. leave _handle_<component name>_<event name>) and # the event listeners is set up manually. For automatic core registration # the components have to contain dependencies explicitly. for dep in self.dependencies: if not self._standalone: if core.core.hasComponent(dep): dep_layer = core.components[dep] # Register actual event handlers on dependent layer dep_layer.addListeners(self) # Register dependent layer's event handlers on actual layer self.addListeners(dep_layer) else: raise AttributeError( "Component is not registered on core") else: # In case of standalone mode set up a StandaloneHelper in this object # with the name of the dependency to handle raised events # automatically setattr(self, dep, SimpleStandaloneHelper(self, dep)) # Subscribe for GoingDownEvent to finalize API classes # shutdown() function will be called if POX's core going down core.addListenerByName('GoingDownEvent', self.shutdown) # Subscribe for UpEvent to call functions after everithing is up core.addListenerByName('UpEvent', self.post_up_hook) # Subscribe core event for advanced functions # Listeners' name must follow POX naming conventions core.addListeners(self) # Everything is set up an "running" so register the component on pox.core # as a final step. Other dependent component can finish initialization # now. core.core.register(self._core_name, self) # Set "running" config for convenience purposes CONFIG.set_layer_loaded(self._core_name) except KeyboardInterrupt: quit_with_error( msg="Initialization of %s was interrrupted by user!" % self.__class__.__name__) except Exception as e: quit_with_error(msg="Abort ESCAPEv2 initialization...", exception=e)
def __init__ (self): """ Init. """ super(NFIBManager, self).__init__() log.debug("Init %s based on neo4j" % self.__class__.__name__) # Suppress low level logging self.__suppress_neo4j_logging() try: self.graph_db = Graph() except Unauthorized as e: quit_with_error( "Got Unauthorozed error on: %s from neo4j! Disable the authorization " "in /etc/neo4j/neoj4-server.properties!" % e)
def _load_cfg_file (path): """ Load external configuration from file. Support JSON and YAML format. :param path: file path :type path: str :return: loaded configuration :rtype: dict """ try: with open(path) as f: return yaml.safe_load(f) except IOError: quit_with_error('Default config file: %s is not found!' % path) except (yaml.YAMLError, Exception) as e: quit_with_error("An error occurred when load configuration: %s" % e)
def launch(standalone=False, topo=None): """ Launch function called by POX core when core is up. :param standalone: Run layer without dependency checking (optional) :type standalone: bool :param topo: Load the topology description from file (optional) :type topo: str :return: None """ global init_param init_param.update(locals()) if os.geteuid() != 0: quit_with_error(msg="Mininet emulation requires root privileges!", logger=InfrastructureLayerAPI._core_name) # Load additional params into CONFIG if necessary core.addListenerByName("UpEvent", _start_layer)
def __init__(self, net=None, opts=None, fallback=True, run_dry=True): """ Initialize NetworkBuilder. If the topology definition is not found, an exception will be raised or an empty :class:`mininet.net.Mininet` topology will be created if ``run_dry`` is set. :param net: update given Mininet object instead of creating a new one :type net: :class:`mininet.net.Mininet` :param opts: update default options with the given opts :type opts: dict :param fallback: search for fallback topology (default: True) :type fallback: bool :param run_dry: do not raise an Exception and return with bare Mininet obj. :type run_dry: bool :return: None """ self.opts = dict(self.default_opts) if opts is not None: self.opts.update(opts) self.fallback = fallback self.run_dry = run_dry if net is not None: if isinstance(net, Mininet): # Initial settings - Create new Mininet object if necessary self.mn = net else: raise TopologyBuilderException( "Network object's type must be a derived class of Mininet!" ) else: # self.mn = Mininet(**self.opts) try: self.mn = MininetWithControlNet(**self.opts) except KeyboardInterrupt: quit_with_error( msg="Assembly of Mininet network was interrupted by user!", logger=log) # Basically a wrapper for mn to offer helping functions self.mn_bridge = None # Cache of the topology description as an NFFG which is parsed during # initialization self.topo_desc = None self.__dpid_cntr = self.dpidBase
def initialize (self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Controller Adaptation Sublayer...") self.controller_adapter = ControllerAdapter(self, with_infr=self._with_infr) if self._mapped_nffg: try: mapped_request = self._read_data_from_file(self._mapped_nffg) mapped_request = NFFG.parse(mapped_request) self.__proceed_installation(mapped_nffg=mapped_request) except (ValueError, IOError, TypeError) as e: log.error("Can't load service request from file because of: " + str(e)) quit_with_error(msg=str(e), logger=log) else: log.debug("Graph representation is loaded successfully!") log.info("Controller Adaptation Sublayer has been initialized!")
def initialize(self): """ Initialize NFIB with test data. """ try: try: host, port = CONFIG.get_neo4j_host_port() host = host if host else self.DB_HOST port = port if port else self.DB_PORT log.debug("Initiating Graph database connection[%s:%s]..." % (host, port)) self.graph_db = Graph(host=host, http_port=port) except Unauthorized as e: quit_with_error( "Got Unauthorized error on: %s from neo4j! Disable the authorization " "in /etc/neo4j/neoj4-server.properties!" % e) return self except SocketError: log.warning( "NFIBManager has not been initialized! Only cause problem " "if ESCAPE is used as a Local Orchestrator!") return self self.__initialize() except SocketError as e: log.error( "NFIB is not reachable due to failed neo4j service! Cause: " + str(e)) except KeyboardInterrupt: log.warning("NFIB was interrupted by user!") except Unauthorized: log.error( "neo4j responded with Unauthorized error! Maybe you forgot disabling " "authentication in '/etc/neo4j/neo4j.conf' ?") except IOError as e: if ".neo4j/known_hosts" in str(e): # Skip Permission denied in case of accessing neo4j cache file (v3.0.2) pass else: raise except: log.exception("Got unexpected error during NFIB initialization!") return self
def _load_cfg_file(path): """ Load external configuration from file. Support JSON and YAML format. :param path: file path :type path: str :return: loaded configuration :rtype: dict """ try: with open(path) as f: if path.endswith('yml'): import yaml return yaml.safe_load(f) elif path.endswith('json') or path.endswith('config'): return json.load(f, object_hook=unicode_to_str) else: raise ConfigurationError( "Unsupported configuration extension: %s" % path) except IOError: quit_with_error('Default config file: %s is not found!' % path) except Exception as e: quit_with_error("An error occurred when load configuration: %s" % e)
def __init_from_NFFG (self, nffg): """ Initialize topology from an :any:`NFFG` representation. :param nffg: topology object structure :type nffg: :any:`NFFG` :return: None """ # pprint(nffg.network.__dict__) log.info("Start topology creation from NFFG(name: %s)..." % nffg.name) created_mn_nodes = {} # created nodes as 'NFFG-id': <node> created_mn_links = {} # created links as 'NFFG-id': <link> # If not set then cache the given NFFG as the topology description self.topo_desc = nffg # Create a Controller which will be the default internal POX controller try: self.create_Controller("ESCAPE") except SystemExit: raise TopologyBuilderException("Controller creations was unsuccessful!") # Convert INFRAs for infra in nffg.infras: # Create EE if infra.infra_type == NodeInfra.TYPE_EE: if infra.domain == "INTERNAL": ee_type = self.TYPE_EE_LOCAL else: log.warning( "Detected domain of infra: %s is not INTERNAL! Remote EE creation " "for domains other than INTERNAL is not supported yet!" % infra) # ee_type = self.TYPE_EE_REMOTE ee_type = self.TYPE_EE_LOCAL # FIXME - set resource info in MN EE if can - cpu,mem,delay,bandwidth? agt, sw = self.create_NETCONF_EE(name=infra.id, type=ee_type) created_mn_nodes[infra.id] = sw # Create Switch elif infra.infra_type == NodeInfra.TYPE_SDN_SWITCH: switch = self.create_Switch(name=infra.id) created_mn_nodes[infra.id] = switch elif infra.infra_type == NodeInfra.TYPE_STATIC_EE: static_ee = self.create_static_EE(name=infra.id) created_mn_nodes[infra.id] = static_ee else: quit_with_error( msg="Type: %s in %s is not supported by the topology creation " "process in %s!" % ( infra.infra_type, infra, self.__class__.__name__), logger=log) # Create SAPs - skip the temporary, inter-domain SAPs for sap in {s for s in nffg.saps if not s.binding}: # Create SAP sap_host = self.create_SAP(name=sap.id) created_mn_nodes[sap.id] = sap_host # Convert VNFs # TODO - implement --> currently the default Mininet topology does not # TODO contain NFs but it could be possible # Convert connections - copy link ref in a list and iter over it for edge in [l for l in nffg.links]: # Skip initiation of links which connected to an inter-domain SAP if (edge.src.node.type == NFFG.TYPE_SAP and edge.src.node.binding is not None) or ( edge.dst.node.type == NFFG.TYPE_SAP and edge.dst.node.binding is not None): continue # Create Links mn_src_node = created_mn_nodes.get(edge.src.node.id) mn_dst_node = created_mn_nodes.get(edge.dst.node.id) if mn_src_node is None or mn_dst_node is None: raise TopologyBuilderException( "Created topology node is missing! Something really went wrong!") src_port = int(edge.src.id) if int(edge.src.id) < 65535 else None if src_port is None: log.warning( "Source port id of Link: %s is generated dynamically! Using " "automatic port assignment based on internal Mininet " "implementation!" % edge) dst_port = int(edge.dst.id) if int(edge.dst.id) < 65535 else None if dst_port is None: log.warning( "Destination port id of Link: %s is generated dynamically! Using " "automatic port assignment based on internal Mininet " "implementation!" % edge) link = self.create_Link(src=mn_src_node, src_port=src_port, dst=mn_dst_node, dst_port=dst_port, bw=edge.bandwidth, delay=str(edge.delay) + 'ms') created_mn_links[edge.id] = link # Set port properties of SAP nodes. # A possible excerpt from a escape-mn-topo.nffg file: # "ports": [{ "id": 1, # "property": ["ip:10.0.10.1/24"] }] # for n in {s for s in nffg.saps if not s.binding}: mn_node = self.mn.getNodeByName(n.id) for port in n.ports: # ip should be something like '10.0.123.1/24'. if len(port.l3): if len(port.l3) == 1: ip = port.l3.container[0].provided else: log.warning( "Multiple L3 address is detected! Skip explicit IP address " "definition...") ip = None else: # or None ip = port.get_property('ip') if port.l2: mac = port.l2 else: mac = port.get_property('mac') intf = mn_node.intfs.get(port.id) if intf is None: log.warn(("Port %s of node %s is not connected," "it will remain unconfigured!") % (port.id, n.name)) continue if intf == mn_node.defaultIntf(): # Workaround a bug in Mininet mn_node.params.update({'ip': ip}) mn_node.params.update({'mac': mac}) if ip is not None: mn_node.setIP(ip, intf=intf) log.debug("Use explicit IP: %s for node: %s" % (ip, n)) if mac is not None: mn_node.setMAC(mac, intf=intf) log.debug("Use explicit MAC: %s for node: %s" % (mac, n)) # For inter-domain SAPs no need to create host/xterm just add the SAP as # a port to the border Node # Iterate inter-domain SAPs self.bind_inter_domain_SAPs(nffg=nffg) log.info("Topology creation from NFFG has been finished!")