示例#1
0
 def start(self, multiplex_sockets=False):
   """
   Start a new controller process based on the config's start_cmd
   attribute. Registers the Popen member variable for deletion upon a SIG*
   received in the simulator process
   """
   self.log.info(self.welcome_msg)
   if self.state != ControllerState.DEAD:
     self.log.warn("Starting controller %s when it is not dead!" % self.label)
     return
   if self.config.start_cmd == "":
     raise RuntimeError(
       "No command found to start controller %s!" % self.label)
   self.log.info(
     "Launching controller %s: %s" % (
       self.label, " ".join(self.config.expanded_start_cmd)))
   # These configurations are specific to controllers launched in namespaces
   # Probably it should be factored somewhere else
   launch_in_network_namespace = getattr(self.config,
                                         'launch_in_network_namespace', None)
   if launch_in_network_namespace:
     unclaimed_address = IPAddressSpace.find_unclaimed_address(
       ip_prefix=self.config.address)
     (self.process, self.guest_eth_addr, self.host_device) = \
         launch_namespace(" ".join(self.config.expanded_start_cmd),
                          self.config.address, self.cid,
                          host_ip_addr_str=unclaimed_address)
   else:
     self.process = popen_filtered("[%s]" % self.label,
                                   self.config.expanded_start_cmd,
                                   self.config.cwd)
   self._register_proc(self.process)
   self._check_snapshot_connect()
   self.state = ControllerState.ALIVE
示例#2
0
 def start(self, multiplex_sockets=False):
     """
 Start a new controller process based on the config's start_cmd
 attribute. Registers the Popen member variable for deletion upon a SIG*
 received in the simulator process
 """
     self.log.info(self.welcome_msg)
     if self.state != ControllerState.DEAD:
         self.log.warn("Starting controller %s when it is not dead!" %
                       self.label)
         return
     if self.config.start_cmd == "":
         raise RuntimeError("No command found to start controller %s!" %
                            self.label)
     self.log.info("Launching controller %s: %s" %
                   (self.label, " ".join(self.config.expanded_start_cmd)))
     # These configurations are specific to controllers launched in namespaces
     # Probably it should be factored somewhere else
     launch_in_network_namespace = getattr(self.config,
                                           'launch_in_network_namespace',
                                           None)
     if launch_in_network_namespace:
         unclaimed_address = IPAddressSpace.find_unclaimed_address(
             ip_prefix=self.config.address)
         (self.process, self.guest_eth_addr, self.host_device) = \
             launch_namespace(" ".join(self.config.expanded_start_cmd),
                              self.config.address, self.cid,
                              host_ip_addr_str=unclaimed_address)
     else:
         self.process = popen_filtered("[%s]" % self.label,
                                       self.config.expanded_start_cmd,
                                       self.config.cwd)
     self._register_proc(self.process)
     self._check_snapshot_connect()
     self.state = ControllerState.ALIVE
示例#3
0
 def start(self):
   ''' Start a new controller process based on the config's start_cmd
   attribute. Registers the Popen member variable for deletion upon a SIG*
   received in the simulator process '''
   if self.state != ControllerState.DEAD:
     self.log.warn("Starting controller %s when it is not dead!" % self.label)
     return
   if self.config.start_cmd == "":
     raise RuntimeError("No command found to start controller %s!" % self.label)
   self.log.info("Launching controller %s: %s" % (self.label, " ".join(self.config.expanded_start_cmd)))
   if self.config.launch_in_network_namespace:
     (self.process, self.guest_eth_addr, self.host_device) = \
         launch_namespace(" ".join(self.config.expanded_start_cmd),
                          self.config.address, self.cid,
                          host_ip_addr_str=IPAddressSpace.find_unclaimed_address(ip_prefix=self.config.address))
   else:
     self.process = popen_filtered("[%s]" % self.label, self.config.expanded_start_cmd, self.config.cwd)
   self._register_proc(self.process)
   self.state = ControllerState.ALIVE
    def __init__(self,
                 start_cmd="",
                 address="127.0.0.1",
                 port=None,
                 additional_ports={},
                 cwd=None,
                 sync=None,
                 controller_type=None,
                 label=None,
                 config_file=None,
                 config_template=None,
                 try_new_ports=False,
                 kill_cmd="",
                 restart_cmd="",
                 get_address_cmd="",
                 launch_in_network_namespace=False,
                 snapshot_address=""):
        '''
    Store metadata for the controller.
      - start_cmd: command that starts a controller or a set of controllers,
          followed by a list of command line tokens as arguments. You may make
          use of two macros: __address__ expands to some available IP address
          for the controller, and __port__ expands to some available (OpenFlow) port.
      - kill_cmd: command that kills a controller or a set of controllers,
          followed by a list of command line tokens as arguments
      - address, port: controller socket info for listening to OpenFlow
        connections from switches. address may be specified as "auto" to automatically find a
        non-localhost IP address in the range 192.168.1.0/24, or "__address__" to use
        get_address_cmd to choose an address.
      - get_address_cmd: an optional bash command that returns an address for
        the controller to bind to.
      - controller_type: controller type, specified by the corresponding Controller
          class itself, or a string chosen from one of the keys in controller_type_map
      - snapshot_address: path to unix domain socket where (if configured)
        controller will be listening for snapshot commands
    '''
        if start_cmd == "":
            raise RuntimeError("Must specify boot parameters.")
        self.start_cmd = start_cmd
        self.kill_cmd = kill_cmd
        self.restart_cmd = restart_cmd
        self.launch_in_network_namespace = launch_in_network_namespace
        self.snapshot_address = snapshot_address
        if launch_in_network_namespace and (address == "127.0.0.1"
                                            or address == "localhost"):
            raise ValueError(
                """Must set a non-localhost address for namespace controller.\n"""
                """Specify `auto` to automatically find an available IP.""")

        # Set label
        if label is None:
            label = "c%s" % str(self._controller_count_gen.next())
        if label in self._controller_labels:
            raise ValueError("Label %s already registered!" % label)
        self._controller_labels.add(label)
        self.label = label

        # Set index, for assigning IP addresses in the case of multiple controllers
        match = re.search("c(\d+)", self.label)
        if match:
            self.index = int(match.groups()[0])
        else:
            self.index = None

        # Set address.
        if address == "__address__":
            address = self.get_address(get_address_cmd, cwd)
        elif address == "auto":
            # TODO(cs): need to add support for auto to the sync uri.
            address = IPAddressSpace.find_unclaimed_address()
        self.address = address
        IPAddressSpace.register_address(address)

        if address_is_ip(address) or address == "localhost":
            # Normal TCP socket
            if not port:
                port = self._port_gen[address].next()
            if try_new_ports:
                port = find_port(xrange(port, port + 2000))
            self.port = port
            self._server_info = (self.address, port)
        else:
            # Unix domain socket
            self.port = None
            self._server_info = address

        self.controller_type = controller_type
        if controller_type is None:
            for t in controller_type_map.keys():
                if t in self.start_cmd:
                    self.controller_class = controller_type_map[t]
                    break
            else:
                # Default to Base Controller class
                self.controller_class = Controller
        else:
            if controller_type not in controller_type_map.keys():
                raise RuntimeError("Unknown controller type: %s" %
                                   controller_type)
            self.controller_class = controller_type_map[controller_type]

        self.cwd = cwd
        if not cwd:
            sys.stderr.write("""
        =======================================================================
        WARN - no working directory defined for controller with command line
        %s
        The controller is run in the STS base directory. This may result
        in unintended consequences (i.e. controller not logging correctly).
        =======================================================================
        \n""" % (self.start_cmd))

        self.sync = sync

        self.config_file = config_file
        self.config_template = config_template
        self.additional_ports = additional_ports
示例#5
0
  def start(self, multiplex_sockets=False):
    """
    Start a new POX controller process based on the config's start_cmd
    attribute. Registers the Popen member variable for deletion upon a SIG*
    received in the simulator process
    """
    self.log.info(self.welcome_msg)

    if self.state != ControllerState.DEAD:
      self.log.warn(
        "Starting controller %s when controller is not dead!" % self.label)
      return

    msg.event("Starting POX controller %s" % (str(self.cid)))
    env = None

    if self.config.sync:
      # If a sync connection has been configured in the controller conf
      # launch the controller with environment variable 'sts_sync' set
      # to the appropriate listening port. This is quite a hack.
      env = os.environ.copy()
      port_match = re.search(r':(\d+)$', self.config.sync)
      if port_match is None:
        raise ValueError("sync: cannot find port in %s" % self.config.sync)
      port = port_match.group(1)
      env['sts_sync'] = "ptcp:0.0.0.0:%d" % (int(port),)

    if self.config.sync or multiplex_sockets:
      src_dir = os.path.join(os.path.dirname(__file__), "../../")
      pox_ext_dir = os.path.join(self.config.cwd, "ext")
      if os.path.exists(pox_ext_dir):
        for f in ("sts/util/io_master.py", "sts/syncproto/base.py",
                  "sts/syncproto/pox_syncer.py", "sts/__init__.py",
                  "sts/util/socket_mux/__init__.py",
                  "sts/util/socket_mux/pox_monkeypatcher.py",
                  "sts/util/socket_mux/base.py",
                  "sts/util/socket_mux/server_socket_multiplexer.py"):
          src_path = os.path.join(src_dir, f)
          if not os.path.exists(src_path):
            raise ValueError(
              "Integrity violation: sts sync source path %s (abs: %s) "
              "does not exist" % (src_path, os.path.abspath(src_path)))
          dst_path = os.path.join(pox_ext_dir, f)
          dst_dir = os.path.dirname(dst_path)
          init_py = os.path.join(dst_dir, "__init__.py")
          if not os.path.exists(dst_dir):
            os.makedirs(dst_dir)
          if not os.path.exists(init_py):
            open(init_py, "a").close()
          if os.path.islink(dst_path):
            # Remove symlink and recreate
            os.remove(dst_path)
          if not os.path.exists(dst_path):
            rel_link = os.path.abspath(src_path)
            self.log.debug("Creating symlink %s -> %s", rel_link, dst_path)
            os.symlink(rel_link, dst_path)
      else:
        self.log.warn("Could not find pox ext dir in %s. " +
                      "Cannot check/link in sync module" % pox_ext_dir)

    if self.config.start_cmd in ["", None]:
      raise RuntimeError(
        "No command found to start controller %s!" % self.label)

    start_cmd = getattr(self.config, "expanded_start_cmd",
                        self.config.start_cmd)
    self.log.info(
      "Launching controller %s: %s" % (self.label, " ".join(start_cmd)))

    launch_in_network_namespace = getattr(self.config,
                                          "launch_in_network_namespace",
                                          False)
    if launch_in_network_namespace:
      (self.process, self.guest_eth_addr, self.host_device) = \
          launch_namespace(
            " ".join(start_cmd),
            self.config.address, self.cid,
            host_ip_addr_str=IPAddressSpace.find_unclaimed_address(
              ip_prefix=self.config.address),
            cwd=self.config.cwd, env=env)
    else:
      self.process = popen_filtered("[%s]" % self.label,
                                    start_cmd, self.config.cwd, env)
    self._register_proc(self.process)
    if self.config.sync:
      self.sync_connection = self.sync_connection_manager.connect(
        self, self.config.sync)
    self._check_snapshot_connect()
    self.state = ControllerState.ALIVE
示例#6
0
    def start(self, multiplex_sockets=False):
        """
    Start a new POX controller process based on the config's start_cmd
    attribute. Registers the Popen member variable for deletion upon a SIG*
    received in the simulator process
    """
        self.log.info(self.welcome_msg)

        if self.state != ControllerState.DEAD:
            self.log.warn(
                "Starting controller %s when controller is not dead!" %
                self.label)
            return

        msg.event("Starting POX controller %s" % (str(self.cid)))
        env = None

        if self.config.sync:
            # If a sync connection has been configured in the controller conf
            # launch the controller with environment variable 'sts_sync' set
            # to the appropriate listening port. This is quite a hack.
            env = os.environ.copy()
            port_match = re.search(r':(\d+)$', self.config.sync)
            if port_match is None:
                raise ValueError("sync: cannot find port in %s" %
                                 self.config.sync)
            port = port_match.group(1)
            env['sts_sync'] = "ptcp:0.0.0.0:%d" % (int(port), )

        if self.config.sync or multiplex_sockets:
            src_dir = os.path.join(os.path.dirname(__file__), "../../")
            pox_ext_dir = os.path.join(self.config.cwd, "ext")
            if os.path.exists(pox_ext_dir):
                for f in ("sts/util/io_master.py", "sts/syncproto/base.py",
                          "sts/syncproto/pox_syncer.py", "sts/__init__.py",
                          "sts/util/socket_mux/__init__.py",
                          "sts/util/socket_mux/pox_monkeypatcher.py",
                          "sts/util/socket_mux/base.py",
                          "sts/util/socket_mux/server_socket_multiplexer.py"):
                    src_path = os.path.join(src_dir, f)
                    if not os.path.exists(src_path):
                        raise ValueError(
                            "Integrity violation: sts sync source path %s (abs: %s) "
                            "does not exist" %
                            (src_path, os.path.abspath(src_path)))
                    dst_path = os.path.join(pox_ext_dir, f)
                    dst_dir = os.path.dirname(dst_path)
                    init_py = os.path.join(dst_dir, "__init__.py")
                    if not os.path.exists(dst_dir):
                        os.makedirs(dst_dir)
                    if not os.path.exists(init_py):
                        open(init_py, "a").close()
                    if os.path.islink(dst_path):
                        # Remove symlink and recreate
                        os.remove(dst_path)
                    if not os.path.exists(dst_path):
                        rel_link = os.path.abspath(src_path)
                        self.log.debug("Creating symlink %s -> %s", rel_link,
                                       dst_path)
                        os.symlink(rel_link, dst_path)
            else:
                self.log.warn("Could not find pox ext dir in %s. " +
                              "Cannot check/link in sync module" % pox_ext_dir)

        if self.config.start_cmd in ["", None]:
            raise RuntimeError("No command found to start controller %s!" %
                               self.label)

        start_cmd = getattr(self.config, "expanded_start_cmd",
                            self.config.start_cmd)
        self.log.info("Launching controller %s: %s" %
                      (self.label, " ".join(start_cmd)))

        launch_in_network_namespace = getattr(self.config,
                                              "launch_in_network_namespace",
                                              False)
        if launch_in_network_namespace:
            (self.process, self.guest_eth_addr, self.host_device) = \
                launch_namespace(
                  " ".join(start_cmd),
                  self.config.address, self.cid,
                  host_ip_addr_str=IPAddressSpace.find_unclaimed_address(
                    ip_prefix=self.config.address),
                  cwd=self.config.cwd, env=env)
        else:
            self.process = popen_filtered("[%s]" % self.label, start_cmd,
                                          self.config.cwd, env)
        self._register_proc(self.process)
        if self.config.sync:
            self.sync_connection = self.sync_connection_manager.connect(
                self, self.config.sync)
        self._check_snapshot_connect()
        self.state = ControllerState.ALIVE
  def __init__(self, start_cmd="", address="127.0.0.1", port=None, additional_ports={},
               cwd=None, sync=None, controller_type=None, label=None, config_file=None,
               config_template=None, try_new_ports=False, kill_cmd="", restart_cmd="",
               get_address_cmd="", launch_in_network_namespace=False):
    '''
    Store metadata for the controller.
      - start_cmd: command that starts a controller or a set of controllers,
          followed by a list of command line tokens as arguments. You may make
          use of two macros: __address__ expands to some available IP address
          for the controller, and __port__ expands to some available (OpenFlow) port.
      - kill_cmd: command that kills a controller or a set of controllers,
          followed by a list of command line tokens as arguments
      - address, port: controller socket info for listening to OpenFlow
        connections from switches. address may be specified as "auto" to automatically find a
        non-localhost IP address in the range 192.168.1.0/24, or "__address__" to use
        get_address_cmd to choose an address.
      - get_address_cmd: an optional bash command that returns an address for
        the controller to bind to.
      - controller_type: controller type, specified by the corresponding Controller
          class itself, or a string chosen from one of the keys in controller_type_map
    '''
    if start_cmd == "":
      raise RuntimeError("Must specify boot parameters.")
    self.start_cmd = start_cmd
    self.kill_cmd = kill_cmd
    self.restart_cmd = restart_cmd
    self.launch_in_network_namespace = launch_in_network_namespace
    if launch_in_network_namespace and (address == "127.0.0.1" or address == "localhost"):
      raise ValueError("""Must set a non-localhost address for namespace controller.\n"""
                       """Specify `auto` to automatically find an available IP.""")

    # Set label
    if label is None:
      label = "c%s" % str(self._controller_count_gen.next())
    if label in self._controller_labels:
      raise ValueError("Label %s already registered!" % label)
    self._controller_labels.add(label)
    self.label = label

    # Set index, for assigning IP addresses in the case of multiple controllers
    match = re.search("c(\d+)", self.label)
    if match:
      self.index = int(match.groups()[0])
    else:
      self.index = None

    # Set address.
    if address == "__address__":
      address = self.get_address(get_address_cmd, cwd)
    elif address == "auto":
      # TODO(cs): need to add support for auto to the sync uri.
      address = IPAddressSpace.find_unclaimed_address()
    self.address = address
    IPAddressSpace.register_address(address)

    if address_is_ip(address) or address == "localhost":
      # Normal TCP socket
      if not port:
        port = self._port_gen[address].next()
      if try_new_ports:
        port = find_port(xrange(port, port+2000))
      self.port = port
      self._server_info = (self.address, port)
    else:
      # Unix domain socket
      self.port = None
      self._server_info = address

    self.controller_type = controller_type
    if controller_type is None:
      for t in controller_type_map.keys():
        if t in self.start_cmd:
          self.controller_class = controller_type_map[t]
          break
      else:
        # Default to Base Controller class
        self.controller_class = Controller
    else:
      if controller_type not in controller_type_map.keys():
        raise RuntimeError("Unknown controller type: %s" % controller_type)
      self.controller_class = controller_type_map[controller_type]

    self.cwd = cwd
    if not cwd:
        sys.stderr.write("""
        =======================================================================
        WARN - no working directory defined for controller with command line
        %s
        The controller is run in the STS base directory. This may result
        in unintended consequences (i.e. controller not logging correctly).
        =======================================================================
        \n""" % (self.start_cmd) )

    self.sync = sync

    self.config_file = config_file
    self.config_template = config_template
    self.additional_ports = additional_ports