X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FN2VC.git;a=blobdiff_plain;f=tests%2Fintegration%2Ftest_metrics.py;fp=tests%2Fintegration%2Ftest_metrics.py;h=1151d46355ae41ff48f3f307e6b85bd0f4c2ca01;hp=0000000000000000000000000000000000000000;hb=5afe05434f65dabf514636eff28cbb2069ccb419;hpb=b09436613925b2eb334c10f219b743868e4b3fe5 diff --git a/tests/integration/test_metrics.py b/tests/integration/test_metrics.py new file mode 100644 index 0000000..1151d46 --- /dev/null +++ b/tests/integration/test_metrics.py @@ -0,0 +1,315 @@ +"""Test the collection of charm metrics. + 1. Deploy a charm w/metrics to a unit + 2. Collect metrics or wait for collection to run + 3. Execute n2vc.GetMetrics() + 5. Destroy Juju unit +""" +import asyncio +import functools +import logging +import sys +import time +import unittest +from .. import utils + +NSD_YAML = """ +nsd:nsd-catalog: + nsd: + - id: singlecharmvdu-ns + name: singlecharmvdu-ns + short-name: singlecharmvdu-ns + description: NS with 1 VNFs singlecharmvdu-vnf connected by datanet and mgmtnet VLs + version: '1.0' + logo: osm.png + constituent-vnfd: + - vnfd-id-ref: singlecharmvdu-vnf + member-vnf-index: '1' + vld: + - id: mgmtnet + name: mgmtnet + short-name: mgmtnet + type: ELAN + mgmt-network: 'true' + vim-network-name: mgmt + vnfd-connection-point-ref: + - vnfd-id-ref: singlecharmvdu-vnf + member-vnf-index-ref: '1' + vnfd-connection-point-ref: vnf-mgmt + - vnfd-id-ref: singlecharmvdu-vnf + member-vnf-index-ref: '2' + vnfd-connection-point-ref: vnf-mgmt + - id: datanet + name: datanet + short-name: datanet + type: ELAN + vnfd-connection-point-ref: + - vnfd-id-ref: singlecharmvdu-vnf + member-vnf-index-ref: '1' + vnfd-connection-point-ref: vnf-data + - vnfd-id-ref: singlecharmvdu-vnf + member-vnf-index-ref: '2' + vnfd-connection-point-ref: vnf-data +""" + +VNFD_YAML = """ +vnfd:vnfd-catalog: + vnfd: + - id: singlecharmvdu-vnf + name: singlecharmvdu-vnf + short-name: singlecharmvdu-vnf + version: '1.0' + description: A VNF consisting of 2 VDUs w/charms connected to an internal VL, and one VDU with cloud-init + logo: osm.png + connection-point: + - id: vnf-mgmt + name: vnf-mgmt + short-name: vnf-mgmt + type: VPORT + - id: vnf-data + name: vnf-data + short-name: vnf-data + type: VPORT + mgmt-interface: + cp: vnf-mgmt + internal-vld: + - id: internal + name: internal + short-name: internal + type: ELAN + internal-connection-point: + - id-ref: mgmtVM-internal + - id-ref: dataVM-internal + vdu: + - id: mgmtVM + name: mgmtVM + image: xenial + count: '1' + vm-flavor: + vcpu-count: '1' + memory-mb: '1024' + storage-gb: '10' + interface: + - name: mgmtVM-eth0 + position: '1' + type: EXTERNAL + virtual-interface: + type: VIRTIO + external-connection-point-ref: vnf-mgmt + - name: mgmtVM-eth1 + position: '2' + type: INTERNAL + virtual-interface: + type: VIRTIO + internal-connection-point-ref: mgmtVM-internal + internal-connection-point: + - id: mgmtVM-internal + name: mgmtVM-internal + short-name: mgmtVM-internal + type: VPORT + cloud-init-file: cloud-config.txt + vnf-configuration: + juju: + charm: metrics-ci + config-primitive: + - name: touch + parameter: + - name: filename + data-type: STRING + default-value: '/home/ubuntu/touched' +""" + + +class PythonTest(unittest.TestCase): + n2vc = None + charm = None + + def setUp(self): + self.log = logging.getLogger() + self.log.level = logging.DEBUG + + self.stream_handler = logging.StreamHandler(sys.stdout) + self.log.addHandler(self.stream_handler) + + self.loop = asyncio.get_event_loop() + + self.n2vc = utils.get_n2vc() + + # Parse the descriptor + self.log.debug("Parsing the descriptor") + self.nsd = utils.get_descriptor(NSD_YAML) + self.vnfd = utils.get_descriptor(VNFD_YAML) + + + # Build the charm + + vnf_config = self.vnfd.get("vnf-configuration") + if vnf_config: + juju = vnf_config['juju'] + charm = juju['charm'] + + self.log.debug("Building charm {}".format(charm)) + self.charm = utils.build_charm(charm) + + def tearDown(self): + self.loop.run_until_complete(self.n2vc.logout()) + self.log.removeHandler(self.stream_handler) + + def n2vc_callback(self, model_name, application_name, workload_status,\ + workload_message, task=None): + """We pass the vnfd when setting up the callback, so expect it to be + returned as a tuple.""" + self.log.debug("status: {}; task: {}".format(workload_status, task)) + + # if workload_status in ["stop_test"]: + # # Stop the test + # self.log.debug("Stopping the test1") + # self.loop.call_soon_threadsafe(self.loop.stop) + # return + + if workload_status: + if workload_status in ["active"] and not task: + # Force a run of the metric collector, so we don't have + # to wait for it's normal 5 minute interval run. + # NOTE: this shouldn't be done outside of CI + utils.collect_metrics(application_name) + + # get the current metrics + task = asyncio.ensure_future( + self.n2vc.GetMetrics( + model_name, + application_name, + ) + ) + task.add_done_callback( + functools.partial( + self.n2vc_callback, + model_name, + application_name, + "collect_metrics", + task, + ) + ) + + elif workload_status in ["collect_metrics"]: + + if task: + # Check if task returned metrics + results = task.result() + + foo = utils.parse_metrics(application_name, results) + if 'load' in foo: + self.log.debug("Removing charm") + task = asyncio.ensure_future( + self.n2vc.RemoveCharms(model_name, application_name, self.n2vc_callback) + ) + task.add_done_callback( + functools.partial( + self.n2vc_callback, + model_name, + application_name, + "stop_test", + task, + ) + ) + return + + # No metrics are available yet, so try again in a minute. + self.log.debug("Sleeping for 60 seconds") + time.sleep(60) + task = asyncio.ensure_future( + self.n2vc.GetMetrics( + model_name, + application_name, + ) + ) + task.add_done_callback( + functools.partial( + self.n2vc_callback, + model_name, + application_name, + "collect_metrics", + task, + ) + ) + elif workload_status in ["stop_test"]: + # Stop the test + self.log.debug("Stopping the test2") + self.loop.call_soon_threadsafe(self.loop.stop) + + def test_deploy_application(self): + """Deploy proxy charm to a unit.""" + if self.nsd and self.vnfd: + params = {} + vnf_index = 0 + + def deploy(): + """An inner function to do the deployment of a charm from + either a vdu or vnf. + """ + charm_dir = "{}/builds/{}".format(utils.get_charm_path(), charm) + + # Setting this to an IP that will fail the initial config. + # This will be detected in the callback, which will execute + # the "config" primitive with the right IP address. + # mgmtaddr = self.container.state().network['eth0']['addresses'] + # params['rw_mgmt_ip'] = mgmtaddr[0]['address'] + + # Legacy method is to set the ssh-private-key config + # with open(utils.get_juju_private_key(), "r") as f: + # pkey = f.readline() + # params['ssh-private-key'] = pkey + + ns_name = "default" + + vnf_name = self.n2vc.FormatApplicationName( + ns_name, + self.vnfd['name'], + str(vnf_index), + ) + + self.loop.run_until_complete( + self.n2vc.DeployCharms( + ns_name, + vnf_name, + self.vnfd, + charm_dir, + params, + {}, + self.n2vc_callback + ) + ) + + # Check if the VDUs in this VNF have a charm + # for vdu in vnfd['vdu']: + # vdu_config = vdu.get('vdu-configuration') + # if vdu_config: + # juju = vdu_config['juju'] + # self.assertIsNotNone(juju) + # + # charm = juju['charm'] + # self.assertIsNotNone(charm) + # + # params['initial-config-primitive'] = vdu_config['initial-config-primitive'] + # + # deploy() + # vnf_index += 1 + # + # # Check if this VNF has a charm + vnf_config = self.vnfd.get("vnf-configuration") + if vnf_config: + juju = vnf_config['juju'] + self.assertIsNotNone(juju) + + charm = juju['charm'] + self.assertIsNotNone(charm) + + if 'initial-config-primitive' in vnf_config: + params['initial-config-primitive'] = vnf_config['initial-config-primitive'] + + deploy() + vnf_index += 1 + + self.loop.run_forever() + # while self.loop.is_running(): + # # await asyncio.sleep(1) + # time.sleep(1)