Beispiel #1
0
 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
Beispiel #2
0
    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...")
Beispiel #3
0
  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)
Beispiel #4
0
  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!")
Beispiel #5
0
  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)
Beispiel #6
0
    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
Beispiel #7
0
 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)
Beispiel #8
0
    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!")
Beispiel #9
0
 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!")
Beispiel #10
0
  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()
Beispiel #11
0
  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!")
Beispiel #12
0
  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!")