1 # Copyright (c) 2019 Viosoft Corporation
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
20 from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
21 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
22 from yardstick.network_services.vnf_generic.vnf import vcmts_vnf
23 from yardstick.common import exceptions
25 from influxdb.resultset import ResultSet
30 class TestInfluxDBHelper(unittest.TestCase):
32 def test___init__(self):
33 influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
34 self.assertEqual(influxdb_helper._vcmts_influxdb_ip, "localhost")
35 self.assertEqual(influxdb_helper._vcmts_influxdb_port, 8086)
36 self.assertIsNotNone(influxdb_helper._last_upstream_rx)
37 self.assertIsNotNone(influxdb_helper._last_values_time)
40 influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
41 influxdb_helper.start()
42 self.assertIsNotNone(influxdb_helper._read_client)
43 self.assertIsNotNone(influxdb_helper._write_client)
45 def test__get_last_value_time(self):
46 influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
47 self.assertEqual(influxdb_helper._get_last_value_time('cpu_value'),
48 vcmts_vnf.InfluxDBHelper.INITIAL_VALUE)
50 influxdb_helper._last_values_time['cpu_value'] = "RANDOM"
51 self.assertEqual(influxdb_helper._get_last_value_time('cpu_value'),
54 def test__set_last_value_time(self):
55 influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
56 influxdb_helper._set_last_value_time('cpu_value', '00:00')
57 self.assertEqual(influxdb_helper._last_values_time['cpu_value'],
60 def test__query_measurement(self):
61 influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
62 influxdb_helper._read_client = mock.MagicMock()
64 resulted_generator = mock.MagicMock()
65 resulted_generator.keys.return_value = []
66 influxdb_helper._read_client.query.return_value = resulted_generator
67 query_result = influxdb_helper._query_measurement('cpu_value')
68 self.assertIsNone(query_result)
70 resulted_generator = mock.MagicMock()
71 resulted_generator.keys.return_value = ["", ""]
72 resulted_generator.get_points.return_value = ResultSet({"":""})
73 influxdb_helper._read_client.query.return_value = resulted_generator
74 query_result = influxdb_helper._query_measurement('cpu_value')
75 self.assertIsNotNone(query_result)
77 def test__rw_measurment(self):
78 influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
79 influxdb_helper._query_measurement = mock.MagicMock()
80 influxdb_helper._query_measurement.return_value = None
81 influxdb_helper._rw_measurment('cpu_value', [])
82 self.assertEqual(len(influxdb_helper._last_values_time), 0)
91 influxdb_helper._query_measurement.return_value = [entry]
92 influxdb_helper._write_client = mock.MagicMock()
93 influxdb_helper._rw_measurment('cpu_value', ["id", "value"])
94 self.assertEqual(len(influxdb_helper._last_values_time), 1)
95 influxdb_helper._write_client.write_points.assert_called_once()
97 def test_copy_kpi(self):
98 influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
99 influxdb_helper._rw_measurment = mock.MagicMock()
100 influxdb_helper.copy_kpi()
101 influxdb_helper._rw_measurment.assert_called()
104 class TestVcmtsdSetupEnvHelper(unittest.TestCase):
107 "cpu_socket_id": "0",
108 "ds_core_pool_index": "2",
109 "ds_core_type": "exclusive",
114 "power_mgmt": "pm_on",
116 "service_group_config": "",
118 "vcmtsd_image": "vcmts-d:perf"
122 "pktgen_values": "/tmp/pktgen_values.yaml",
126 "vcmts_influxdb_ip": "10.80.5.150",
127 "vcmts_influxdb_port": 8086,
128 "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
140 vnfd_helper = VnfdHelper(
141 TestVcmtsVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
142 ssh_helper = mock.Mock()
143 scenario_helper = mock.Mock()
144 scenario_helper.options = self.OPTIONS
146 self.setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper(
147 vnfd_helper, ssh_helper, scenario_helper)
149 def _build_us_parameters(self):
150 return vcmts_vnf.VcmtsdSetupEnvHelper.BASE_PARAMETERS + " " \
151 + " /opt/bin/cmk isolate --conf-dir=/etc/cmk" \
152 + " --socket-id=" + str(self.POD_CFG['cpu_socket_id']) \
154 + " /vcmts-config/run_upstream.sh " + self.POD_CFG['sg_id'] \
155 + " " + self.POD_CFG['ds_core_type'] \
156 + " " + str(self.POD_CFG['num_ofdm']) + "ofdm" \
157 + " " + str(self.POD_CFG['num_subs']) + "cm" \
158 + " " + self.POD_CFG['cm_crypto'] \
159 + " " + self.POD_CFG['qat'] \
160 + " " + self.POD_CFG['net_us'] \
161 + " " + self.POD_CFG['power_mgmt']
163 def test_build_us_parameters(self):
164 constructed = self._build_us_parameters()
165 result = self.setup_helper.build_us_parameters(self.POD_CFG)
166 self.assertEqual(constructed, result)
168 def _build_ds_parameters(self):
169 return vcmts_vnf.VcmtsdSetupEnvHelper.BASE_PARAMETERS + " " \
170 + " /opt/bin/cmk isolate --conf-dir=/etc/cmk" \
171 + " --socket-id=" + str(self.POD_CFG['cpu_socket_id']) \
172 + " --pool=" + self.POD_CFG['ds_core_type'] \
173 + " /vcmts-config/run_downstream.sh " + self.POD_CFG['sg_id'] \
174 + " " + self.POD_CFG['ds_core_type'] \
175 + " " + str(self.POD_CFG['ds_core_pool_index']) \
176 + " " + str(self.POD_CFG['num_ofdm']) + "ofdm" \
177 + " " + str(self.POD_CFG['num_subs']) + "cm" \
178 + " " + self.POD_CFG['cm_crypto'] \
179 + " " + self.POD_CFG['qat'] \
180 + " " + self.POD_CFG['net_ds'] \
181 + " " + self.POD_CFG['power_mgmt']
183 def test_build_ds_parameters(self):
184 constructed = self._build_ds_parameters()
185 result = self.setup_helper.build_ds_parameters(self.POD_CFG)
186 self.assertEqual(constructed, result)
188 def test_build_cmd(self):
189 us_constructed = self._build_us_parameters()
190 us_result = self.setup_helper.build_cmd('us', self.POD_CFG)
191 self.assertEqual(us_constructed, us_result)
192 ds_constructed = self._build_ds_parameters()
193 ds_result = self.setup_helper.build_cmd('ds', self.POD_CFG)
194 self.assertEqual(ds_constructed, ds_result)
196 def test_run_vcmtsd(self):
197 us_constructed = self._build_us_parameters()
199 vnfd_helper = VnfdHelper(
200 TestVcmtsVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
201 ssh_helper = mock.MagicMock()
202 scenario_helper = mock.Mock()
203 scenario_helper.options = self.OPTIONS
205 setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper(
206 vnfd_helper, ssh_helper, scenario_helper)
208 setup_helper.run_vcmtsd('us', self.POD_CFG)
209 ssh_helper.send_command.assert_called_with(us_constructed)
211 def test_setup_vnf_environment(self):
212 self.assertIsNone(self.setup_helper.setup_vnf_environment())
214 class TestVcmtsVNF(unittest.TestCase):
216 VNFD = {'vnfd:vnfd-catalog':
221 "upstream/bits_per_second"
224 "connection-point": [
234 "description": "vCMTS Upstream-Downstream Kubernetes",
237 "ip": "192.168.100.35",
238 "key_filename": "/tmp/yardstick_key-81dcca91",
240 "vdu-id": "vcmtsvnf-kubernetes"
243 "short-name": "vcmtsvnf",
246 "description": "vCMTS Upstream-Downstream Kubernetes",
247 "external-interface": [],
248 "id": "vcmtsvnf-kubernetes",
249 "name": "vcmtsvnf-kubernetes"
263 "cpu_socket_id": "0",
264 "ds_core_pool_index": "2",
265 "ds_core_type": "exclusive",
270 "power_mgmt": "pm_on",
272 "service_group_config": "",
274 "vcmtsd_image": "vcmts-d:perf"
280 "tg__0": "pktgen0-k8syardstick-afae18b2",
281 "vnf__0": "vnf0us-k8syardstick-afae18b2",
282 "vnf__1": "vnf0ds-k8syardstick-afae18b2"
285 "pktgen_values": "/tmp/pktgen_values.yaml",
289 "vcmts_influxdb_ip": "10.80.5.150",
290 "vcmts_influxdb_port": 8086,
291 "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
301 "task_id": "afae18b2-9902-477f-8128-49afde7c3040",
302 "task_path": "samples/vnf_samples/nsut/cmts",
303 "tc": "tc_vcmts_k8s_pktgen",
304 "topology": "k8s_vcmts_topology.yaml",
305 "traffic_profile": "../../traffic_profiles/fixed.yaml",
323 "VNF model": "../../vnf_descriptors/tg_vcmts_tpl.yaml",
326 "local_ip": "192.168.24.110",
328 "network_name": "flannel"
331 "local_ip": "192.168.24.110",
333 "network_name": "xe0"
336 "local_ip": "192.168.24.110",
338 "network_name": "xe1"
341 "ip": "192.168.24.110",
342 "key_filename": "/tmp/yardstick_key-afae18b2",
343 "member-vnf-index": "1",
344 "name": "pktgen0-k8syardstick-afae18b2",
345 "private_ip": "192.168.24.110",
364 "vnfd-id-ref": "tg__0"
367 "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
370 "local_ip": "192.168.100.53",
372 "network_name": "flannel"
375 "local_ip": "192.168.100.53",
377 "network_name": "xe0"
380 "local_ip": "192.168.100.53",
382 "network_name": "xe1"
385 "ip": "192.168.100.53",
386 "key_filename": "/tmp/yardstick_key-afae18b2",
387 "member-vnf-index": "3",
388 "name": "vnf0us-k8syardstick-afae18b2",
389 "private_ip": "192.168.100.53",
408 "vnfd-id-ref": "vnf__0"
411 "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
414 "local_ip": "192.168.100.52",
416 "network_name": "flannel"
419 "local_ip": "192.168.100.52",
421 "network_name": "xe0"
424 "local_ip": "192.168.100.52",
426 "network_name": "xe1"
429 "ip": "192.168.100.52",
430 "key_filename": "/tmp/yardstick_key-afae18b2",
431 "member-vnf-index": "4",
432 "name": "vnf0ds-k8syardstick-afae18b2",
433 "private_ip": "192.168.100.52",
452 "vnfd-id-ref": "vnf__1"
457 VCMTSD_VALUES_PATH = "/tmp/vcmtsd_values.yaml"
460 "serviceAccount: cmk-serviceaccount\n" \
462 " vcmts_replicas: 16\n" \
464 " - service_group_config:\n" \
466 " net_us: 18:02.0\n" \
467 " net_ds: 18:02.1\n" \
470 " cm_crypto: aes\n" \
472 " power_mgmt: pm_on\n" \
473 " cpu_socket_id: 0\n" \
474 " ds_core_type: exclusive\n" \
475 " ds_core_pool_index: 0\n" \
476 " vcmtsd_image: vcmts-d:feat"
478 VCMTSD_VALUES_INCOMPLETE = \
479 "serviceAccount: cmk-serviceaccount\n" \
481 " vcmts_replicas: 16"
484 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
485 self.vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd)
487 def test___init__(self, *args):
488 self.assertIsNotNone(self.vnf.setup_helper)
490 def test_extract_pod_cfg(self):
491 pod_cfg = self.vnf.extract_pod_cfg(self.POD_CFG, "0")
492 self.assertIsNotNone(pod_cfg)
493 self.assertEqual(pod_cfg['sg_id'], '0')
494 pod_cfg = self.vnf.extract_pod_cfg(self.POD_CFG, "1")
495 self.assertIsNone(pod_cfg)
497 def test_instantiate_missing_influxdb_info(self):
498 err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
499 err_scenario_cfg['options'].pop('vcmts_influxdb_ip', None)
500 with self.assertRaises(KeyError):
501 self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
503 def test_instantiate_missing_vcmtsd_values_file(self):
504 if os.path.isfile(self.VCMTSD_VALUES_PATH):
505 os.remove(self.VCMTSD_VALUES_PATH)
506 err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
507 err_scenario_cfg['options']['vcmtsd_values'] = self.VCMTSD_VALUES_PATH
508 with self.assertRaises(RuntimeError):
509 self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
511 def test_instantiate_empty_vcmtsd_values_file(self):
512 yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
513 yaml_sample.write("")
516 err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
517 err_scenario_cfg['options']['vcmtsd_values'] = self.VCMTSD_VALUES_PATH
518 with self.assertRaises(RuntimeError):
519 self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
521 if os.path.isfile(self.VCMTSD_VALUES_PATH):
522 os.remove(self.VCMTSD_VALUES_PATH)
524 def test_instantiate_missing_vcmtsd_values_key(self):
525 err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
526 err_scenario_cfg['options'].pop('vcmtsd_values', None)
527 with self.assertRaises(KeyError):
528 self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
530 def test_instantiate_invalid_vcmtsd_values(self):
531 yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
532 yaml_sample.write(self.VCMTSD_VALUES_INCOMPLETE)
535 err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
536 with self.assertRaises(KeyError):
537 self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
539 if os.path.isfile(self.VCMTSD_VALUES_PATH):
540 os.remove(self.VCMTSD_VALUES_PATH)
542 def test_instantiate_invalid_sg_id(self):
543 yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
544 yaml_sample.write(self.VCMTSD_VALUES)
547 err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
548 err_scenario_cfg['options'][NAME]['sg_id'] = 8
549 with self.assertRaises(exceptions.IncorrectConfig):
550 self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
552 if os.path.isfile(self.VCMTSD_VALUES_PATH):
553 os.remove(self.VCMTSD_VALUES_PATH)
555 @mock.patch('yardstick.network_services.vnf_generic.vnf.vcmts_vnf.VnfSshHelper')
556 def test_instantiate_all_valid(self, ssh, *args):
559 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
560 vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd)
562 yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
563 yaml_sample.write(self.VCMTSD_VALUES)
566 vnf.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG)
567 self.assertEqual(vnf.vcmts_influxdb_ip, "10.80.5.150")
568 self.assertEqual(vnf.vcmts_influxdb_port, 8086)
570 if os.path.isfile(self.VCMTSD_VALUES_PATH):
571 os.remove(self.VCMTSD_VALUES_PATH)
573 def test__update_collectd_options(self):
574 scenario_cfg = {'options':
578 {'plugin3': {'param': 3}}},
583 {'plugin3': {'param': 2},
584 'plugin2': {'param': 2}}}}}}
585 context_cfg = {'nodes':
590 {'plugin3': {'param': 1},
591 'plugin2': {'param': 1},
592 'plugin1': {'param': 1}}}}}}
593 expected = {'interval': 1,
595 {'plugin3': {'param': 1},
596 'plugin2': {'param': 1},
597 'plugin1': {'param': 1}}}
599 self.vnf._update_collectd_options(scenario_cfg, context_cfg)
600 self.assertEqual(self.vnf.setup_helper.collectd_options, expected)
602 def test__update_options(self):
603 options1 = {'interval': 1,
606 {'plugin3': {'param': 3},
607 'plugin2': {'param': 1},
608 'plugin1': {'param': 1}}}
609 options2 = {'interval': 2,
612 {'plugin4': {'param': 4},
613 'plugin2': {'param': 2},
614 'plugin1': {'param': 2}}}
615 expected = {'interval': 1,
619 {'plugin4': {'param': 4},
620 'plugin3': {'param': 3},
621 'plugin2': {'param': 1},
622 'plugin1': {'param': 1}}}
624 vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
625 vnf = vcmts_vnf.VcmtsVNF('vnf1', vnfd)
626 vnf._update_options(options2, options1)
627 self.assertEqual(options2, expected)
629 def test_wait_for_instantiate(self):
630 self.assertIsNone(self.vnf.wait_for_instantiate())
632 def test_terminate(self):
633 self.assertIsNone(self.vnf.terminate())
635 def test_scale(self):
636 self.assertIsNone(self.vnf.scale())
638 def test_collect_kpi(self):
639 self.vnf.influxdb_helper = mock.MagicMock()
640 self.vnf.collect_kpi()
641 self.vnf.influxdb_helper.copy_kpi.assert_called_once()
643 def test_start_collect(self):
644 self.vnf.vcmts_influxdb_ip = "localhost"
645 self.vnf.vcmts_influxdb_port = 8800
647 self.assertIsNone(self.vnf.start_collect())
648 self.assertIsNotNone(self.vnf.influxdb_helper)
650 def test_stop_collect(self):
651 self.assertIsNone(self.vnf.stop_collect())