update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / rwlaunchpad / ra / pytest / multivm_vnf / test_multi_vm_vnf_trafgen.py
1 #!/usr/bin/env python
2 """
3 #
4 # Copyright 2016 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18
19 @file test_multi_vm_vnf_trafgen.py
20 @author Karun Ganesharatnam (karun.ganesharatnam@riftio.com)
21 @date 03/16/2016
22 @brief Scriptable load-balancer test with multi-vm VNFs
23 """
24
25 import gi
26 import json
27 import logging
28 import os
29 import pytest
30 import shlex
31 import shutil
32 import subprocess
33 import time
34 import uuid
35
36 from gi.repository import (
37 RwProjectNsdYang,
38 NsrYang,
39 RwNsrYang,
40 VnfrYang,
41 VldYang,
42 RwProjectVnfdYang,
43 RwLaunchpadYang,
44 RwBaseYang
45 )
46 gi.require_version('RwKeyspec', '1.0')
47 from gi.repository.RwKeyspec import quoted_key
48
49 import rift.auto.mano
50
51 logging.basicConfig(level=logging.DEBUG)
52 logger = logging.getLogger(__name__)
53
54 @pytest.fixture(scope='module')
55 def multi_vm_vnf_nsd_package_file(request, package_gen_script, mvv_descr_dir, package_dir):
56 pkg_cmd = "{pkg_scr} --descriptor-type='nsd' --format='xml' --infile='{infile}' --outdir='{outdir}'".format(
57 pkg_scr=package_gen_script,
58 infile=os.path.join(mvv_descr_dir, 'nsd/xml/multivm_tg_ts_config_nsd.xml'),
59 outdir=package_dir)
60 pkg_file = os.path.join(package_dir, 'multivm_tg_ts_config_nsd.tar.gz')
61 logger.debug("Generating NSD package: %s", pkg_file)
62 command = shlex.split(pkg_cmd)
63 print("Running the command arguments: %s" % command)
64 command = [package_gen_script,
65 "--descriptor-type", "nsd",
66 "--format", "xml",
67 "--infile", "%s" % os.path.join(mvv_descr_dir, 'vnfd/xml/multivm_tg_ts_config_nsd.xml'),
68 "--outdir", "%s" % package_dir]
69 print("Running new command arguments: %s" % command)
70 subprocess.check_call(shlex.split(pkg_cmd))
71 return pkg_file
72
73 def create_nsr(nsd_id, input_param_list, cloud_account_name):
74 """
75 Create the NSR record object
76
77 Arguments:
78 nsd_id - NSD id
79 input_param_list - list of input-parameter objects
80
81 Return:
82 NSR object
83 """
84 nsr = RwNsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr()
85
86 nsr.id = str(uuid.uuid4())
87 nsr.name = rift.auto.mano.resource_name(nsr.id)
88 nsr.short_name = "nsr_short_name"
89 nsr.description = "This is a description"
90 nsr.nsd_ref = nsd_id
91 nsr.admin_status = "ENABLED"
92 nsr.input_parameter.extend(input_param_list)
93 nsr.datacenter = cloud_account_name
94
95 return nsr
96
97
98 def upload_descriptor(logger, descriptor_file, host="127.0.0.1"):
99 curl_cmd = 'curl --insecure -F "descriptor=@{file}" http://{host}:4567/api/upload '.format(
100 file=descriptor_file,
101 host=host,
102 )
103 logger.debug("Uploading descriptor %s using cmd: %s", descriptor_file, curl_cmd)
104 stdout = subprocess.check_output(shlex.split(curl_cmd), universal_newlines=True)
105
106 json_out = json.loads(stdout)
107 transaction_id = json_out["transaction_id"]
108
109 return transaction_id
110
111
112 class DescriptorOnboardError(Exception):
113 pass
114
115
116 def wait_onboard_transaction_finished(logger, transaction_id, timeout=10, host="127.0.0.1", project="default"):
117 logger.info("Waiting for onboard trans_id %s to complete", transaction_id)
118 def check_status_onboard_status():
119 uri = 'http://%s:8008/api/operational/project/%s/create-jobs/job/%s' % (host, project, transaction_id)
120 curl_cmd = 'curl --insecure {uri}'.format(
121 uri=uri
122 )
123 return subprocess.check_output(shlex.split(curl_cmd), universal_newlines=True)
124
125 elapsed = 0
126 start = time.time()
127 while elapsed < timeout:
128 reply = check_status_onboard_status()
129 state = json.loads(reply)
130 if state["status"] == "success":
131 break
132
133 if state["status"] != "pending":
134 raise DescriptorOnboardError(state)
135
136 time.sleep(1)
137 elapsed = time.time() - start
138
139 if state["status"] != "success":
140 raise DescriptorOnboardError(state)
141
142 logger.info("Descriptor onboard was successful")
143
144
145 @pytest.mark.setup('multivmvnf')
146 @pytest.mark.depends('launchpad')
147 @pytest.mark.incremental
148 class TestMultiVmVnfTrafgenApp(object):
149 pkg_dir = None
150 @classmethod
151 def teardown_class(cls):
152 """ remove the temporary directory contains the descriptor packages
153 """
154 logger.debug("Removing the temporary package directory: %s", cls.pkg_dir)
155 if not cls.pkg_dir is None:
156 shutil.rmtree(cls.pkg_dir)
157
158 def test_onboard_trafgen_vnfd(self, logger, launchpad_host, vnfd_proxy, trafgen_vnfd_package_file):
159 TestMultiVmVnfTrafgenApp.pkg_dir = os.path.dirname(trafgen_vnfd_package_file)
160 logger.info("Onboarding trafgen vnfd package: %s", trafgen_vnfd_package_file)
161 trans_id = upload_descriptor(logger, trafgen_vnfd_package_file, launchpad_host)
162 wait_onboard_transaction_finished(logger, trans_id, host=launchpad_host)
163
164 catalog = vnfd_proxy.get_config('/rw-project:project[rw-project:name="default"]/vnfd-catalog')
165 vnfds = catalog.vnfd
166 assert len(vnfds) == 1, "There should only be a single vnfd"
167 vnfd = vnfds[0]
168 assert vnfd.name == "multivm_trafgen_vnfd"
169
170 def test_onboard_trafsink_vnfd(self, logger, launchpad_host, vnfd_proxy, trafsink_vnfd_package_file):
171 TestMultiVmVnfTrafgenApp.pkg_dir = os.path.dirname(trafsink_vnfd_package_file)
172 logger.info("Onboarding trafsink vnfd package: %s", trafsink_vnfd_package_file)
173 trans_id = upload_descriptor(logger, trafsink_vnfd_package_file, launchpad_host)
174 wait_onboard_transaction_finished(logger, trans_id, host=launchpad_host)
175
176 catalog = vnfd_proxy.get_config('/rw-project:project[rw-project:name="default"]/vnfd-catalog')
177 vnfds = catalog.vnfd
178 assert len(vnfds) == 2, "There should be two vnfds"
179 assert "multivm_trafsink_vnfd" in [vnfds[0].name, vnfds[1].name]
180
181 def test_onboard_multi_vm_vnf_nsd(self, logger, launchpad_host, nsd_proxy, multi_vm_vnf_nsd_package_file):
182 logger.info("Onboarding tg_ts nsd package: %s", multi_vm_vnf_nsd_package_file)
183 trans_id = upload_descriptor(logger, multi_vm_vnf_nsd_package_file, launchpad_host)
184 wait_onboard_transaction_finished(logger, trans_id, host=launchpad_host)
185
186 catalog = nsd_proxy.get_config('/rw-project:project[rw-project:name="default"]/nsd-catalog')
187 nsds = catalog.nsd
188 assert len(nsds) == 1, "There should only be a single nsd"
189 nsd = nsds[0]
190 assert nsd.name == "multivm_tg_ts_config_nsd"
191
192 def test_instantiate_multi_vm_vnf_nsr(self, logger, nsd_proxy, nsr_proxy, rwnsr_proxy, base_proxy, cloud_account_name):
193
194 def verify_input_parameters (running_config, config_param):
195 """
196 Verify the configured parameter set against the running configuration
197 """
198 for run_input_param in running_config.input_parameter:
199 if (input_param.xpath == config_param.xpath and
200 input_param.value == config_param.value):
201 return True
202
203 assert False, ("Verification of configured input parameters: { xpath:%s, value:%s} "
204 "is unsuccessful.\nRunning configuration: %s" % (config_param.xpath,
205 config_param.value,
206 running_nsr_config.input_parameter))
207
208 catalog = nsd_proxy.get_config('/rw-project:project[rw-project:name="default"]/nsd-catalog')
209 nsd = catalog.nsd[0]
210
211 input_parameters = []
212 descr_xpath = "/rw-project:project/project-nsd:nsd-catalog/project-nsd:nsd[project-nsd:id=%s]/project-nsd:description" % quoted_key(nsd.id)
213 descr_value = "New NSD Description"
214 in_param_id = str(uuid.uuid4())
215
216 input_param_1= NsrYang.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
217 xpath=descr_xpath,
218 value=descr_value)
219
220 input_parameters.append(input_param_1)
221
222 nsr = create_nsr(nsd.id, input_parameters, cloud_account_name)
223
224 logger.info("Instantiating the Network Service")
225 rwnsr_proxy.create_config('/rw-project:project[rw-project:name="default"]/ns-instance-config/nsr', nsr)
226
227 nsr_opdata = rwnsr_proxy.get('/rw-project:project[rw-project:name="default"]/ns-instance-opdata')
228 nsrs = nsr_opdata.nsr
229
230 # Verify the input parameter configuration
231 running_config = rwnsr_proxy.get_config("/rw-project:project[rw-project:name='default']/ns-instance-config/nsr[id=%s]" % quoted_key(nsr.id))
232 for input_param in input_parameters:
233 verify_input_parameters(running_config, input_param)
234
235 assert len(nsrs) == 1
236 assert nsrs[0].ns_instance_config_ref == nsr.id
237
238 xpath = "/rw-project:project[rw-project:name='default']/ns-instance-opdata/nsr[ns-instance-config-ref={}]/operational-status".format(quoted_key(nsr.id))
239 rwnsr_proxy.wait_for(xpath, "running", fail_on=['failed'], timeout=360)
240
241
242 @pytest.mark.teardown('multivmvnf')
243 @pytest.mark.depends('launchpad')
244 @pytest.mark.incremental
245 class TestMultiVmVnfTrafgenAppTeardown(object):
246 def test_terminate_nsr(self, nsr_proxy, vnfr_proxy, rwnsr_proxy, logger):
247 """
248 Terminate the instance and check if the record is deleted.
249
250 Asserts:
251 1. NSR record is deleted from instance-config.
252
253 """
254 logger.debug("Terminating Multi VM VNF's NSR")
255
256 nsr_path = "/rw-project:project[rw-project:name='default']/ns-instance-config"
257 nsr = rwnsr_proxy.get_config(nsr_path)
258
259 ping_pong = nsr.nsr[0]
260 rwnsr_proxy.delete_config("/rw-project:project[rw-project:name='default']/ns-instance-config/nsr[id={}]".format(quoted_key(ping_pong.id)))
261 time.sleep(30)
262
263
264 def test_delete_records(self, nsd_proxy, vnfd_proxy):
265 """Delete the NSD & VNFD records
266
267 Asserts:
268 The records are deleted.
269 """
270 nsds = nsd_proxy.get("/rw-project:project[rw-project:name='default']/nsd-catalog/nsd", list_obj=True)
271 for nsd in nsds.nsd:
272 xpath = "/rw-project:project[rw-project:name='default']/nsd-catalog/nsd[id={}]".format(quoted_key(nsd.id))
273 nsd_proxy.delete_config(xpath)
274
275 vnfds = vnfd_proxy.get("/rw-project:project[rw-project:name='default']/vnfd-catalog/vnfd", list_obj=True)
276 for vnfd_record in vnfds.vnfd:
277 xpath = "/rw-project:project[rw-project:name='default']/vnfd-catalog/vnfd[id={}]".format(quoted_key(vnfd_record.id))
278 vnfd_proxy.delete_config(xpath)
279
280 time.sleep(5)
281 nsds = nsd_proxy.get("/rw-project:project[rw-project:name='default']/nsd-catalog/nsd", list_obj=True)
282 assert nsds is None or len(nsds.nsd) == 0
283
284 vnfds = vnfd_proxy.get("/rw-project:project[rw-project:name='default']/vnfd-catalog/vnfd", list_obj=True)
285 assert vnfds is None or len(vnfds.vnfd) == 0