Coverage for osm_pla/test/test_mznModelGenerator.py: 98%

134 statements  

« prev     ^ index     » next       coverage.py v6.4.1, created at 2024-06-30 08:29 +0000

1# Copyright 2020 ArctosLabs Scandinavia AB 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 

12# implied. 

13# See the License for the specific language governing permissions and 

14# limitations under the License. 

15import datetime 

16import logging 

17# import unittest 

18from unittest import TestCase 

19# import random 

20# from operator import itemgetter 

21import re 

22 

23from jinja2 import Template 

24 

25from osm_pla.placement.mznplacement import MznModelGenerator 

26 

27test_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 

49test_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 

71test_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 

93test_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 

117test_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 

141test_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 

158expected_model_fragment = """ 

159%This is the NETWORK RESOURCE MODEL 

160enum Vims = { 

161vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87, 

162vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87, 

163vimcccccccc_ed84_4e49_b5df_a9d117bd731f, 

164vimdddddddd_ed84_4e49_b5df_a9d117bd731f, 

165vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts 

166array[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 

172array[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 

178array[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 

184array[Vims] of int: vim_price_list_1 = [50,51,52,53,54]; 

185array[Vims] of int: vim_price_list_2 = [20,21,22,23,24]; 

186array[Vims] of int: vim_price_list_3 = [70,71,72,73,74]; 

187array[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 

195var Vims: VNF1; 

196var Vims: VNF2; 

197var Vims: VNF3; 

198var Vims: VNF4; 

199 

200 

201% These are the set of rules for selecting DCs to VNFs 

202constraint trp_link_latency[VNF1, VNF2] <= 150; 

203constraint trp_link_latency[VNF2, VNF3] <= 140; 

204constraint trp_link_latency[VNF3, VNF4] <= 130; 

205constraint trp_link_jitter[VNF1, VNF2] <= 30; 

206constraint trp_link_jitter[VNF2, VNF3] <= 30; 

207constraint trp_link_jitter[VNF3, VNF4] <= 30; 

208 

209% Calculate the cost for VNFs and cost for transport link and total cost 

210var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+ 

211trp_link_price_list[VNF2, VNF3]+ 

212trp_link_price_list[VNF3, VNF4]; 

213 

214var int: used_vim_cost =vim_price_list_1[VNF1]+ 

215vim_price_list_2[VNF2]+ 

216vim_price_list_3[VNF3]+ 

217vim_price_list_4[VNF4]; 

218 

219var int: total_cost = used_transport_cost + used_vim_cost; 

220 

221solve minimize total_cost; 

222""" 

223expected_model_fragment_str = """ 

224%This is the NETWORK RESOURCE MODEL 

225enum Vims = { 

226vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87, 

227vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87, 

228vimcccccccc_ed84_4e49_b5df_a9d117bd731f, 

229vimdddddddd_ed84_4e49_b5df_a9d117bd731f, 

230vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts 

231array[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 

237array[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 

243array[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 

249array[Vims] of int: vim_price_list_one = [50,51,52,53,54]; 

250array[Vims] of int: vim_price_list_two = [20,21,22,23,24]; 

251array[Vims] of int: vim_price_list_three = [70,71,72,73,74]; 

252array[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 

260var Vims: VNFone; 

261var Vims: VNFtwo; 

262var Vims: VNFthree; 

263var Vims: VNFfour; 

264 

265 

266% These are the set of rules for selecting DCs to VNFs 

267constraint trp_link_latency[VNFone, VNFtwo] <= 150; 

268constraint trp_link_latency[VNFtwo, VNFthree] <= 140; 

269constraint trp_link_latency[VNFthree, VNFfour] <= 130; 

270constraint trp_link_jitter[VNFone, VNFtwo] <= 30; 

271constraint trp_link_jitter[VNFtwo, VNFthree] <= 30; 

272constraint trp_link_jitter[VNFthree, VNFfour] <= 30; 

273 

274% Calculate the cost for VNFs and cost for transport link and total cost 

275var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+ 

276trp_link_price_list[VNFtwo, VNFthree]+ 

277trp_link_price_list[VNFthree, VNFfour]; 

278 

279var int: used_vim_cost =vim_price_list_one[VNFone]+ 

280vim_price_list_two[VNFtwo]+ 

281vim_price_list_three[VNFthree]+ 

282vim_price_list_four[VNFfour]; 

283 

284var int: total_cost = used_transport_cost + used_vim_cost; 

285 

286solve minimize total_cost; 

287""" 

288 

289expected_model_fragment_str_no_vld_constraints = """ 

290%This is the NETWORK RESOURCE MODEL 

291enum Vims = { 

292vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87, 

293vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87, 

294vimcccccccc_ed84_4e49_b5df_a9d117bd731f, 

295vimdddddddd_ed84_4e49_b5df_a9d117bd731f, 

296vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts 

297array[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 

303array[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 

309array[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 

315array[Vims] of int: vim_price_list_one = [50,51,52,53,54]; 

316array[Vims] of int: vim_price_list_two = [20,21,22,23,24]; 

317array[Vims] of int: vim_price_list_three = [70,71,72,73,74]; 

318array[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 

326var Vims: VNFone; 

327var Vims: VNFtwo; 

328var Vims: VNFthree; 

329var 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 

335var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+ 

336trp_link_price_list[VNFtwo, VNFthree]+ 

337trp_link_price_list[VNFthree, VNFfour]; 

338 

339var int: used_vim_cost =vim_price_list_one[VNFone]+ 

340vim_price_list_two[VNFtwo]+ 

341vim_price_list_three[VNFthree]+ 

342vim_price_list_four[VNFfour]; 

343 

344var int: total_cost = used_transport_cost + used_vim_cost; 

345 

346solve minimize total_cost; 

347""" 

348 

349expected_model_fragment_w_pinning = """ 

350%This is the NETWORK RESOURCE MODEL 

351enum Vims = { 

352vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87, 

353vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87, 

354vimcccccccc_ed84_4e49_b5df_a9d117bd731f, 

355vimdddddddd_ed84_4e49_b5df_a9d117bd731f, 

356vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts 

357array[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 

363array[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 

369array[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 

375array[Vims] of int: vim_price_list_1 = [50,51,52,53,54]; 

376array[Vims] of int: vim_price_list_2 = [20,21,22,23,24]; 

377array[Vims] of int: vim_price_list_3 = [70,71,72,73,74]; 

378array[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 

386var Vims: VNF1; 

387Vims: VNF2 = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87; 

388var Vims: VNF3; 

389Vims: VNF4 = vimcccccccc_ed84_4e49_b5df_a9d117bd731f; 

390 

391 

392% These are the set of rules for selecting DCs to VNFs 

393constraint trp_link_latency[VNF1, VNF2] <= 150; 

394constraint trp_link_latency[VNF2, VNF3] <= 140; 

395constraint trp_link_latency[VNF3, VNF4] <= 130; 

396constraint trp_link_jitter[VNF1, VNF2] <= 30; 

397constraint trp_link_jitter[VNF2, VNF3] <= 30; 

398constraint trp_link_jitter[VNF3, VNF4] <= 30; 

399 

400% Calculate the cost for VNFs and cost for transport link and total cost 

401var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+ 

402trp_link_price_list[VNF2, VNF3]+ 

403trp_link_price_list[VNF3, VNF4]; 

404 

405var int: used_vim_cost =vim_price_list_1[VNF1]+ 

406vim_price_list_2[VNF2]+ 

407vim_price_list_3[VNF3]+ 

408vim_price_list_4[VNF4]; 

409 

410var int: total_cost = used_transport_cost + used_vim_cost; 

411 

412solve minimize total_cost; 

413""" 

414 

415expected_model_fragment_w_pinning_str = """ 

416%This is the NETWORK RESOURCE MODEL 

417enum Vims = { 

418vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87, 

419vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87, 

420vimcccccccc_ed84_4e49_b5df_a9d117bd731f, 

421vimdddddddd_ed84_4e49_b5df_a9d117bd731f, 

422vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts 

423array[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 

429array[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 

435array[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 

441array[Vims] of int: vim_price_list_one = [50,51,52,53,54]; 

442array[Vims] of int: vim_price_list_two = [20,21,22,23,24]; 

443array[Vims] of int: vim_price_list_three = [70,71,72,73,74]; 

444array[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 

452var Vims: VNFone; 

453Vims: VNFtwo = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87; 

454var Vims: VNFthree; 

455Vims: VNFfour = vimcccccccc_ed84_4e49_b5df_a9d117bd731f; 

456 

457 

458% These are the set of rules for selecting DCs to VNFs 

459constraint trp_link_latency[VNFone, VNFtwo] <= 150; 

460constraint trp_link_latency[VNFtwo, VNFthree] <= 140; 

461constraint trp_link_latency[VNFthree, VNFfour] <= 130; 

462constraint trp_link_jitter[VNFone, VNFtwo] <= 30; 

463constraint trp_link_jitter[VNFtwo, VNFthree] <= 30; 

464constraint trp_link_jitter[VNFthree, VNFfour] <= 30; 

465 

466% Calculate the cost for VNFs and cost for transport link and total cost 

467var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+ 

468trp_link_price_list[VNFtwo, VNFthree]+ 

469trp_link_price_list[VNFthree, VNFfour]; 

470 

471var int: used_vim_cost =vim_price_list_one[VNFone]+ 

472vim_price_list_two[VNFtwo]+ 

473vim_price_list_three[VNFthree]+ 

474vim_price_list_four[VNFfour]; 

475 

476var int: total_cost = used_transport_cost + used_vim_cost; 

477 

478solve minimize total_cost; 

479""" 

480 

481expected_model_fragment_str_no_vld = """ 

482%This is the NETWORK RESOURCE MODEL 

483enum Vims = { 

484vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87, 

485vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87, 

486vimcccccccc_ed84_4e49_b5df_a9d117bd731f, 

487vimdddddddd_ed84_4e49_b5df_a9d117bd731f, 

488vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts 

489array[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 

495array[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 

501array[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 

507array[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 

516var 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 

521var int: used_transport_cost =0; 

522 

523var int: used_vim_cost =vim_price_list_one[VNFone]; 

524 

525var int: total_cost = used_transport_cost + used_vim_cost; 

526 

527solve minimize total_cost; 

528""" 

529 

530 

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