Add vCMTS VNF for running vCMTSd containers
[yardstick.git] / yardstick / tests / unit / network_services / vnf_generic / vnf / test_vcmts_vnf.py
1 # Copyright (c) 2019 Viosoft Corporation
2 #
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
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 import unittest
16 import mock
17 import copy
18 import os
19
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
24
25 from influxdb.resultset import ResultSet
26
27 NAME = "vnf__0"
28
29
30 class TestInfluxDBHelper(unittest.TestCase):
31
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)
38
39     def test_start(self):
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)
44
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)
49
50         influxdb_helper._last_values_time['cpu_value'] = "RANDOM"
51         self.assertEqual(influxdb_helper._get_last_value_time('cpu_value'),
52                          "RANDOM")
53
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'],
58                          "'00:00'")
59
60     def test__query_measurement(self):
61         influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
62         influxdb_helper._read_client = mock.MagicMock()
63
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)
69
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)
76
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)
83
84         entry = {
85             "type":"type",
86             "host":"host",
87             "time":"time",
88             "id": "1",
89             "value": "1.0"
90         }
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()
96
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()
102
103
104 class TestVcmtsdSetupEnvHelper(unittest.TestCase):
105     POD_CFG = {
106         "cm_crypto": "aes",
107         "cpu_socket_id": "0",
108         "ds_core_pool_index": "2",
109         "ds_core_type": "exclusive",
110         "net_ds": "1a:02.1",
111         "net_us": "1a:02.0",
112         "num_ofdm": "1",
113         "num_subs": "100",
114         "power_mgmt": "pm_on",
115         "qat": "qat_off",
116         "service_group_config": "",
117         "sg_id": "0",
118         "vcmtsd_image": "vcmts-d:perf"
119     }
120
121     OPTIONS = {
122         "pktgen_values": "/tmp/pktgen_values.yaml",
123         "tg__0": {
124             "pktgen_id": 0
125         },
126         "vcmts_influxdb_ip": "10.80.5.150",
127         "vcmts_influxdb_port": 8086,
128         "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
129         "vnf__0": {
130             "sg_id": 0,
131             "stream_dir": "us"
132         },
133         "vnf__1": {
134             "sg_id": 0,
135             "stream_dir": "ds"
136         }
137     }
138
139     def setUp(self):
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
145
146         self.setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper(
147             vnfd_helper, ssh_helper, scenario_helper)
148
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']) \
153              + " --pool=shared" \
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']
162
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)
167
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']
182
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)
187
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)
195
196     def test_run_vcmtsd(self):
197         us_constructed = self._build_us_parameters()
198
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
204
205         setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper(
206             vnfd_helper, ssh_helper, scenario_helper)
207
208         setup_helper.run_vcmtsd('us', self.POD_CFG)
209         ssh_helper.send_command.assert_called_with(us_constructed)
210
211     def test_setup_vnf_environment(self):
212         self.assertIsNone(self.setup_helper.setup_vnf_environment())
213
214 class TestVcmtsVNF(unittest.TestCase):
215
216     VNFD = {'vnfd:vnfd-catalog':
217             {'vnfd':
218             [{
219             "benchmark": {
220                 "kpi": [
221                     "upstream/bits_per_second"
222                 ]
223             },
224             "connection-point": [
225                 {
226                     "name": "xe0",
227                     "type": "VPORT"
228                 },
229                 {
230                     "name": "xe1",
231                     "type": "VPORT"
232                 }
233             ],
234             "description": "vCMTS Upstream-Downstream Kubernetes",
235             "id": "VcmtsVNF",
236             "mgmt-interface": {
237                 "ip": "192.168.100.35",
238                 "key_filename": "/tmp/yardstick_key-81dcca91",
239                 "user": "root",
240                 "vdu-id": "vcmtsvnf-kubernetes"
241             },
242             "name": "vcmtsvnf",
243             "short-name": "vcmtsvnf",
244             "vdu": [
245                 {
246                     "description": "vCMTS Upstream-Downstream Kubernetes",
247                     "external-interface": [],
248                     "id": "vcmtsvnf-kubernetes",
249                     "name": "vcmtsvnf-kubernetes"
250                 }
251             ],
252             "vm-flavor": {
253                 "memory-mb": "4096",
254                 "vcpu-count": "4"
255             }
256         }]
257         }
258     }
259
260     POD_CFG = [
261         {
262             "cm_crypto": "aes",
263             "cpu_socket_id": "0",
264             "ds_core_pool_index": "2",
265             "ds_core_type": "exclusive",
266             "net_ds": "1a:02.1",
267             "net_us": "1a:02.0",
268             "num_ofdm": "1",
269             "num_subs": "100",
270             "power_mgmt": "pm_on",
271             "qat": "qat_off",
272             "service_group_config": "",
273             "sg_id": "0",
274             "vcmtsd_image": "vcmts-d:perf"
275         },
276     ]
277
278     SCENARIO_CFG = {
279         "nodes": {
280             "tg__0": "pktgen0-k8syardstick-afae18b2",
281             "vnf__0": "vnf0us-k8syardstick-afae18b2",
282             "vnf__1": "vnf0ds-k8syardstick-afae18b2"
283         },
284         "options": {
285             "pktgen_values": "/tmp/pktgen_values.yaml",
286             "tg__0": {
287                 "pktgen_id": 0
288             },
289             "vcmts_influxdb_ip": "10.80.5.150",
290             "vcmts_influxdb_port": 8086,
291             "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
292             "vnf__0": {
293                 "sg_id": 0,
294                 "stream_dir": "us"
295             },
296             "vnf__1": {
297                 "sg_id": 0,
298                 "stream_dir": "ds"
299             }
300         },
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",
306         "type": "NSPerf"
307     }
308
309     CONTEXT_CFG = {
310         "networks": {
311             "flannel": {
312                 "name": "flannel"
313             },
314             "xe0": {
315                 "name": "xe0"
316             },
317             "xe1": {
318                 "name": "xe1"
319             }
320         },
321         "nodes": {
322             "tg__0": {
323                 "VNF model": "../../vnf_descriptors/tg_vcmts_tpl.yaml",
324                 "interfaces": {
325                     "flannel": {
326                         "local_ip": "192.168.24.110",
327                         "local_mac": None,
328                         "network_name": "flannel"
329                     },
330                     "xe0": {
331                         "local_ip": "192.168.24.110",
332                         "local_mac": None,
333                         "network_name": "xe0"
334                     },
335                     "xe1": {
336                         "local_ip": "192.168.24.110",
337                         "local_mac": None,
338                         "network_name": "xe1"
339                     }
340                 },
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",
346                 "service_ports": [
347                     {
348                         "name": "ssh",
349                         "node_port": 17153,
350                         "port": 22,
351                         "protocol": "TCP",
352                         "target_port": 22
353                     },
354                     {
355                         "name": "lua",
356                         "node_port": 51250,
357                         "port": 22022,
358                         "protocol": "TCP",
359                         "target_port": 22022
360                     }
361                 ],
362                 "ssh_port": 17153,
363                 "user": "root",
364                 "vnfd-id-ref": "tg__0"
365             },
366             "vnf__0": {
367                 "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
368                 "interfaces": {
369                     "flannel": {
370                         "local_ip": "192.168.100.53",
371                         "local_mac": None,
372                         "network_name": "flannel"
373                     },
374                     "xe0": {
375                         "local_ip": "192.168.100.53",
376                         "local_mac": None,
377                         "network_name": "xe0"
378                     },
379                     "xe1": {
380                         "local_ip": "192.168.100.53",
381                         "local_mac": None,
382                         "network_name": "xe1"
383                     }
384                 },
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",
390                 "service_ports": [
391                     {
392                         "name": "ssh",
393                         "node_port": 34027,
394                         "port": 22,
395                         "protocol": "TCP",
396                         "target_port": 22
397                     },
398                     {
399                         "name": "lua",
400                         "node_port": 32580,
401                         "port": 22022,
402                         "protocol": "TCP",
403                         "target_port": 22022
404                     }
405                 ],
406                 "ssh_port": 34027,
407                 "user": "root",
408                 "vnfd-id-ref": "vnf__0"
409             },
410             "vnf__1": {
411                 "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
412                 "interfaces": {
413                     "flannel": {
414                         "local_ip": "192.168.100.52",
415                         "local_mac": None,
416                         "network_name": "flannel"
417                     },
418                     "xe0": {
419                         "local_ip": "192.168.100.52",
420                         "local_mac": None,
421                         "network_name": "xe0"
422                     },
423                     "xe1": {
424                         "local_ip": "192.168.100.52",
425                         "local_mac": None,
426                         "network_name": "xe1"
427                     }
428                 },
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",
434                 "service_ports": [
435                     {
436                         "name": "ssh",
437                         "node_port": 58661,
438                         "port": 22,
439                         "protocol": "TCP",
440                         "target_port": 22
441                     },
442                     {
443                         "name": "lua",
444                         "node_port": 58233,
445                         "port": 22022,
446                         "protocol": "TCP",
447                         "target_port": 22022
448                     }
449                 ],
450                 "ssh_port": 58661,
451                 "user": "root",
452                 "vnfd-id-ref": "vnf__1"
453             },
454         }
455     }
456
457     VCMTSD_VALUES_PATH = "/tmp/vcmtsd_values.yaml"
458
459     VCMTSD_VALUES = \
460             "serviceAccount: cmk-serviceaccount\n" \
461             "topology:\n" \
462             "  vcmts_replicas: 16\n" \
463             "  vcmts_pods:\n" \
464             "    - service_group_config:\n" \
465             "      sg_id: 0\n" \
466             "      net_us: 18:02.0\n" \
467             "      net_ds: 18:02.1\n" \
468             "      num_ofdm: 4\n" \
469             "      num_subs: 300\n" \
470             "      cm_crypto: aes\n" \
471             "      qat: qat_off\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"
477
478     VCMTSD_VALUES_INCOMPLETE = \
479             "serviceAccount: cmk-serviceaccount\n" \
480             "topology:\n" \
481             "  vcmts_replicas: 16"
482
483     def setUp(self):
484         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
485         self.vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd)
486
487     def test___init__(self, *args):
488         self.assertIsNotNone(self.vnf.setup_helper)
489
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)
496
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)
502
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)
510
511     def test_instantiate_empty_vcmtsd_values_file(self):
512         yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
513         yaml_sample.write("")
514         yaml_sample.close()
515
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)
520
521         if os.path.isfile(self.VCMTSD_VALUES_PATH):
522             os.remove(self.VCMTSD_VALUES_PATH)
523
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)
529
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)
533         yaml_sample.close()
534
535         err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
536         with self.assertRaises(KeyError):
537             self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
538
539         if os.path.isfile(self.VCMTSD_VALUES_PATH):
540             os.remove(self.VCMTSD_VALUES_PATH)
541
542     def test_instantiate_invalid_sg_id(self):
543         yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
544         yaml_sample.write(self.VCMTSD_VALUES)
545         yaml_sample.close()
546
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)
551
552         if os.path.isfile(self.VCMTSD_VALUES_PATH):
553             os.remove(self.VCMTSD_VALUES_PATH)
554
555     @mock.patch('yardstick.network_services.vnf_generic.vnf.vcmts_vnf.VnfSshHelper')
556     def test_instantiate_all_valid(self, ssh, *args):
557         mock_ssh(ssh)
558
559         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
560         vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd)
561
562         yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
563         yaml_sample.write(self.VCMTSD_VALUES)
564         yaml_sample.close()
565
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)
569
570         if os.path.isfile(self.VCMTSD_VALUES_PATH):
571             os.remove(self.VCMTSD_VALUES_PATH)
572
573     def test__update_collectd_options(self):
574         scenario_cfg = {'options':
575                             {'collectd':
576                                  {'interval': 3,
577                                   'plugins':
578                                       {'plugin3': {'param': 3}}},
579                              'vnf__0':
580                                  {'collectd':
581                                       {'interval': 2,
582                                        'plugins':
583                                            {'plugin3': {'param': 2},
584                                             'plugin2': {'param': 2}}}}}}
585         context_cfg = {'nodes':
586                            {'vnf__0':
587                                 {'collectd':
588                                      {'interval': 1,
589                                       'plugins':
590                                           {'plugin3': {'param': 1},
591                                            'plugin2': {'param': 1},
592                                            'plugin1': {'param': 1}}}}}}
593         expected = {'interval': 1,
594                     'plugins':
595                         {'plugin3': {'param': 1},
596                          'plugin2': {'param': 1},
597                          'plugin1': {'param': 1}}}
598
599         self.vnf._update_collectd_options(scenario_cfg, context_cfg)
600         self.assertEqual(self.vnf.setup_helper.collectd_options, expected)
601
602     def test__update_options(self):
603         options1 = {'interval': 1,
604                     'param1': 'value1',
605                     'plugins':
606                         {'plugin3': {'param': 3},
607                          'plugin2': {'param': 1},
608                          'plugin1': {'param': 1}}}
609         options2 = {'interval': 2,
610                     'param2': 'value2',
611                     'plugins':
612                         {'plugin4': {'param': 4},
613                          'plugin2': {'param': 2},
614                          'plugin1': {'param': 2}}}
615         expected = {'interval': 1,
616                     'param1': 'value1',
617                     'param2': 'value2',
618                     'plugins':
619                         {'plugin4': {'param': 4},
620                          'plugin3': {'param': 3},
621                          'plugin2': {'param': 1},
622                          'plugin1': {'param': 1}}}
623
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)
628
629     def test_wait_for_instantiate(self):
630         self.assertIsNone(self.vnf.wait_for_instantiate())
631
632     def test_terminate(self):
633         self.assertIsNone(self.vnf.terminate())
634
635     def test_scale(self):
636         self.assertIsNone(self.vnf.scale())
637
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()
642
643     def test_start_collect(self):
644         self.vnf.vcmts_influxdb_ip = "localhost"
645         self.vnf.vcmts_influxdb_port = 8800
646
647         self.assertIsNone(self.vnf.start_collect())
648         self.assertIsNotNone(self.vnf.influxdb_helper)
649
650     def test_stop_collect(self):
651         self.assertIsNone(self.vnf.stop_collect())