Code Coverage

Cobertura Coverage Report > osm_pla.test >

test_mznModelGenerator.py

Trend

Classes100%
 
Lines98%
   
Conditionals100%
 

File Coverage summary

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

Coverage Breakdown by Class

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

Source

osm_pla/test/test_mznModelGenerator.py
1 # Copyright 2020 ArctosLabs Scandinavia AB
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 1 import datetime
16 1 import logging
17 # import unittest
18 1 from unittest import TestCase
19 # import random
20 # from operator import itemgetter
21 1 import re
22
23 1 from jinja2 import Template
24
25 1 from osm_pla.placement.mznplacement import MznModelGenerator
26
27 1 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 1 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 1 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 1 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 1 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 1 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 1 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 1 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 1 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 1 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 1 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 1 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 1 class TestMznModelGenerator(TestCase):
532 1     def test_create_model(self):
533 1         mg = MznModelGenerator(logging.getLogger(__name__))
534 1         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 1         self.assertTrue(expected_model_fragment_str.replace('\n', '') in
538                         mzn_model.replace('\n', ''), "faulty model generated")
539
540 1     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 1         mg = MznModelGenerator(logging.getLogger(__name__))
546 1         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 1         self.assertTrue(expected_model_fragment_str_no_vld_constraints.replace('\n', '') in
550                         mzn_model.replace('\n', ''), "faulty model generated")
551
552 1     def test_create_model_w_pinning(self):
553 1         mg = MznModelGenerator(logging.getLogger(__name__))
554 1         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 1         self.assertTrue(expected_model_fragment_w_pinning_str.replace('\n', '') in
558                         mzn_model.replace('\n', ''), "faulty model generated")
559
560 1     def test_create_model_no_vld(self):
561 1         mg = MznModelGenerator(logging.getLogger(__name__))
562 1         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 1         self.assertTrue(expected_model_fragment_str_no_vld.replace('\n', '') in
566                         mzn_model.replace('\n', ''), "faulty model generated")
567
568 1     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 1         mg = MznModelGenerator(logging.getLogger(__name__))
575 1         template = mg._load_jinja_template()  # Note we use the default template
576 1         self.assertTrue(isinstance(template, Template), "failed to load jinja2 template")
577
578 1     def test_vim_account_replace(self):
579 1         mg = MznModelGenerator(logging.getLogger(__name__))
580 1         nspd = test_ns_placement_data_str
581 1         mzn_model = mg.create_model(nspd)
582
583 1         expected = '%This is the NETWORK RESOURCE MODEL' + '\n' + 'enum  Vims = {' + '\n'
584 1         for val in test_ns_placement_data_str['vim_accounts']:
585 1             expected = expected + val.replace('-', '_') + ',\n'
586 1         expected = expected[:-2] + '}; % The vim-accounts'
587 1         res = re.findall(expected, mzn_model)
588 1         self.assertEqual(1, len(res), "vim accounts didnt replace from - to _")
589
590 1     def test_trp_link_price_list(self):
591 1         mg = MznModelGenerator(logging.getLogger(__name__))
592 1         mzn_model = mg.create_model(test_ns_placement_data_str)
593
594 1         expected = 'array\\[Vims, Vims\\] of int: trp_link_price_list = \\['
595 1         for price_list in test_ns_placement_data_str['trp_link_price_list']:
596 1             expected = expected + '\\|' + (str(price_list)[1:-1]).replace(" ", "") + ',\n'
597 1         expected = expected + '\\|\\]; % Transport link price list'
598 1         res = re.findall(expected, mzn_model)
599 1         self.assertEqual(1, len(res), "price list is not correct")
600
601 1     def test_link_latency(self):
602 1         mg = MznModelGenerator(logging.getLogger(__name__))
603 1         mzn_model = mg.create_model(test_ns_placement_data_str)
604
605 1         expected = 'array\\[Vims, Vims\\] of int: trp_link_latency = \\['
606 1         for link_latency in test_ns_placement_data_str['trp_link_latency']:
607 1             expected = expected + '\\|' + (str(link_latency)[1:-1]).replace(" ", "") + ',\n'
608 1         expected = expected + '\\|\\]; % Transport link latency between data centers'
609 1         res = re.findall(expected, mzn_model)
610 1         self.assertEqual(1, len(res), "trp_link_latency values is not correct")
611
612 1     def test_link_jitter(self):
613 1         mg = MznModelGenerator(logging.getLogger(__name__))
614 1         mzn_model = mg.create_model(test_ns_placement_data_str)
615
616 1         expected = 'array\\[Vims, Vims\\] of int: trp_link_jitter = \\['
617 1         for link_jitter in test_ns_placement_data_str['trp_link_jitter']:
618 1             expected = expected + '\\|' + (str(link_jitter)[1:-1]).replace(" ", "") + ',\n'
619 1         expected = expected + '\\|\\]; % Transport link jitter between data centers'
620
621 1         res = re.findall(expected, mzn_model)
622
623 1         self.assertEqual(1, len(res), "trp_link_jitter values is not correct")
624
625 1     def test_price_per_vim(self):
626 1         mg = MznModelGenerator(logging.getLogger(__name__))
627 1         mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
628
629 1         expected = ""
630 1         for price_list in test_ns_placement_data_w_pinning_str['ns_desc']:
631 1             expected += 'array\\[Vims\\] of int: vim_price_list_' + price_list.get('vnf_id') + " = "
632 1             temp = str(price_list.get('vnf_price_per_vim'))[1:-1].replace(" ", "")
633 1             expected += "\\[" + temp + "\\];\n"
634
635 1         res = re.findall(expected, mzn_model)
636 1         self.assertEqual(1, len(res), "mzn_model contains pinning")
637
638 1     def test_pinning(self):
639 1         mg = MznModelGenerator(logging.getLogger(__name__))
640 1         mzn_model = mg.create_model(test_ns_placement_data_str)
641
642 1         expected = ""
643 1         for pin_list in test_ns_placement_data_str['ns_desc']:
644 1             if pin_list.get('vim_account'):
645 0                 expected += 'Vims: VNF' + pin_list.get('vnf_id') + ' = ' + pin_list.get('vim_account') + ';\n'
646             else:
647 1                 expected += 'var Vims: VNF' + pin_list.get('vnf_id') + ';\n'
648
649 1         res = re.findall(expected, mzn_model)
650 1         self.assertEqual(1, len(res), "mzn_model has no pinning")
651
652 1     def test__without_pinning(self):
653 1         mg = MznModelGenerator(logging.getLogger(__name__))
654 1         mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
655
656 1         expected = ""
657 1         for pin_list in test_ns_placement_data_w_pinning_str['ns_desc']:
658 1             if pin_list.get('vim_account'):
659 1                 expected += 'Vims: VNF' + pin_list.get('vnf_id') + ' = ' + pin_list.get('vim_account') + ';\n'
660             else:
661 1                 expected += 'var Vims: VNF' + pin_list.get('vnf_id') + ';\n'
662
663 1         res = re.findall(expected, mzn_model)
664 1         self.assertEqual(1, len(res), "mzn_model contains pinning")
665
666 1     def test__without_constraints_for_jitter_and_latency(self):
667 1         mg = MznModelGenerator(logging.getLogger(__name__))
668 1         mzn_model = mg.create_model(test_ns_placement_data_str_no_vld_constraints)
669
670 1         expected_latency = "constraint trp_link_latency"
671 1         expected_jitter = "constraint trp_link_jitter"
672 1         latency_or_jitter_was_found = 0
673 1         for l_o_j in test_ns_placement_data_str_no_vld_constraints['vld_desc']:
674 1             if l_o_j.get('latency') or l_o_j.get('jitter'):
675 0                 latency_or_jitter_was_found = 1
676
677 1         res_latency = re.findall(expected_latency, mzn_model)
678 1         res_jitter = re.findall(expected_jitter, mzn_model)
679 1         self.assertEqual(0, latency_or_jitter_was_found, "Jitter or latency was found in the test input")
680 1         self.assertEqual(0, len(res_latency), "constraint trp_link_latency was found in mzn_model")
681 1         self.assertEqual(0, len(res_jitter), "constraint trp_link_latency was found in mzn_model")
682
683 1     def test__constraints_for_jitter_and_latency(self):
684 1         mg = MznModelGenerator(logging.getLogger(__name__))
685 1         mzn_model = mg.create_model(test_ns_placement_data_str)
686
687 1         expected_latency = ""
688 1         expected_jitter = ""
689 1         latency_or_jitter_was_found = 0
690 1         for l_o_j in test_ns_placement_data_str['vld_desc']:
691 1             if not (l_o_j.get('latency') or l_o_j.get('jitter')):
692 0                 latency_or_jitter_was_found = 1
693 1             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 1             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 1         res = re.findall(expected_latency + expected_jitter, mzn_model)
700 1         self.assertEqual(0, latency_or_jitter_was_found, "Jitter or latency was not found in the test input")
701 1         self.assertEqual(1, len(res), "faulty model generated")