def construct (self, builder=None): # nc1 = self.addEE(name='NC1', {}) # nc2 = self.addEE(name='NC2', {}) log.info("Start static topology creation...") log.debug("Create Switch with name: SW1") sw1 = self.addSwitch('SW1') log.debug("Create Switch with name: SW2") sw2 = self.addSwitch('SW2') log.debug("Create Switch with name: SW3") sw3 = self.addSwitch('SW3') log.debug("Create Switch with name: SW4") sw4 = self.addSwitch('SW4') log.debug("Create SAP with name: SAP1") sap1 = self.addHost('SAP1') log.debug("Create SAP with name: SAP2") sap2 = self.addHost('SAP2') log.debug("Create Link SW3 <--> SW1") self.addLink(sw3, sw1) log.debug("Create Link SW4 <--> SW2") self.addLink(sw4, sw2) log.debug("Create Link SW3 <--> SW4") self.addLink(sw3, sw4) log.debug("Create Link SAP1 <--> SW3") self.addLink(sap1, sw3) log.debug("Create Link SAP2 <--> SW4") self.addLink(sap2, sw4) log.info("Static topology creation has been finished!") return self
def _handle_ComponentRegistered(self, event): """ Wait for controller (internal POX module) :param event: registered component event :type event: :class:`ComponentRegistered` :return: None """ # Check if our POX controller is up # ESCAPEConfig follows Singleton design pattern internal_adapters = CONFIG.get_component_params( component="INTERNAL")['adapters'] # print internal_adapters internal_controller = CONFIG.get_component(component="CONTROLLER", parent=internal_adapters) # print internal_controller if event.name == internal_controller.name and isinstance( event.component, OpenFlow_01_Task): if self.topology is not None: log.info( "Internal domain controller is up! Initiate network emulation " "now...") self.topology.start_network() else: log.error( "Mininet topology is missing! Skip network starting...")
def cleanup (self): """ Clean up junk which might be left over from old runs. ..seealso:: :func:`mininet.clean.cleanup() <mininet.clean.cleanup>` """ if self.started: log.warning( "Mininet network is not stopped yet! Skipping cleanup task...") else: log.info("Schedule cleanup task after Mininet emulation...") # Kill remained xterms log.debug("Close SAP xterms...") import os import signal for term in self.xterms: os.killpg(term.pid, signal.SIGTERM) # Schedule a cleanup as a coop task to avoid threading issues from escape.util.misc import remove_junks # call_as_coop_task(remove_junks, log=log) # threading.Thread(target=remove_junks, name="cleanup", args=(log, # )).start() # multiprocessing.Process(target=remove_junks, name="cleanup", # args=(log,)).start() remove_junks(log=log)
def __init_from_file (self, path, format=DEFAULT_NFFG_FORMAT): """ Build a pre-defined topology from an NFFG stored in a file. The file path is searched in CONFIG with tha name ``TOPO``. :param path: file path :type path: str :param format: NF-FG storing format (default: internal NFFG representation) :type format: str :return: None """ if path is None: log.error("Missing file path of Topology description") return try: with open(path, 'r') as f: log.info("Load topology from file: %s" % path) if format == self.DEFAULT_NFFG_FORMAT: log.info("Using file format: %s" % format) self.__init_from_NFFG(nffg=NFFG.parse(f.read())) else: raise TopologyBuilderException("Unsupported file format: %s!" % format) except IOError: log.warning("Additional topology file not found: %s" % path) raise TopologyBuilderException("Missing topology file!") except ValueError as e: log.error("An error occurred when load topology from file: %s" % e.message) raise TopologyBuilderException("File parsing error!")
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 construct(self, builder=None): """ Assemble the topology description statically. :param builder: optional builder object :return: self :rtype: :any:`FallbackStaticTopology` """ # nc1 = self.addEE(name='NC1', {}) # nc2 = self.addEE(name='NC2', {}) log.info("Start static topology creation...") log.debug("Create Switch with name: SW1") sw1 = self.addSwitch('SW1') log.debug("Create Switch with name: SW2") sw2 = self.addSwitch('SW2') log.debug("Create Switch with name: SW3") sw3 = self.addSwitch('SW3') log.debug("Create Switch with name: SW4") sw4 = self.addSwitch('SW4') log.debug("Create SAP with name: SAP1") sap1 = self.addHost('SAP1') log.debug("Create SAP with name: SAP2") sap2 = self.addHost('SAP2') log.debug("Create Link SW3 <--> SW1") self.addLink(sw3, sw1) log.debug("Create Link SW4 <--> SW2") self.addLink(sw4, sw2) log.debug("Create Link SW3 <--> SW4") self.addLink(sw3, sw4) log.debug("Create Link SAP1 <--> SW3") self.addLink(sap1, sw3) log.debug("Create Link SAP2 <--> SW4") self.addLink(sap2, sw4) log.info("Static topology creation has been finished!") return self
def __init__(self, standalone=False, **kwargs): """ .. seealso:: :func:`AbstractAPI.__init__() <escape.util.api.AbstractAPI.__init__>` """ log.info("Starting Infrastructure Layer...") self.topology = None super(InfrastructureLayerAPI, self).__init__(standalone, **kwargs)
def shutdown(self, event): """ .. seealso:: :func:`AbstractAPI.shutdown() <escape.util.api.AbstractAPI.shutdown>` :param event: event object """ log.info("Infrastructure Layer is going down...") if self.topology: try: self.topology.stop_network() except KeyboardInterrupt: log.warning( "Shutdown of Mininet network was interrupted by user!")
def initialize(self): """ .. seealso:: :func:`AbstractAPI.initialize() <escape.util.api.AbstractAPI.initialize>` """ log.debug("Initializing Infrastructure Layer...") # Set layer's LOADED value manually here to avoid issues CONFIG.set_layer_loaded(self._core_name) mn_opts = CONFIG.get_mn_network_opts() # Build the emulated topology with the NetworkBuilder optional_topo = getattr(self, '_topo', None) self.topology = ESCAPENetworkBuilder(**mn_opts).build( topo=optional_topo) log.info("Infrastructure Layer has been initialized!")
def __init_from_AbstractTopology (self, topo_class): """ Build topology from pre-defined Topology class. :param topo_class: topology :type topo_class: :any:`AbstractTopology` :return: None """ log.info("Load topology from class: %s" % topo_class.__name__) if topo_class.TYPE == "STATIC": self.mn.topo = topo_class().construct() self.mn.build() elif topo_class.TYPE == "DYNAMIC": # self.mn = topo_class().construct() topo_class().construct(builder=self) else: raise TopologyBuilderException( "TYPE field of the Topology class need to be set!") self.topo_desc = topo_class.get_topo_desc()
def construct (self, builder=None): """ Set a topology with NETCONF capability for mostly testing. :param builder: builder object :return: None """ log.info("Start dynamic topology creation...") builder.create_Controller("ESCAPE") agt1, nc_sw1 = builder.create_NETCONF_EE(name='NC1') agt2, nc_sw2 = builder.create_NETCONF_EE(name='NC2') sw3 = builder.create_Switch(name='SW3') sw4 = builder.create_Switch(name='SW4') sap1 = builder.create_SAP(name='SAP1') sap2 = builder.create_SAP(name='SAP2') builder.create_Link(sw3, nc_sw1) builder.create_Link(sw4, nc_sw2) builder.create_Link(sw3, sw4) builder.create_Link(sap1, sw3) builder.create_Link(sap2, sw4) log.info("Dynamic topology creation has been finished!")
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!")