def spawn_lvnf(self, image, cpp, lvnf_id=None): """Spawn a new LVNF on the specified CPP.""" if not lvnf_id: lvnf_id = uuid.uuid4() else: lvnf_id = uuid.UUID(lvnf_id) tenant = RUNTIME.tenants[self.tenant_id] if lvnf_id in tenant.lvnfs: raise KeyError("LVNF found %s", lvnf_id) lvnf = LVNF(lvnf_id=lvnf_id, tenant_id=self.tenant_id, image=image, cpp=cpp) lvnf.start() # the LVNF is added to the list because in this way its state is # maintained as spawning, then as a result of the lvnf status message # this can change to running or stopped. tenant.lvnfs[lvnf_id] = lvnf
def _handle_lvnf_status_response(self, response): """Handle an incoming LVNF_STATUS_RESPONSE message. Args: status_lvnf, a LVNF_STATUS_RESPONSE message Returns: None """ # update dpid dpid = DPID(response['dpid']) if dpid not in RUNTIME.datapaths: RUNTIME.datapaths[dpid] = Datapath(dpid) self.cpp.datapath = RUNTIME.datapaths[dpid] # update network ports for port in response['ports'].values(): if port['ovs_port_id'] not in self.cpp.datapath.network_ports: network_port = NetworkPort(dp=self.cpp.datapath, port_id=port['ovs_port_id'], hwaddr=EtherAddress(port['hwaddr']), iface=port['iface']) self.cpp.datapath.network_ports[port['ovs_port_id']] = \ network_port # update lvnf tenant_id = uuid.UUID(response['tenant_id']) lvnf_id = uuid.UUID(response['lvnf_id']) if tenant_id not in RUNTIME.tenants: LOG.warning("Tenant %s not found, ignoring LVNF %s", tenant_id, lvnf_id) return tenant = RUNTIME.tenants[tenant_id] # Add lvnf to tenant if not present if lvnf_id not in tenant.lvnfs: LOG.warning("LVNF %s not found, adding.", lvnf_id) img_dict = response['image'] image = Image(nb_ports=img_dict['nb_ports'], vnf=img_dict['vnf'], state_handlers=img_dict['state_handlers'], handlers=img_dict['handlers']) tenant.lvnfs[lvnf_id] = LVNF(lvnf_id, tenant, image, PROCESS_RUNNING) tenant.lvnfs[lvnf_id]._cpp = self.cpp tenant.lvnfs[lvnf_id].datapath = self.cpp.datapath lvnf = tenant.lvnfs[lvnf_id] # update virtual ports for port in response['ports'].values(): network_port = self.cpp.datapath.network_ports[port['ovs_port_id']] virtual_port_id = port['virtual_port_id'] virtual_port = VirtualPort(endpoint=lvnf, network_port=network_port, virtual_port_id=virtual_port_id) lvnf.ports[virtual_port.virtual_port_id] = virtual_port LOG.info("LVNF Status: %s", lvnf)
def _handle_status_lvnf(self, status_lvnf): """Handle an incoming STATUS_LVNF message. Args: status_lvnf, a STATUS_LVNF message Returns: None """ addr = EtherAddress(status_lvnf['addr']) cpp = RUNTIME.cpps[addr] tenant_id = uuid.UUID(status_lvnf['tenant_id']) lvnf_id = uuid.UUID(status_lvnf['lvnf_id']) tenant = RUNTIME.tenants[tenant_id] LOG.info("LVNF %s status update: %s" % (lvnf_id, status_lvnf['process'])) # Add lvnf to tenant if not present if lvnf_id not in tenant.lvnfs: LOG.warning("LVNF %s not found, adding." % lvnf_id) img_dict = status_lvnf['image'] image = Image(nb_ports=img_dict['nb_ports'], vnf=img_dict['vnf'], state_handlers=img_dict['state_handlers'], handlers=img_dict['handlers']) tenant.lvnfs[lvnf_id] = LVNF(lvnf_id, tenant_id, image, cpp) lvnf = tenant.lvnfs[lvnf_id] # Got a LVNF stop message, this could be due to a migration, i.e. the # old LVNF being removed or as a response to a del_lvnf message from # the controller. if status_lvnf['process'] == PROCESS_STOPPED: # A migration is undergoing, process stopped message must be # ignored otherwise the LVNF state will be lost. Just set lvnf # process property so migration can continue if lvnf.process == PROCESS_M2: lvnf.process = PROCESS_STOPPED return # this should not happen if lvnf.cpp != cpp: raise IOError("CPP mismatch") # Stop messages must not arrive during migration if lvnf.process in [PROCESS_M1, PROCESS_M3]: raise IOError("Unknown LVNF") # The status update is coming from the CPP where this LVNF was # active, then this is the result of LVNF delete command coming # from the controller. LOG.info("LVNF LEAVE %s" % (lvnf_id)) for handler in self.server.pt_types_handlers[PT_LVNF_LEAVE]: handler(lvnf) LOG.info("Removing LVNF %s" % lvnf_id) del tenant.lvnfs[lvnf_id] return # reset ports and returcode/message lvnf.ports = {} lvnf.returncode = None lvnf.message = None if status_lvnf['process'] == PROCESS_RUNNING: # Raise LVNF join event if lvnf.process != PROCESS_RUNNING: LOG.info("LVNF JOIN %s" % (lvnf_id)) for handler in self.server.pt_types_handlers[PT_LVNF_JOIN]: handler(lvnf) # Configure ports for port in status_lvnf['ports'].values(): virtual_port_id = port['virtual_port_id'] if port['hwaddr']: hwaddr = EtherAddress(port['hwaddr']) else: hwaddr = None if port['ovs_port_id']: ovs_port_id = int(port['ovs_port_id']) else: ovs_port_id = None virtual_port = VirtualPort(dpid=lvnf.cpp.addr, ovs_port_id=ovs_port_id, virtual_port_id=virtual_port_id, iface=port['iface'], hwaddr=hwaddr) # these are used by the overridden dict methods virtual_port.next.lvnf = lvnf virtual_port.next.port = virtual_port lvnf.ports[virtual_port.virtual_port_id] = virtual_port if status_lvnf['process'] == PROCESS_DONE: # Raise LVNF leave event if lvnf.process != PROCESS_DONE: LOG.info("LVNF LEAVE %s" % (lvnf_id)) for handler in self.server.pt_types_handlers[PT_LVNF_LEAVE]: handler(lvnf) # Set error message lvnf.returncode = status_lvnf['returncode'] lvnf.message = status_lvnf['message'] # set new process lvnf.process = status_lvnf['process']
def post(self, *args, **kwargs): """ Add an LVNF to a tenant. Args: tenant_id: network name of a tenant lvnf_id: the lvnf id Example URLs: POST /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/lvnfs POST /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/ lvnfs/49313ecb-9d00-4a7c-b873-b55d3d9ada34 """ try: if len(args) > 2 or len(args) < 1: raise ValueError("Invalid url") request = tornado.escape.json_decode(self.request.body) if "version" not in request: raise ValueError("missing version element") if "image" not in request: raise ValueError("missing image element") if "addr" not in request: raise ValueError("missing addr element") if "nb_ports" not in request['image']: raise ValueError("missing image/nb_ports element") if "vnf" not in request['image']: raise ValueError("missing image/vnf element") handlers = [] if "handlers" in request['image']: handlers = request['image']['handlers'] state_handlers = [] if "state_handlers" in request['image']: state_handlers = request['image']['state_handlers'] tenant_id = uuid.UUID(args[0]) addr = EtherAddress(request['addr']) tenant = RUNTIME.tenants[tenant_id] cpp = tenant.cpps[addr] if not cpp.is_online(): raise ValueError("CPP %s is not online" % addr) image = Image(nb_ports=request['image']['nb_ports'], vnf=request['image']['vnf'], state_handlers=state_handlers, handlers=handlers) if len(args) == 1: lvnf_id = uuid.uuid4() else: lvnf_id = uuid.UUID(args[1]) lvnf = LVNF(uuid=lvnf_id, tenant=tenant, image=image) lvnf.cpp = cpp tenant.lvnfs[lvnf_id] = lvnf except ValueError as ex: self.send_error(400, message=ex) except KeyError as ex: self.send_error(404, message=ex) self.set_status(201, None)
def _handle_status_lvnf(self, status_lvnf): """Handle an incoming STATUS_LVNF message. Args: status_lvnf, a STATUS_LVNF message Returns: None """ addr = EtherAddress(status_lvnf['addr']) cpp = RUNTIME.cpps[addr] tenant_id = uuid.UUID(status_lvnf['tenant_id']) lvnf_id = uuid.UUID(status_lvnf['lvnf_id']) tenant = RUNTIME.tenants[tenant_id] LOG.info("LVNF %s status update", lvnf_id) # Add lvnf to tenant if not present if lvnf_id not in tenant.lvnfs: LOG.warning("LVNF %s not found, adding.", lvnf_id) img_dict = status_lvnf['image'] image = Image(nb_ports=img_dict['nb_ports'], vnf=img_dict['vnf'], state_handlers=img_dict['state_handlers'], handlers=img_dict['handlers']) tenant.lvnfs[lvnf_id] = LVNF(lvnf_id, tenant_id, image, cpp) lvnf = tenant.lvnfs[lvnf_id] if lvnf.state in (None, PROCESS_RUNNING, PROCESS_SPAWNING, PROCESS_MIGRATING_START): if status_lvnf['returncode']: # Raise LVNF leave event if lvnf.state: LOG.info("LVNF LEAVE %s", lvnf_id) handlers = self.server.pt_types_handlers[PT_LVNF_LEAVE] for handler in handlers: handler(lvnf) lvnf.returncode = status_lvnf['returncode'] lvnf.contex = status_lvnf['context'] lvnf.state = PROCESS_STOPPED return # Configure ports for port in status_lvnf['ports'].values(): virtual_port_id = port['virtual_port_id'] if port['hwaddr']: hwaddr = EtherAddress(port['hwaddr']) else: hwaddr = None if port['ovs_port_id']: ovs_port_id = int(port['ovs_port_id']) else: ovs_port_id = None iface = port['iface'] phy_port = \ NetworkPort(lvnf.cpp.addr, ovs_port_id, hwaddr, iface) virtual_port = VirtualPortLvnf(virtual_port_id=virtual_port_id, phy_port=phy_port) lvnf.ports[virtual_port.virtual_port_id] = virtual_port lvnf.returncode = status_lvnf['returncode'] lvnf.contex = status_lvnf['context'] lvnf.state = PROCESS_RUNNING # Raise LVNF join event if lvnf.state == PROCESS_RUNNING: LOG.info("LVNF JOIN %s", lvnf.lvnf_id) handlers = self.server.pt_types_handlers[PT_LVNF_JOIN] for handler in handlers: handler(lvnf) elif lvnf.state == PROCESS_STOPPING: if status_lvnf['returncode']: # Raise LVNF leave event if lvnf.state: LOG.info("LVNF LEAVE %s", lvnf_id) handlers = self.server.pt_types_handlers[PT_LVNF_LEAVE] for handler in handlers: handler(lvnf) lvnf.returncode = status_lvnf['returncode'] lvnf.contex = status_lvnf['context'] lvnf.state = PROCESS_STOPPED # remove lvnf del tenant.lvnfs[lvnf_id] return IOError("No return code on stopping LVNF") elif lvnf.state == PROCESS_MIGRATING_STOP: if status_lvnf['returncode']: lvnf.returncode = status_lvnf['returncode'] lvnf.context = status_lvnf['context'] lvnf.state = PROCESS_MIGRATING_START return IOError("No returncode on migrating LVNF") else: raise IOError("Invalid transistion")
def post(self, *args, **kwargs): """ Add an LVNF to a tenant. Args: tenant_id: network name of a tenant lvnf_id: the lvnf id Example URLs: POST /api/v1/pools/52313ecb-9d00-4b7d-b873-b55d3d9ada26/lvnfs POST /api/v1/pools/52313ecb-9d00-4b7d-b873-b55d3d9ada26/ lvnfs/49313ecb-9d00-4a7c-b873-b55d3d9ada34 """ try: if len(args) > 2 or len(args) < 1: raise ValueError("Invalid url") request = tornado.escape.json_decode(self.request.body) if "version" not in request: raise ValueError("missing version element") if "image" not in request: raise ValueError("missing image element") if "addr" not in request: raise ValueError("missing addr element") if "nb_ports" not in request['image']: raise ValueError("missing image/nb_ports element") if "vnf" not in request['image']: raise ValueError("missing image/vnf element") handlers = [] if "handlers" in request['image']: handlers = request['image']['handlers'] state_handlers = [] if "state_handlers" in request['image']: state_handlers = request['image']['state_handlers'] tenant_id = uuid.UUID(args[0]) addr = EtherAddress(request['addr']) tenant = RUNTIME.tenants[tenant_id] cpp = tenant.cpps[addr] image = Image(nb_ports=request['image']['nb_ports'], vnf=request['image']['vnf'], state_handlers=state_handlers, handlers=handlers) if not cpp.connection: raise ValueError("CPP disconnected %s" % addr) if len(args) == 1: lvnf_id = uuid.uuid4() else: lvnf_id = uuid.UUID(args[1]) lvnf = LVNF(lvnf_id=lvnf_id, tenant_id=tenant_id, image=image, cpp=cpp) lvnf.start() # the LVNF is added to the list because in this way its state is # maintained as spawning, then as a result of the lvnf status # message this can change to running or stopped. tenant.lvnfs[lvnf_id] = lvnf except ValueError as ex: self.send_error(400, message=ex) except KeyError as ex: self.send_error(404, message=ex) self.set_status(201, None)
def post(self, *args, **kwargs): """ Add an LVNF to a tenant. Args: tenant_id: network name of a tenant lvnf_id: the lvnf id Example URLs: POST /api/v1/pools/52313ecb-9d00-4b7d-b873-b55d3d9ada26/lvnfs POST /api/v1/pools/52313ecb-9d00-4b7d-b873-b55d3d9ada26/ lvnfs/49313ecb-9d00-4a7c-b873-b55d3d9ada34 """ try: if len(args) > 2 or len(args) < 1: raise ValueError("Invalid url") request = tornado.escape.json_decode(self.request.body) if "version" not in request: raise ValueError("missing version element") if "image" not in request: raise ValueError("missing image element") if "addr" not in request: raise ValueError("missing addr element") if "nb_ports" not in request['image']: raise ValueError("missing image/nb_ports element") if "vnf" not in request['image']: raise ValueError("missing image/vnf element") handlers = [] if "handlers" in request['image']: handlers = request['image']['handlers'] state_handlers = [] if "state_handlers" in request['image']: state_handlers = request['image']['state_handlers'] tenant_id = uuid.UUID(args[0]) addr = EtherAddress(request['addr']) tenant = RUNTIME.tenants[tenant_id] cpp = tenant.cpps[addr] image = Image(nb_ports=request['image']['nb_ports'], vnf=request['image']['vnf'], state_handlers=state_handlers, handlers=handlers) if not cpp.connection: raise ValueError("CPP disconnected %s" % addr) if len(args) == 1: lvnf_id = uuid.uuid4() else: lvnf_id = uuid.UUID(args[1]) if lvnf_id in tenant.lvnfs: raise ValueError("already defined %s" % lvnf_id) lvnf = LVNF(lvnf_id=lvnf_id, tenant_id=tenant_id, image=image, cpp=cpp) lvnf.start() except ValueError as ex: self.send_error(400, message=ex) except KeyError as ex: self.send_error(404, message=ex) self.set_status(201, None)