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