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