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") |