4 # Copyright 2016 RIFT.IO Inc
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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.
20 @author Varun Prasad (varun.prasad@riftio.com)
21 @brief Onboard descriptors
36 import rift
.auto
.session
39 gi
.require_version('RwNsrYang', '1.0')
40 gi
.require_version('RwProjectVnfdYang', '1.0')
41 gi
.require_version('RwLaunchpadYang', '1.0')
42 gi
.require_version('RwBaseYang', '1.0')
44 from gi
.repository
import (
46 ProjectNsdYang
as NsdYang
,
52 RwProjectVnfdYang
as RwVnfdYang
,
57 logging
.basicConfig(level
=logging
.DEBUG
)
60 @pytest.fixture(scope
='module')
61 def vnfd_proxy(request
, mgmt_session
):
62 return mgmt_session
.proxy(RwVnfdYang
)
64 @pytest.fixture(scope
='module')
65 def rwvnfr_proxy(request
, mgmt_session
):
66 return mgmt_session
.proxy(RwVnfrYang
)
68 @pytest.fixture(scope
='module')
69 def vld_proxy(request
, mgmt_session
):
70 return mgmt_session
.proxy(VldYang
)
73 @pytest.fixture(scope
='module')
74 def nsd_proxy(request
, mgmt_session
):
75 return mgmt_session
.proxy(NsdYang
)
78 @pytest.fixture(scope
='module')
79 def rwnsr_proxy(request
, mgmt_session
):
80 return mgmt_session
.proxy(RwNsrYang
)
82 @pytest.fixture(scope
='module')
83 def base_proxy(request
, mgmt_session
):
84 return mgmt_session
.proxy(RwBaseYang
)
87 @pytest.fixture(scope
="module")
91 def create_nsr(nsd
, input_param_list
, cloud_account_name
):
93 Create the NSR record object
97 input_param_list - list of input-parameter objects
102 nsr
= RwNsrYang
.YangData_RwProject_Project_NsInstanceConfig_Nsr()
104 nsr
.id = str(uuid
.uuid4())
105 nsr
.name
= rift
.auto
.mano
.resource_name(nsr
.id)
106 nsr
.short_name
= "nsr_short_name"
107 nsr
.description
= "This is a description"
108 nsr
.nsd
.from_dict(nsd
.as_dict())
109 nsr
.admin_status
= "ENABLED"
110 nsr
.input_parameter
.extend(input_param_list
)
111 nsr
.cloud_account
= cloud_account_name
116 def upload_descriptor(
123 curl_cmd
= ('curl --cert {cert} --key {key} -F "descriptor=@{file}" -k '
124 '{scheme}://{host}:4567/api/{endpoint}'.format(
129 file=descriptor_file
,
133 logger
.debug("Uploading descriptor %s using cmd: %s", descriptor_file
, curl_cmd
)
134 stdout
= subprocess
.check_output(shlex
.split(curl_cmd
), universal_newlines
=True)
136 json_out
= json
.loads(stdout
)
137 transaction_id
= json_out
["transaction_id"]
139 return transaction_id
142 class DescriptorOnboardError(Exception):
146 def wait_onboard_transaction_finished(
155 logger
.info("Waiting for onboard trans_id %s to complete", transaction_id
)
156 uri
= '%s://%s:4567/api/%s/%s/state' % (scheme
, host
, endpoint
, transaction_id
)
160 while elapsed
< timeout
:
161 reply
= requests
.get(uri
, cert
=cert
, verify
=False)
163 if state
["status"] == "success":
165 if state
["status"] != "pending":
166 raise DescriptorOnboardError(state
)
169 elapsed
= time
.time() - start
172 if state
["status"] != "success":
173 raise DescriptorOnboardError(state
)
174 logger
.info("Descriptor onboard was successful")
177 def onboard_descriptor(host
, file_name
, logger
, endpoint
, scheme
, cert
):
178 """On-board/update the descriptor.
181 host (str): Launchpad IP
182 file_name (str): Full file path.
183 logger: Logger instance
184 endpoint (str): endpoint to be used for the upload operation.
187 logger
.info("Onboarding package: %s", file_name
)
188 trans_id
= upload_descriptor(
195 wait_onboard_transaction_finished(
203 def terminate_nsr(rwvnfr_proxy
, rwnsr_proxy
, logger
, wait_after_kill
=True):
205 Terminate the instance and check if the record is deleted.
208 1. NSR record is deleted from instance-config.
211 logger
.debug("Terminating NSRs")
213 nsr_path
= "/ns-instance-config"
214 nsr
= rwnsr_proxy
.get_config(nsr_path
)
219 xpath
= "/ns-instance-config/nsr[id='{}']".format(nsr
.id)
220 rwnsr_proxy
.delete_config(xpath
)
229 nsr
= rwnsr_proxy
.get_config(xpath
)
232 # Get the ns-instance-config
233 ns_instance_config
= rwnsr_proxy
.get_config("/ns-instance-config")
236 vnfr
= "/vnfr-catalog/vnfr"
237 vnfrs
= rwvnfr_proxy
.get(vnfr
, list_obj
=True)
238 assert vnfrs
is None or len(vnfrs
.vnfr
) == 0
240 # nsr = "/ns-instance-opdata/nsr"
241 # nsrs = rwnsr_proxy.get(nsr, list_obj=True)
242 # assert len(nsrs.nsr) == 0
246 @pytest.mark
.setup('nsr')
247 @pytest.mark
.depends('launchpad')
248 @pytest.mark
.incremental
249 class TestNsrStart(object):
250 """A brief overview of the steps performed.
251 1. Generate & on-board new descriptors
255 def test_upload_descriptors(
265 """Generates & On-boards the descriptors.
269 for file_name
in descriptors
:
278 descriptor_vnfds
, descriptor_nsd
= descriptors
[:-1], descriptors
[-1]
280 catalog
= vnfd_proxy
.get_config('/vnfd-catalog')
281 actual_vnfds
= catalog
.vnfd
282 assert len(actual_vnfds
) == len(descriptor_vnfds
), \
283 "There should {} vnfds".format(len(descriptor_vnfds
))
285 catalog
= nsd_proxy
.get_config('/nsd-catalog')
286 actual_nsds
= catalog
.nsd
287 assert len(actual_nsds
) == 1, "There should only be a single nsd"
289 @pytest.mark
.feature("upload-image")
290 def test_upload_images(self
, descriptor_images
, cloud_host
, cloud_user
, cloud_tenants
):
292 openstack
= rift
.auto
.mano
.OpenstackManoSetup(
295 [(tenant
, "private") for tenant
in cloud_tenants
])
297 for image_location
in descriptor_images
:
298 image
= RwcalYang
.ImageInfoItem
.from_dict({
299 'name': os
.path
.basename(image_location
),
300 'location': image_location
,
301 'disk_format': 'qcow2',
302 'container_format': 'bare'})
303 openstack
.create_image(image
)
306 def test_set_scaling_params(self
, nsd_proxy
):
307 nsds
= nsd_proxy
.get('/nsd-catalog')
309 for scaling_group
in nsd
.scaling_group_descriptor
:
310 scaling_group
.max_instance_count
= 2
312 nsd_proxy
.replace_config('/nsd-catalog/nsd[id="{}"]'.format(
316 def test_instantiate_nsr(self
, logger
, nsd_proxy
, rwnsr_proxy
, base_proxy
, cloud_account_name
):
318 def verify_input_parameters(running_config
, config_param
):
320 Verify the configured parameter set against the running configuration
322 for run_input_param
in running_config
.input_parameter
:
323 if (run_input_param
.xpath
== config_param
.xpath
and
324 run_input_param
.value
== config_param
.value
):
327 assert False, ("Verification of configured input parameters: { xpath:%s, value:%s} "
328 "is unsuccessful.\nRunning configuration: %s" % (config_param
.xpath
,
330 running_config
.input_parameter
))
332 catalog
= nsd_proxy
.get_config('/nsd-catalog')
335 input_parameters
= []
336 descr_xpath
= "/rw-project:project/project-nsd:nsd-catalog/project-nsd:nsd[project-nsd:id='%s']/project-nsd:description" % nsd
.id
337 descr_value
= "New NSD Description"
338 in_param_id
= str(uuid
.uuid4())
340 input_param_1
= NsrYang
.YangData_RwProject_Project_NsInstanceConfig_Nsr_InputParameter(
344 input_parameters
.append(input_param_1
)
346 nsr
= create_nsr(nsd
, input_parameters
, cloud_account_name
)
348 logger
.info("Instantiating the Network Service")
349 rwnsr_proxy
.create_config('/ns-instance-config/nsr', nsr
)
351 nsr_opdata
= rwnsr_proxy
.get('/ns-instance-opdata/nsr[ns-instance-config-ref="{}"]'.format(nsr
.id))
352 assert nsr_opdata
is not None
354 # Verify the input parameter configuration
355 running_config
= rwnsr_proxy
.get_config("/ns-instance-config/nsr[id='%s']" % nsr
.id)
356 for input_param
in input_parameters
:
357 verify_input_parameters(running_config
, input_param
)
359 def test_wait_for_nsr_started(self
, rwnsr_proxy
):
360 nsr_opdata
= rwnsr_proxy
.get('/ns-instance-opdata')
361 nsrs
= nsr_opdata
.nsr
364 xpath
= "/ns-instance-opdata/nsr[ns-instance-config-ref='{}']/operational-status".format(nsr
.ns_instance_config_ref
)
365 rwnsr_proxy
.wait_for(xpath
, "running", fail_on
=['failed'], timeout
=240)
368 @pytest.mark
.teardown('nsr')
369 @pytest.mark
.depends('launchpad')
370 @pytest.mark
.incremental
371 class TestNsrTeardown(object):
372 def test_terminate_nsr(self
, rwvnfr_proxy
, rwnsr_proxy
, logger
, cloud_type
):
374 Terminate the instance and check if the record is deleted.
377 1. NSR record is deleted from instance-config.
380 logger
.debug("Terminating NSR")
382 wait_after_kill
= True
383 if cloud_type
== "mock":
384 wait_after_kill
= False
386 terminate_nsr(rwvnfr_proxy
, rwnsr_proxy
, logger
, wait_after_kill
=wait_after_kill
)
388 def test_delete_records(self
, nsd_proxy
, vnfd_proxy
):
389 """Delete the NSD & VNFD records
392 The records are deleted.
394 nsds
= nsd_proxy
.get("/nsd-catalog/nsd", list_obj
=True)
396 xpath
= "/nsd-catalog/nsd[id='{}']".format(nsd
.id)
397 nsd_proxy
.delete_config(xpath
)
399 nsds
= nsd_proxy
.get("/nsd-catalog/nsd", list_obj
=True)
400 assert nsds
is None or len(nsds
.nsd
) == 0
402 vnfds
= vnfd_proxy
.get("/vnfd-catalog/vnfd", list_obj
=True)
403 for vnfd_record
in vnfds
.vnfd
:
404 xpath
= "/vnfd-catalog/vnfd[id='{}']".format(vnfd_record
.id)
405 vnfd_proxy
.delete_config(xpath
)
407 vnfds
= vnfd_proxy
.get("/vnfd-catalog/vnfd", list_obj
=True)
408 assert vnfds
is None or len(vnfds
.vnfd
) == 0