Code Coverage

Cobertura Coverage Report > osm_pla.test >

test_mznModelGenerator.py

Trend

File Coverage summary

NameClassesLinesConditionals
test_mznModelGenerator.py
100%
1/1
98%
131/134
100%
0/0

Coverage Breakdown by Class

NameLinesConditionals
test_mznModelGenerator.py
98%
131/134
N/A

Source

osm_pla/test/test_mznModelGenerator.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 1 import datetime
16 1 import logging
17
18 # import unittest
19 1 from unittest import TestCase
20
21 # import random
22 # from operator import itemgetter
23 1 import re
24
25 1 from jinja2 import Template
26
27 1 from osm_pla.placement.mznplacement import MznModelGenerator
28
29 1 test_ns_placement_data_str = {
30     "vim_accounts": [
31         "vim" + vim_account.replace("-", "_")
32         for vim_account in [
33             "aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
34             "bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
35             "cccccccc-ed84-4e49-b5df-a9d117bd731f",
36             "dddddddd-ed84-4e49-b5df-a9d117bd731f",
37             "eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
38         ]
39     ],
40     "trp_link_latency": [
41         [0, 50, 100, 150, 200],
42         [0, 0, 100, 150, 200],
43         [0, 0, 0, 150, 200],
44         [0, 0, 0, 0, 200],
45         [0, 0, 0, 0, 0],
46     ],
47     "trp_link_jitter": [
48         [0, 5, 10, 15, 20],
49         [0, 0, 10, 15, 20],
50         [0, 0, 0, 15, 20],
51         [0, 0, 0, 0, 20],
52         [0, 0, 0, 0, 0],
53     ],
54     "trp_link_price_list": [
55         [0, 5, 6, 6, 7],
56         [0, 0, 6, 6, 7],
57         [0, 0, 0, 6, 7],
58         [0, 0, 0, 0, 7],
59         [0, 0, 0, 0, 0],
60     ],
61     "ns_desc": [
62         {"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
63         {"vnf_id": "two", "vnf_price_per_vim": [20, 21, 22, 23, 24]},
64         {"vnf_id": "three", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
65         {"vnf_id": "four", "vnf_price_per_vim": [40, 41, 42, 43, 44]},
66     ],
67     "vld_desc": [
68         {"cp_refs": ["one", "two"], "latency": 150, "jitter": 30},
69         {"cp_refs": ["two", "three"], "latency": 140, "jitter": 30},
70         {"cp_refs": ["three", "four"], "latency": 130, "jitter": 30},
71     ],
72     "generator_data": {"file": __file__, "time": datetime.datetime.now()},
73 }
74
75 1 test_ns_placement_data_str_no_vld_constraints = {
76     "vim_accounts": [
77         "vim" + vim_account.replace("-", "_")
78         for vim_account in [
79             "aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
80             "bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
81             "cccccccc-ed84-4e49-b5df-a9d117bd731f",
82             "dddddddd-ed84-4e49-b5df-a9d117bd731f",
83             "eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
84         ]
85     ],
86     "trp_link_latency": [
87         [0, 50, 100, 150, 200],
88         [0, 0, 100, 150, 200],
89         [0, 0, 0, 150, 200],
90         [0, 0, 0, 0, 200],
91         [0, 0, 0, 0, 0],
92     ],
93     "trp_link_jitter": [
94         [0, 5, 10, 15, 20],
95         [0, 0, 10, 15, 20],
96         [0, 0, 0, 15, 20],
97         [0, 0, 0, 0, 20],
98         [0, 0, 0, 0, 0],
99     ],
100     "trp_link_price_list": [
101         [0, 5, 6, 6, 7],
102         [0, 0, 6, 6, 7],
103         [0, 0, 0, 6, 7],
104         [0, 0, 0, 0, 7],
105         [0, 0, 0, 0, 0],
106     ],
107     "ns_desc": [
108         {"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
109         {"vnf_id": "two", "vnf_price_per_vim": [20, 21, 22, 23, 24]},
110         {"vnf_id": "three", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
111         {"vnf_id": "four", "vnf_price_per_vim": [40, 41, 42, 43, 44]},
112     ],
113     "vld_desc": [
114         {"cp_refs": ["one", "two"]},
115         {"cp_refs": ["two", "three"]},
116         {"cp_refs": ["three", "four"]},
117     ],
118     "generator_data": {"file": __file__, "time": datetime.datetime.now()},
119 }
120
121 1 test_ns_placement_data = {
122     "vim_accounts": [
123         "vim" + vim_account.replace("-", "_")
124         for vim_account in [
125             "aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
126             "bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
127             "cccccccc-ed84-4e49-b5df-a9d117bd731f",
128             "dddddddd-ed84-4e49-b5df-a9d117bd731f",
129             "eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
130         ]
131     ],
132     "trp_link_latency": [
133         [0, 50, 100, 150, 200],
134         [0, 0, 100, 150, 200],
135         [0, 0, 0, 150, 200],
136         [0, 0, 0, 0, 200],
137         [0, 0, 0, 0, 0],
138     ],
139     "trp_link_jitter": [
140         [0, 5, 10, 15, 20],
141         [0, 0, 10, 15, 20],
142         [0, 0, 0, 15, 20],
143         [0, 0, 0, 0, 20],
144         [0, 0, 0, 0, 0],
145     ],
146     "trp_link_price_list": [
147         [0, 5, 6, 6, 7],
148         [0, 0, 6, 6, 7],
149         [0, 0, 0, 6, 7],
150         [0, 0, 0, 0, 7],
151         [0, 0, 0, 0, 0],
152     ],
153     "ns_desc": [
154         {"vnf_id": "1", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
155         {"vnf_id": "2", "vnf_price_per_vim": [20, 21, 22, 23, 24]},
156         {"vnf_id": "3", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
157         {"vnf_id": "4", "vnf_price_per_vim": [40, 41, 42, 43, 44]},
158     ],
159     "vld_desc": [
160         {"cp_refs": ["1", "2"], "latency": 150, "jitter": 30},
161         {"cp_refs": ["2", "3"], "latency": 140, "jitter": 30},
162         {"cp_refs": ["3", "4"], "latency": 130, "jitter": 30},
163     ],
164     "generator_data": {"file": __file__, "time": datetime.datetime.now()},
165 }
166
167 1 test_ns_placement_data_w_pinning = {
168     "vim_accounts": [
169         "vim" + vim_account.replace("-", "_")
170         for vim_account in [
171             "aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
172             "bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
173             "cccccccc-ed84-4e49-b5df-a9d117bd731f",
174             "dddddddd-ed84-4e49-b5df-a9d117bd731f",
175             "eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
176         ]
177     ],
178     "trp_link_latency": [
179         [0, 50, 100, 150, 200],
180         [0, 0, 100, 150, 200],
181         [0, 0, 0, 150, 200],
182         [0, 0, 0, 0, 200],
183         [0, 0, 0, 0, 0],
184     ],
185     "trp_link_jitter": [
186         [0, 5, 10, 15, 20],
187         [0, 0, 10, 15, 20],
188         [0, 0, 0, 15, 20],
189         [0, 0, 0, 0, 20],
190         [0, 0, 0, 0, 0],
191     ],
192     "trp_link_price_list": [
193         [0, 5, 6, 6, 7],
194         [0, 0, 6, 6, 7],
195         [0, 0, 0, 6, 7],
196         [0, 0, 0, 0, 7],
197         [0, 0, 0, 0, 0],
198     ],
199     "ns_desc": [
200         {"vnf_id": "1", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
201         {
202             "vnf_id": "2",
203             "vnf_price_per_vim": [20, 21, 22, 23, 24],
204             "vim_account": "vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87",
205         },
206         {"vnf_id": "3", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
207         {
208             "vnf_id": "4",
209             "vnf_price_per_vim": [40, 41, 42, 43, 44],
210             "vim_account": "vimcccccccc_ed84_4e49_b5df_a9d117bd731f",
211         },
212     ],
213     "vld_desc": [
214         {"cp_refs": ["1", "2"], "latency": 150, "jitter": 30},
215         {"cp_refs": ["2", "3"], "latency": 140, "jitter": 30},
216         {"cp_refs": ["3", "4"], "latency": 130, "jitter": 30},
217     ],
218     "generator_data": {"file": __file__, "time": datetime.datetime.now()},
219 }
220
221 1 test_ns_placement_data_w_pinning_str = {
222     "vim_accounts": [
223         "vim" + vim_account.replace("-", "_")
224         for vim_account in [
225             "aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
226             "bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
227             "cccccccc-ed84-4e49-b5df-a9d117bd731f",
228             "dddddddd-ed84-4e49-b5df-a9d117bd731f",
229             "eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
230         ]
231     ],
232     "trp_link_latency": [
233         [0, 50, 100, 150, 200],
234         [0, 0, 100, 150, 200],
235         [0, 0, 0, 150, 200],
236         [0, 0, 0, 0, 200],
237         [0, 0, 0, 0, 0],
238     ],
239     "trp_link_jitter": [
240         [0, 5, 10, 15, 20],
241         [0, 0, 10, 15, 20],
242         [0, 0, 0, 15, 20],
243         [0, 0, 0, 0, 20],
244         [0, 0, 0, 0, 0],
245     ],
246     "trp_link_price_list": [
247         [0, 5, 6, 6, 7],
248         [0, 0, 6, 6, 7],
249         [0, 0, 0, 6, 7],
250         [0, 0, 0, 0, 7],
251         [0, 0, 0, 0, 0],
252     ],
253     "ns_desc": [
254         {"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
255         {
256             "vnf_id": "two",
257             "vnf_price_per_vim": [20, 21, 22, 23, 24],
258             "vim_account": "vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87",
259         },
260         {"vnf_id": "three", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
261         {
262             "vnf_id": "four",
263             "vnf_price_per_vim": [40, 41, 42, 43, 44],
264             "vim_account": "vimcccccccc_ed84_4e49_b5df_a9d117bd731f",
265         },
266     ],
267     "vld_desc": [
268         {"cp_refs": ["one", "two"], "latency": 150, "jitter": 30},
269         {"cp_refs": ["two", "three"], "latency": 140, "jitter": 30},
270         {"cp_refs": ["three", "four"], "latency": 130, "jitter": 30},
271     ],
272     "generator_data": {"file": __file__, "time": datetime.datetime.now()},
273 }
274
275 1 test_ns_placement_data_str_no_vld = {
276     "vim_accounts": [
277         "vim" + vim_account.replace("-", "_")
278         for vim_account in [
279             "aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
280             "bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
281             "cccccccc-ed84-4e49-b5df-a9d117bd731f",
282             "dddddddd-ed84-4e49-b5df-a9d117bd731f",
283             "eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
284         ]
285     ],
286     "trp_link_latency": [
287         [0, 50, 100, 150, 200],
288         [0, 0, 100, 150, 200],
289         [0, 0, 0, 150, 200],
290         [0, 0, 0, 0, 200],
291         [0, 0, 0, 0, 0],
292     ],
293     "trp_link_jitter": [
294         [0, 5, 10, 15, 20],
295         [0, 0, 10, 15, 20],
296         [0, 0, 0, 15, 20],
297         [0, 0, 0, 0, 20],
298         [0, 0, 0, 0, 0],
299     ],
300     "trp_link_price_list": [
301         [0, 5, 6, 6, 7],
302         [0, 0, 6, 6, 7],
303         [0, 0, 0, 6, 7],
304         [0, 0, 0, 0, 7],
305         [0, 0, 0, 0, 0],
306     ],
307     "ns_desc": [{"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]}],
308     "vld_desc": [],
309     "generator_data": {"file": __file__, "time": datetime.datetime.now()},
310 }
311
312 1 expected_model_fragment = """
313 %This is the NETWORK RESOURCE MODEL
314 enum  Vims = {
315 vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
316 vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
317 vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
318 vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
319 vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
320 array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
321 |0,0,100,150,200,
322 |0,0,0,150,200,
323 |0,0,0,0,200,
324 |0,0,0,0,0,
325 |]; % Transport link latency between data centers
326 array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
327 |0,0,10,15,20,
328 |0,0,0,15,20,
329 |0,0,0,0,20,
330 |0,0,0,0,0,
331 |]; % Transport link jitter between data centers
332 array[Vims, Vims] of int: trp_link_price_list = [|0,5,6,6,7,
333 |0,0,6,6,7,
334 |0,0,0,6,7,
335 |0,0,0,0,7,
336 |0,0,0,0,0,
337 |]; % Transport link price list
338 array[Vims] of int: vim_price_list_1 = [50,51,52,53,54];
339 array[Vims] of int: vim_price_list_2 = [20,21,22,23,24];
340 array[Vims] of int: vim_price_list_3 = [70,71,72,73,74];
341 array[Vims] of int: vim_price_list_4 = [40,41,42,43,44];
342
343
344 % This is the NETWORK BASIC LOAD MODEL (CONSUMED)
345 % NOTE. This is not applicable in OSM Release 7
346
347 % This is the SERVICE CONSUMPTION MODEL
348 % These are the variables, i.e. which DC to select for each VNF
349 var Vims: VNF1;
350 var Vims: VNF2;
351 var Vims: VNF3;
352 var Vims: VNF4;
353
354
355 % These are the set of rules for selecting DCs to VNFs
356 constraint trp_link_latency[VNF1, VNF2] <= 150;
357 constraint trp_link_latency[VNF2, VNF3] <= 140;
358 constraint trp_link_latency[VNF3, VNF4] <= 130;
359 constraint trp_link_jitter[VNF1, VNF2] <= 30;
360 constraint trp_link_jitter[VNF2, VNF3] <= 30;
361 constraint trp_link_jitter[VNF3, VNF4] <= 30;
362
363 % Calculate the cost for VNFs and cost for transport link and total cost
364 var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+
365 trp_link_price_list[VNF2, VNF3]+
366 trp_link_price_list[VNF3, VNF4];
367
368 var int: used_vim_cost =vim_price_list_1[VNF1]+
369 vim_price_list_2[VNF2]+
370 vim_price_list_3[VNF3]+
371 vim_price_list_4[VNF4];
372
373 var int: total_cost = used_transport_cost + used_vim_cost;
374
375 solve minimize total_cost;
376 """
377 1 expected_model_fragment_str = """
378 %This is the NETWORK RESOURCE MODEL
379 enum  Vims = {
380 vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
381 vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
382 vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
383 vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
384 vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
385 array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
386 |0,0,100,150,200,
387 |0,0,0,150,200,
388 |0,0,0,0,200,
389 |0,0,0,0,0,
390 |]; % Transport link latency between data centers
391 array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
392 |0,0,10,15,20,
393 |0,0,0,15,20,
394 |0,0,0,0,20,
395 |0,0,0,0,0,
396 |]; % Transport link jitter between data centers
397 array[Vims, Vims] of int: trp_link_price_list = [|0,5,6,6,7,
398 |0,0,6,6,7,
399 |0,0,0,6,7,
400 |0,0,0,0,7,
401 |0,0,0,0,0,
402 |]; % Transport link price list
403 array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
404 array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
405 array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
406 array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
407
408
409 % This is the NETWORK BASIC LOAD MODEL (CONSUMED)
410 % NOTE. This is not applicable in OSM Release 7
411
412 % This is the SERVICE CONSUMPTION MODEL
413 % These are the variables, i.e. which DC to select for each VNF
414 var Vims: VNFone;
415 var Vims: VNFtwo;
416 var Vims: VNFthree;
417 var Vims: VNFfour;
418
419
420 % These are the set of rules for selecting DCs to VNFs
421 constraint trp_link_latency[VNFone, VNFtwo] <= 150;
422 constraint trp_link_latency[VNFtwo, VNFthree] <= 140;
423 constraint trp_link_latency[VNFthree, VNFfour] <= 130;
424 constraint trp_link_jitter[VNFone, VNFtwo] <= 30;
425 constraint trp_link_jitter[VNFtwo, VNFthree] <= 30;
426 constraint trp_link_jitter[VNFthree, VNFfour] <= 30;
427
428 % Calculate the cost for VNFs and cost for transport link and total cost
429 var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
430 trp_link_price_list[VNFtwo, VNFthree]+
431 trp_link_price_list[VNFthree, VNFfour];
432
433 var int: used_vim_cost =vim_price_list_one[VNFone]+
434 vim_price_list_two[VNFtwo]+
435 vim_price_list_three[VNFthree]+
436 vim_price_list_four[VNFfour];
437
438 var int: total_cost = used_transport_cost + used_vim_cost;
439
440 solve minimize total_cost;
441 """
442
443 1 expected_model_fragment_str_no_vld_constraints = """
444 %This is the NETWORK RESOURCE MODEL
445 enum  Vims = {
446 vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
447 vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
448 vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
449 vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
450 vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
451 array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
452 |0,0,100,150,200,
453 |0,0,0,150,200,
454 |0,0,0,0,200,
455 |0,0,0,0,0,
456 |]; % Transport link latency between data centers
457 array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
458 |0,0,10,15,20,
459 |0,0,0,15,20,
460 |0,0,0,0,20,
461 |0,0,0,0,0,
462 |]; % Transport link jitter between data centers
463 array[Vims, Vims] of int: trp_link_price_list = [|0,5,6,6,7,
464 |0,0,6,6,7,
465 |0,0,0,6,7,
466 |0,0,0,0,7,
467 |0,0,0,0,0,
468 |]; % Transport link price list
469 array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
470 array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
471 array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
472 array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
473
474
475 % This is the NETWORK BASIC LOAD MODEL (CONSUMED)
476 % NOTE. This is not applicable in OSM Release 7
477
478 % This is the SERVICE CONSUMPTION MODEL
479 % These are the variables, i.e. which DC to select for each VNF
480 var Vims: VNFone;
481 var Vims: VNFtwo;
482 var Vims: VNFthree;
483 var Vims: VNFfour;
484
485
486 % These are the set of rules for selecting DCs to VNFs
487
488 % Calculate the cost for VNFs and cost for transport link and total cost
489 var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
490 trp_link_price_list[VNFtwo, VNFthree]+
491 trp_link_price_list[VNFthree, VNFfour];
492
493 var int: used_vim_cost =vim_price_list_one[VNFone]+
494 vim_price_list_two[VNFtwo]+
495 vim_price_list_three[VNFthree]+
496 vim_price_list_four[VNFfour];
497
498 var int: total_cost = used_transport_cost + used_vim_cost;
499
500 solve minimize total_cost;
501 """
502
503 1 expected_model_fragment_w_pinning = """
504 %This is the NETWORK RESOURCE MODEL
505 enum  Vims = {
506 vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
507 vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
508 vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
509 vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
510 vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
511 array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
512 |0,0,100,150,200,
513 |0,0,0,150,200,
514 |0,0,0,0,200,
515 |0,0,0,0,0,
516 |]; % Transport link latency between data centers
517 array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
518 |0,0,10,15,20,
519 |0,0,0,15,20,
520 |0,0,0,0,20,
521 |0,0,0,0,0,
522 |]; % Transport link jitter between data centers
523 array[Vims, Vims] of int: trp_link_price_list = [|0,5,6,6,7,
524 |0,0,6,6,7,
525 |0,0,0,6,7,
526 |0,0,0,0,7,
527 |0,0,0,0,0,
528 |]; % Transport link price list
529 array[Vims] of int: vim_price_list_1 = [50,51,52,53,54];
530 array[Vims] of int: vim_price_list_2 = [20,21,22,23,24];
531 array[Vims] of int: vim_price_list_3 = [70,71,72,73,74];
532 array[Vims] of int: vim_price_list_4 = [40,41,42,43,44];
533
534
535 % This is the NETWORK BASIC LOAD MODEL (CONSUMED)
536 % NOTE. This is not applicable in OSM Release 7
537
538 % This is the SERVICE CONSUMPTION MODEL
539 % These are the variables, i.e. which DC to select for each VNF
540 var Vims: VNF1;
541 Vims: VNF2 = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
542 var Vims: VNF3;
543 Vims: VNF4 = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
544
545
546 % These are the set of rules for selecting DCs to VNFs
547 constraint trp_link_latency[VNF1, VNF2] <= 150;
548 constraint trp_link_latency[VNF2, VNF3] <= 140;
549 constraint trp_link_latency[VNF3, VNF4] <= 130;
550 constraint trp_link_jitter[VNF1, VNF2] <= 30;
551 constraint trp_link_jitter[VNF2, VNF3] <= 30;
552 constraint trp_link_jitter[VNF3, VNF4] <= 30;
553
554 % Calculate the cost for VNFs and cost for transport link and total cost
555 var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+
556 trp_link_price_list[VNF2, VNF3]+
557 trp_link_price_list[VNF3, VNF4];
558
559 var int: used_vim_cost =vim_price_list_1[VNF1]+
560 vim_price_list_2[VNF2]+
561 vim_price_list_3[VNF3]+
562 vim_price_list_4[VNF4];
563
564 var int: total_cost = used_transport_cost + used_vim_cost;
565
566 solve minimize total_cost;
567 """
568
569 1 expected_model_fragment_w_pinning_str = """
570 %This is the NETWORK RESOURCE MODEL
571 enum  Vims = {
572 vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
573 vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
574 vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
575 vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
576 vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
577 array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
578 |0,0,100,150,200,
579 |0,0,0,150,200,
580 |0,0,0,0,200,
581 |0,0,0,0,0,
582 |]; % Transport link latency between data centers
583 array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
584 |0,0,10,15,20,
585 |0,0,0,15,20,
586 |0,0,0,0,20,
587 |0,0,0,0,0,
588 |]; % Transport link jitter between data centers
589 array[Vims, Vims] of int: trp_link_price_list = [|0,5,6,6,7,
590 |0,0,6,6,7,
591 |0,0,0,6,7,
592 |0,0,0,0,7,
593 |0,0,0,0,0,
594 |]; % Transport link price list
595 array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
596 array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
597 array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
598 array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
599
600
601 % This is the NETWORK BASIC LOAD MODEL (CONSUMED)
602 % NOTE. This is not applicable in OSM Release 7
603
604 % This is the SERVICE CONSUMPTION MODEL
605 % These are the variables, i.e. which DC to select for each VNF
606 var Vims: VNFone;
607 Vims: VNFtwo = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
608 var Vims: VNFthree;
609 Vims: VNFfour = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
610
611
612 % These are the set of rules for selecting DCs to VNFs
613 constraint trp_link_latency[VNFone, VNFtwo] <= 150;
614 constraint trp_link_latency[VNFtwo, VNFthree] <= 140;
615 constraint trp_link_latency[VNFthree, VNFfour] <= 130;
616 constraint trp_link_jitter[VNFone, VNFtwo] <= 30;
617 constraint trp_link_jitter[VNFtwo, VNFthree] <= 30;
618 constraint trp_link_jitter[VNFthree, VNFfour] <= 30;
619
620 % Calculate the cost for VNFs and cost for transport link and total cost
621 var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
622 trp_link_price_list[VNFtwo, VNFthree]+
623 trp_link_price_list[VNFthree, VNFfour];
624
625 var int: used_vim_cost =vim_price_list_one[VNFone]+
626 vim_price_list_two[VNFtwo]+
627 vim_price_list_three[VNFthree]+
628 vim_price_list_four[VNFfour];
629
630 var int: total_cost = used_transport_cost + used_vim_cost;
631
632 solve minimize total_cost;
633 """
634
635 1 expected_model_fragment_str_no_vld = """
636 %This is the NETWORK RESOURCE MODEL
637 enum  Vims = {
638 vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
639 vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
640 vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
641 vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
642 vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
643 array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
644 |0,0,100,150,200,
645 |0,0,0,150,200,
646 |0,0,0,0,200,
647 |0,0,0,0,0,
648 |]; % Transport link latency between data centers
649 array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
650 |0,0,10,15,20,
651 |0,0,0,15,20,
652 |0,0,0,0,20,
653 |0,0,0,0,0,
654 |]; % Transport link jitter between data centers
655 array[Vims, Vims] of int: trp_link_price_list = [|0,5,6,6,7,
656 |0,0,6,6,7,
657 |0,0,0,6,7,
658 |0,0,0,0,7,
659 |0,0,0,0,0,
660 |]; % Transport link price list
661 array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
662
663
664 % This is the NETWORK BASIC LOAD MODEL (CONSUMED)
665 % NOTE. This is not applicable in OSM Release 7
666
667 % This is the SERVICE CONSUMPTION MODEL
668 % These are the variables, i.e. which DC to select for each VNF
669
670 var Vims: VNFone;
671
672 % These are the set of rules for selecting DCs to VNFs
673
674 % Calculate the cost for VNFs and cost for transport link and total cost
675 var int: used_transport_cost =0;
676
677 var int: used_vim_cost =vim_price_list_one[VNFone];
678
679 var int: total_cost = used_transport_cost + used_vim_cost;
680
681 solve minimize total_cost;
682 """
683
684
685 1 class TestMznModelGenerator(TestCase):
686 1     def test_create_model(self):
687 1         mg = MznModelGenerator(logging.getLogger(__name__))
688 1         mzn_model = mg.create_model(test_ns_placement_data_str)
689
690         # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
691 1         self.assertTrue(
692             expected_model_fragment_str.replace("\n", "")
693             in mzn_model.replace("\n", ""),
694             "faulty model generated",
695         )
696
697 1     def test_create_model_no_vld_constraints(self):
698         """
699         instantiate w/o constraints in nsd or order params has a valid model
700         :return:
701         """
702 1         mg = MznModelGenerator(logging.getLogger(__name__))
703 1         mzn_model = mg.create_model(test_ns_placement_data_str_no_vld_constraints)
704
705         # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
706 1         self.assertTrue(
707             expected_model_fragment_str_no_vld_constraints.replace("\n", "")
708             in mzn_model.replace("\n", ""),
709             "faulty model generated",
710         )
711
712 1     def test_create_model_w_pinning(self):
713 1         mg = MznModelGenerator(logging.getLogger(__name__))
714 1         mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
715
716         # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
717 1         self.assertTrue(
718             expected_model_fragment_w_pinning_str.replace("\n", "")
719             in mzn_model.replace("\n", ""),
720             "faulty model generated",
721         )
722
723 1     def test_create_model_no_vld(self):
724 1         mg = MznModelGenerator(logging.getLogger(__name__))
725 1         mzn_model = mg.create_model(test_ns_placement_data_str_no_vld)
726
727         # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
728 1         self.assertTrue(
729             expected_model_fragment_str_no_vld.replace("\n", "")
730             in mzn_model.replace("\n", ""),
731             "faulty model generated",
732         )
733
734 1     def test__load_jinja_template(self):
735         """
736
737         add other test to check exception if template not loaded (e.g. invalid template name,
738         perhaps also valid name but invalid content (in case jinja2 detects such things))
739         """
740 1         mg = MznModelGenerator(logging.getLogger(__name__))
741 1         template = mg._load_jinja_template()  # Note we use the default template
742 1         self.assertTrue(
743             isinstance(template, Template), "failed to load jinja2 template"
744         )
745
746 1     def test_vim_account_replace(self):
747 1         mg = MznModelGenerator(logging.getLogger(__name__))
748 1         nspd = test_ns_placement_data_str
749 1         mzn_model = mg.create_model(nspd)
750
751 1         expected = (
752             "%This is the NETWORK RESOURCE MODEL" + "\n" + "enum  Vims = {" + "\n"
753         )
754 1         for val in test_ns_placement_data_str["vim_accounts"]:
755 1             expected = expected + val.replace("-", "_") + ",\n"
756 1         expected = expected[:-2] + "}; % The vim-accounts"
757 1         res = re.findall(expected, mzn_model)
758 1         self.assertEqual(1, len(res), "vim accounts didnt replace from - to _")
759
760 1     def test_trp_link_price_list(self):
761 1         mg = MznModelGenerator(logging.getLogger(__name__))
762 1         mzn_model = mg.create_model(test_ns_placement_data_str)
763
764 1         expected = "array\\[Vims, Vims\\] of int: trp_link_price_list = \\["
765 1         for price_list in test_ns_placement_data_str["trp_link_price_list"]:
766 1             expected = (
767                 expected + "\\|" + (str(price_list)[1:-1]).replace(" ", "") + ",\n"
768             )
769 1         expected = expected + "\\|\\]; % Transport link price list"
770 1         res = re.findall(expected, mzn_model)
771 1         self.assertEqual(1, len(res), "price list is not correct")
772
773 1     def test_link_latency(self):
774 1         mg = MznModelGenerator(logging.getLogger(__name__))
775 1         mzn_model = mg.create_model(test_ns_placement_data_str)
776
777 1         expected = "array\\[Vims, Vims\\] of int: trp_link_latency = \\["
778 1         for link_latency in test_ns_placement_data_str["trp_link_latency"]:
779 1             expected = (
780                 expected + "\\|" + (str(link_latency)[1:-1]).replace(" ", "") + ",\n"
781             )
782 1         expected = expected + "\\|\\]; % Transport link latency between data centers"
783 1         res = re.findall(expected, mzn_model)
784 1         self.assertEqual(1, len(res), "trp_link_latency values is not correct")
785
786 1     def test_link_jitter(self):
787 1         mg = MznModelGenerator(logging.getLogger(__name__))
788 1         mzn_model = mg.create_model(test_ns_placement_data_str)
789
790 1         expected = "array\\[Vims, Vims\\] of int: trp_link_jitter = \\["
791 1         for link_jitter in test_ns_placement_data_str["trp_link_jitter"]:
792 1             expected = (
793                 expected + "\\|" + (str(link_jitter)[1:-1]).replace(" ", "") + ",\n"
794             )
795 1         expected = expected + "\\|\\]; % Transport link jitter between data centers"
796
797 1         res = re.findall(expected, mzn_model)
798
799 1         self.assertEqual(1, len(res), "trp_link_jitter values is not correct")
800
801 1     def test_price_per_vim(self):
802 1         mg = MznModelGenerator(logging.getLogger(__name__))
803 1         mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
804
805 1         expected = ""
806 1         for price_list in test_ns_placement_data_w_pinning_str["ns_desc"]:
807 1             expected += (
808                 "array\\[Vims\\] of int: vim_price_list_"
809                 + price_list.get("vnf_id")
810                 + " = "
811             )
812 1             temp = str(price_list.get("vnf_price_per_vim"))[1:-1].replace(" ", "")
813 1             expected += "\\[" + temp + "\\];\n"
814
815 1         res = re.findall(expected, mzn_model)
816 1         self.assertEqual(1, len(res), "mzn_model contains pinning")
817
818 1     def test_pinning(self):
819 1         mg = MznModelGenerator(logging.getLogger(__name__))
820 1         mzn_model = mg.create_model(test_ns_placement_data_str)
821
822 1         expected = ""
823 1         for pin_list in test_ns_placement_data_str["ns_desc"]:
824 1             if pin_list.get("vim_account"):
825 0                 expected += (
826                     "Vims: VNF"
827                     + pin_list.get("vnf_id")
828                     + " = "
829                     + pin_list.get("vim_account")
830                     + ";\n"
831                 )
832             else:
833 1                 expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
834
835 1         res = re.findall(expected, mzn_model)
836 1         self.assertEqual(1, len(res), "mzn_model has no pinning")
837
838 1     def test__without_pinning(self):
839 1         mg = MznModelGenerator(logging.getLogger(__name__))
840 1         mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
841
842 1         expected = ""
843 1         for pin_list in test_ns_placement_data_w_pinning_str["ns_desc"]:
844 1             if pin_list.get("vim_account"):
845 1                 expected += (
846                     "Vims: VNF"
847                     + pin_list.get("vnf_id")
848                     + " = "
849                     + pin_list.get("vim_account")
850                     + ";\n"
851                 )
852             else:
853 1                 expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
854
855 1         res = re.findall(expected, mzn_model)
856 1         self.assertEqual(1, len(res), "mzn_model contains pinning")
857
858 1     def test__without_constraints_for_jitter_and_latency(self):
859 1         mg = MznModelGenerator(logging.getLogger(__name__))
860 1         mzn_model = mg.create_model(test_ns_placement_data_str_no_vld_constraints)
861
862 1         expected_latency = "constraint trp_link_latency"
863 1         expected_jitter = "constraint trp_link_jitter"
864 1         latency_or_jitter_was_found = 0
865 1         for l_o_j in test_ns_placement_data_str_no_vld_constraints["vld_desc"]:
866 1             if l_o_j.get("latency") or l_o_j.get("jitter"):
867 0                 latency_or_jitter_was_found = 1
868
869 1         res_latency = re.findall(expected_latency, mzn_model)
870 1         res_jitter = re.findall(expected_jitter, mzn_model)
871 1         self.assertEqual(
872             0,
873             latency_or_jitter_was_found,
874             "Jitter or latency was found in the test input",
875         )
876 1         self.assertEqual(
877             0, len(res_latency), "constraint trp_link_latency was found in mzn_model"
878         )
879 1         self.assertEqual(
880             0, len(res_jitter), "constraint trp_link_latency was found in mzn_model"
881         )
882
883 1     def test__constraints_for_jitter_and_latency(self):
884 1         mg = MznModelGenerator(logging.getLogger(__name__))
885 1         mzn_model = mg.create_model(test_ns_placement_data_str)
886
887 1         expected_latency = ""
888 1         expected_jitter = ""
889 1         latency_or_jitter_was_found = 0
890 1         for l_o_j in test_ns_placement_data_str["vld_desc"]:
891 1             if not (l_o_j.get("latency") or l_o_j.get("jitter")):
892 0                 latency_or_jitter_was_found = 1
893 1             expected_latency += (
894                 "constraint trp_link_latency"
895                 + "\\[VNF"
896                 + l_o_j.get("cp_refs")[0]
897                 + ", VNF"
898                 + l_o_j.get("cp_refs")[1]
899                 + "\\] \\<= "
900                 + str(l_o_j.get("latency"))
901                 + ";\n\n"
902             )
903
904 1             expected_jitter += (
905                 "constraint trp_link_jitter"
906                 + "\\[VNF"
907                 + l_o_j.get("cp_refs")[0]
908                 + ", VNF"
909                 + l_o_j.get("cp_refs")[1]
910                 + "\\] \\<= "
911                 + str(l_o_j.get("jitter"))
912                 + ";\n\n"
913             )
914
915 1         res = re.findall(expected_latency + expected_jitter, mzn_model)
916 1         self.assertEqual(
917             0,
918             latency_or_jitter_was_found,
919             "Jitter or latency was not found in the test input",
920         )
921 1         self.assertEqual(1, len(res), "faulty model generated")