Coverage for osm_pla/test/test_mznModelGenerator.py: 98%
134 statements
« prev ^ index » next coverage.py v7.3.1, created at 2024-06-22 10:12 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2024-06-22 10:12 +0000
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.
15import datetime
16import logging
18# import unittest
19from unittest import TestCase
21# import random
22# from operator import itemgetter
23import re
25from jinja2 import Template
27from osm_pla.placement.mznplacement import MznModelGenerator
29test_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}
75test_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}
121test_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}
167test_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}
221test_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}
275test_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}
312expected_model_fragment = """
313%This is the NETWORK RESOURCE MODEL
314enum Vims = {
315vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
316vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
317vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
318vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
319vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
320array[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
326array[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
332array[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
338array[Vims] of int: vim_price_list_1 = [50,51,52,53,54];
339array[Vims] of int: vim_price_list_2 = [20,21,22,23,24];
340array[Vims] of int: vim_price_list_3 = [70,71,72,73,74];
341array[Vims] of int: vim_price_list_4 = [40,41,42,43,44];
344% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
345% NOTE. This is not applicable in OSM Release 7
347% This is the SERVICE CONSUMPTION MODEL
348% These are the variables, i.e. which DC to select for each VNF
349var Vims: VNF1;
350var Vims: VNF2;
351var Vims: VNF3;
352var Vims: VNF4;
355% These are the set of rules for selecting DCs to VNFs
356constraint trp_link_latency[VNF1, VNF2] <= 150;
357constraint trp_link_latency[VNF2, VNF3] <= 140;
358constraint trp_link_latency[VNF3, VNF4] <= 130;
359constraint trp_link_jitter[VNF1, VNF2] <= 30;
360constraint trp_link_jitter[VNF2, VNF3] <= 30;
361constraint trp_link_jitter[VNF3, VNF4] <= 30;
363% Calculate the cost for VNFs and cost for transport link and total cost
364var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+
365trp_link_price_list[VNF2, VNF3]+
366trp_link_price_list[VNF3, VNF4];
368var int: used_vim_cost =vim_price_list_1[VNF1]+
369vim_price_list_2[VNF2]+
370vim_price_list_3[VNF3]+
371vim_price_list_4[VNF4];
373var int: total_cost = used_transport_cost + used_vim_cost;
375solve minimize total_cost;
376"""
377expected_model_fragment_str = """
378%This is the NETWORK RESOURCE MODEL
379enum Vims = {
380vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
381vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
382vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
383vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
384vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
385array[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
391array[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
397array[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
403array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
404array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
405array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
406array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
409% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
410% NOTE. This is not applicable in OSM Release 7
412% This is the SERVICE CONSUMPTION MODEL
413% These are the variables, i.e. which DC to select for each VNF
414var Vims: VNFone;
415var Vims: VNFtwo;
416var Vims: VNFthree;
417var Vims: VNFfour;
420% These are the set of rules for selecting DCs to VNFs
421constraint trp_link_latency[VNFone, VNFtwo] <= 150;
422constraint trp_link_latency[VNFtwo, VNFthree] <= 140;
423constraint trp_link_latency[VNFthree, VNFfour] <= 130;
424constraint trp_link_jitter[VNFone, VNFtwo] <= 30;
425constraint trp_link_jitter[VNFtwo, VNFthree] <= 30;
426constraint trp_link_jitter[VNFthree, VNFfour] <= 30;
428% Calculate the cost for VNFs and cost for transport link and total cost
429var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
430trp_link_price_list[VNFtwo, VNFthree]+
431trp_link_price_list[VNFthree, VNFfour];
433var int: used_vim_cost =vim_price_list_one[VNFone]+
434vim_price_list_two[VNFtwo]+
435vim_price_list_three[VNFthree]+
436vim_price_list_four[VNFfour];
438var int: total_cost = used_transport_cost + used_vim_cost;
440solve minimize total_cost;
441"""
443expected_model_fragment_str_no_vld_constraints = """
444%This is the NETWORK RESOURCE MODEL
445enum Vims = {
446vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
447vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
448vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
449vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
450vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
451array[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
457array[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
463array[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
469array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
470array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
471array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
472array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
475% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
476% NOTE. This is not applicable in OSM Release 7
478% This is the SERVICE CONSUMPTION MODEL
479% These are the variables, i.e. which DC to select for each VNF
480var Vims: VNFone;
481var Vims: VNFtwo;
482var Vims: VNFthree;
483var Vims: VNFfour;
486% These are the set of rules for selecting DCs to VNFs
488% Calculate the cost for VNFs and cost for transport link and total cost
489var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
490trp_link_price_list[VNFtwo, VNFthree]+
491trp_link_price_list[VNFthree, VNFfour];
493var int: used_vim_cost =vim_price_list_one[VNFone]+
494vim_price_list_two[VNFtwo]+
495vim_price_list_three[VNFthree]+
496vim_price_list_four[VNFfour];
498var int: total_cost = used_transport_cost + used_vim_cost;
500solve minimize total_cost;
501"""
503expected_model_fragment_w_pinning = """
504%This is the NETWORK RESOURCE MODEL
505enum Vims = {
506vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
507vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
508vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
509vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
510vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
511array[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
517array[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
523array[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
529array[Vims] of int: vim_price_list_1 = [50,51,52,53,54];
530array[Vims] of int: vim_price_list_2 = [20,21,22,23,24];
531array[Vims] of int: vim_price_list_3 = [70,71,72,73,74];
532array[Vims] of int: vim_price_list_4 = [40,41,42,43,44];
535% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
536% NOTE. This is not applicable in OSM Release 7
538% This is the SERVICE CONSUMPTION MODEL
539% These are the variables, i.e. which DC to select for each VNF
540var Vims: VNF1;
541Vims: VNF2 = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
542var Vims: VNF3;
543Vims: VNF4 = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
546% These are the set of rules for selecting DCs to VNFs
547constraint trp_link_latency[VNF1, VNF2] <= 150;
548constraint trp_link_latency[VNF2, VNF3] <= 140;
549constraint trp_link_latency[VNF3, VNF4] <= 130;
550constraint trp_link_jitter[VNF1, VNF2] <= 30;
551constraint trp_link_jitter[VNF2, VNF3] <= 30;
552constraint trp_link_jitter[VNF3, VNF4] <= 30;
554% Calculate the cost for VNFs and cost for transport link and total cost
555var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+
556trp_link_price_list[VNF2, VNF3]+
557trp_link_price_list[VNF3, VNF4];
559var int: used_vim_cost =vim_price_list_1[VNF1]+
560vim_price_list_2[VNF2]+
561vim_price_list_3[VNF3]+
562vim_price_list_4[VNF4];
564var int: total_cost = used_transport_cost + used_vim_cost;
566solve minimize total_cost;
567"""
569expected_model_fragment_w_pinning_str = """
570%This is the NETWORK RESOURCE MODEL
571enum Vims = {
572vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
573vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
574vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
575vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
576vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
577array[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
583array[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
589array[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
595array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
596array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
597array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
598array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
601% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
602% NOTE. This is not applicable in OSM Release 7
604% This is the SERVICE CONSUMPTION MODEL
605% These are the variables, i.e. which DC to select for each VNF
606var Vims: VNFone;
607Vims: VNFtwo = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
608var Vims: VNFthree;
609Vims: VNFfour = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
612% These are the set of rules for selecting DCs to VNFs
613constraint trp_link_latency[VNFone, VNFtwo] <= 150;
614constraint trp_link_latency[VNFtwo, VNFthree] <= 140;
615constraint trp_link_latency[VNFthree, VNFfour] <= 130;
616constraint trp_link_jitter[VNFone, VNFtwo] <= 30;
617constraint trp_link_jitter[VNFtwo, VNFthree] <= 30;
618constraint trp_link_jitter[VNFthree, VNFfour] <= 30;
620% Calculate the cost for VNFs and cost for transport link and total cost
621var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
622trp_link_price_list[VNFtwo, VNFthree]+
623trp_link_price_list[VNFthree, VNFfour];
625var int: used_vim_cost =vim_price_list_one[VNFone]+
626vim_price_list_two[VNFtwo]+
627vim_price_list_three[VNFthree]+
628vim_price_list_four[VNFfour];
630var int: total_cost = used_transport_cost + used_vim_cost;
632solve minimize total_cost;
633"""
635expected_model_fragment_str_no_vld = """
636%This is the NETWORK RESOURCE MODEL
637enum Vims = {
638vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
639vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
640vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
641vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
642vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
643array[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
649array[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
655array[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
661array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
664% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
665% NOTE. This is not applicable in OSM Release 7
667% This is the SERVICE CONSUMPTION MODEL
668% These are the variables, i.e. which DC to select for each VNF
670var Vims: VNFone;
672% These are the set of rules for selecting DCs to VNFs
674% Calculate the cost for VNFs and cost for transport link and total cost
675var int: used_transport_cost =0;
677var int: used_vim_cost =vim_price_list_one[VNFone];
679var int: total_cost = used_transport_cost + used_vim_cost;
681solve minimize total_cost;
682"""
685class TestMznModelGenerator(TestCase):
686 def test_create_model(self):
687 mg = MznModelGenerator(logging.getLogger(__name__))
688 mzn_model = mg.create_model(test_ns_placement_data_str)
690 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
691 self.assertTrue(
692 expected_model_fragment_str.replace("\n", "")
693 in mzn_model.replace("\n", ""),
694 "faulty model generated",
695 )
697 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 mg = MznModelGenerator(logging.getLogger(__name__))
703 mzn_model = mg.create_model(test_ns_placement_data_str_no_vld_constraints)
705 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
706 self.assertTrue(
707 expected_model_fragment_str_no_vld_constraints.replace("\n", "")
708 in mzn_model.replace("\n", ""),
709 "faulty model generated",
710 )
712 def test_create_model_w_pinning(self):
713 mg = MznModelGenerator(logging.getLogger(__name__))
714 mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
716 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
717 self.assertTrue(
718 expected_model_fragment_w_pinning_str.replace("\n", "")
719 in mzn_model.replace("\n", ""),
720 "faulty model generated",
721 )
723 def test_create_model_no_vld(self):
724 mg = MznModelGenerator(logging.getLogger(__name__))
725 mzn_model = mg.create_model(test_ns_placement_data_str_no_vld)
727 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
728 self.assertTrue(
729 expected_model_fragment_str_no_vld.replace("\n", "")
730 in mzn_model.replace("\n", ""),
731 "faulty model generated",
732 )
734 def test__load_jinja_template(self):
735 """
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 mg = MznModelGenerator(logging.getLogger(__name__))
741 template = mg._load_jinja_template() # Note we use the default template
742 self.assertTrue(
743 isinstance(template, Template), "failed to load jinja2 template"
744 )
746 def test_vim_account_replace(self):
747 mg = MznModelGenerator(logging.getLogger(__name__))
748 nspd = test_ns_placement_data_str
749 mzn_model = mg.create_model(nspd)
751 expected = (
752 "%This is the NETWORK RESOURCE MODEL" + "\n" + "enum Vims = {" + "\n"
753 )
754 for val in test_ns_placement_data_str["vim_accounts"]:
755 expected = expected + val.replace("-", "_") + ",\n"
756 expected = expected[:-2] + "}; % The vim-accounts"
757 res = re.findall(expected, mzn_model)
758 self.assertEqual(1, len(res), "vim accounts didnt replace from - to _")
760 def test_trp_link_price_list(self):
761 mg = MznModelGenerator(logging.getLogger(__name__))
762 mzn_model = mg.create_model(test_ns_placement_data_str)
764 expected = "array\\[Vims, Vims\\] of int: trp_link_price_list = \\["
765 for price_list in test_ns_placement_data_str["trp_link_price_list"]:
766 expected = (
767 expected + "\\|" + (str(price_list)[1:-1]).replace(" ", "") + ",\n"
768 )
769 expected = expected + "\\|\\]; % Transport link price list"
770 res = re.findall(expected, mzn_model)
771 self.assertEqual(1, len(res), "price list is not correct")
773 def test_link_latency(self):
774 mg = MznModelGenerator(logging.getLogger(__name__))
775 mzn_model = mg.create_model(test_ns_placement_data_str)
777 expected = "array\\[Vims, Vims\\] of int: trp_link_latency = \\["
778 for link_latency in test_ns_placement_data_str["trp_link_latency"]:
779 expected = (
780 expected + "\\|" + (str(link_latency)[1:-1]).replace(" ", "") + ",\n"
781 )
782 expected = expected + "\\|\\]; % Transport link latency between data centers"
783 res = re.findall(expected, mzn_model)
784 self.assertEqual(1, len(res), "trp_link_latency values is not correct")
786 def test_link_jitter(self):
787 mg = MznModelGenerator(logging.getLogger(__name__))
788 mzn_model = mg.create_model(test_ns_placement_data_str)
790 expected = "array\\[Vims, Vims\\] of int: trp_link_jitter = \\["
791 for link_jitter in test_ns_placement_data_str["trp_link_jitter"]:
792 expected = (
793 expected + "\\|" + (str(link_jitter)[1:-1]).replace(" ", "") + ",\n"
794 )
795 expected = expected + "\\|\\]; % Transport link jitter between data centers"
797 res = re.findall(expected, mzn_model)
799 self.assertEqual(1, len(res), "trp_link_jitter values is not correct")
801 def test_price_per_vim(self):
802 mg = MznModelGenerator(logging.getLogger(__name__))
803 mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
805 expected = ""
806 for price_list in test_ns_placement_data_w_pinning_str["ns_desc"]:
807 expected += (
808 "array\\[Vims\\] of int: vim_price_list_"
809 + price_list.get("vnf_id")
810 + " = "
811 )
812 temp = str(price_list.get("vnf_price_per_vim"))[1:-1].replace(" ", "")
813 expected += "\\[" + temp + "\\];\n"
815 res = re.findall(expected, mzn_model)
816 self.assertEqual(1, len(res), "mzn_model contains pinning")
818 def test_pinning(self):
819 mg = MznModelGenerator(logging.getLogger(__name__))
820 mzn_model = mg.create_model(test_ns_placement_data_str)
822 expected = ""
823 for pin_list in test_ns_placement_data_str["ns_desc"]:
824 if pin_list.get("vim_account"):
825 expected += (
826 "Vims: VNF"
827 + pin_list.get("vnf_id")
828 + " = "
829 + pin_list.get("vim_account")
830 + ";\n"
831 )
832 else:
833 expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
835 res = re.findall(expected, mzn_model)
836 self.assertEqual(1, len(res), "mzn_model has no pinning")
838 def test__without_pinning(self):
839 mg = MznModelGenerator(logging.getLogger(__name__))
840 mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
842 expected = ""
843 for pin_list in test_ns_placement_data_w_pinning_str["ns_desc"]:
844 if pin_list.get("vim_account"):
845 expected += (
846 "Vims: VNF"
847 + pin_list.get("vnf_id")
848 + " = "
849 + pin_list.get("vim_account")
850 + ";\n"
851 )
852 else:
853 expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
855 res = re.findall(expected, mzn_model)
856 self.assertEqual(1, len(res), "mzn_model contains pinning")
858 def test__without_constraints_for_jitter_and_latency(self):
859 mg = MznModelGenerator(logging.getLogger(__name__))
860 mzn_model = mg.create_model(test_ns_placement_data_str_no_vld_constraints)
862 expected_latency = "constraint trp_link_latency"
863 expected_jitter = "constraint trp_link_jitter"
864 latency_or_jitter_was_found = 0
865 for l_o_j in test_ns_placement_data_str_no_vld_constraints["vld_desc"]:
866 if l_o_j.get("latency") or l_o_j.get("jitter"):
867 latency_or_jitter_was_found = 1
869 res_latency = re.findall(expected_latency, mzn_model)
870 res_jitter = re.findall(expected_jitter, mzn_model)
871 self.assertEqual(
872 0,
873 latency_or_jitter_was_found,
874 "Jitter or latency was found in the test input",
875 )
876 self.assertEqual(
877 0, len(res_latency), "constraint trp_link_latency was found in mzn_model"
878 )
879 self.assertEqual(
880 0, len(res_jitter), "constraint trp_link_latency was found in mzn_model"
881 )
883 def test__constraints_for_jitter_and_latency(self):
884 mg = MznModelGenerator(logging.getLogger(__name__))
885 mzn_model = mg.create_model(test_ns_placement_data_str)
887 expected_latency = ""
888 expected_jitter = ""
889 latency_or_jitter_was_found = 0
890 for l_o_j in test_ns_placement_data_str["vld_desc"]:
891 if not (l_o_j.get("latency") or l_o_j.get("jitter")):
892 latency_or_jitter_was_found = 1
893 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 )
904 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 )
915 res = re.findall(expected_latency + expected_jitter, mzn_model)
916 self.assertEqual(
917 0,
918 latency_or_jitter_was_found,
919 "Jitter or latency was not found in the test input",
920 )
921 self.assertEqual(1, len(res), "faulty model generated")