def remove_service_node(self, service_name, force=False): """ Remove an instance that has service_name """ network_function = self.services.get(service_name, None) if network_function: if network_function.active_chains == 0: self.network.remove_container(network_function.id) network_function.stop() del self.services[service_name] del network_function elif force: pending_chains = [] for chain_id, chain in self.chains.items(): if network_function in chain: pending_chains.append(chain_id) for chain_id in pending_chains: self.remove_service_chain(chain_id, force=True) self.network.remove_container(network_function.id) network_function.stop() del self.services[service_name] del network_function else: logger.warning( "Service node is currently used in an active SFC. " "Please use option --force=true to remove it completely") return True
def remove_service_chain(self, chain_id, force=False): """ Remove a service chain identified by (dpid,idx) """ if self.client is None: logger.warning('There is no connection to the SDN controller') return chain = self.chains.get(chain_id, None) if chain: pending_paths = [] for endpoints, cid in self.paths.items(): if chain_id == cid: pending_paths.append(endpoints) if len(pending_paths) == 0 or force: for ep in pending_paths: u, v = ep self.remove_service_path(u, v) for node in chain: node.active_chains -= 1 del chain del self.chains[chain_id] else: logger.warning("Service chain is currently used in an active " "service path. Please use option --force=true " "to remove it completely") return True msg = self.msg_gen.new_delchain_message(chain_id) self.client.send(msg.pack().encode()) return True
def sfc_create_chain(self, services): """ This function expects services to be a space-separated string, consisting of network function services """ if len(set(services)) < len(services): logger.warning('Cannot have duplicated network function in an SFC') return None return self.sfc_orchestrator.create_service_chain(services)
def stop_service(self, name): """ Stop and deregister """ old_service = self.services.pop(name, None) if old_service: old_service.stop() self.used_ports.remove(old_service.port) logger.info(f"Removed service: {old_service.name}") return True logger.warning(f"Service {name} does not exist") return False
def start_service(self, image, name, port, scale=1, command=None): """ Start a service with initial scale and register it """ if name in self.services: logger.warning(f"Service {name} already exists") return False if port in self.used_ports: logger.warning(f"Port {port} has already been used!") return False new_service = MyCloudService(image, name, self.network, port, scale, command) self.services[name] = new_service self.used_ports.add(port) return True
def start_service_node(self, function, service_name): """ Start an instance of a service function (in a Docker container) """ if function not in vnf: logger.warning('Virtual network function not supported') return False else: if service_name not in self.services: network_function = self._start_vnf(function, service_name) self.services[service_name] = network_function else: logger.warning( f"Namespace {service_name} has already been used. " f"Ignoring this operation") return True
def remove_service_path(self, src, dst): """ Remove a service path identified by (src,dst) """ if self.client is None: logger.warning('There is no connection to the SDN controller') return False path_id = (src, dst) if path_id in self.paths: del self.paths[path_id] src_interface = self.network.resolve_interface(src.id) dst_interface = self.network.resolve_interface(dst.id) msg = self.msg_gen.new_delpath_message(src_interface.to_dict(), dst_interface.to_dict()) self.client.send(msg.pack().encode()) return True
def create_service_chain(self, services): """ Create a service chain from existing service nodes in the network """ if not services: logger.warning('List of services cannot be empty') return if self.client is None: logger.warning('There is no connection to the SDN controller') return chain_id = f"{self.network.dpid:08x}-{self.chain_index}" chain = [] for service_name in services: node = self.services.get(service_name, None) if not node: logger.warning( 'Service not found. Chain creation is cancelled') return else: chain.append(node) self.chains[chain_id] = chain for node in chain: node.active_chains += 1 self.chain_index += 1 chain_str = [] for node in chain: interface = self.network.resolve_interface(node.id) chain_str.append(interface.to_dict()) msg = self.msg_gen.new_addchain_message(chain_id, chain_str) self.client.send(msg.pack().encode()) return chain_id
def create_service_path(self, src, dst, chain_id): """ Create a service path from src to dst via the service chain (dpid,idx) """ if self.client is None: logger.warning('There is no connection to the SDN controller') return False path_id = (src, dst) if path_id in self.paths: logger.warning('Path already exists between src and dst nodes') return False else: self.paths[path_id] = chain_id src_interface = self.network.resolve_interface(src.id) dst_interface = self.network.resolve_interface(dst.id) msg = self.msg_gen.new_addpath_message(src_interface.to_dict(), dst_interface.to_dict(), chain_id) self.client.send(msg.pack().encode()) return True