示例#1
0
    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
示例#2
0
    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)
示例#5
0
    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")
示例#6
0
    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)