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
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
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
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 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