blob: 4f0423da75f1ad0a616f8c6da51ebce81ade5fdb [file] [log] [blame]
# Copyright 2020 ArctosLabs Scandinavia AB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import datetime
import logging
# import unittest
from unittest import TestCase
# import random
# from operator import itemgetter
import re
from jinja2 import Template
from osm_pla.placement.mznplacement import MznModelGenerator
test_ns_placement_data_str = {
"vim_accounts": [
"vim" + vim_account.replace("-", "_")
for vim_account in [
"aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
"bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
"cccccccc-ed84-4e49-b5df-a9d117bd731f",
"dddddddd-ed84-4e49-b5df-a9d117bd731f",
"eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
]
],
"trp_link_latency": [
[0, 50, 100, 150, 200],
[0, 0, 100, 150, 200],
[0, 0, 0, 150, 200],
[0, 0, 0, 0, 200],
[0, 0, 0, 0, 0],
],
"trp_link_jitter": [
[0, 5, 10, 15, 20],
[0, 0, 10, 15, 20],
[0, 0, 0, 15, 20],
[0, 0, 0, 0, 20],
[0, 0, 0, 0, 0],
],
"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],
],
"ns_desc": [
{"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
{"vnf_id": "two", "vnf_price_per_vim": [20, 21, 22, 23, 24]},
{"vnf_id": "three", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
{"vnf_id": "four", "vnf_price_per_vim": [40, 41, 42, 43, 44]},
],
"vld_desc": [
{"cp_refs": ["one", "two"], "latency": 150, "jitter": 30},
{"cp_refs": ["two", "three"], "latency": 140, "jitter": 30},
{"cp_refs": ["three", "four"], "latency": 130, "jitter": 30},
],
"generator_data": {"file": __file__, "time": datetime.datetime.now()},
}
test_ns_placement_data_str_no_vld_constraints = {
"vim_accounts": [
"vim" + vim_account.replace("-", "_")
for vim_account in [
"aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
"bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
"cccccccc-ed84-4e49-b5df-a9d117bd731f",
"dddddddd-ed84-4e49-b5df-a9d117bd731f",
"eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
]
],
"trp_link_latency": [
[0, 50, 100, 150, 200],
[0, 0, 100, 150, 200],
[0, 0, 0, 150, 200],
[0, 0, 0, 0, 200],
[0, 0, 0, 0, 0],
],
"trp_link_jitter": [
[0, 5, 10, 15, 20],
[0, 0, 10, 15, 20],
[0, 0, 0, 15, 20],
[0, 0, 0, 0, 20],
[0, 0, 0, 0, 0],
],
"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],
],
"ns_desc": [
{"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
{"vnf_id": "two", "vnf_price_per_vim": [20, 21, 22, 23, 24]},
{"vnf_id": "three", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
{"vnf_id": "four", "vnf_price_per_vim": [40, 41, 42, 43, 44]},
],
"vld_desc": [
{"cp_refs": ["one", "two"]},
{"cp_refs": ["two", "three"]},
{"cp_refs": ["three", "four"]},
],
"generator_data": {"file": __file__, "time": datetime.datetime.now()},
}
test_ns_placement_data = {
"vim_accounts": [
"vim" + vim_account.replace("-", "_")
for vim_account in [
"aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
"bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
"cccccccc-ed84-4e49-b5df-a9d117bd731f",
"dddddddd-ed84-4e49-b5df-a9d117bd731f",
"eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
]
],
"trp_link_latency": [
[0, 50, 100, 150, 200],
[0, 0, 100, 150, 200],
[0, 0, 0, 150, 200],
[0, 0, 0, 0, 200],
[0, 0, 0, 0, 0],
],
"trp_link_jitter": [
[0, 5, 10, 15, 20],
[0, 0, 10, 15, 20],
[0, 0, 0, 15, 20],
[0, 0, 0, 0, 20],
[0, 0, 0, 0, 0],
],
"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],
],
"ns_desc": [
{"vnf_id": "1", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
{"vnf_id": "2", "vnf_price_per_vim": [20, 21, 22, 23, 24]},
{"vnf_id": "3", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
{"vnf_id": "4", "vnf_price_per_vim": [40, 41, 42, 43, 44]},
],
"vld_desc": [
{"cp_refs": ["1", "2"], "latency": 150, "jitter": 30},
{"cp_refs": ["2", "3"], "latency": 140, "jitter": 30},
{"cp_refs": ["3", "4"], "latency": 130, "jitter": 30},
],
"generator_data": {"file": __file__, "time": datetime.datetime.now()},
}
test_ns_placement_data_w_pinning = {
"vim_accounts": [
"vim" + vim_account.replace("-", "_")
for vim_account in [
"aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
"bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
"cccccccc-ed84-4e49-b5df-a9d117bd731f",
"dddddddd-ed84-4e49-b5df-a9d117bd731f",
"eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
]
],
"trp_link_latency": [
[0, 50, 100, 150, 200],
[0, 0, 100, 150, 200],
[0, 0, 0, 150, 200],
[0, 0, 0, 0, 200],
[0, 0, 0, 0, 0],
],
"trp_link_jitter": [
[0, 5, 10, 15, 20],
[0, 0, 10, 15, 20],
[0, 0, 0, 15, 20],
[0, 0, 0, 0, 20],
[0, 0, 0, 0, 0],
],
"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],
],
"ns_desc": [
{"vnf_id": "1", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
{
"vnf_id": "2",
"vnf_price_per_vim": [20, 21, 22, 23, 24],
"vim_account": "vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87",
},
{"vnf_id": "3", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
{
"vnf_id": "4",
"vnf_price_per_vim": [40, 41, 42, 43, 44],
"vim_account": "vimcccccccc_ed84_4e49_b5df_a9d117bd731f",
},
],
"vld_desc": [
{"cp_refs": ["1", "2"], "latency": 150, "jitter": 30},
{"cp_refs": ["2", "3"], "latency": 140, "jitter": 30},
{"cp_refs": ["3", "4"], "latency": 130, "jitter": 30},
],
"generator_data": {"file": __file__, "time": datetime.datetime.now()},
}
test_ns_placement_data_w_pinning_str = {
"vim_accounts": [
"vim" + vim_account.replace("-", "_")
for vim_account in [
"aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
"bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
"cccccccc-ed84-4e49-b5df-a9d117bd731f",
"dddddddd-ed84-4e49-b5df-a9d117bd731f",
"eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
]
],
"trp_link_latency": [
[0, 50, 100, 150, 200],
[0, 0, 100, 150, 200],
[0, 0, 0, 150, 200],
[0, 0, 0, 0, 200],
[0, 0, 0, 0, 0],
],
"trp_link_jitter": [
[0, 5, 10, 15, 20],
[0, 0, 10, 15, 20],
[0, 0, 0, 15, 20],
[0, 0, 0, 0, 20],
[0, 0, 0, 0, 0],
],
"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],
],
"ns_desc": [
{"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]},
{
"vnf_id": "two",
"vnf_price_per_vim": [20, 21, 22, 23, 24],
"vim_account": "vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87",
},
{"vnf_id": "three", "vnf_price_per_vim": [70, 71, 72, 73, 74]},
{
"vnf_id": "four",
"vnf_price_per_vim": [40, 41, 42, 43, 44],
"vim_account": "vimcccccccc_ed84_4e49_b5df_a9d117bd731f",
},
],
"vld_desc": [
{"cp_refs": ["one", "two"], "latency": 150, "jitter": 30},
{"cp_refs": ["two", "three"], "latency": 140, "jitter": 30},
{"cp_refs": ["three", "four"], "latency": 130, "jitter": 30},
],
"generator_data": {"file": __file__, "time": datetime.datetime.now()},
}
test_ns_placement_data_str_no_vld = {
"vim_accounts": [
"vim" + vim_account.replace("-", "_")
for vim_account in [
"aaaaaaaa-38f5-438d-b8ee-3f93b3531f87",
"bbbbbbbb-38f5-438d-b8ee-3f93b3531f87",
"cccccccc-ed84-4e49-b5df-a9d117bd731f",
"dddddddd-ed84-4e49-b5df-a9d117bd731f",
"eeeeeeee-38f5-438d-b8ee-3f93b3531f87",
]
],
"trp_link_latency": [
[0, 50, 100, 150, 200],
[0, 0, 100, 150, 200],
[0, 0, 0, 150, 200],
[0, 0, 0, 0, 200],
[0, 0, 0, 0, 0],
],
"trp_link_jitter": [
[0, 5, 10, 15, 20],
[0, 0, 10, 15, 20],
[0, 0, 0, 15, 20],
[0, 0, 0, 0, 20],
[0, 0, 0, 0, 0],
],
"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],
],
"ns_desc": [{"vnf_id": "one", "vnf_price_per_vim": [50, 51, 52, 53, 54]}],
"vld_desc": [],
"generator_data": {"file": __file__, "time": datetime.datetime.now()},
}
expected_model_fragment = """
%This is the NETWORK RESOURCE MODEL
enum Vims = {
vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
|0,0,100,150,200,
|0,0,0,150,200,
|0,0,0,0,200,
|0,0,0,0,0,
|]; % Transport link latency between data centers
array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
|0,0,10,15,20,
|0,0,0,15,20,
|0,0,0,0,20,
|0,0,0,0,0,
|]; % Transport link jitter between data centers
array[Vims, Vims] of int: 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,
|]; % Transport link price list
array[Vims] of int: vim_price_list_1 = [50,51,52,53,54];
array[Vims] of int: vim_price_list_2 = [20,21,22,23,24];
array[Vims] of int: vim_price_list_3 = [70,71,72,73,74];
array[Vims] of int: vim_price_list_4 = [40,41,42,43,44];
% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
% NOTE. This is not applicable in OSM Release 7
% This is the SERVICE CONSUMPTION MODEL
% These are the variables, i.e. which DC to select for each VNF
var Vims: VNF1;
var Vims: VNF2;
var Vims: VNF3;
var Vims: VNF4;
% These are the set of rules for selecting DCs to VNFs
constraint trp_link_latency[VNF1, VNF2] <= 150;
constraint trp_link_latency[VNF2, VNF3] <= 140;
constraint trp_link_latency[VNF3, VNF4] <= 130;
constraint trp_link_jitter[VNF1, VNF2] <= 30;
constraint trp_link_jitter[VNF2, VNF3] <= 30;
constraint trp_link_jitter[VNF3, VNF4] <= 30;
% Calculate the cost for VNFs and cost for transport link and total cost
var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+
trp_link_price_list[VNF2, VNF3]+
trp_link_price_list[VNF3, VNF4];
var int: used_vim_cost =vim_price_list_1[VNF1]+
vim_price_list_2[VNF2]+
vim_price_list_3[VNF3]+
vim_price_list_4[VNF4];
var int: total_cost = used_transport_cost + used_vim_cost;
solve minimize total_cost;
"""
expected_model_fragment_str = """
%This is the NETWORK RESOURCE MODEL
enum Vims = {
vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
|0,0,100,150,200,
|0,0,0,150,200,
|0,0,0,0,200,
|0,0,0,0,0,
|]; % Transport link latency between data centers
array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
|0,0,10,15,20,
|0,0,0,15,20,
|0,0,0,0,20,
|0,0,0,0,0,
|]; % Transport link jitter between data centers
array[Vims, Vims] of int: 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,
|]; % Transport link price list
array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
% NOTE. This is not applicable in OSM Release 7
% This is the SERVICE CONSUMPTION MODEL
% These are the variables, i.e. which DC to select for each VNF
var Vims: VNFone;
var Vims: VNFtwo;
var Vims: VNFthree;
var Vims: VNFfour;
% These are the set of rules for selecting DCs to VNFs
constraint trp_link_latency[VNFone, VNFtwo] <= 150;
constraint trp_link_latency[VNFtwo, VNFthree] <= 140;
constraint trp_link_latency[VNFthree, VNFfour] <= 130;
constraint trp_link_jitter[VNFone, VNFtwo] <= 30;
constraint trp_link_jitter[VNFtwo, VNFthree] <= 30;
constraint trp_link_jitter[VNFthree, VNFfour] <= 30;
% Calculate the cost for VNFs and cost for transport link and total cost
var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
trp_link_price_list[VNFtwo, VNFthree]+
trp_link_price_list[VNFthree, VNFfour];
var int: used_vim_cost =vim_price_list_one[VNFone]+
vim_price_list_two[VNFtwo]+
vim_price_list_three[VNFthree]+
vim_price_list_four[VNFfour];
var int: total_cost = used_transport_cost + used_vim_cost;
solve minimize total_cost;
"""
expected_model_fragment_str_no_vld_constraints = """
%This is the NETWORK RESOURCE MODEL
enum Vims = {
vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
|0,0,100,150,200,
|0,0,0,150,200,
|0,0,0,0,200,
|0,0,0,0,0,
|]; % Transport link latency between data centers
array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
|0,0,10,15,20,
|0,0,0,15,20,
|0,0,0,0,20,
|0,0,0,0,0,
|]; % Transport link jitter between data centers
array[Vims, Vims] of int: 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,
|]; % Transport link price list
array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
% NOTE. This is not applicable in OSM Release 7
% This is the SERVICE CONSUMPTION MODEL
% These are the variables, i.e. which DC to select for each VNF
var Vims: VNFone;
var Vims: VNFtwo;
var Vims: VNFthree;
var Vims: VNFfour;
% These are the set of rules for selecting DCs to VNFs
% Calculate the cost for VNFs and cost for transport link and total cost
var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
trp_link_price_list[VNFtwo, VNFthree]+
trp_link_price_list[VNFthree, VNFfour];
var int: used_vim_cost =vim_price_list_one[VNFone]+
vim_price_list_two[VNFtwo]+
vim_price_list_three[VNFthree]+
vim_price_list_four[VNFfour];
var int: total_cost = used_transport_cost + used_vim_cost;
solve minimize total_cost;
"""
expected_model_fragment_w_pinning = """
%This is the NETWORK RESOURCE MODEL
enum Vims = {
vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
|0,0,100,150,200,
|0,0,0,150,200,
|0,0,0,0,200,
|0,0,0,0,0,
|]; % Transport link latency between data centers
array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
|0,0,10,15,20,
|0,0,0,15,20,
|0,0,0,0,20,
|0,0,0,0,0,
|]; % Transport link jitter between data centers
array[Vims, Vims] of int: 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,
|]; % Transport link price list
array[Vims] of int: vim_price_list_1 = [50,51,52,53,54];
array[Vims] of int: vim_price_list_2 = [20,21,22,23,24];
array[Vims] of int: vim_price_list_3 = [70,71,72,73,74];
array[Vims] of int: vim_price_list_4 = [40,41,42,43,44];
% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
% NOTE. This is not applicable in OSM Release 7
% This is the SERVICE CONSUMPTION MODEL
% These are the variables, i.e. which DC to select for each VNF
var Vims: VNF1;
Vims: VNF2 = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
var Vims: VNF3;
Vims: VNF4 = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
% These are the set of rules for selecting DCs to VNFs
constraint trp_link_latency[VNF1, VNF2] <= 150;
constraint trp_link_latency[VNF2, VNF3] <= 140;
constraint trp_link_latency[VNF3, VNF4] <= 130;
constraint trp_link_jitter[VNF1, VNF2] <= 30;
constraint trp_link_jitter[VNF2, VNF3] <= 30;
constraint trp_link_jitter[VNF3, VNF4] <= 30;
% Calculate the cost for VNFs and cost for transport link and total cost
var int: used_transport_cost =trp_link_price_list[VNF1, VNF2]+
trp_link_price_list[VNF2, VNF3]+
trp_link_price_list[VNF3, VNF4];
var int: used_vim_cost =vim_price_list_1[VNF1]+
vim_price_list_2[VNF2]+
vim_price_list_3[VNF3]+
vim_price_list_4[VNF4];
var int: total_cost = used_transport_cost + used_vim_cost;
solve minimize total_cost;
"""
expected_model_fragment_w_pinning_str = """
%This is the NETWORK RESOURCE MODEL
enum Vims = {
vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
|0,0,100,150,200,
|0,0,0,150,200,
|0,0,0,0,200,
|0,0,0,0,0,
|]; % Transport link latency between data centers
array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
|0,0,10,15,20,
|0,0,0,15,20,
|0,0,0,0,20,
|0,0,0,0,0,
|]; % Transport link jitter between data centers
array[Vims, Vims] of int: 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,
|]; % Transport link price list
array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
array[Vims] of int: vim_price_list_two = [20,21,22,23,24];
array[Vims] of int: vim_price_list_three = [70,71,72,73,74];
array[Vims] of int: vim_price_list_four = [40,41,42,43,44];
% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
% NOTE. This is not applicable in OSM Release 7
% This is the SERVICE CONSUMPTION MODEL
% These are the variables, i.e. which DC to select for each VNF
var Vims: VNFone;
Vims: VNFtwo = vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87;
var Vims: VNFthree;
Vims: VNFfour = vimcccccccc_ed84_4e49_b5df_a9d117bd731f;
% These are the set of rules for selecting DCs to VNFs
constraint trp_link_latency[VNFone, VNFtwo] <= 150;
constraint trp_link_latency[VNFtwo, VNFthree] <= 140;
constraint trp_link_latency[VNFthree, VNFfour] <= 130;
constraint trp_link_jitter[VNFone, VNFtwo] <= 30;
constraint trp_link_jitter[VNFtwo, VNFthree] <= 30;
constraint trp_link_jitter[VNFthree, VNFfour] <= 30;
% Calculate the cost for VNFs and cost for transport link and total cost
var int: used_transport_cost =trp_link_price_list[VNFone, VNFtwo]+
trp_link_price_list[VNFtwo, VNFthree]+
trp_link_price_list[VNFthree, VNFfour];
var int: used_vim_cost =vim_price_list_one[VNFone]+
vim_price_list_two[VNFtwo]+
vim_price_list_three[VNFthree]+
vim_price_list_four[VNFfour];
var int: total_cost = used_transport_cost + used_vim_cost;
solve minimize total_cost;
"""
expected_model_fragment_str_no_vld = """
%This is the NETWORK RESOURCE MODEL
enum Vims = {
vimaaaaaaaa_38f5_438d_b8ee_3f93b3531f87,
vimbbbbbbbb_38f5_438d_b8ee_3f93b3531f87,
vimcccccccc_ed84_4e49_b5df_a9d117bd731f,
vimdddddddd_ed84_4e49_b5df_a9d117bd731f,
vimeeeeeeee_38f5_438d_b8ee_3f93b3531f87}; % The vim-accounts
array[Vims, Vims] of int: trp_link_latency = [|0,50,100,150,200,
|0,0,100,150,200,
|0,0,0,150,200,
|0,0,0,0,200,
|0,0,0,0,0,
|]; % Transport link latency between data centers
array[Vims, Vims] of int: trp_link_jitter = [|0,5,10,15,20,
|0,0,10,15,20,
|0,0,0,15,20,
|0,0,0,0,20,
|0,0,0,0,0,
|]; % Transport link jitter between data centers
array[Vims, Vims] of int: 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,
|]; % Transport link price list
array[Vims] of int: vim_price_list_one = [50,51,52,53,54];
% This is the NETWORK BASIC LOAD MODEL (CONSUMED)
% NOTE. This is not applicable in OSM Release 7
% This is the SERVICE CONSUMPTION MODEL
% These are the variables, i.e. which DC to select for each VNF
var Vims: VNFone;
% These are the set of rules for selecting DCs to VNFs
% Calculate the cost for VNFs and cost for transport link and total cost
var int: used_transport_cost =0;
var int: used_vim_cost =vim_price_list_one[VNFone];
var int: total_cost = used_transport_cost + used_vim_cost;
solve minimize total_cost;
"""
class TestMznModelGenerator(TestCase):
def test_create_model(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str)
# so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
self.assertTrue(
expected_model_fragment_str.replace("\n", "")
in mzn_model.replace("\n", ""),
"faulty model generated",
)
def test_create_model_no_vld_constraints(self):
"""
instantiate w/o constraints in nsd or order params has a valid model
:return:
"""
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str_no_vld_constraints)
# so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
self.assertTrue(
expected_model_fragment_str_no_vld_constraints.replace("\n", "")
in mzn_model.replace("\n", ""),
"faulty model generated",
)
def test_create_model_w_pinning(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
# so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
self.assertTrue(
expected_model_fragment_w_pinning_str.replace("\n", "")
in mzn_model.replace("\n", ""),
"faulty model generated",
)
def test_create_model_no_vld(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str_no_vld)
# so asserting exact content is difficult due to the datetime.now(), therefore we ignore the first lines
self.assertTrue(
expected_model_fragment_str_no_vld.replace("\n", "")
in mzn_model.replace("\n", ""),
"faulty model generated",
)
def test__load_jinja_template(self):
"""
add other test to check exception if template not loaded (e.g. invalid template name,
perhaps also valid name but invalid content (in case jinja2 detects such things))
"""
mg = MznModelGenerator(logging.getLogger(__name__))
template = mg._load_jinja_template() # Note we use the default template
self.assertTrue(
isinstance(template, Template), "failed to load jinja2 template"
)
def test_vim_account_replace(self):
mg = MznModelGenerator(logging.getLogger(__name__))
nspd = test_ns_placement_data_str
mzn_model = mg.create_model(nspd)
expected = (
"%This is the NETWORK RESOURCE MODEL" + "\n" + "enum Vims = {" + "\n"
)
for val in test_ns_placement_data_str["vim_accounts"]:
expected = expected + val.replace("-", "_") + ",\n"
expected = expected[:-2] + "}; % The vim-accounts"
res = re.findall(expected, mzn_model)
self.assertEqual(1, len(res), "vim accounts didnt replace from - to _")
def test_trp_link_price_list(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str)
expected = "array\\[Vims, Vims\\] of int: trp_link_price_list = \\["
for price_list in test_ns_placement_data_str["trp_link_price_list"]:
expected = (
expected + "\\|" + (str(price_list)[1:-1]).replace(" ", "") + ",\n"
)
expected = expected + "\\|\\]; % Transport link price list"
res = re.findall(expected, mzn_model)
self.assertEqual(1, len(res), "price list is not correct")
def test_link_latency(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str)
expected = "array\\[Vims, Vims\\] of int: trp_link_latency = \\["
for link_latency in test_ns_placement_data_str["trp_link_latency"]:
expected = (
expected + "\\|" + (str(link_latency)[1:-1]).replace(" ", "") + ",\n"
)
expected = expected + "\\|\\]; % Transport link latency between data centers"
res = re.findall(expected, mzn_model)
self.assertEqual(1, len(res), "trp_link_latency values is not correct")
def test_link_jitter(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str)
expected = "array\\[Vims, Vims\\] of int: trp_link_jitter = \\["
for link_jitter in test_ns_placement_data_str["trp_link_jitter"]:
expected = (
expected + "\\|" + (str(link_jitter)[1:-1]).replace(" ", "") + ",\n"
)
expected = expected + "\\|\\]; % Transport link jitter between data centers"
res = re.findall(expected, mzn_model)
self.assertEqual(1, len(res), "trp_link_jitter values is not correct")
def test_price_per_vim(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
expected = ""
for price_list in test_ns_placement_data_w_pinning_str["ns_desc"]:
expected += (
"array\\[Vims\\] of int: vim_price_list_"
+ price_list.get("vnf_id")
+ " = "
)
temp = str(price_list.get("vnf_price_per_vim"))[1:-1].replace(" ", "")
expected += "\\[" + temp + "\\];\n"
res = re.findall(expected, mzn_model)
self.assertEqual(1, len(res), "mzn_model contains pinning")
def test_pinning(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str)
expected = ""
for pin_list in test_ns_placement_data_str["ns_desc"]:
if pin_list.get("vim_account"):
expected += (
"Vims: VNF"
+ pin_list.get("vnf_id")
+ " = "
+ pin_list.get("vim_account")
+ ";\n"
)
else:
expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
res = re.findall(expected, mzn_model)
self.assertEqual(1, len(res), "mzn_model has no pinning")
def test__without_pinning(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_w_pinning_str)
expected = ""
for pin_list in test_ns_placement_data_w_pinning_str["ns_desc"]:
if pin_list.get("vim_account"):
expected += (
"Vims: VNF"
+ pin_list.get("vnf_id")
+ " = "
+ pin_list.get("vim_account")
+ ";\n"
)
else:
expected += "var Vims: VNF" + pin_list.get("vnf_id") + ";\n"
res = re.findall(expected, mzn_model)
self.assertEqual(1, len(res), "mzn_model contains pinning")
def test__without_constraints_for_jitter_and_latency(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str_no_vld_constraints)
expected_latency = "constraint trp_link_latency"
expected_jitter = "constraint trp_link_jitter"
latency_or_jitter_was_found = 0
for l_o_j in test_ns_placement_data_str_no_vld_constraints["vld_desc"]:
if l_o_j.get("latency") or l_o_j.get("jitter"):
latency_or_jitter_was_found = 1
res_latency = re.findall(expected_latency, mzn_model)
res_jitter = re.findall(expected_jitter, mzn_model)
self.assertEqual(
0,
latency_or_jitter_was_found,
"Jitter or latency was found in the test input",
)
self.assertEqual(
0, len(res_latency), "constraint trp_link_latency was found in mzn_model"
)
self.assertEqual(
0, len(res_jitter), "constraint trp_link_latency was found in mzn_model"
)
def test__constraints_for_jitter_and_latency(self):
mg = MznModelGenerator(logging.getLogger(__name__))
mzn_model = mg.create_model(test_ns_placement_data_str)
expected_latency = ""
expected_jitter = ""
latency_or_jitter_was_found = 0
for l_o_j in test_ns_placement_data_str["vld_desc"]:
if not (l_o_j.get("latency") or l_o_j.get("jitter")):
latency_or_jitter_was_found = 1
expected_latency += (
"constraint trp_link_latency"
+ "\\[VNF"
+ l_o_j.get("cp_refs")[0]
+ ", VNF"
+ l_o_j.get("cp_refs")[1]
+ "\\] \\<= "
+ str(l_o_j.get("latency"))
+ ";\n\n"
)
expected_jitter += (
"constraint trp_link_jitter"
+ "\\[VNF"
+ l_o_j.get("cp_refs")[0]
+ ", VNF"
+ l_o_j.get("cp_refs")[1]
+ "\\] \\<= "
+ str(l_o_j.get("jitter"))
+ ";\n\n"
)
res = re.findall(expected_latency + expected_jitter, mzn_model)
self.assertEqual(
0,
latency_or_jitter_was_found,
"Jitter or latency was not found in the test input",
)
self.assertEqual(1, len(res), "faulty model generated")