blob: 4f0423da75f1ad0a616f8c6da51ebce81ade5fdb [file] [log] [blame]
magnussonl2b0e2d72020-02-04 10:52:46 +01001# 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
garciadeblas20fc3b72022-11-14 00:48:32 +010017
magnussonl2b0e2d72020-02-04 10:52:46 +010018# import unittest
19from unittest import TestCase
garciadeblas20fc3b72022-11-14 00:48:32 +010020
magnussonl2b0e2d72020-02-04 10:52:46 +010021# import random
22# from operator import itemgetter
23import re
24
25from jinja2 import Template
26
27from osm_pla.placement.mznplacement import MznModelGenerator
28
29test_ns_placement_data_str = {
garciadeblas20fc3b72022-11-14 00:48:32 +010030 "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()},
magnussonl2b0e2d72020-02-04 10:52:46 +010073}
74
75test_ns_placement_data_str_no_vld_constraints = {
garciadeblas20fc3b72022-11-14 00:48:32 +010076 "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()},
magnussonl2b0e2d72020-02-04 10:52:46 +0100119}
120
121test_ns_placement_data = {
garciadeblas20fc3b72022-11-14 00:48:32 +0100122 "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()},
magnussonl2b0e2d72020-02-04 10:52:46 +0100165}
166
167test_ns_placement_data_w_pinning = {
garciadeblas20fc3b72022-11-14 00:48:32 +0100168 "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()},
magnussonl2b0e2d72020-02-04 10:52:46 +0100219}
220
221test_ns_placement_data_w_pinning_str = {
garciadeblas20fc3b72022-11-14 00:48:32 +0100222 "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()},
magnussonl2b0e2d72020-02-04 10:52:46 +0100273}
274
275test_ns_placement_data_str_no_vld = {
garciadeblas20fc3b72022-11-14 00:48:32 +0100276 "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()},
magnussonl2b0e2d72020-02-04 10:52:46 +0100310}
311
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];
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
349var Vims: VNF1;
350var Vims: VNF2;
351var Vims: VNF3;
352var Vims: VNF4;
353
354
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;
362
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];
367
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];
372
373var int: total_cost = used_transport_cost + used_vim_cost;
374
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];
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
414var Vims: VNFone;
415var Vims: VNFtwo;
416var Vims: VNFthree;
417var Vims: VNFfour;
418
419
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;
427
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];
432
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];
437
438var int: total_cost = used_transport_cost + used_vim_cost;
439
440solve minimize total_cost;
441"""
442
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];
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
480var Vims: VNFone;
481var Vims: VNFtwo;
482var Vims: VNFthree;
483var 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
489var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
490trp_link_price_list[VNFtwo, VNFthree]+
491trp_link_price_list[VNFthree, VNFfour];
492
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];
497
498var int: total_cost = used_transport_cost + used_vim_cost;
499
500solve minimize total_cost;
501"""
502
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];
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
540var Vims: VNF1;
541Vims: VNF2 = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
542var Vims: VNF3;
543Vims: VNF4 = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
544
545
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;
553
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];
558
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];
563
564var int: total_cost = used_transport_cost + used_vim_cost;
565
566solve minimize total_cost;
567"""
568
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];
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
606var Vims: VNFone;
607Vims: VNFtwo = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
608var Vims: VNFthree;
609Vims: VNFfour = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
610
611
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;
619
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];
624
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];
629
630var int: total_cost = used_transport_cost + used_vim_cost;
631
632solve minimize total_cost;
633"""
634
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];
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
670var 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
675var int: used_transport_cost =0;
676
677var int: used_vim_cost =vim_price_list_one[VNFone];
678
679var int: total_cost = used_transport_cost + used_vim_cost;
680
681solve minimize total_cost;
682"""
683
684
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)
689
690 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
garciadeblas20fc3b72022-11-14 00:48:32 +0100691 self.assertTrue(
692 expected_model_fragment_str.replace("\n", "")
693 in mzn_model.replace("\n", ""),
694 "faulty model generated",
695 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100696
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)
704
705 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
garciadeblas20fc3b72022-11-14 00:48:32 +0100706 self.assertTrue(
707 expected_model_fragment_str_no_vld_constraints.replace("\n", "")
708 in mzn_model.replace("\n", ""),
709 "faulty model generated",
710 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100711
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)
715
716 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
garciadeblas20fc3b72022-11-14 00:48:32 +0100717 self.assertTrue(
718 expected_model_fragment_w_pinning_str.replace("\n", "")
719 in mzn_model.replace("\n", ""),
720 "faulty model generated",
721 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100722
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)
726
727 # so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
garciadeblas20fc3b72022-11-14 00:48:32 +0100728 self.assertTrue(
729 expected_model_fragment_str_no_vld.replace("\n", "")
730 in mzn_model.replace("\n", ""),
731 "faulty model generated",
732 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100733
734 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 mg = MznModelGenerator(logging.getLogger(__name__))
741 template = mg._load_jinja_template() # Note we use the default template
garciadeblas20fc3b72022-11-14 00:48:32 +0100742 self.assertTrue(
743 isinstance(template, Template), "failed to load jinja2 template"
744 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100745
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)
750
garciadeblas20fc3b72022-11-14 00:48:32 +0100751 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"
magnussonl2b0e2d72020-02-04 10:52:46 +0100757 res = re.findall(expected, mzn_model)
758 self.assertEqual(1, len(res), "vim accounts didnt replace from - to _")
759
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)
763
garciadeblas20fc3b72022-11-14 00:48:32 +0100764 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"
magnussonl2b0e2d72020-02-04 10:52:46 +0100770 res = re.findall(expected, mzn_model)
771 self.assertEqual(1, len(res), "price list is not correct")
772
773 def test_link_latency(self):
774 mg = MznModelGenerator(logging.getLogger(__name__))
775 mzn_model = mg.create_model(test_ns_placement_data_str)
776
garciadeblas20fc3b72022-11-14 00:48:32 +0100777 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"
magnussonl2b0e2d72020-02-04 10:52:46 +0100783 res = re.findall(expected, mzn_model)
784 self.assertEqual(1, len(res), "trp_link_latency values is not correct")
785
786 def test_link_jitter(self):
787 mg = MznModelGenerator(logging.getLogger(__name__))
788 mzn_model = mg.create_model(test_ns_placement_data_str)
789
garciadeblas20fc3b72022-11-14 00:48:32 +0100790 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"
magnussonl2b0e2d72020-02-04 10:52:46 +0100796
797 res = re.findall(expected, mzn_model)
798
799 self.assertEqual(1, len(res), "trp_link_jitter values is not correct")
800
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)
804
805 expected = ""
garciadeblas20fc3b72022-11-14 00:48:32 +0100806 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(" ", "")
magnussonl2b0e2d72020-02-04 10:52:46 +0100813 expected += "\\[" + temp + "\\];\n"
814
815 res = re.findall(expected, mzn_model)
816 self.assertEqual(1, len(res), "mzn_model contains pinning")
817
818 def test_pinning(self):
819 mg = MznModelGenerator(logging.getLogger(__name__))
820 mzn_model = mg.create_model(test_ns_placement_data_str)
821
822 expected = ""
garciadeblas20fc3b72022-11-14 00:48:32 +0100823 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 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100832 else:
garciadeblas20fc3b72022-11-14 00:48:32 +0100833 expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
magnussonl2b0e2d72020-02-04 10:52:46 +0100834
835 res = re.findall(expected, mzn_model)
836 self.assertEqual(1, len(res), "mzn_model has no pinning")
837
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)
841
842 expected = ""
garciadeblas20fc3b72022-11-14 00:48:32 +0100843 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 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100852 else:
garciadeblas20fc3b72022-11-14 00:48:32 +0100853 expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
magnussonl2b0e2d72020-02-04 10:52:46 +0100854
855 res = re.findall(expected, mzn_model)
856 self.assertEqual(1, len(res), "mzn_model contains pinning")
857
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)
861
862 expected_latency = "constraint trp_link_latency"
863 expected_jitter = "constraint trp_link_jitter"
864 latency_or_jitter_was_found = 0
garciadeblas20fc3b72022-11-14 00:48:32 +0100865 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"):
magnussonl2b0e2d72020-02-04 10:52:46 +0100867 latency_or_jitter_was_found = 1
868
869 res_latency = re.findall(expected_latency, mzn_model)
870 res_jitter = re.findall(expected_jitter, mzn_model)
garciadeblas20fc3b72022-11-14 00:48:32 +0100871 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 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100882
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)
886
887 expected_latency = ""
888 expected_jitter = ""
889 latency_or_jitter_was_found = 0
garciadeblas20fc3b72022-11-14 00:48:32 +0100890 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")):
magnussonl2b0e2d72020-02-04 10:52:46 +0100892 latency_or_jitter_was_found = 1
garciadeblas20fc3b72022-11-14 00:48:32 +0100893 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 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100903
garciadeblas20fc3b72022-11-14 00:48:32 +0100904 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 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100914
915 res = re.findall(expected_latency + expected_jitter, mzn_model)
garciadeblas20fc3b72022-11-14 00:48:32 +0100916 self.assertEqual(
917 0,
918 latency_or_jitter_was_found,
919 "Jitter or latency was not found in the test input",
920 )
magnussonl2b0e2d72020-02-04 10:52:46 +0100921 self.assertEqual(1, len(res), "faulty model generated")