예제 #1
0
    def test_vnfr_add_update_delete(self):
        """
        When a VNFR is added to the Monitor a record is created of the
        relationship between the VNFR and any VDURs that it contains. Each VDUR
        is then registered with the VdurNfviMetricsManager. A VNFR can also be
        updated so that it contains more of less VDURs. Any VDURs that are
        added to the VNFR are registered with the NdurNfviMetricsManager, and
        any that are removed are unregistered. When a VNFR is deleted, all of
        the VDURs contained in the VNFR are unregistered.
        """
        # Define the VDUR to be registered
        vdur = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur()
        vdur.vim_id = 'test-vim-id-1'
        vdur.id = 'test-vdur-id-1'

        vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr()
        vnfr.cloud_account = self.account.name
        vnfr.id = 'test-vnfr-id'

        vnfr.vdur.append(vdur)

        self.monitor.add_cloud_account(self.account)

        # Add the VNFR to the monitor. This will also register VDURs contained
        # in the VNFR with the monitor.
        self.monitor.add_vnfr(vnfr)
        self.assertTrue(self.monitor.is_registered_vdur('test-vdur-id-1'))

        # Add another VDUR to the VNFR and update the monitor. Both VDURs
        # should now be registered
        vdur = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur()
        vdur.vim_id = 'test-vim-id-2'
        vdur.id = 'test-vdur-id-2'

        vnfr.vdur.append(vdur)

        self.monitor.update_vnfr(vnfr)
        self.assertTrue(self.monitor.is_registered_vdur('test-vdur-id-1'))
        self.assertTrue(self.monitor.is_registered_vdur('test-vdur-id-2'))

        # Delete the VNFR from the monitor. This should remove the VNFR and all
        # of the associated VDURs from the monitor.
        self.monitor.remove_vnfr(vnfr.id)
        self.assertFalse(self.monitor.is_registered_vnfr('test-vnfr-id'))
        self.assertFalse(self.monitor.is_registered_vdur('test-vdur-id-1'))
        self.assertFalse(self.monitor.is_registered_vdur('test-vdur-id-2'))

        with self.assertRaises(KeyError):
            self.monitor.retrieve_nfvi_metrics('test-vdur-id-1')

        with self.assertRaises(KeyError):
            self.monitor.retrieve_nfvi_metrics('test-vdur-id-2')
    def test_vnfr_crash(self):
        vnf_handler = store.VnfrCatalogSubscriber(self.log, self.dts,
                                                  self.loop)

        def get_reg_flags(self):
            from gi.repository import RwDts as rwdts
            return rwdts.Flag.SUBSCRIBER | rwdts.Flag.DELTA_READY | rwdts.Flag.CACHE

        vnf_handler.get_reg_flags = types.MethodType(get_reg_flags,
                                                     vnf_handler)

        # publish
        yield from vnf_handler.register()

        mock_vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr()
        mock_vnfr.id = str(uuid.uuid1())

        def mon_xpath(param_id=None):
            """ Monitoring params xpath """
            return ("D,/rw-project:project/vnfr:vnfr-catalog" +
                    "/vnfr:vnfr[vnfr:id={}]".format(quoted_key(mock_vnfr.id)) +
                    "/vnfr:monitoring-param" + ("[vnfr:id={}]".format(
                        quoted_key(param_id)) if param_id else ""))

        w_xpath = "D,/rw-project:project/vnfr:vnfr-catalog/vnfr:vnfr"
        xpath = "{}[vnfr:id={}]".format(w_xpath, quoted_key(mock_vnfr.id))
        yield from self.publisher.publish(w_xpath, xpath, mock_vnfr)

        mock_param = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_MonitoringParam.from_dict(
            {"id": "1"})
        mock_vnfr.monitoring_param.append(mock_param)
        yield from self.publisher.publish(w_xpath, xpath, mock_vnfr)
예제 #3
0
    def start(self):
        """ The task start callback """
        super(RwLogTestTasklet, self).start()

        self._dts = rift.tasklets.DTS(self.tasklet_info,
                                      RwVnfrYang.get_schema(), self.loop,
                                      self.on_dts_state_change)
예제 #4
0
    def __init__(self, log, loop, account, plugin, vdur):
        """Creates an instance of NfviMetrics

        Arguments:
            manager - a NfviInterface instance
            account - a CloudAccount instance
            plugin  - an NFVI plugin
            vdur    - a VDUR instance

        """
        self._log = log
        self._loop = loop
        self._account = account
        self._plugin = plugin
        self._timestamp = 0
        self._metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics()
        self._vdur = vdur
        self._vim_id = vdur.vim_id
        self._updating = None
예제 #5
0
    def test_monitor_cloud_accounts_illegal_removal(self):
        """
        A cloud account may not be removed while there are plugins or records
        that are associated with it. Attempting to delete such a cloud account
        will raise an exception.
        """
        # Add the cloud account to the monitor
        self.monitor.add_cloud_account(self.account)

        # Create a VNFR associated with the cloud account
        vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr()
        vnfr.cloud_account = self.account.name
        vnfr.id = 'test-vnfr-id'

        # Add a VDUR to the VNFR
        vdur = vnfr.vdur.add()
        vdur.vim_id = 'test-vim-id-1'
        vdur.id = 'test-vdur-id-1'

        # Now add the VNFR to the monitor
        self.monitor.add_vnfr(vnfr)

        # Check that the monitor contains the VNFR, VDUR, and metrics
        self.assertTrue(self.monitor.is_registered_vdur(vdur.id))
        self.assertTrue(self.monitor.is_registered_vnfr(vnfr.id))
        self.assertEqual(1, len(self.monitor.metrics))

        # Deleting the cloud account now should raise an exception because the
        # VNFR and VDUR are associated with the cloud account.
        with self.assertRaises(AccountInUseError):
            self.monitor.remove_cloud_account(self.account.name)

        # Now remove the VNFR from the monitor
        self.monitor.remove_vnfr(vnfr.id)
        self.assertFalse(self.monitor.is_registered_vdur(vdur.id))
        self.assertFalse(self.monitor.is_registered_vnfr(vnfr.id))
        self.assertEqual(0, len(self.monitor.metrics))

        # Safely delete the cloud account
        self.monitor.remove_cloud_account(self.account.name)
    def test_vnfr_handler(self):
        yield from self.store.register()

        mock_vnfr = RwVnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr()
        mock_vnfr.id = str(uuid.uuid1())

        w_xpath = "D,/rw-project:project/vnfr:vnfr-catalog/vnfr:vnfr"
        xpath = "{}[vnfr:id={}]".format(w_xpath, quoted_key(mock_vnfr.id))
        yield from self.publisher.publish(w_xpath, xpath, mock_vnfr)

        yield from asyncio.sleep(5, loop=self.loop)
        assert len(self.store.vnfr) == 1
        assert self.store.get_vnfr(self.store.vnfr[0].id) is not None

        yield from self.dts.query_update(xpath, rwdts.XactFlag.ADVISE,
                                         mock_vnfr)
        yield from asyncio.sleep(5, loop=self.loop)
        assert len(self.store.vnfr) == 1

        yield from self.dts.query_delete(xpath, flags=rwdts.XactFlag.ADVISE)
        yield from asyncio.sleep(5, loop=self.loop)
        assert len(self.store.vnfr) == 0
예제 #7
0
    def update(self):
        """Update the NFVI metrics for the associated VDUR

        This coroutine will request new metrics from the data-source and update
        the current metrics.

        """
        try:
            try:
                # Make the request to the plugin in a separate thread and do
                # not exceed the timeout
                _, metrics = yield from asyncio.wait_for(
                        self.loop.run_in_executor(
                            None,
                            self._plugin.nfvi_metrics,
                            self._account,
                            self._vim_id,
                            ),
                        timeout=NfviMetrics.TIMEOUT,
                        loop=self.loop,
                        )

            except asyncio.TimeoutError:
                msg = "timeout on request for nfvi metrics (vim-id = {})"
                self.log.warning(msg.format(self._vim_id))
                return

            except Exception as e:
                self.log.exception(e)
                return

            try:
                # Create uninitialized metric structure
                vdu_metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics()

                # VCPU
                vdu_metrics.vcpu.total = self.vdur.vm_flavor.vcpu_count
                vdu_metrics.vcpu.utilization = metrics.vcpu.utilization

                # Memory (in bytes)
                vdu_metrics.memory.used = metrics.memory.used
                vdu_metrics.memory.total = self.vdur.vm_flavor.memory_mb
                vdu_metrics.memory.utilization = 100 * vdu_metrics.memory.used / vdu_metrics.memory.total

                # Storage
                vdu_metrics.storage.used = metrics.storage.used
                vdu_metrics.storage.total = 1e9 * self.vdur.vm_flavor.storage_gb
                vdu_metrics.storage.utilization = 100 * vdu_metrics.storage.used / vdu_metrics.storage.total

                # Network (incoming)
                vdu_metrics.network.incoming.packets = metrics.network.incoming.packets
                vdu_metrics.network.incoming.packet_rate = metrics.network.incoming.packet_rate
                vdu_metrics.network.incoming.bytes = metrics.network.incoming.bytes
                vdu_metrics.network.incoming.byte_rate = metrics.network.incoming.byte_rate

                # Network (outgoing)
                vdu_metrics.network.outgoing.packets = metrics.network.outgoing.packets
                vdu_metrics.network.outgoing.packet_rate = metrics.network.outgoing.packet_rate
                vdu_metrics.network.outgoing.bytes = metrics.network.outgoing.bytes
                vdu_metrics.network.outgoing.byte_rate = metrics.network.outgoing.byte_rate

                # External ports
                vdu_metrics.external_ports.total = len(self.vdur.external_interface)

                # Internal ports
                vdu_metrics.internal_ports.total = len(self.vdur.internal_interface)

                self._metrics = vdu_metrics

            except Exception as e:
                self.log.exception(e)

        finally:
            # Regardless of the result of the query, we want to make sure that
            # we do not poll the data source until another sample duration has
            # passed.
            self._timestamp = time.time()
예제 #8
0
def update(loop, log, executor, account, plugin, vim_id):
    """Update the NFVI metrics for the associated VDUR

    This coroutine will request new metrics from the data-source and update
    the current metrics.

    """
    try:
        # Make the request to the plugin in a separate thread and do
        # not exceed the timeout
        _, metrics = yield from asyncio.wait_for(
                loop.run_in_executor(
                    executor,
                    plugin.nfvi_metrics,
                    account,
                    vim_id
                    ),
                timeout=10,
                loop=loop,
                )

    except asyncio.TimeoutError:
        msg = "timeout on request for nfvi metrics (vim-id = {})"
        log.warning(msg.format(vim_id))
        return

    except Exception as e:
        log.exception(e)
        return

    try:
        # Create uninitialized metric structure
        vdu_metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics()

        # VCPU
        vdu_metrics.vcpu.total = 5
        vdu_metrics.vcpu.utilization = metrics.vcpu.utilization

        # Memory (in bytes)
        vdu_metrics.memory.used = metrics.memory.used
        vdu_metrics.memory.total = 5000
        vdu_metrics.memory.utilization = 100 * vdu_metrics.memory.used / vdu_metrics.memory.total

        # Storage
        try:
            vdu_metrics.storage.used = metrics.storage.used
            utilization = 100 * vdu_metrics.storage.used / vdu_metrics.storage.total
            if utilization > 100:
                utilization = 100

            vdu_metrics.storage.utilization = utilization

        except ZeroDivisionError:
            vdu_metrics.storage.utilization = 0

        # Network (incoming)
        vdu_metrics.network.incoming.packets = metrics.network.incoming.packets
        vdu_metrics.network.incoming.packet_rate = metrics.network.incoming.packet_rate
        vdu_metrics.network.incoming.bytes = metrics.network.incoming.bytes
        vdu_metrics.network.incoming.byte_rate = metrics.network.incoming.byte_rate

        # Network (outgoing)
        vdu_metrics.network.outgoing.packets = metrics.network.outgoing.packets
        vdu_metrics.network.outgoing.packet_rate = metrics.network.outgoing.packet_rate
        vdu_metrics.network.outgoing.bytes = metrics.network.outgoing.bytes
        vdu_metrics.network.outgoing.byte_rate = metrics.network.outgoing.byte_rate

        # External ports
        vdu_metrics.external_ports.total = 5

        # Internal ports
        vdu_metrics.internal_ports.total = 5

        return vdu_metrics

    except Exception as e:
        log.exception(e)
예제 #9
0
    def test_complete(self):
        """
        This test simulates the addition of a VNFR to the Monitor (along with
        updates), and retrieves NFVI metrics from the VDUR. The VNFR is then
        deleted, which should result in a cleanup of all the data in the
        Monitor.
        """
        # Create the VNFR
        vnfr = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr()
        vnfr.cloud_account = self.account.name
        vnfr.id = 'test-vnfr-id'

        # Create 2 VDURs
        vdur = vnfr.vdur.add()
        vdur.id = 'test-vdur-id-1'
        vdur.vim_id = 'test-vim-id-1'
        vdur.vm_flavor.vcpu_count = 4
        vdur.vm_flavor.memory_mb = 100
        vdur.vm_flavor.storage_gb = 2

        vdur = vnfr.vdur.add()
        vdur.id = 'test-vdur-id-2'
        vdur.vim_id = 'test-vim-id-2'
        vdur.vm_flavor.vcpu_count = 4
        vdur.vm_flavor.memory_mb = 100
        vdur.vm_flavor.storage_gb = 2

        class MockPlugin(object):
            def __init__(self):
                self._metrics = dict()
                self._metrics['test-vim-id-1'] = RwmonYang.NfviMetrics()
                self._metrics['test-vim-id-2'] = RwmonYang.NfviMetrics()

            def nfvi_metrics(self, account, vim_id):
                metrics = self._metrics[vim_id]

                if vim_id == 'test-vim-id-1':
                    metrics.memory.used += 1000
                else:
                    metrics.memory.used += 2000

                return metrics

        class MockFactory(PluginFactory):
            PLUGIN_NAME = "mock"

            def create(self, cloud_account):
                plugin = rw_peas.PeasPlugin("rwmon_mock", 'RwMon-1.0')
                impl = plugin.get_interface("Monitoring")
                impl.set_impl(MockPlugin())
                return impl

        # Modify the mock plugin factory
        self.monitor._nfvi_plugins._factories["mock"] = MockFactory()

        # Add the cloud account the monitor
        self.monitor.add_cloud_account(self.account)

        # Add the VNFR to the monitor.
        self.monitor.add_vnfr(vnfr)

        @wait_for_pending_tasks(self.loop)
        @asyncio.coroutine
        def call1():
            # call #1 (time = 0.00s)
            # The metrics for these VDURs have not been populated yet so a
            # default metrics object (all zeros) is returned, and a request is
            # scheduled with the data source to retrieve the metrics.
            metrics1 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-1')
            metrics2 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-2')

            self.assertEqual(0, metrics1.memory.used)
            self.assertEqual(0, metrics2.memory.used)

        self.loop.run_until_complete(call1())

        @wait_for_pending_tasks(self.loop)
        @asyncio.coroutine
        def call2():
            # call #2 (wait 0.05s)
            # The metrics have been populated with data from the data source
            # due to the request made during call #1.
            yield from asyncio.sleep(0.05)

            metrics1 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-1')
            metrics2 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-2')

            self.assertEqual(1000, metrics1.memory.used)
            self.assertEqual(2000, metrics2.memory.used)

        self.loop.run_until_complete(call2())

        @wait_for_pending_tasks(self.loop)
        @asyncio.coroutine
        def call3():
            # call #3 (wait 0.50s)
            # This call exceeds 0.1s (the sample interval of the plugin)
            # from when the data was retrieved. The cached metrics are
            # immediately returned, but a request is made to the data source to
            # refresh these metrics.
            yield from asyncio.sleep(0.10)

            metrics1 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-1')
            metrics2 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-2')

            self.assertEqual(1000, metrics1.memory.used)
            self.assertEqual(2000, metrics2.memory.used)

        self.loop.run_until_complete(call3())

        @wait_for_pending_tasks(self.loop)
        @asyncio.coroutine
        def call4():
            # call #4 (wait 1.00s)
            # The metrics retrieved differ from those in call #3 because the
            # cached metrics have been updated.
            yield from asyncio.sleep(0.10)
            metrics1 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-1')
            metrics2 = self.monitor.retrieve_nfvi_metrics('test-vdur-id-2')

            self.assertEqual(2000, metrics1.memory.used)
            self.assertEqual(4000, metrics2.memory.used)

        self.loop.run_until_complete(call4())
예제 #10
0
 def nfvi_metrics(self, account, vim_id):
     metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics(
     )
     metrics.vcpu.utilization = 0.5
     return None, metrics
예제 #11
0
 def __init__(self, *args, **kwargs):
     super(RwLogTestTasklet, self).__init__(*args, **kwargs)
     self._dts = None
     self.rwlog.set_category("rw-logtest-log")
     self._metrics = RwVnfrYang.YangData_Vnfr_VnfrCatalog_Vnfr_Vdur_NfviMetrics(
     )
 def configure_schema(cls):
     return RwVnfrYang.get_schema()