Initial commit to gerrit repo
[osm/PLA.git] / osm_pla / test / test_nsPlacementDataFactory.py
1 # Copyright 2020 ArctosLabs Scandinavia AB
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
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 import os
16 import unittest
17 from collections import Counter
18 from pathlib import Path
19 from unittest import TestCase, mock
20 from unittest.mock import call
21
22 import yaml
23
24 from osm_pla.placement.mznplacement import NsPlacementDataFactory
25
26
27 class TestNsPlacementDataFactory(TestCase):
28 vim_accounts = [{"vim_password": "FxtnynxBCnouzAT4Hkerhg==", "config": {},
29 "_admin": {"modified": 1564579854.0480285, "created": 1564579854.0480285,
30 "operationalState": "ENABLED",
31 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
32 "deployed": {"RO-account": "6beb4e2e-b397-11e9-a7a3-02420aff0008",
33 "RO": "6bcfc3fc-b397-11e9-a7a3-02420aff0008"},
34 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"], "detailed-status": "Done"},
35 "name": "OpenStack1", "vim_type": "openstack", "_id": "92b056a7-38f5-438d-b8ee-3f93b3531f87",
36 "schema_version": "1.1", "vim_user": "admin", "vim_url": "http://10.234.12.47:5000/v3",
37 "vim_tenant_name": "admin"},
38 {"config": {}, "vim_tenant_name": "osm_demo", "schema_version": "1.1", "name": "OpenStack2",
39 "vim_password": "gK5v4Gh2Pl41o6Skwp6RCw==", "vim_type": "openstack",
40 "_admin": {"modified": 1567148372.2490237, "created": 1567148372.2490237,
41 "operationalState": "ENABLED",
42 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
43 "deployed": {"RO-account": "b7fb0034-caf3-11e9-9388-02420aff000a",
44 "RO": "b7f129ce-caf3-11e9-9388-02420aff000a"},
45 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"], "detailed-status": "Done"},
46 "vim_user": "admin", "vim_url": "http://10.234.12.44:5000/v3",
47 "_id": "6618d412-d7fc-4eb0-a6f8-d2c258e0e900"},
48 {"config": {}, "schema_version": "1.1", "name": "OpenStack3",
49 "vim_password": "1R2FoMQnaL6rNSosoRP2hw==", "vim_type": "openstack", "vim_tenant_name": "osm_demo",
50 "_admin": {"modified": 1567599746.689582, "created": 1567599746.689582,
51 "operationalState": "ENABLED",
52 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
53 "deployed": {"RO-account": "a8161f54-cf0e-11e9-9388-02420aff000a",
54 "RO": "a80b6280-cf0e-11e9-9388-02420aff000a"},
55 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"], "detailed-status": "Done"},
56 "vim_user": "admin", "vim_url": "http://10.234.12.46:5000/v3",
57 "_id": "331ffdec-44a8-4707-94a1-af7a292d9735"},
58 {"config": {}, "schema_version": "1.1", "name": "OpenStack4",
59 "vim_password": "6LScyPeMq3QFh3GRb/xwZw==", "vim_type": "openstack", "vim_tenant_name": "osm_demo",
60 "_admin": {"modified": 1567599911.5108898, "created": 1567599911.5108898,
61 "operationalState": "ENABLED",
62 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
63 "deployed": {"RO-account": "0a651200-cf0f-11e9-9388-02420aff000a",
64 "RO": "0a4defc6-cf0f-11e9-9388-02420aff000a"},
65 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"], "detailed-status": "Done"},
66 "vim_user": "admin", "vim_url": "http://10.234.12.43:5000/v3",
67 "_id": "eda92f47-29b9-4007-9709-c1833dbfbe31"}]
68
69 vim_accounts_fewer_vims = [{"vim_password": "FxtnynxBCnouzAT4Hkerhg==", "config": {},
70 "_admin": {"modified": 1564579854.0480285, "created": 1564579854.0480285,
71 "operationalState": "ENABLED",
72 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
73 "deployed": {"RO-account": "6beb4e2e-b397-11e9-a7a3-02420aff0008",
74 "RO": "6bcfc3fc-b397-11e9-a7a3-02420aff0008"},
75 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
76 "detailed-status": "Done"},
77 "name": "OpenStack1", "vim_type": "openstack",
78 "_id": "92b056a7-38f5-438d-b8ee-3f93b3531f87",
79 "schema_version": "1.1", "vim_user": "admin", "vim_url": "http://10.234.12.47:5000/v3",
80 "vim_tenant_name": "admin"},
81 {"config": {}, "vim_tenant_name": "osm_demo", "schema_version": "1.1",
82 "name": "OpenStack2",
83 "vim_password": "gK5v4Gh2Pl41o6Skwp6RCw==", "vim_type": "openstack",
84 "_admin": {"modified": 1567148372.2490237, "created": 1567148372.2490237,
85 "operationalState": "ENABLED",
86 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
87 "deployed": {"RO-account": "b7fb0034-caf3-11e9-9388-02420aff000a",
88 "RO": "b7f129ce-caf3-11e9-9388-02420aff000a"},
89 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
90 "detailed-status": "Done"},
91 "vim_user": "admin", "vim_url": "http://10.234.12.44:5000/v3",
92 "_id": "6618d412-d7fc-4eb0-a6f8-d2c258e0e900"},
93 {"config": {}, "schema_version": "1.1", "name": "OpenStack4",
94 "vim_password": "6LScyPeMq3QFh3GRb/xwZw==", "vim_type": "openstack",
95 "vim_tenant_name": "osm_demo",
96 "_admin": {"modified": 1567599911.5108898, "created": 1567599911.5108898,
97 "operationalState": "ENABLED",
98 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
99 "deployed": {"RO-account": "0a651200-cf0f-11e9-9388-02420aff000a",
100 "RO": "0a4defc6-cf0f-11e9-9388-02420aff000a"},
101 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
102 "detailed-status": "Done"},
103 "vim_user": "admin", "vim_url": "http://10.234.12.43:5000/v3",
104 "_id": "eda92f47-29b9-4007-9709-c1833dbfbe31"}]
105
106 vim_accounts_more_vims = [{"vim_password": "FxtnynxBCnouzAT4Hkerhg==", "config": {},
107 "_admin": {"modified": 1564579854.0480285, "created": 1564579854.0480285,
108 "operationalState": "ENABLED",
109 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
110 "deployed": {"RO-account": "6beb4e2e-b397-11e9-a7a3-02420aff0008",
111 "RO": "6bcfc3fc-b397-11e9-a7a3-02420aff0008"},
112 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
113 "detailed-status": "Done"},
114 "name": "OpenStack1", "vim_type": "openstack",
115 "_id": "92b056a7-38f5-438d-b8ee-3f93b3531f87",
116 "schema_version": "1.1", "vim_user": "admin", "vim_url": "http://10.234.12.47:5000/v3",
117 "vim_tenant_name": "admin"},
118 {"config": {}, "vim_tenant_name": "osm_demo", "schema_version": "1.1",
119 "name": "OpenStack2",
120 "vim_password": "gK5v4Gh2Pl41o6Skwp6RCw==", "vim_type": "openstack",
121 "_admin": {"modified": 1567148372.2490237, "created": 1567148372.2490237,
122 "operationalState": "ENABLED",
123 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
124 "deployed": {"RO-account": "b7fb0034-caf3-11e9-9388-02420aff000a",
125 "RO": "b7f129ce-caf3-11e9-9388-02420aff000a"},
126 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
127 "detailed-status": "Done"},
128 "vim_user": "admin", "vim_url": "http://10.234.12.44:5000/v3",
129 "_id": "6618d412-d7fc-4eb0-a6f8-d2c258e0e900"},
130 {"config": {}, "schema_version": "1.1", "name": "OpenStack4",
131 "vim_password": "6LScyPeMq3QFh3GRb/xwZw==", "vim_type": "openstack",
132 "vim_tenant_name": "osm_demo",
133 "_admin": {"modified": 1567599911.5108898, "created": 1567599911.5108898,
134 "operationalState": "ENABLED",
135 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
136 "deployed": {"RO-account": "0a651200-cf0f-11e9-9388-02420aff000a",
137 "RO": "0a4defc6-cf0f-11e9-9388-02420aff000a"},
138 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
139 "detailed-status": "Done"},
140 "vim_user": "admin", "vim_url": "http://10.234.12.43:5000/v3",
141 "_id": "eda92f47-29b9-4007-9709-c1833dbfbe31"},
142 {"config": {}, "schema_version": "1.1", "name": "OpenStack3",
143 "vim_password": "6LScyPeMq3QFh3GRb/xwZw==", "vim_type": "openstack",
144 "vim_tenant_name": "osm_demo",
145 "_admin": {"modified": 1567599911.5108898, "created": 1567599911.5108898,
146 "operationalState": "ENABLED",
147 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
148 "deployed": {"RO-account": "0a651200-cf0f-11e9-9388-02420aff000a",
149 "RO": "0a4defc6-cf0f-11e9-9388-02420aff000a"},
150 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
151 "detailed-status": "Done"},
152 "vim_user": "admin", "vim_url": "http://10.234.12.46:5000/v3",
153 "_id": "eda92f47-29b9-4007-9709-c1833dbfbe31"},
154 {"config": {}, "schema_version": "1.1", "name": "OpenStack5",
155 "vim_password": "6LScyPeMq3QFh3GRb/xwZw==", "vim_type": "openstack",
156 "vim_tenant_name": "osm_demo",
157 "_admin": {"modified": 1567599911.5108898, "created": 1567599911.5108898,
158 "operationalState": "ENABLED",
159 "projects_read": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
160 "deployed": {"RO-account": "0a651200-cf0f-11e9-9388-02420aff000a",
161 "RO": "0a4defc6-cf0f-11e9-9388-02420aff000a"},
162 "projects_write": ["69915588-e5e2-46d3-96b0-a29bedef6f73"],
163 "detailed-status": "Done"},
164 "vim_user": "admin", "vim_url": "http://1.1.1.1:5000/v3",
165 "_id": "ffffffff-29b9-4007-9709-c1833dbfbe31"}]
166
167 def _produce_ut_vim_accounts_info(self, vim_accounts):
168 """
169 FIXME temporary, we will need more control over vim_urls and _id for test purpose - make a generator
170 :return: vim_url and _id as dict, i.e. extract these from vim_accounts data
171 """
172 return {_['vim_url']: _['_id'] for _ in vim_accounts}
173
174 def _adjust_path(self, file):
175 """In case we are not running from test directory,
176 then assume we are in top level directory (e.g. running from tox) and adjust file path accordingly"""
177 path_component = '/osm_pla/test/'
178 real_path = os.path.realpath(file)
179 if path_component not in real_path:
180 return os.path.dirname(real_path) + path_component + os.path.basename(real_path)
181 else:
182 return real_path
183
184 def _populate_pil_info(self, file):
185 """
186 Note str(Path()) is a 3.5 thing
187 """
188 with open(str(Path(self._adjust_path(file)))) as pp_fd:
189 test_data = yaml.safe_load_all(pp_fd)
190 return next(test_data)
191
192 def _get_ut_nsd_from_file(self, nsd_file_name):
193 """
194 creates the structure representing the nsd.
195
196 IMPORTANT NOTE: If using .yaml files from the NS packages for the unit tests (which we do),
197 then the files must be modified with respect to the way booleans are processed at on-boarding in OSM.
198 The following construct in the NS package yaml file:
199 mgmt-network: 'false'
200 will become a boolean in the MongoDB, and therefore the yaml used in these unit test must use yaml
201 tag as follows:
202 mgmt-network: !!bool False
203 The modification also applies to 'true' => !!bool True
204 This will ensure that the object returned from this function is as expected by PLA.
205 """
206 with open(str(Path(self._adjust_path(nsd_file_name)))) as nsd_fd:
207 test_data = yaml.safe_load_all(nsd_fd)
208 return next(test_data)
209
210 def _produce_ut_vnf_price_list(self):
211 price_list_file = "vnf_price_list.yaml"
212 with open(str(Path(self._adjust_path(price_list_file)))) as pl_fd:
213 price_list_data = yaml.safe_load_all(pl_fd)
214 return {i['vnfd']: {i1['vim_url']: i1['price'] for i1 in i['prices']} for i in next(price_list_data)}
215
216 def _produce_ut_vnf_test_price_list(self, price_list):
217 price_list_file = price_list
218 with open(str(Path(self._adjust_path(price_list_file)))) as pl_fd:
219 price_list_data = yaml.safe_load_all(pl_fd)
220 return {i['vnfd']: {i1['vim_url']: i1['price'] for i1 in i['prices']} for i in next(price_list_data)}
221
222 def test__produce_trp_link_characteristics_link_latency_with_more_vims(self):
223 """
224 -test with more(other) vims compared to pil
225 """
226 content_expected = [0, 0, 0, 0, 0, 120, 120, 130, 130, 140, 140, 230, 230, 240, 240,
227 340, 340, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767]
228 nspdf = NsPlacementDataFactory(
229 self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts_more_vims),
230 self._produce_ut_vnf_price_list(),
231 nsd=None,
232 pil_info=self._populate_pil_info('pil_unittest1.yaml'),
233 pinning=None)
234 pil_latencies = nspdf._produce_trp_link_characteristics_data('pil_latency')
235 content_produced = [i for row in pil_latencies for i in row]
236 self.assertEqual(Counter(content_expected), Counter(content_produced), 'trp_link_latency incorrect')
237
238 def test__produce_trp_link_characteristics_link_latency_with_fewer_vims(self):
239 """
240 -test with fewer vims compared to pil
241 :return:
242 """
243 content_expected = [0, 0, 0, 120, 120, 140, 140, 240, 240]
244 nspdf = NsPlacementDataFactory(
245 self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts_fewer_vims),
246 self._produce_ut_vnf_price_list(),
247 nsd=None,
248 pil_info=self._populate_pil_info('pil_unittest1.yaml'),
249 pinning=None)
250 pil_latencies = nspdf._produce_trp_link_characteristics_data('pil_latency')
251 content_produced = [i for row in pil_latencies for i in row]
252 self.assertEqual(Counter(content_expected), Counter(content_produced), 'trp_link_latency incorrect')
253
254 def test__produce_trp_link_characteristic_not_supported(self):
255 """
256 - test with non-supported characteristic
257 """
258 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
259 self._produce_ut_vnf_price_list(),
260 nsd=None,
261 pil_info=self._populate_pil_info('pil_unittest1.yaml'), pinning=None)
262
263 with self.assertRaises(Exception) as e:
264 nspdf._produce_trp_link_characteristics_data('test_no_support')
265 self.assertRegex(str(e.exception), r'characteristic.*not supported', "invalid exception content")
266
267 def test__produce_trp_link_characteristics_link_latency(self):
268 """
269 -test with full set of vims as in pil
270 -test with fewer vims compared to pil
271 -test with more(other) vims compared to pil
272 -test with invalid/corrupt pil configuration file (e.g. missing endpoint), empty file, not yaml conformant
273 - test with non-supported characteristic
274
275 :return:
276 """
277 content_expected = [0, 0, 0, 0, 120, 120, 130, 130, 140, 140, 230, 230, 240, 240, 340, 340]
278
279 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
280 self._produce_ut_vnf_price_list(),
281 nsd=None,
282 pil_info=self._populate_pil_info('pil_unittest1.yaml'), pinning=None)
283 pil_latencies = nspdf._produce_trp_link_characteristics_data('pil_latency')
284 content_produced = [i for row in pil_latencies for i in row]
285 self.assertEqual(Counter(content_expected), Counter(content_produced), 'trp_link_latency incorrect')
286
287 def test__produce_trp_link_characteristics_link_jitter(self):
288 """
289 -test with full set of vims as in pil
290 """
291 content_expected = [0, 0, 0, 0, 1200, 1200, 1300, 1300, 1400, 1400, 2300, 2300, 2400, 2400, 3400, 3400]
292
293 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
294 self._produce_ut_vnf_price_list(),
295 nsd=None,
296 pil_info=self._populate_pil_info('pil_unittest1.yaml'), pinning=None)
297 pil_jitter = nspdf._produce_trp_link_characteristics_data('pil_jitter')
298 content_produced = [i for row in pil_jitter for i in row]
299 self.assertEqual(Counter(content_expected), Counter(content_produced), 'trp_link_jitter incorrect')
300
301 def test__produce_trp_link_characteristics_link_jitter_with_fewer_vims(self):
302 """
303 -test with fewer vims compared to pil, link jitter
304 """
305 content_expected = [0, 0, 0, 1200, 1200, 1400, 1400, 2400, 2400]
306 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(self.vim_accounts_fewer_vims),
307 self._produce_ut_vnf_price_list(),
308 nsd=None,
309 pil_info=self._populate_pil_info('pil_unittest1.yaml'), pinning=None)
310 pil_latencies = nspdf._produce_trp_link_characteristics_data('pil_jitter')
311 content_produced = [i for row in pil_latencies for i in row]
312 self.assertEqual(Counter(content_expected), Counter(content_produced), 'trp_link_jitter incorrect')
313
314 def test__produce_trp_link_characteristics_link_jitter_with_more_vims(self):
315 """
316 -test with more vims compared to pil, link jitter
317 """
318 content_expected = [0, 0, 0, 0, 0, 1200, 1200, 1300, 1300, 1400, 1400, 2300,
319 2300, 2400, 2400, 3400, 3400, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767]
320 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(self.vim_accounts_more_vims),
321 self._produce_ut_vnf_price_list(),
322 nsd=None,
323 pil_info=self._populate_pil_info('pil_unittest1.yaml'), pinning=None)
324 pil_latencies = nspdf._produce_trp_link_characteristics_data('pil_jitter')
325 content_produced = [i for row in pil_latencies for i in row]
326 self.assertEqual(Counter(content_expected), Counter(content_produced), 'trp_link_jitter incorrect')
327
328 def test__produce_trp_link_characteristics_link_price(self):
329 """
330 -test with full set of vims as in pil
331 """
332 content_expected = [0, 0, 0, 0, 12, 12, 13, 13, 14, 14, 23, 23, 24, 24, 34, 34]
333 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
334 self._produce_ut_vnf_price_list(),
335 nsd=None,
336 pil_info=self._populate_pil_info('pil_unittest1.yaml'), pinning=None)
337 pil_prices = nspdf._produce_trp_link_characteristics_data('pil_price')
338 content_produced = [i for row in pil_prices for i in row]
339 self.assertEqual(Counter(content_expected), Counter(content_produced), 'invalid trp link prices')
340
341 def test__produce_trp_link_characteristics_link_price_with_fewer_vims(self):
342 """
343 -test with fewer vims compared to pil
344 """
345 content_expected = [0, 0, 0, 12, 12, 14, 14, 24, 24]
346 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(self.vim_accounts_fewer_vims),
347 self._produce_ut_vnf_price_list(),
348 nsd=None,
349 pil_info=self._populate_pil_info('pil_unittest1.yaml'), pinning=None)
350 pil_prices = nspdf._produce_trp_link_characteristics_data('pil_price')
351 content_produced = [i for row in pil_prices for i in row]
352 self.assertEqual(Counter(content_expected), Counter(content_produced), 'invalid trp link prices')
353
354 def test__produce_trp_link_characteristics_partly_constrained(self):
355 content_expected = [0, 0, 0, 0, 32767, 32767, 32767, 32767, 1200, 1200, 1400, 1400, 2400, 2400, 3400, 3400]
356 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
357 self._produce_ut_vnf_price_list(),
358 nsd=None,
359 pil_info=self._populate_pil_info('pil_unittest2.yaml'), pinning=None)
360 pil_jitter = nspdf._produce_trp_link_characteristics_data('pil_jitter')
361 content_produced = [i for row in pil_jitter for i in row]
362 self.assertEqual(Counter(content_expected), Counter(content_produced),
363 'invalid trp link jitter, partly constrained')
364
365 def test__produce_vld_desc_partly_constrained(self):
366 vld_desc_expected = [{'cp_refs': ['one', 'two'], 'jitter': 30},
367 {'cp_refs': ['two', 'three'], 'latency': 120}]
368
369 nsd = self._get_ut_nsd_from_file('nsd_unittest2.yaml')
370 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
371 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
372 self._produce_ut_vnf_price_list(),
373 nsd=nsd,
374 pil_info=None, pinning=None)
375 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(),
376 "vld_desc incorrect")
377
378 def test__produce_trp_link_characteristics_link_latency_not_yaml_conformant(self):
379 """
380 -test with invalid/corrupt pil configuration file (not yaml conformant)
381 """
382 with self.assertRaises(Exception) as e:
383 _ = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
384 self._produce_ut_vnf_price_list(),
385 nsd=None,
386 pil_info=self._populate_pil_info('not_yaml_conformant.yaml'),
387 pinning=None)
388 self.assertRegex(str(e.exception), r'mapping values are not allowed here.*', "invalid exception content")
389
390 def test__produce_trp_link_characteristics_with_invalid_pil_config(self):
391 """
392 -test with invalid/corrupt pil configuration file (missing endpoint)
393 """
394 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
395 self._produce_ut_vnf_price_list(),
396 nsd=None,
397 pil_info=self._populate_pil_info('corrupt_pil_endpoints_config_unittest1.yaml'),
398 pinning=None)
399 with self.assertRaises(Exception) as e:
400 _ = nspdf._produce_trp_link_characteristics_data('pil_latency')
401 self.assertEqual('list index out of range', str(e.exception), "unexpected exception")
402
403 def test__produce_vld_desc_w_instantiate_override(self):
404
405 vld_desc_expected = [{'cp_refs': ['one', 'two'], 'latency': 150, 'jitter': 30},
406 {'cp_refs': ['two', 'three'], 'latency': 90, 'jitter': 30}]
407
408 nsd = self._get_ut_nsd_from_file('nsd_unittest_no_vld_constraints.yaml')
409 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
410 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
411 self._produce_ut_vnf_price_list(),
412 nsd=nsd,
413 pil_info=None, pinning=None,
414 order_constraints=None)
415
416 self.assertNotEqual(nspdf._produce_vld_desc(),
417 vld_desc_expected, "vld_desc incorrect")
418
419 def test__produce_vld_desc_nsd_w_instantiate_wo(self):
420 """
421 nsd w/ constraints, instantiate w/o constraints
422 :return:
423 """
424 vld_desc_expected = [{'cp_refs': ['one', 'two'], 'latency': 150, 'jitter': 30},
425 {'cp_refs': ['two', 'three'], 'latency': 90, 'jitter': 30}]
426
427 nsd = self._get_ut_nsd_from_file('nsd_unittest3.yaml')
428 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
429 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
430 self._produce_ut_vnf_price_list(),
431 nsd=nsd,
432 pil_info=None, pinning=None,
433 order_constraints=None)
434
435 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(),
436 "vld_desc incorrect")
437
438 def test__produce_vld_desc_nsd_w_instantiate_w(self):
439 """
440 nsd w/ constraints, instantiate w/ constraints => override
441 :return:
442 """
443 vld_desc_expected = [{'cp_refs': ['one', 'two'], 'latency': 120, 'jitter': 21},
444 {'cp_refs': ['two', 'three'], 'latency': 121, 'jitter': 22}]
445
446 nsd = self._get_ut_nsd_from_file('nsd_unittest3.yaml')
447 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
448 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
449 self._produce_ut_vnf_price_list(),
450 nsd=nsd,
451 pil_info=None, pinning=None,
452 order_constraints={
453 'vld-constraints': [{'id': 'three_vnf_constrained_nsd_vld1',
454 'link-constraints': {'latency': 120,
455 'jitter': 21}},
456 {'id': 'three_vnf_constrained_nsd_vld2',
457 'link-constraints': {'latency': 121,
458 'jitter': 22}}]})
459
460 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(),
461 "vld_desc incorrect")
462
463 def test__produce_vld_desc_nsd_wo_instantiate_wo(self):
464 """
465 nsd w/o constraints, instantiate w/o constraints = no constraints in model
466 :return:
467 """
468 vld_desc_expected = [{'cp_refs': ['one', 'two']},
469 {'cp_refs': ['two', 'three']}]
470
471 nsd = self._get_ut_nsd_from_file('nsd_unittest_no_vld_constraints.yaml')
472 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
473 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
474 self._produce_ut_vnf_price_list(),
475 nsd=nsd,
476 pil_info=None, pinning=None,
477 order_constraints=None)
478
479 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(),
480 "vld_desc incorrect")
481
482 def test__produce_vld_desc_nsd_wo_instantiate_w(self):
483 """
484 nsd w/o constraints, instantiate w/ constraints => add constraints
485 :return:
486 """
487 vld_desc_expected = [{'cp_refs': ['one', 'two'], 'latency': 140, 'jitter': 41},
488 {'cp_refs': ['two', 'three'], 'latency': 141, 'jitter': 42}]
489
490 nsd = self._get_ut_nsd_from_file('nsd_unittest_no_vld_constraints.yaml')
491 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
492 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
493 self._produce_ut_vnf_price_list(),
494 nsd=nsd,
495 pil_info=None, pinning=None,
496 order_constraints={
497 'vld-constraints': [{'id': 'three_vnf_constrained_nsd_vld1',
498 'link-constraints': {'latency': 140,
499 'jitter': 41}},
500 {'id': 'three_vnf_constrained_nsd_vld2',
501 'link-constraints': {'latency': 141,
502 'jitter': 42}}]})
503
504 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(),
505 "vld_desc incorrect")
506
507 def test__produce_vld_desc_nsd_wo_instantiate_w_faulty_input(self):
508 """
509 nsd w/o constraints, instantiate w/ constraints => add constraints that can be parsed
510 :return:
511 """
512 vld_desc_expected = [{'cp_refs': ['one', 'two']},
513 {'cp_refs': ['two', 'three'], 'latency': 151}]
514
515 nsd = self._get_ut_nsd_from_file('nsd_unittest_no_vld_constraints.yaml')
516 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
517 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
518 self._produce_ut_vnf_price_list(),
519 nsd=nsd,
520 pil_info=None, pinning=None,
521 order_constraints={'vld-constraints': [{'id': 'not_included_vld',
522 'misspelled-constraints':
523 {'latency': 120,
524 'jitter': 20}},
525 {'id': 'three_vnf_constrained_nsd_vld2',
526 'link-constraints': {
527 'latency': 151}}]})
528
529 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(),
530 "vld_desc incorrect")
531
532 def test__produce_vld_desc_nsd_wo_instantiate_w_faulty_input_again(self):
533 """
534 nsd w/o constraints, instantiate w/ faulty constraints => add constraints that can be parsed
535 :return:
536 """
537 vld_desc_expected = [{'cp_refs': ['one', 'two'], 'jitter': 21},
538 {'cp_refs': ['two', 'three']}]
539
540 nsd = self._get_ut_nsd_from_file('nsd_unittest_no_vld_constraints.yaml')
541 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
542 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
543 self._produce_ut_vnf_price_list(),
544 nsd=nsd,
545 pil_info=None, pinning=None,
546 order_constraints={
547 'vld-constraints': [{'id': 'three_vnf_constrained_nsd_vld1',
548 'link-constraints': {'delay': 120,
549 'jitter': 21}},
550 {'id': 'three_vnf_constrained_nsd_vld2',
551 'misspelled-constraints': {'latency': 121,
552 'jitter': 22}}]})
553
554 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(),
555 "vld_desc incorrect")
556
557 def test__produce_vld_desc_mgmt_network(self):
558 vld_desc_expected = [{'cp_refs': ['1', '2'], 'latency': 120, 'jitter': 20},
559 {'cp_refs': ['2', '4'], 'latency': 50, 'jitter': 10},
560 {'cp_refs': ['2', '3'], 'latency': 20, 'jitter': 10}, ]
561
562 nsd = self._get_ut_nsd_from_file('test_five_nsd.yaml')
563 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
564 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
565 self._produce_ut_vnf_price_list(),
566 nsd=nsd,
567 pil_info=None, pinning=None,
568 order_constraints=None)
569
570 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(), "vld_desc incorrect")
571
572 def test__produce_vld_desc_single_vnf_nsd(self):
573 vld_desc_expected = []
574
575 nsd = self._get_ut_nsd_from_file('nsd_unittest4.yaml')
576 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
577 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
578 self._produce_ut_vnf_price_list(),
579 nsd=nsd,
580 pil_info=None, pinning=None,
581 order_constraints=None)
582
583 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(), "vld_desc_incorrect")
584
585 def test__produce_vld_desc(self):
586 """
587
588 :return:
589 """
590 vld_desc_expected = [{'cp_refs': ['one', 'two'], 'latency': 150, 'jitter': 30},
591 {'cp_refs': ['two', 'three'], 'latency': 90, 'jitter': 30}]
592
593 nsd = self._get_ut_nsd_from_file('nsd_unittest3.yaml')
594 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
595 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
596 self._produce_ut_vnf_price_list(),
597 nsd=nsd,
598 pil_info=None, pinning=None,
599 order_constraints=None)
600
601 self.assertEqual(vld_desc_expected, nspdf._produce_vld_desc(), "vld_desc incorrect")
602
603 def test__produce_ns_desc(self):
604 """
605 ToDo
606 - price list sheet with more vims than associated with session
607 - price list sheet with fewer vims than associated with session
608 - nsd with different vndfd-id-refs
609 - fault case scenarios with non-existing vims, non-existing vnfds
610 """
611 nsd = self._get_ut_nsd_from_file('nsd_unittest3.yaml')
612 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
613 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
614 self._produce_ut_vnf_price_list(),
615 nsd=nsd,
616 pil_info=None,
617 pinning=None)
618
619 ns_desc = nspdf._produce_ns_desc()
620 # check that all expected member-vnf-index are present
621 vnfs = [e['vnf_id'] for e in ns_desc]
622 self.assertEqual(Counter(['one', 'two', 'three']), Counter(vnfs), 'vnf_id invalid')
623
624 expected_keys = ['vnf_id', 'vnf_price_per_vim']
625 for e in ns_desc:
626 # check that vnf_price_per_vim has proper values
627 self.assertEqual(Counter([5, 10, 30, 30]), Counter(e['vnf_price_per_vim']), 'vnf_price_per_vim invalid')
628 # check that no pinning directives included
629 self.assertEqual(Counter(expected_keys), Counter(e.keys()), 'pinning directive misplaced')
630
631 def test__produce_ns_desc_with_more_vims(self):
632 nsd = self._get_ut_nsd_from_file('nsd_unittest1.yaml')
633 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
634 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(self.vim_accounts_more_vims),
635 self._produce_ut_vnf_test_price_list('vnf_price_list_more_vims.yaml'),
636 nsd=nsd,
637 pil_info=None,
638 pinning=None)
639
640 ns_desc = nspdf._produce_ns_desc()
641 # check that all expected member-vnf-index are present
642 vnfs = [e['vnf_id'] for e in ns_desc]
643 self.assertEqual(Counter([1, 3, 2]), Counter(vnfs), 'vnf_id invalid')
644
645 expected_keys = ['vnf_id', 'vnf_price_per_vim']
646 for e in ns_desc:
647 # check that vnf_price_per_vim has proper values
648 self.assertEqual(Counter([5, 10, 30, 30, 3]), Counter(e['vnf_price_per_vim']), 'vnf_price_per_vim invalid')
649 # check that no pinning directives included
650 self.assertEqual(Counter(expected_keys), Counter(e.keys()), 'pinning directive misplaced')
651
652 def test__produce_ns_desc_with_fewer_vims(self):
653 nsd = self._get_ut_nsd_from_file('nsd_unittest1.yaml')
654 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
655 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(self.vim_accounts_fewer_vims),
656 self._produce_ut_vnf_price_list(),
657 nsd=nsd,
658 pil_info=None,
659 pinning=None)
660
661 ns_desc = nspdf._produce_ns_desc()
662 # check that all expected member-vnf-index are present
663 vnfs = [e['vnf_id'] for e in ns_desc]
664 self.assertEqual(Counter([1, 3, 2]), Counter(vnfs), 'vnf_id invalid')
665
666 expected_keys = ['vnf_id', 'vnf_price_per_vim']
667 for e in ns_desc:
668 # check that vnf_price_per_vim has proper values
669 self.assertEqual(Counter([5, 10, 30]), Counter(e['vnf_price_per_vim']), 'vnf_price_per_vim invalid')
670 # check that no pinning directives included
671 self.assertEqual(Counter(expected_keys), Counter(e.keys()), 'pinning directive misplaced')
672
673 def test__produce_ns_desc_w_pinning(self):
674 nsd = self._get_ut_nsd_from_file('nsd_unittest3.yaml')
675 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
676 pinning = [{'member-vnf-index': 'two', 'vimAccountId': '331ffdec-44a8-4707-94a1-af7a292d9735'}]
677 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
678 self._produce_ut_vnf_price_list(),
679 nsd=nsd,
680 pil_info=None,
681 pinning=pinning)
682 ns_desc = nspdf._produce_ns_desc()
683 # check that all expected member-vnf-index are present
684 vnfs = [e['vnf_id'] for e in ns_desc]
685 self.assertEqual(Counter(['one', 'three', 'two']), Counter(vnfs), 'vnf_id invalid')
686
687 for e in ns_desc:
688 # check that vnf_price_per_vim has proper values
689 self.assertEqual(Counter([5, 10, 30, 30]), Counter(e['vnf_price_per_vim']), 'vnf_price_per_vim invalid')
690 # check that member-vnf-index 2 is pinned correctly
691 if e['vnf_id'] == 'two':
692 self.assertTrue('vim_account' in e.keys(), 'missing pinning directive')
693 self.assertTrue(pinning[0]['vimAccountId'] == e['vim_account'][3:].replace('_', '-'),
694 'invalid pinning vim-account')
695 else:
696 self.assertTrue('vim-account' not in e.keys(), 'pinning directive misplaced')
697
698 @mock.patch.object(NsPlacementDataFactory, '_produce_trp_link_characteristics_data')
699 @mock.patch.object(NsPlacementDataFactory, '_produce_vld_desc')
700 @mock.patch.object(NsPlacementDataFactory, '_produce_ns_desc')
701 def test_create_ns_placement_data_wo_order(self, mock_prd_ns_desc, mock_prd_vld_desc, mock_prd_trp_link_char):
702 """
703 :return:
704 """
705 vim_accounts_expected = [v.replace('-', '_') for v in ['vim92b056a7-38f5-438d-b8ee-3f93b3531f87',
706 'vim6618d412-d7fc-4eb0-a6f8-d2c258e0e900',
707 'vim331ffdec-44a8-4707-94a1-af7a292d9735',
708 'vimeda92f47-29b9-4007-9709-c1833dbfbe31']]
709
710 nsd = self._get_ut_nsd_from_file('nsd_unittest3.yaml')
711 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
712 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
713 self._produce_ut_vnf_price_list(),
714 nsd=nsd,
715 pil_info=self._populate_pil_info('pil_unittest1.yaml'),
716 pinning=None,
717 order_constraints=None)
718 nspd = nspdf.create_ns_placement_data()
719 self.assertEqual(Counter(vim_accounts_expected), Counter(nspd['vim_accounts']),
720 "vim_accounts incorrect")
721 # mock1.assert_called_once() Note for python > 3.5
722 self.assertTrue(mock_prd_ns_desc.called, '_produce_ns_desc not called')
723 # mock2.assert_called_once() Note for python > 3.5
724 self.assertTrue(mock_prd_vld_desc.called, ' _produce_vld_desc not called')
725 mock_prd_trp_link_char.assert_has_calls([call('pil_latency'), call('pil_jitter'), call('pil_price')])
726
727 regexps = [r"\{.*\}", r".*'file':.*mznplacement.py", r".*'time':.*datetime.datetime\(.*\)"]
728 generator_data = str(nspd['generator_data'])
729 for regex in regexps:
730 self.assertRegex(generator_data, regex, "generator data invalid")
731
732 @mock.patch.object(NsPlacementDataFactory, '_produce_trp_link_characteristics_data')
733 @mock.patch.object(NsPlacementDataFactory, '_produce_vld_desc')
734 @mock.patch.object(NsPlacementDataFactory, '_produce_ns_desc')
735 def test_create_ns_placement_data_w_order(self, mock_prd_ns_desc, mock_prd_vld_desc,
736 mock_prd_trp_link_char):
737 """
738 :return:
739 """
740 vim_accounts_expected = [v.replace('-', '_') for v in ['vim92b056a7-38f5-438d-b8ee-3f93b3531f87',
741 'vim6618d412-d7fc-4eb0-a6f8-d2c258e0e900',
742 'vim331ffdec-44a8-4707-94a1-af7a292d9735',
743 'vimeda92f47-29b9-4007-9709-c1833dbfbe31']]
744
745 nsd = self._get_ut_nsd_from_file('nsd_unittest3.yaml')
746 nsd = nsd['nsd:nsd-catalog']['nsd'][0]
747 nspdf = NsPlacementDataFactory(self._produce_ut_vim_accounts_info(TestNsPlacementDataFactory.vim_accounts),
748 self._produce_ut_vnf_price_list(),
749 nsd=nsd,
750 pil_info=self._populate_pil_info('pil_unittest1.yaml'),
751 pinning=None,
752 order_constraints={
753 'vld-constraints': [{'id': 'three_vnf_constrained_nsd_vld1',
754 'link-constraints': {'latency': 120,
755 'jitter': 21}},
756 {'id': 'three_vnf_constrained_nsd_vld2',
757 'link-constraints': {'latency': 121,
758 'jitter': 22}}]}
759 )
760 nspd = nspdf.create_ns_placement_data()
761 self.assertEqual(Counter(vim_accounts_expected), Counter(nspd['vim_accounts']),
762 "vim_accounts incorrect")
763 # mock1.assert_called_once() Note for python > 3.5
764 self.assertTrue(mock_prd_ns_desc.called, '_produce_ns_desc not called')
765 # mock2.assert_called_once() Note for python > 3.5
766 self.assertTrue(mock_prd_vld_desc.called, ' _produce_vld_desc not called')
767 mock_prd_trp_link_char.assert_has_calls([call('pil_latency'), call('pil_jitter'), call('pil_price')])
768
769 regexps = [r"\{.*\}", r".*'file':.*mznplacement.py", r".*'time':.*datetime.datetime\(.*\)"]
770 generator_data = str(nspd['generator_data'])
771 for regex in regexps:
772 self.assertRegex(generator_data, regex, "generator data invalid")
773
774
775 if __name__ == "__main__":
776 if __name__ == '__main__':
777 unittest.main()