ca6e9b529d5621343ce22d61c6448db6d979bf8d
[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 json
26 import logging
27 import os
28 import pytest
29 import shlex
30 import shutil
31 import subprocess
32 import time
33 import uuid
34
35 from gi.repository import (
36 NsdYang,
37 NsrYang,
38 RwNsrYang,
39 VnfrYang,
40 VldYang,
41 RwVnfdYang,
42 RwLaunchpadYang,
43 RwBaseYang
44 )
45
46 import rift.auto.mano
47
48 logging.basicConfig(level=logging.DEBUG)
49 logger = logging.getLogger(__name__)
50
51 @pytest.fixture(scope='module')
52 def multi_vm_vnf_nsd_package_file(request, package_gen_script, mvv_descr_dir, package_dir):
53 pkg_cmd = "{pkg_scr} --descriptor-type='nsd' --format='xml' --infile='{infile}' --outdir='{outdir}'".format(
54 pkg_scr=package_gen_script,
55 infile=os.path.join(mvv_descr_dir, 'nsd/xml/multivm_tg_ts_config_nsd.xml'),
56 outdir=package_dir)
57 pkg_file = os.path.join(package_dir, 'multivm_tg_ts_config_nsd.tar.gz')
58 logger.debug("Generating NSD package: %s", pkg_file)
59 command = shlex.split(pkg_cmd)
60 print("Running the command arguments: %s" % command)
61 command = [package_gen_script,
62 "--descriptor-type", "nsd",
63 "--format", "xml",
64 "--infile", "%s" % os.path.join(mvv_descr_dir, 'vnfd/xml/multivm_tg_ts_config_nsd.xml'),
65 "--outdir", "%s" % package_dir]
66 print("Running new command arguments: %s" % command)
67 subprocess.check_call(shlex.split(pkg_cmd))
68 return pkg_file
69
70 def create_nsr(nsd_id, input_param_list, cloud_account_name):
71 """
72 Create the NSR record object
73
74 Arguments:
75 nsd_id - NSD id
76 input_param_list - list of input-parameter objects
77
78 Return:
79 NSR object
80 """
81 nsr = RwNsrYang.YangData_Nsr_NsInstanceConfig_Nsr()
82
83 nsr.id = str(uuid.uuid4())
84 nsr.name = rift.auto.mano.resource_name(nsr.id)
85 nsr.short_name = "nsr_short_name"
86 nsr.description = "This is a description"
87 nsr.nsd_ref = nsd_id
88 nsr.admin_status = "ENABLED"
89 nsr.input_parameter.extend(input_param_list)
90 nsr.cloud_account = cloud_account_name
91
92 return nsr
93
94
95 def upload_descriptor(logger, descriptor_file, host="127.0.0.1"):
96 curl_cmd = 'curl --insecure -F "descriptor=@{file}" http://{host}:4567/api/upload '.format(
97 file=descriptor_file,
98 host=host,
99 )
100 logger.debug("Uploading descriptor %s using cmd: %s", descriptor_file, curl_cmd)
101 stdout = subprocess.check_output(shlex.split(curl_cmd), universal_newlines=True)
102
103 json_out = json.loads(stdout)
104 transaction_id = json_out["transaction_id"]
105
106 return transaction_id
107
108
109 class DescriptorOnboardError(Exception):
110 pass
111
112
113 def wait_onboard_transaction_finished(logger, transaction_id, timeout=10, host="127.0.0.1"):
114 logger.info("Waiting for onboard trans_id %s to complete", transaction_id)
115 def check_status_onboard_status():
116 uri = 'http://%s:4567/api/upload/%s/state' % (host, transaction_id)
117 curl_cmd = 'curl --insecure {uri}'.format(
118 uri=uri
119 )
120 return subprocess.check_output(shlex.split(curl_cmd), universal_newlines=True)
121
122 elapsed = 0
123 start = time.time()
124 while elapsed < timeout:
125 reply = check_status_onboard_status()
126 state = json.loads(reply)
127 if state["status"] == "success":
128 break
129
130 if state["status"] != "pending":
131 raise DescriptorOnboardError(state)
132
133 time.sleep(1)
134 elapsed = time.time() - start
135
136 if state["status"] != "success":
137 raise DescriptorOnboardError(state)
138
139 logger.info("Descriptor onboard was successful")
140
141
142 @pytest.mark.setup('multivmvnf')
143 @pytest.mark.depends('launchpad')
144 @pytest.mark.incremental
145 class TestMultiVmVnfTrafgenApp(object):
146 pkg_dir = None
147 @classmethod
148 def teardown_class(cls):
149 """ remove the temporary directory contains the descriptor packages
150 """
151 logger.debug("Removing the temporary package directory: %s", cls.pkg_dir)
152 if not cls.pkg_dir is None:
153 shutil.rmtree(cls.pkg_dir)
154
155 def test_onboard_trafgen_vnfd(self, logger, launchpad_host, vnfd_proxy, trafgen_vnfd_package_file):
156 TestMultiVmVnfTrafgenApp.pkg_dir = os.path.dirname(trafgen_vnfd_package_file)
157 logger.info("Onboarding trafgen vnfd package: %s", trafgen_vnfd_package_file)
158 trans_id = upload_descriptor(logger, trafgen_vnfd_package_file, launchpad_host)
159 wait_onboard_transaction_finished(logger, trans_id, host=launchpad_host)
160
161 catalog = vnfd_proxy.get_config('/vnfd-catalog')
162 vnfds = catalog.vnfd
163 assert len(vnfds) == 1, "There should only be a single vnfd"
164 vnfd = vnfds[0]
165 assert vnfd.name == "multivm_trafgen_vnfd"
166
167 def test_onboard_trafsink_vnfd(self, logger, launchpad_host, vnfd_proxy, trafsink_vnfd_package_file):
168 TestMultiVmVnfTrafgenApp.pkg_dir = os.path.dirname(trafsink_vnfd_package_file)
169 logger.info("Onboarding trafsink vnfd package: %s", trafsink_vnfd_package_file)
170 trans_id = upload_descriptor(logger, trafsink_vnfd_package_file, launchpad_host)
171 wait_onboard_transaction_finished(logger, trans_id, host=launchpad_host)
172
173 catalog = vnfd_proxy.get_config('/vnfd-catalog')
174 vnfds = catalog.vnfd
175 assert len(vnfds) == 2, "There should be two vnfds"
176 assert "multivm_trafsink_vnfd" in [vnfds[0].name, vnfds[1].name]
177
178 def test_onboard_multi_vm_vnf_nsd(self, logger, launchpad_host, nsd_proxy, multi_vm_vnf_nsd_package_file):
179 logger.info("Onboarding tg_ts nsd package: %s", multi_vm_vnf_nsd_package_file)
180 trans_id = upload_descriptor(logger, multi_vm_vnf_nsd_package_file, launchpad_host)
181 wait_onboard_transaction_finished(logger, trans_id, host=launchpad_host)
182
183 catalog = nsd_proxy.get_config('/nsd-catalog')
184 nsds = catalog.nsd
185 assert len(nsds) == 1, "There should only be a single nsd"
186 nsd = nsds[0]
187 assert nsd.name == "multivm_tg_ts_config_nsd"
188
189 def test_instantiate_multi_vm_vnf_nsr(self, logger, nsd_proxy, nsr_proxy, rwnsr_proxy, base_proxy, cloud_account_name):
190
191 def verify_input_parameters (running_config, config_param):
192 """
193 Verify the configured parameter set against the running configuration
194 """
195 for run_input_param in running_config.input_parameter:
196 if (input_param.xpath == config_param.xpath and
197 input_param.value == config_param.value):
198 return True
199
200 assert False, ("Verification of configured input parameters: { xpath:%s, value:%s} "
201 "is unsuccessful.\nRunning configuration: %s" % (config_param.xpath,
202 config_param.value,
203 running_nsr_config.input_parameter))
204
205 catalog = nsd_proxy.get_config('/nsd-catalog')
206 nsd = catalog.nsd[0]
207
208 input_parameters = []
209 descr_xpath = "/nsd:nsd-catalog/nsd:nsd[nsd:id='%s']/nsd:description" % nsd.id
210 descr_value = "New NSD Description"
211 in_param_id = str(uuid.uuid4())
212
213 input_param_1= NsrYang.YangData_Nsr_NsInstanceConfig_Nsr_InputParameter(
214 xpath=descr_xpath,
215 value=descr_value)
216
217 input_parameters.append(input_param_1)
218
219 nsr = create_nsr(nsd.id, input_parameters, cloud_account_name)
220
221 logger.info("Instantiating the Network Service")
222 rwnsr_proxy.create_config('/ns-instance-config/nsr', nsr)
223
224 nsr_opdata = rwnsr_proxy.get('/ns-instance-opdata')
225 nsrs = nsr_opdata.nsr
226
227 # Verify the input parameter configuration
228 running_config = rwnsr_proxy.get_config("/ns-instance-config/nsr[id='%s']" % nsr.id)
229 for input_param in input_parameters:
230 verify_input_parameters(running_config, input_param)
231
232 assert len(nsrs) == 1
233 assert nsrs[0].ns_instance_config_ref == nsr.id
234
235 xpath = "/ns-instance-opdata/nsr[ns-instance-config-ref='{}']/operational-status".format(nsr.id)
236 rwnsr_proxy.wait_for(xpath, "running", fail_on=['failed'], timeout=360)
237
238
239 @pytest.mark.teardown('multivmvnf')
240 @pytest.mark.depends('launchpad')
241 @pytest.mark.incremental
242 class TestMultiVmVnfTrafgenAppTeardown(object):
243 def test_terminate_nsr(self, nsr_proxy, vnfr_proxy, rwnsr_proxy, logger):
244 """
245 Terminate the instance and check if the record is deleted.
246
247 Asserts:
248 1. NSR record is deleted from instance-config.
249
250 """
251 logger.debug("Terminating Multi VM VNF's NSR")
252
253 nsr_path = "/ns-instance-config"
254 nsr = rwnsr_proxy.get_config(nsr_path)
255
256 ping_pong = nsr.nsr[0]
257 rwnsr_proxy.delete_config("/ns-instance-config/nsr[id='{}']".format(ping_pong.id))
258 time.sleep(30)
259
260
261 def test_delete_records(self, nsd_proxy, vnfd_proxy):
262 """Delete the NSD & VNFD records
263
264 Asserts:
265 The records are deleted.
266 """
267 nsds = nsd_proxy.get("/nsd-catalog/nsd", list_obj=True)
268 for nsd in nsds.nsd:
269 xpath = "/nsd-catalog/nsd[id='{}']".format(nsd.id)
270 nsd_proxy.delete_config(xpath)
271
272 vnfds = vnfd_proxy.get("/vnfd-catalog/vnfd", list_obj=True)
273 for vnfd_record in vnfds.vnfd:
274 xpath = "/vnfd-catalog/vnfd[id='{}']".format(vnfd_record.id)
275 vnfd_proxy.delete_config(xpath)
276
277 time.sleep(5)
278 nsds = nsd_proxy.get("/nsd-catalog/nsd", list_obj=True)
279 assert nsds is None or len(nsds.nsd) == 0
280
281 vnfds = vnfd_proxy.get("/vnfd-catalog/vnfd", list_obj=True)
282 assert vnfds is None or len(vnfds.vnfd) == 0