Apply Robot Framework for testing
Support ETSI NFV compliant automated testing by using the Robot Framework and ETSI NFV-TST API test codes. Implements: blueprint use-robot-api-tests Spec: https://specs.openstack.org/openstack/tacker-specs/specs/victoria/use_robot_api_tests.html Change-Id: Ic2fe5e3eb8b279f9a9d193a00e0cf9ac97fe75a2
This commit is contained in:
parent
233a12c378
commit
e71fd7667c
11
.zuul.yaml
11
.zuul.yaml
|
@ -542,6 +542,16 @@
|
|||
kubernetes_vim_rsc_wait_timeout: 800
|
||||
tox_envlist: dsvm-functional-sol-kubernetes-v2
|
||||
|
||||
- job:
|
||||
name: tacker-compliance-devstack-multinode-sol
|
||||
parent: tacker-functional-devstack-multinode-legacy
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based compliance tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-compliance-sol-api
|
||||
voting: false
|
||||
|
||||
- project:
|
||||
templates:
|
||||
- check-requirements
|
||||
|
@ -561,3 +571,4 @@
|
|||
- tacker-functional-devstack-multinode-sol-kubernetes-v2
|
||||
- tacker-functional-devstack-multinode-sol-multi-tenant
|
||||
- tacker-functional-devstack-multinode-sol-kubernetes-multi-tenant
|
||||
- tacker-compliance-devstack-multinode-sol
|
||||
|
|
|
@ -11,4 +11,5 @@
|
|||
bindep_profile: test
|
||||
bindep_dir: "{{ zuul_work_dir }}"
|
||||
- ensure-tox
|
||||
- ensure-java
|
||||
- show-net-setup
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Support ETSI NFV compliant automated testing by using the Robot Framework
|
||||
and ETSI NFV-TST API test codes. This feature uses the Robot Framework
|
||||
which utilizes the ETSI NFV-TST API test codes to test tacker for ETSI
|
||||
NFV compliance in a Black Box testing level. This is an additional quality
|
||||
test measure to ensure that the added tacker features comply to the ETSI
|
||||
NFV standards.
|
||||
issues:
|
||||
- |
|
||||
Regarding ETSI NFV compliant automated testing, some of the tests are
|
||||
failing due to bugs (1) Tacker Bug and (2) Issues in the ETSI NFV-TST API
|
||||
test codes.
|
||||
(1) Tacker Bug such as Bug-#1945387 was detected in this compliance test
|
||||
and the corresponding test is currently failing. Test will pass once the
|
||||
bug is fixed.
|
||||
(2) Issues in the ETSI NFV-TST API test codes such as schema and mock
|
||||
server location issues also caused some tests to fail. Tests will pass once
|
||||
the issues are resolved.
|
||||
Due to these existing failed items, this test is currently non-voting.
|
|
@ -0,0 +1,433 @@
|
|||
# Copyright (C) 2022 NEC, Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 json
|
||||
import os
|
||||
import time
|
||||
import xml.etree.ElementTree as et
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import uuidutils
|
||||
import robot
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from tacker.tests.functional import base
|
||||
from tacker.tests.functional.sol.vnflcm import test_vnf_instance as vnflcmtest
|
||||
|
||||
VNFPKG_PATH = '/vnfpkgm/v1/vnf_packages/%s'
|
||||
VNFINSS_PATH = '/vnflcm/v1/vnf_instances'
|
||||
VNFINS_PATH = '/vnflcm/v1/vnf_instances/%s'
|
||||
VNFINS_INST_PATH = '/vnflcm/v1/vnf_instances/%s/instantiate'
|
||||
VNFINS_TERM_PATH = '/vnflcm/v1/vnf_instances/%s/terminate'
|
||||
VNFINS_GET_LCM_OP_OCCS_PATH = '/vnflcm/v1/vnf_lcm_op_occs'
|
||||
VNFINS_GET_IND_LCM_OP_OCCS_PATH = '/vnflcm/v1/vnf_lcm_op_occs/%s'
|
||||
VNFINS_CREATE_SUBSC_PATH = '/vnflcm/v1/subscriptions'
|
||||
VNFINS_DEL_SUBSC_PATH = '/vnflcm/v1/subscriptions/%s'
|
||||
VNFINS_SCALE_PATH = '/vnflcm/v1/vnf_instances/%s/scale'
|
||||
|
||||
INSTANTIATION_BODY = {
|
||||
'flavourId': 'simple',
|
||||
'extVirtualLinks': [
|
||||
{
|
||||
'id': 'net0',
|
||||
'resourceId': None,
|
||||
'extCps': [
|
||||
{
|
||||
'cpdId': 'CP1',
|
||||
'cpConfig': [
|
||||
{
|
||||
'cpProtocolData': [
|
||||
{
|
||||
'layerProtocol': 'IP_OVER_ETHERNET'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
'vimConnectionInfo': [
|
||||
{
|
||||
'id': None,
|
||||
'vimId': None,
|
||||
'vimType': 'ETSINFV.OPENSTACK_KEYSTONE.v_2'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
TERMINATION_BODY = {
|
||||
'terminationType': 'GRACEFUL',
|
||||
'gracefulTerminationTimeout': 120
|
||||
}
|
||||
|
||||
PATCH_BODY = {
|
||||
'vnfInstanceName': 'vnf new name',
|
||||
'vnfInstanceDescription': 'new description'
|
||||
}
|
||||
|
||||
SUBSCRIPTION_BODY = {
|
||||
'filter': {
|
||||
'vnfInstanceSubscriptionFilter': {
|
||||
'vnfdIds': [
|
||||
''
|
||||
]
|
||||
}
|
||||
},
|
||||
'callbackUri': 'http://localhost:9091/endpoint'
|
||||
}
|
||||
|
||||
SCALE_BODY = {
|
||||
'type': 'SCALE_OUT',
|
||||
'aspectId': 'VDU1',
|
||||
'numberOfSteps': 1,
|
||||
'additionalParams': {
|
||||
'samplekey': 'samplevalue'
|
||||
}
|
||||
}
|
||||
|
||||
HEAL_BODY = {
|
||||
'vnfcInstanceId': None,
|
||||
'cause': 'healing'
|
||||
}
|
||||
|
||||
CHG_EXT_CONN_BODY = {
|
||||
"extVirtualLinks": [{
|
||||
"id": "8877c521-7c51-4da8-a5b9-308b40437fd2",
|
||||
"resourceId": "dfc1872e-69a7-4f14-a2c7-5bac8bd545eb",
|
||||
"extCps": [{
|
||||
"cpdId": "CP1",
|
||||
"cpConfig": [{
|
||||
}]
|
||||
}]
|
||||
}],
|
||||
"vimConnectionInfo": [{
|
||||
"id": "748f7d54-9fdf-4e7a-a180-ec057a9eefd8",
|
||||
"vimId": "310e0d4c-7e85-42e4-b289-d09c0bdc44c8",
|
||||
"vimType": "openstack",
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity"
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
class VnfPkgInfo:
|
||||
def __init__(self, vnfpkgid, vnfdid):
|
||||
self._vnfpkgid = vnfpkgid
|
||||
self._vnfdid = vnfdid
|
||||
|
||||
@property
|
||||
def vnfpkgid(self):
|
||||
return self._vnfpkgid
|
||||
|
||||
@property
|
||||
def vnfdid(self):
|
||||
return self._vnfdid
|
||||
|
||||
|
||||
class BaseComplTest(base.BaseTackerTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(BaseComplTest, cls).setUpClass()
|
||||
|
||||
for vim_list in cls.client.list_vims().values():
|
||||
for vim in vim_list:
|
||||
if vim['name'] == 'VIM0':
|
||||
cls.vimid = vim['id']
|
||||
|
||||
for net_list in cls.neutronclient().list_networks().values():
|
||||
for net in net_list:
|
||||
if net['name'] == 'net0':
|
||||
cls.net0_id = net['id']
|
||||
|
||||
cls.base_dir = os.getcwd()
|
||||
cls.test_root_dir = os.path.join(cls.base_dir, 'api-tests')
|
||||
cls.sol_dir = os.path.join(cls.test_root_dir, cls.sol)
|
||||
cls.api_dir = os.path.join(cls.sol_dir, cls.api)
|
||||
cls.test_file = cls.resource + '.robot'
|
||||
os.chdir(cls.api_dir)
|
||||
|
||||
parts = urlparse(cls.http_client.get_endpoint())
|
||||
|
||||
cls.common_variables = []
|
||||
cls.common_variables.append('VNFM_SCHEMA:%s' % parts.scheme)
|
||||
cls.common_variables.append('NFVO_SCHEMA:%s' % parts.scheme)
|
||||
cls.common_variables.append('VNFM_HOST:%s' % parts.hostname)
|
||||
cls.common_variables.append('NFVO_HOST:%s' % parts.hostname)
|
||||
cls.common_variables.append('VNFM_PORT:%s' % parts.port)
|
||||
cls.common_variables.append('NFVO_PORT:%s' % parts.port)
|
||||
cls.common_variables.append('AUTH_USAGE:1')
|
||||
cls.common_variables.append('AUTHORIZATION_HEADER:X-Auth-Token')
|
||||
cls.common_variables.append('AUTHORIZATION_TOKEN:%s' %
|
||||
cls.http_client.get_token())
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
os.chdir(cls.base_dir)
|
||||
|
||||
super(BaseComplTest, cls).tearDownClass()
|
||||
|
||||
@classmethod
|
||||
def _get_responses_from_output(cls, output):
|
||||
result = []
|
||||
for el in et.fromstring(output).findall(
|
||||
".//kw[@name='Output']/[@library='REST']/msg[1]"):
|
||||
result.append(json.loads(el.text))
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def _get_id_from_output(cls, output):
|
||||
res = cls._get_responses_from_output(output)
|
||||
if ('status' in res[0] and
|
||||
res[0]['status'] in [200, 201, 202, 203, 204]):
|
||||
if ('body' in res[0] and 'id' in res[0]['body']):
|
||||
return res[0]['body']['id']
|
||||
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _create_and_upload_vnf_packages(cls, pkgnames):
|
||||
vnfpkginfos = []
|
||||
for pkgname in pkgnames:
|
||||
vnfpkgid, vnfdid = vnflcmtest._create_and_upload_vnf_package(
|
||||
cls.http_client, pkgname, {})
|
||||
vnfpkginfos.append(VnfPkgInfo(vnfpkgid, vnfdid))
|
||||
|
||||
return vnfpkginfos
|
||||
|
||||
@classmethod
|
||||
def _disable_vnf_package(cls, vnfpkgid):
|
||||
cls.http_client.do_request(VNFPKG_PATH % vnfpkgid,
|
||||
'PATCH', content_type='application/json',
|
||||
body=jsonutils.dumps({"operationalState": "DISABLED"}))
|
||||
|
||||
@classmethod
|
||||
def _get_vnfpkgids(cls, vnfpkginfos):
|
||||
vnfpkgids = []
|
||||
for vnfpkginfo in vnfpkginfos:
|
||||
vnfpkgids.append(vnfpkginfo.vnfpkgid)
|
||||
|
||||
return vnfpkgids
|
||||
|
||||
@classmethod
|
||||
def _delete_vnf_package(cls, vnfpkgid):
|
||||
cls.http_client.do_request(VNFPKG_PATH % vnfpkgid, 'DELETE')
|
||||
|
||||
@classmethod
|
||||
def _disable_and_delete_vnf_packages(cls, vnfpkginfos):
|
||||
for vnfpkginfo in vnfpkginfos:
|
||||
cls._disable_vnf_package(vnfpkginfo.vnfpkgid)
|
||||
cls._delete_vnf_package(vnfpkginfo.vnfpkgid)
|
||||
|
||||
@classmethod
|
||||
def _create_vnf_instance(cls, vnfdid, name=None, description=None):
|
||||
body = {'vnfdId': vnfdid}
|
||||
if name:
|
||||
body['vnfInstanceName'] = name
|
||||
if description:
|
||||
body['vnfInstanceDescription'] = description
|
||||
|
||||
res, resbody = cls.http_client.do_request(VNFINSS_PATH, 'POST',
|
||||
body=jsonutils.dumps(body))
|
||||
|
||||
return res, resbody
|
||||
|
||||
@classmethod
|
||||
def _delete_vnf_instance(cls, vnfid):
|
||||
resp, body = cls.http_client.do_request(VNFINS_PATH % vnfid, 'DELETE')
|
||||
|
||||
@classmethod
|
||||
def _instantiate_vnf_instance(cls, vnfid):
|
||||
body = INSTANTIATION_BODY
|
||||
body['extVirtualLinks'][0]['resourceId'] = cls.net0_id
|
||||
body['vimConnectionInfo'][0]['id'] = uuidutils.generate_uuid()
|
||||
body['vimConnectionInfo'][0]['vimId'] = cls.vimid
|
||||
|
||||
cls.http_client.do_request(VNFINS_INST_PATH % vnfid,
|
||||
'POST', body=jsonutils.dumps(body))
|
||||
|
||||
cls._wait_vnf_status(vnfid, 'instantiationState', 'INSTANTIATED')
|
||||
|
||||
@classmethod
|
||||
def _terminate_vnf_instance(cls, vnfid):
|
||||
cls.http_client.do_request(VNFINS_TERM_PATH % vnfid,
|
||||
'POST', body=jsonutils.dumps(TERMINATION_BODY))
|
||||
|
||||
cls._wait_vnf_status(vnfid, 'instantiationState', 'NOT_INSTANTIATED')
|
||||
|
||||
@classmethod
|
||||
def _get_vnf_ind_instance(cls, vnfid):
|
||||
res, resbody = cls.http_client.do_request(VNFINS_PATH % vnfid, 'GET')
|
||||
|
||||
return resbody
|
||||
|
||||
@classmethod
|
||||
def _get_vnf_instance_id(cls):
|
||||
res, resbody = cls.http_client.do_request(VNFINSS_PATH, 'GET')
|
||||
|
||||
return resbody[0]['id']
|
||||
|
||||
@classmethod
|
||||
def _instantiate_vnf_instance_for_scale(cls, vnfid):
|
||||
body = INSTANTIATION_BODY
|
||||
body['flavourId'] = 'default'
|
||||
body['extVirtualLinks'][0]['resourceId'] = cls.net0_id
|
||||
body['vimConnectionInfo'][0]['id'] = uuidutils.generate_uuid()
|
||||
body['vimConnectionInfo'][0]['vimId'] = cls.vimid
|
||||
body['additionalParams'] = {
|
||||
"lcm-operation-user-data": "./UserData/lcm_user_data.py",
|
||||
"lcm-operation-user-data-class": "SampleUserData"
|
||||
}
|
||||
|
||||
cls.http_client.do_request(VNFINS_INST_PATH % vnfid,
|
||||
'POST', body=jsonutils.dumps(body))
|
||||
|
||||
cls._wait_vnf_status(vnfid, 'instantiationState', 'INSTANTIATED')
|
||||
|
||||
@classmethod
|
||||
def _instantiate_error_vnf_instance(cls, vnfid):
|
||||
body = INSTANTIATION_BODY
|
||||
body['flavorId'] = 'sample'
|
||||
body['extVirtualLinks'][0]['resourceId'] = cls.net0_id
|
||||
body['vimConnectionInfo'][0]['id'] = uuidutils.generate_uuid()
|
||||
body['vimConnectionInfo'][0]['vimId'] = cls.vimid
|
||||
body['additionalParams'] = {
|
||||
"lcm-operation-user-data": "./UserData/lcm_user_data2.py",
|
||||
"lcm-operation-user-data-class": "SampleUserData"
|
||||
}
|
||||
|
||||
cls.http_client.do_request(VNFINS_INST_PATH % vnfid,
|
||||
'POST', body=jsonutils.dumps(body))
|
||||
|
||||
cls._wait_vnf_status(vnfid, 'instantiationState', 'INSTANTIATED')
|
||||
|
||||
@classmethod
|
||||
def _get_lcm_op_occs_id(cls, vnfid, lcm='INSTANTIATE'):
|
||||
res, resbody = cls.http_client.do_request(
|
||||
VNFINS_GET_LCM_OP_OCCS_PATH, 'GET')
|
||||
|
||||
lcmid = None
|
||||
for entry in resbody:
|
||||
lcm_dict = entry
|
||||
if ((lcm_dict['vnfInstanceId'] == vnfid) and
|
||||
(lcm_dict['operation'] == lcm)):
|
||||
lcmid = lcm_dict['id']
|
||||
break
|
||||
|
||||
return lcmid
|
||||
|
||||
@classmethod
|
||||
def _create_subscription(cls, vnfdid):
|
||||
body = SUBSCRIPTION_BODY
|
||||
body['filter']['vnfInstanceSubscriptionFilter']['vnfdIds'] = [vnfdid]
|
||||
res, resbody = cls.http_client.do_request(VNFINS_CREATE_SUBSC_PATH,
|
||||
'POST', body=jsonutils.dumps(body))
|
||||
|
||||
subscid = cls._get_id_from_output(resbody)
|
||||
return subscid
|
||||
|
||||
@classmethod
|
||||
def _get_subscription_id(cls):
|
||||
res, resbody = cls.http_client.do_request(VNFINS_CREATE_SUBSC_PATH,
|
||||
'GET')
|
||||
|
||||
subscid = resbody[0]['id']
|
||||
return subscid
|
||||
|
||||
@classmethod
|
||||
def _delete_subscription(cls, subscId):
|
||||
cls.http_client.do_request(VNFINS_DEL_SUBSC_PATH % subscId,
|
||||
'DELETE')
|
||||
|
||||
@classmethod
|
||||
def _scaleout_vnf(cls, vnfid):
|
||||
body = SCALE_BODY
|
||||
body['type'] = 'SCALE_OUT'
|
||||
res_scale, resbody = cls.http_client.do_request(
|
||||
VNFINS_SCALE_PATH % vnfid,
|
||||
'POST', body=jsonutils.dumps(body))
|
||||
|
||||
print("scaleout called")
|
||||
print(res_scale)
|
||||
print(resbody)
|
||||
lcmid = cls._get_lcm_op_occs_id(vnfid, lcm='SCALE')
|
||||
res = cls._wait_lcm_status(lcmid)
|
||||
return res, lcmid
|
||||
|
||||
@classmethod
|
||||
def _wait_lcm_status(cls, lcmid, value='COMPLETED', expire=600):
|
||||
start_time = int(time.time())
|
||||
res = 1
|
||||
|
||||
final_state = ''
|
||||
while True:
|
||||
resp, body = cls.http_client.do_request(
|
||||
VNFINS_GET_IND_LCM_OP_OCCS_PATH % lcmid, 'GET')
|
||||
|
||||
if body is None:
|
||||
break
|
||||
|
||||
if ((body['operationState'] == value) or
|
||||
(((int(time.time()) - start_time) > expire)) or
|
||||
(body['operationState'] == 'FAILED_TEMP')):
|
||||
final_state = body['operationState']
|
||||
break
|
||||
|
||||
time.sleep(5)
|
||||
time.sleep(30)
|
||||
|
||||
if final_state == value:
|
||||
res = 0
|
||||
|
||||
return res
|
||||
|
||||
@classmethod
|
||||
def _wait_vnf_status(cls, vnfid, attr, value, expire=600):
|
||||
start_time = int(time.time())
|
||||
while True:
|
||||
resp, body = cls.http_client.do_request(VNFINS_PATH % vnfid, 'GET')
|
||||
if body[attr] == value:
|
||||
break
|
||||
|
||||
if ((int(time.time()) - start_time) > expire):
|
||||
break
|
||||
|
||||
time.sleep(5)
|
||||
time.sleep(30)
|
||||
|
||||
def _run(self, test_case, variables=[], body=None, filename=None):
|
||||
if (body is not None and filename is not None):
|
||||
with open(os.path.join('jsons', filename), 'w') as f:
|
||||
f.write(body)
|
||||
all_vars = []
|
||||
all_vars.extend(variables)
|
||||
all_vars.extend(self.common_variables)
|
||||
|
||||
odir = os.path.join(self.base_dir, 'log',
|
||||
self.sol, self.api, self.resource,
|
||||
test_case.replace(' ', '_').replace('"', ''))
|
||||
|
||||
if not os.path.exists(odir):
|
||||
os.makedirs(odir)
|
||||
|
||||
with open(os.path.join(odir, 'stdout.txt'), 'w') as stdout:
|
||||
rc = robot.run(self.test_file, variable=all_vars, test=test_case,
|
||||
outputdir=odir, stdout=stdout)
|
||||
|
||||
with open(os.path.join(odir, 'output.xml'), 'r') as ofile:
|
||||
outputxml = ofile.read()
|
||||
|
||||
return rc, outputxml
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright (C) 2022 NEC, Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tacker.tests.compliance import base
|
||||
|
||||
|
||||
class BaseComplSolTest(base.BaseComplTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.sol = 'SOL002'
|
||||
|
||||
super(BaseComplSolTest, cls).setUpClass()
|
|
@ -0,0 +1,413 @@
|
|||
# Copyright (C) 2022 NEC, Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import uuidutils
|
||||
from tacker.tests.compliance import base as rootbase
|
||||
from tacker.tests.compliance.sol002 import base
|
||||
|
||||
|
||||
class BaseVNFLifecycleManagementTest(base.BaseComplSolTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.api = 'VNFLifecycleManagement-API'
|
||||
|
||||
super(BaseVNFLifecycleManagementTest, cls).setUpClass()
|
||||
|
||||
cls.vnfpkginfos = cls._create_and_upload_vnf_packages(['vnflcm1'])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls._disable_and_delete_vnf_packages(cls.vnfpkginfos)
|
||||
|
||||
super(BaseVNFLifecycleManagementTest, cls).tearDownClass()
|
||||
|
||||
|
||||
class BaseVNFLifecycleManagementScaleTest(base.BaseComplSolTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.api = 'VNFLifecycleManagement-API'
|
||||
|
||||
super(BaseVNFLifecycleManagementScaleTest, cls).setUpClass()
|
||||
|
||||
cls.vnfpkginfos = cls._create_and_upload_vnf_packages(
|
||||
['sample_compliance_test'])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls._disable_and_delete_vnf_packages(cls.vnfpkginfos)
|
||||
|
||||
super(BaseVNFLifecycleManagementScaleTest, cls).tearDownClass()
|
||||
|
||||
|
||||
class VNFInstancesTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'VNFInstances'
|
||||
|
||||
super(VNFInstancesTest, cls).setUpClass()
|
||||
|
||||
def test_post_create_new_vnfinstance(self):
|
||||
|
||||
# Pre-conditions:
|
||||
body = jsonutils.dumps({"vnfdId": "%s" % self.vnfpkginfos[0].vnfdid,
|
||||
"vnfInstanceName": "sol_api_test"})
|
||||
|
||||
rc, output = self._run('POST Create a new vnfInstance', body=body,
|
||||
filename='createVnfRequest.json')
|
||||
|
||||
# Post-Conditions: VNF instance created
|
||||
vnfid = self._get_id_from_output(output)
|
||||
if (vnfid is not None):
|
||||
self._delete_vnf_instance(vnfid)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_get_information_about_multiple_vnf_instances(self):
|
||||
|
||||
# Pre-conditions:
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
rc, output = self._run('GET information about multiple VNF instances')
|
||||
|
||||
# Post-Conditions:
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class IndividualVNFInstanceTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'IndividualVNFInstance'
|
||||
|
||||
super(IndividualVNFInstanceTest, cls).setUpClass()
|
||||
|
||||
def test_get_information_about_individual_vnf_instance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid,
|
||||
description="testvnf")
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
rc, output = self._run(
|
||||
'GET Information about an individual VNF Instance', variables)
|
||||
|
||||
# Post-Conditions:
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_delete_individual_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
rc, output = self._run('DELETE Individual VNFInstance', variables)
|
||||
|
||||
# Post-Conditions: VNF instance deleted
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_modify_information_about_individual_vnf_instance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
vnfid = vnf['id']
|
||||
variables = ['vnfInstanceId:' + vnfid]
|
||||
|
||||
body = rootbase.PATCH_BODY
|
||||
body['vnfInstanceName'] = "modify_test"
|
||||
body['vnfInstanceDescription'] = "sample_testcode"
|
||||
|
||||
rc, output = self._run('PATCH Individual VNFInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body))
|
||||
|
||||
# Post-Conditions:
|
||||
self._delete_vnf_instance(vnfid)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class InstantiateVNFTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'InstantiateVNFTask'
|
||||
|
||||
super(InstantiateVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_instantiate_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
|
||||
body = rootbase.INSTANTIATION_BODY
|
||||
|
||||
body['extVirtualLinks'][0]['resourceId'] = self.net0_id
|
||||
body['vimConnectionInfo'][0]['id'] = uuidutils.generate_uuid()
|
||||
body['vimConnectionInfo'][0]['vimId'] = self.vimid
|
||||
|
||||
rc, output = self._run('POST Instantiate a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename='instantiateVnfRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
self._wait_vnf_status(vnf['id'], 'instantiationState', 'INSTANTIATED')
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class TerminateVNFTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'TerminateVNFTask'
|
||||
|
||||
super(TerminateVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_terminate_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
self._instantiate_vnf_instance(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
|
||||
rc, output = self._run('POST Terminate a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(rootbase.TERMINATION_BODY),
|
||||
filename='terminateVnfRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
self._wait_vnf_status(vnf['id'], 'instantiationState',
|
||||
'NOT_INSTANTIATED')
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class ScaleVNFTaskTest(BaseVNFLifecycleManagementScaleTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'ScaleVNFTask'
|
||||
|
||||
super(ScaleVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_expand_by_scaleout(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
self._instantiate_vnf_instance_for_scale(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
body = rootbase.SCALE_BODY
|
||||
body['type'] = 'SCALE_OUT'
|
||||
|
||||
rc, output = self._run('POST Scale a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename='scaleVnfRequest.json')
|
||||
|
||||
res = self._get_responses_from_output(output)
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'], lcm='SCALE')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_post_reduce_by_scalein(self):
|
||||
vnf_id = self._get_vnf_instance_id()
|
||||
|
||||
body = rootbase.SCALE_BODY
|
||||
body['type'] = 'SCALE_IN'
|
||||
|
||||
rc, output = self._run('POST Scale a vnfInstance',
|
||||
variables=['vnfInstanceId:' + vnf_id],
|
||||
body=jsonutils.dumps(body),
|
||||
filename='scaleVnfRequest.json')
|
||||
|
||||
res = self._get_responses_from_output(output)
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf_id, lcm='SCALE')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf_id)
|
||||
self._delete_vnf_instance(vnf_id)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class CreateAndGetSubscriptionsTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
cls.resource = 'Subscriptions'
|
||||
|
||||
super(CreateAndGetSubscriptionsTest, cls).setUpClass()
|
||||
|
||||
def test_create_subscription(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
body = rootbase.SUBSCRIPTION_BODY
|
||||
|
||||
body['filter']['vnfInstanceSubscriptionFilter']['vnfdIds'] = \
|
||||
[self.vnfpkginfos[0].vnfdid]
|
||||
|
||||
rc, output = self._run('POST Create a new subscription',
|
||||
body=jsonutils.dumps(body),
|
||||
filename='lccnSubscriptionRequest.json')
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_get_subscriptions(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
rc, output = self._run('GET Subscriptions')
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class IndividualSubscriptionTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'IndividualSubscription'
|
||||
|
||||
super(IndividualSubscriptionTest, cls).setUpClass()
|
||||
|
||||
def test_get_individual_subscription(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
subscid = self._get_subscription_id()
|
||||
variables = ['subscriptionId:' + subscid]
|
||||
|
||||
rc, output = self._run('GET Individual Subscription',
|
||||
variables=variables)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_remove_individual_subscription(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
subscid = self._get_subscription_id()
|
||||
|
||||
variables = ['subscriptionId:' + subscid]
|
||||
|
||||
rc, output = self._run('DELETE an individual subscription',
|
||||
variables=variables)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class HealVNFTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'HealVNFTask'
|
||||
|
||||
super(HealVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_heal_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
self._instantiate_vnf_instance(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
resbody = self._get_vnf_ind_instance(vnf['id'])
|
||||
body = rootbase.HEAL_BODY
|
||||
body['vnfcInstanceId'] = resbody.get('instantiated'
|
||||
'VnfInfo').get('vnfcResourceInfo')[0].get('id')
|
||||
|
||||
rc, output = self._run('POST Heal a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename=' healVnfRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'], lcm='HEAL')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class RetryOperationTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'RetryOperationTask'
|
||||
|
||||
super(RetryOperationTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_retry_operation(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
self._instantiate_error_vnf_instance(vnf['id'])
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'])
|
||||
|
||||
variables = ['vnfLcmOpOccId:' + lcmid]
|
||||
|
||||
rc, output = self._run('Post Retry operation task',
|
||||
variables=variables)
|
||||
|
||||
# Post-Conditions:
|
||||
res = self._wait_lcm_status(lcmid, value='FAILED_TEMP')
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(1, rc)
|
||||
|
||||
|
||||
class ChangeExternalVNFConnectivityTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'ChangeExternalVNFConnectivityTask'
|
||||
|
||||
super(ChangeExternalVNFConnectivityTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_chgextconn_vnfinstance(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
self._instantiate_vnf_instance(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
|
||||
resbody = self._get_vnf_ind_instance(vnf['id'])
|
||||
|
||||
body = rootbase.CHG_EXT_CONN_BODY
|
||||
body['extVirtualLinks'][0]['resourceId'] = resbody.get('instantiated'
|
||||
'VnfInfo').get('extVirtualLinkInfo')[0].get('resource'
|
||||
'Handle').get('resourceId')
|
||||
|
||||
rc, output = self._run('POST Change external VNF connectivity',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename='changeExtVnfConnectivityRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'], lcm='CHANGE_EXT_CONN')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright (C) 2022 NEC, Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tacker.tests.compliance import base
|
||||
|
||||
|
||||
class BaseComplSolTest(base.BaseComplTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.sol = 'SOL003'
|
||||
|
||||
super(BaseComplSolTest, cls).setUpClass()
|
|
@ -0,0 +1,481 @@
|
|||
# Copyright (C) 2022 NEC, Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import uuidutils
|
||||
from tacker.tests.compliance import base as rootbase
|
||||
from tacker.tests.compliance.sol003 import base
|
||||
|
||||
|
||||
class BaseVNFLifecycleManagementTest(base.BaseComplSolTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.api = 'VNFLifecycleManagement-API'
|
||||
|
||||
super(BaseVNFLifecycleManagementTest, cls).setUpClass()
|
||||
|
||||
cls.vnfpkginfos = cls._create_and_upload_vnf_packages(['vnflcm1'])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls._disable_and_delete_vnf_packages(cls.vnfpkginfos)
|
||||
|
||||
super(BaseVNFLifecycleManagementTest, cls).tearDownClass()
|
||||
|
||||
|
||||
class BaseVNFLifecycleManagementScaleTest(base.BaseComplSolTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.api = 'VNFLifecycleManagement-API'
|
||||
|
||||
super(BaseVNFLifecycleManagementScaleTest, cls).setUpClass()
|
||||
|
||||
cls.vnfpkginfos = cls._create_and_upload_vnf_packages(
|
||||
['sample_compliance_test'])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls._disable_and_delete_vnf_packages(cls.vnfpkginfos)
|
||||
|
||||
super(BaseVNFLifecycleManagementScaleTest, cls).tearDownClass()
|
||||
|
||||
|
||||
class VNFInstancesTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'VNFInstances'
|
||||
|
||||
super(VNFInstancesTest, cls).setUpClass()
|
||||
|
||||
def test_post_create_new_vnfinstance(self):
|
||||
|
||||
# Pre-conditions:
|
||||
body = jsonutils.dumps({"vnfdId": "%s" % self.vnfpkginfos[0].vnfdid,
|
||||
"vnfInstanceName": "sol_api_test"})
|
||||
|
||||
rc, output = self._run('POST Create a new vnfInstance', body=body,
|
||||
filename='createVnfRequest.json')
|
||||
|
||||
# Post-Conditions: VNF instance created
|
||||
vnfid = self._get_id_from_output(output)
|
||||
if (vnfid is not None):
|
||||
self._delete_vnf_instance(vnfid)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_get_information_about_multiple_vnf_instances(self):
|
||||
|
||||
# Pre-conditions:
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
rc, output = self._run('GET information about multiple VNF instances')
|
||||
|
||||
# Post-Conditions:
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class IndividualVNFInstanceTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'IndividualVNFInstance'
|
||||
|
||||
super(IndividualVNFInstanceTest, cls).setUpClass()
|
||||
|
||||
def test_get_information_about_individual_vnf_instance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid,
|
||||
description="testvnf")
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
rc, output = self._run(
|
||||
'Get Information about an individual VNF Instance', variables)
|
||||
|
||||
# Post-Conditions:
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_delete_individual_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
variables = ['notInstantiatedVnfInstanceId:' + vnf['id']]
|
||||
rc, output = self._run('DELETE Individual VNFInstance', variables)
|
||||
|
||||
# Post-Conditions: VNF instance deleted
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_modify_information_about_individual_vnf_instance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
vnfid = vnf['id']
|
||||
variables = ['vnfInstanceId:' + vnfid]
|
||||
|
||||
body = rootbase.PATCH_BODY
|
||||
body['vnfInstanceName'] = "modify_test"
|
||||
body['vnfInstanceDescription'] = "sample_testcode"
|
||||
|
||||
rc, output = self._run('PATCH Individual VNFInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body))
|
||||
|
||||
# Post-Conditions:
|
||||
self._delete_vnf_instance(vnfid)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class InstantiateVNFTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'InstantiateVNFTask'
|
||||
|
||||
super(InstantiateVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_instantiate_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
|
||||
body = rootbase.INSTANTIATION_BODY
|
||||
|
||||
body['extVirtualLinks'][0]['resourceId'] = self.net0_id
|
||||
body['vimConnectionInfo'][0]['id'] = uuidutils.generate_uuid()
|
||||
body['vimConnectionInfo'][0]['vimId'] = self.vimid
|
||||
|
||||
rc, output = self._run('Instantiate a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename='instantiateVnfRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
self._wait_vnf_status(vnf['id'], 'instantiationState', 'INSTANTIATED')
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class TerminateVNFTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'TerminateVNFTask'
|
||||
|
||||
super(TerminateVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_terminate_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
self._instantiate_vnf_instance(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
|
||||
rc, output = self._run('POST Terminate a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(rootbase.TERMINATION_BODY),
|
||||
filename='terminateVnfRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
self._wait_vnf_status(vnf['id'], 'instantiationState',
|
||||
'NOT_INSTANTIATED')
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class VnfLcmOperationOccurencesTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'VnfLcmOperationOccurences'
|
||||
|
||||
super(VnfLcmOperationOccurencesTest, cls).setUpClass()
|
||||
|
||||
def test_get_vnf_lcm_op_occs(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
rc, output = self._run('GET status information about multiple'
|
||||
'VNF LCM Operation OCC')
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class IndividualVnfLcmOperationOccurenceTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'IndividualVnfLcmOperationOccurence'
|
||||
|
||||
super(IndividualVnfLcmOperationOccurenceTest, cls).setUpClass()
|
||||
|
||||
def test_get_ind_vnf_lcm_op_occs(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
self._instantiate_vnf_instance(vnf['id'])
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'])
|
||||
|
||||
variables = ['vnfLcmOpOccId:' + lcmid]
|
||||
|
||||
rc, output = self._run('Get Individual VNF LCM OP occurrence',
|
||||
variables=variables)
|
||||
|
||||
# Post-Conditions:
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class CreateAndGetSubscriptionsTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'Subscriptions'
|
||||
|
||||
super(CreateAndGetSubscriptionsTest, cls).setUpClass()
|
||||
|
||||
def test_create_subscription(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
body = rootbase.SUBSCRIPTION_BODY
|
||||
|
||||
body['filter']['vnfInstanceSubscriptionFilter']['vnfdIds'] = \
|
||||
[self.vnfpkginfos[0].vnfdid]
|
||||
|
||||
rc, output = self._run('POST Create a new subscription',
|
||||
body=jsonutils.dumps(body),
|
||||
filename='lccnSubscriptionRequest.json')
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_get_subscriptions(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
rc, output = self._run('GET Subscriptions')
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class IndividualSubscriptionTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'IndividualSubscription'
|
||||
|
||||
super(IndividualSubscriptionTest, cls).setUpClass()
|
||||
|
||||
def test_get_individual_subscription(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
subscid = self._get_subscription_id()
|
||||
variables = ['subscriptionId:' + subscid]
|
||||
|
||||
rc, output = self._run('GET Individual Subscription',
|
||||
variables=variables)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_remove_individual_subscription(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
subscid = self._get_subscription_id()
|
||||
variables = ['subscriptionId:' + subscid]
|
||||
|
||||
rc, output = self._run('DELETE an individual subscription',
|
||||
variables=variables)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class ScaleVNFTaskTest(BaseVNFLifecycleManagementScaleTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'ScaleVNFTask'
|
||||
|
||||
super(ScaleVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_expand_by_scaleout(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
self._instantiate_vnf_instance_for_scale(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
body = rootbase.SCALE_BODY
|
||||
body['type'] = 'SCALE_OUT'
|
||||
|
||||
rc, output = self._run('POST Scale a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename='scaleVnfRequest.json')
|
||||
|
||||
res = self._get_responses_from_output(output)
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'], lcm='SCALE')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_post_reduce_by_scalein(self):
|
||||
vnf_id = self._get_vnf_instance_id()
|
||||
|
||||
body = rootbase.SCALE_BODY
|
||||
body['type'] = 'SCALE_IN'
|
||||
|
||||
rc, output = self._run('POST Scale a vnfInstance',
|
||||
variables=['vnfInstanceId:' + vnf_id],
|
||||
body=jsonutils.dumps(body),
|
||||
filename='scaleVnfRequest.json')
|
||||
|
||||
res = self._get_responses_from_output(output)
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf_id, lcm='SCALE')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf_id)
|
||||
self._delete_vnf_instance(vnf_id)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class HealVNFTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'HealVNFTask'
|
||||
|
||||
super(HealVNFTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_heal_vnfinstance(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
self._instantiate_vnf_instance(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
resbody = self._get_vnf_ind_instance(vnf['id'])
|
||||
body = rootbase.HEAL_BODY
|
||||
body['vnfcInstanceId'] = resbody.get('instantiated'
|
||||
'VnfInfo').get('vnfcResourceInfo')[0].get('id')
|
||||
|
||||
rc, output = self._run('POST Heal a vnfInstance',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename=' healVnfRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'], lcm='HEAL')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class ChangeExternalVNFConnectivityTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'ChangeExternalVNFConnectivityTask'
|
||||
|
||||
super(ChangeExternalVNFConnectivityTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_chgextconn_vnfinstance(self):
|
||||
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
|
||||
self._instantiate_vnf_instance(vnf['id'])
|
||||
|
||||
variables = ['vnfInstanceId:' + vnf['id']]
|
||||
|
||||
resbody = self._get_vnf_ind_instance(vnf['id'])
|
||||
|
||||
body = rootbase.CHG_EXT_CONN_BODY
|
||||
body['extVirtualLinks'][0]['resourceId'] = resbody.get('instantiated'
|
||||
'VnfInfo').get('extVirtualLinkInfo')[0].get('resource'
|
||||
'Handle').get('resourceId')
|
||||
|
||||
rc, output = self._run('POST Change external VNF connectivity',
|
||||
variables=variables,
|
||||
body=jsonutils.dumps(body),
|
||||
filename='changeExtVnfConnectivityRequest.json')
|
||||
|
||||
# Post-Conditions:
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'], lcm='CHANGE_EXT_CONN')
|
||||
res = self._wait_lcm_status(lcmid)
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class RetryOperationTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'RetryOperationTask'
|
||||
|
||||
super(RetryOperationTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_retry_operation(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
self._instantiate_error_vnf_instance(vnf['id'])
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'])
|
||||
|
||||
variables = ['vnfLcmOpOccId:' + lcmid]
|
||||
|
||||
rc, output = self._run('Post Retry operation task',
|
||||
variables=variables)
|
||||
|
||||
# Post-Conditions:
|
||||
res = self._wait_lcm_status(lcmid, value='FAILED_TEMP')
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(1, rc)
|
||||
|
||||
|
||||
class RollbackOperationTaskTest(BaseVNFLifecycleManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'RollbackOperationTask'
|
||||
|
||||
super(RollbackOperationTaskTest, cls).setUpClass()
|
||||
|
||||
def test_post_rollback_operation(self):
|
||||
# Pre-conditions: none
|
||||
res, vnf = self._create_vnf_instance(self.vnfpkginfos[0].vnfdid)
|
||||
self._instantiate_error_vnf_instance(vnf['id'])
|
||||
lcmid = self._get_lcm_op_occs_id(vnf['id'])
|
||||
|
||||
variables = ['vnfLcmOpOccId:' + lcmid]
|
||||
|
||||
rc, output = self._run('Post Rollback operation task',
|
||||
variables=variables)
|
||||
|
||||
# Post-Conditions:
|
||||
res = self._wait_lcm_status(lcmid, value='ROLLED_BACK')
|
||||
self.assertEqual(0, res)
|
||||
self._terminate_vnf_instance(vnf['id'])
|
||||
self._delete_vnf_instance(vnf['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright (C) 2022 NEC, Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tacker.tests.compliance import base
|
||||
|
||||
|
||||
class BaseComplSolTest(base.BaseComplTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.sol = 'SOL005'
|
||||
|
||||
super(BaseComplSolTest, cls).setUpClass()
|
|
@ -0,0 +1,143 @@
|
|||
# Copyright (C) 2022 NEC, Corp.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from tacker.tests.compliance.sol005 import base
|
||||
|
||||
|
||||
class BaseVNFPackageManagementTest(base.BaseComplSolTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.api = 'VNFPackageManagement-API'
|
||||
|
||||
super(BaseVNFPackageManagementTest, cls).setUpClass()
|
||||
|
||||
|
||||
class VNFPackagesTest(BaseVNFPackageManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'VNFPackages'
|
||||
|
||||
super(VNFPackagesTest, cls).setUpClass()
|
||||
|
||||
def test_get_all_vnf_packages(self):
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO.
|
||||
vnfpkginfos = self._create_and_upload_vnf_packages(
|
||||
['vnflcm1', 'vnflcm2'])
|
||||
|
||||
rc, output = self._run('GET all VNF Packages')
|
||||
|
||||
# Post-Conditions: none
|
||||
self._disable_and_delete_vnf_packages(vnfpkginfos)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_get_vnf_packages_with_attribute_based_filter(self):
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO.
|
||||
self._run('GET VNF Packages with attribute-based filter')
|
||||
# Post-Conditions: none
|
||||
|
||||
def test_get_vnf_packages_with_all_fields_attribute_selector(self):
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO.
|
||||
self._run('GET VNF Packages with "all_fields" attribute selector')
|
||||
# Post-Conditions: none
|
||||
|
||||
def test_vnf_packages_with_exclude_default_attribute_selector(self):
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO.
|
||||
self._run('GET VNF Packages with "exclude_default" attribute selector')
|
||||
# Post-Conditions: none
|
||||
|
||||
def test_get_vnf_packages_with_fields_attribute_selector(self):
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO.
|
||||
self._run('GET VNF Packages with "fields" attribute selector')
|
||||
# Post-Conditions: none
|
||||
|
||||
def test_get_vnf_packages_with_exclude_fields_attribute_selector(self):
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO.
|
||||
self._run('GET VNF Packages with "exclude_fields" attribute selector')
|
||||
# Post-Conditions: none
|
||||
|
||||
def test_create_vnf_package(self):
|
||||
# Pre-conditions: none
|
||||
rc, output = self._run('Create new VNF Package Resource')
|
||||
|
||||
# Post-Conditions: The VNF Package Resource is successfully created
|
||||
# on the NFVO
|
||||
res = self._get_responses_from_output(output)
|
||||
if ('status' in res[0] and res[0]['status'] == 201):
|
||||
if ('body' in res[0] and 'id' in res[0]['body']):
|
||||
# delete created vnf package
|
||||
self._delete_vnf_package(res[0]['body']['id'])
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
|
||||
class IndividualVNFPackageTest(BaseVNFPackageManagementTest):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.resource = 'IndividualVNFPackage'
|
||||
|
||||
super(IndividualVNFPackageTest, cls).setUpClass()
|
||||
|
||||
def test_get_individual_vnf_package(self):
|
||||
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO.
|
||||
vnfpkginfos = self._create_and_upload_vnf_packages(['vnflcm1'])
|
||||
variables = ['vnfPackageId:' + vnfpkginfos[0].vnfpkgid]
|
||||
|
||||
rc, output = self._run('GET Individual VNF Package', variables)
|
||||
|
||||
# Post-Conditions: none
|
||||
self._disable_and_delete_vnf_packages(vnfpkginfos)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_disable_individual_vnf_package(self):
|
||||
# Pre-conditions: One or more VNF Packages are onboarded in the NFVO
|
||||
# in ENABLED operational state.
|
||||
vnfpkginfos = self._create_and_upload_vnf_packages(['vnflcm1'])
|
||||
variables = ['vnfPackageId:' + vnfpkginfos[0].vnfpkgid]
|
||||
|
||||
rc, output = self._run('Disable Individual VNF Package', variables)
|
||||
|
||||
# Post-Conditions: The VNF Package is in operational state DISABLED
|
||||
self._delete_vnf_package(vnfpkginfos[0].vnfpkgid)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_enable_individual_vnf_package(self):
|
||||
# Pre-conditions: One or more VNF Packages are onboarded in the NFVO
|
||||
# in DISABLED operational state.
|
||||
vnfpkginfos = self._create_and_upload_vnf_packages(['vnflcm1'])
|
||||
self._disable_vnf_package(vnfpkginfos[0].vnfpkgid)
|
||||
variables = ['vnfPackageId:' + vnfpkginfos[0].vnfpkgid]
|
||||
|
||||
rc, output = self._run('Enable Individual VNF Package', variables)
|
||||
|
||||
# Post-Conditions: The VNF Package is in operational state ENABLED
|
||||
self._disable_and_delete_vnf_packages(vnfpkginfos)
|
||||
|
||||
self.assertEqual(0, rc)
|
||||
|
||||
def test_delete_individual_vnf_package(self):
|
||||
# Pre-conditions: One or more VNF packages are onboarded in the NFVO
|
||||
# in DISABLED operational state
|
||||
vnfpkginfos = self._create_and_upload_vnf_packages(['vnflcm1'])
|
||||
self._disable_vnf_package(vnfpkginfos[0].vnfpkgid)
|
||||
variables = ['disabledVnfPackageId:' + vnfpkginfos[0].vnfpkgid]
|
||||
|
||||
rc, output = self._run('DELETE Individual VNF Package', variables)
|
||||
|
||||
# Post-Conditions: The VNF Package is not available anymore in the NFVO
|
||||
self.assertEqual(0, rc)
|
|
@ -0,0 +1,50 @@
|
|||
heat_template_version: 2013-05-23
|
||||
description: 'default deployment flavour for Sample VNF'
|
||||
|
||||
parameters:
|
||||
nfv:
|
||||
type: json
|
||||
|
||||
resources:
|
||||
VDU1:
|
||||
type: OS::Heat::AutoScalingGroup
|
||||
properties:
|
||||
min_size: 1
|
||||
max_size: 50
|
||||
desired_capacity: 1
|
||||
resource:
|
||||
type: VDU1.yaml
|
||||
properties:
|
||||
flavor: { get_param: [ nfv, VDU, VDU1, flavor ] }
|
||||
image: { get_param: [ nfv, VDU, VDU1, image ] }
|
||||
name: vdu1
|
||||
net1: { get_resource: internalNW_1 }
|
||||
|
||||
VDU1_scale_out:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
scaling_adjustment: 1
|
||||
auto_scaling_group_id:
|
||||
get_resource: VDU1
|
||||
adjustment_type: change_in_capacity
|
||||
|
||||
VDU1_scale_in:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
scaling_adjustment: -1
|
||||
auto_scaling_group_id:
|
||||
get_resource: VDU1
|
||||
adjustment_type: change_in_capacity
|
||||
|
||||
internalNW_1:
|
||||
type: OS::Neutron::Net
|
||||
|
||||
internalNW_1_subnet:
|
||||
type: OS::Neutron::Subnet
|
||||
properties:
|
||||
ip_version: 4
|
||||
network:
|
||||
get_resource: internalNW_1
|
||||
cidr: 192.168.0.0/24
|
||||
|
||||
outputs: {}
|
|
@ -0,0 +1,45 @@
|
|||
heat_template_version: 2013-05-23
|
||||
description: 'Child HOT for mmp scale'
|
||||
|
||||
parameters:
|
||||
flavor:
|
||||
type: string
|
||||
image:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
net1:
|
||||
type: string
|
||||
|
||||
resources:
|
||||
VDU1:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: { get_param: flavor }
|
||||
name: { get_param: name }
|
||||
image: { get_param: image }
|
||||
networks:
|
||||
- port:
|
||||
get_resource: CP1
|
||||
- port:
|
||||
get_resource: CP2
|
||||
|
||||
CP1:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: { get_param: net1 }
|
||||
|
||||
CP2:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: { get_param: net1 }
|
||||
|
||||
outputs:
|
||||
mgmt_ip-VDU1:
|
||||
value:
|
||||
get_attr:
|
||||
- CP1
|
||||
- fixed_ips
|
||||
- 0
|
||||
- ip_address
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Simple deployment flavour for Sample VNF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- helloworld3_types.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
descriptor_id:
|
||||
type: string
|
||||
descriptor_version:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
product_name:
|
||||
type: string
|
||||
software_version:
|
||||
type: string
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
flavour_id:
|
||||
type: string
|
||||
flavour_description:
|
||||
type: string
|
||||
|
||||
substitution_mappings:
|
||||
node_type: SAMPLE.VNF
|
||||
properties:
|
||||
flavour_id: default
|
||||
requirements:
|
||||
virtual_link_external: []
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: SAMPLE.VNF
|
||||
properties:
|
||||
flavour_description: 'n-vnf'
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
scale: []
|
||||
scale_start: []
|
||||
scale_end: []
|
||||
heal: []
|
||||
heal_start: []
|
||||
heal_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
VDU1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: vdu1
|
||||
description: vdu1
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 50
|
||||
sw_image_data:
|
||||
name: DemoVirtualStorage
|
||||
version: '0.5.2'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6b813aa46bb90b4da216a4d19376593fa3f4fc7e617f03a92b7fe11e9a3981cbe8f0959dbebe36225e5f53dc4492341a4863cac4ed1ee0909f3fc78ef9c3e869
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
min_ram: 256 MB
|
||||
size: 12 GB
|
||||
|
||||
artifacts:
|
||||
sw_image:
|
||||
type: tosca.artifacts.nfv.SwImage
|
||||
file: ../Files/images/cirros-0.5.2-x86_64-disk.img
|
||||
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: m1.tiny
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 8192 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 2
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 200 GB
|
||||
|
||||
CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU1
|
||||
- virtual_link: internalNW_1
|
||||
|
||||
CP2:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
protocol:
|
||||
- associated_layer_protocol: ipv4
|
||||
address_data:
|
||||
- address_type: ip_address
|
||||
l3_address_data:
|
||||
ip_address_assignment: true
|
||||
floating_ip_activated: false
|
||||
requirements:
|
||||
- virtual_binding: VDU1
|
||||
- virtual_link: internalNW_1
|
||||
|
||||
internalNW_1:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
vl_profile:
|
||||
max_bitrate_requirements:
|
||||
root: 2000000
|
||||
min_bitrate_requirements:
|
||||
root: 1000000
|
||||
virtual_link_protocol_data:
|
||||
- associated_layer_protocol: ipv4
|
||||
l2_protocol_data:
|
||||
network_type: vlan
|
||||
l3_protocol_data:
|
||||
ip_version: ipv4
|
||||
cidr: '192.168.0.0/24'
|
||||
dhcp_enabled: true
|
||||
|
||||
policies:
|
||||
- vnf:
|
||||
type: tosca.policies.nfv.ScalingAspects
|
||||
properties:
|
||||
aspects:
|
||||
VDU1:
|
||||
name: vdu1
|
||||
description: vdu1
|
||||
max_scale_level: 49
|
||||
step_deltas:
|
||||
- delta_1
|
||||
|
||||
- vdu1_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- vdu1_scaling_aspect_deltas:
|
||||
type: tosca.policies.nfv.VduScalingAspectDeltas
|
||||
properties:
|
||||
aspect: VDU1
|
||||
deltas:
|
||||
delta_1:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- instantiation_levels:
|
||||
type: tosca.policies.nfv.InstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
n-vnf-min:
|
||||
description: n-msc-min structure
|
||||
scale_info:
|
||||
VDU1:
|
||||
scale_level: 0
|
||||
n-vnf-ten:
|
||||
description: n-msc-max structure
|
||||
scale_info:
|
||||
VDU1:
|
||||
scale_level: 9
|
||||
n-vnf-max:
|
||||
description: n-msc-max structure
|
||||
scale_info:
|
||||
VDU1:
|
||||
scale_level: 49
|
||||
default_level: n-vnf-min
|
||||
|
||||
- vdu1_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
n-vnf-min:
|
||||
number_of_instances: 1
|
||||
n-vnf-ten:
|
||||
number_of_instances: 10
|
||||
n-vnf-max:
|
||||
number_of_instances: 50
|
||||
targets: [ VDU1 ]
|
|
@ -0,0 +1,28 @@
|
|||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: VNF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- helloworld3_types.yaml
|
||||
- helloworld3_df_default.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
selected_flavour:
|
||||
type: string
|
||||
description: VNF deployment flavour selected by the consumer. Itis provided in the API.
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: SAMPLE.VNF
|
||||
properties:
|
||||
flavour_id: { get_input: selected_flavour }
|
||||
descriptor_id: 72700000-0000-0000-0000-202101290004
|
||||
provider: SAMPLE
|
||||
product_name: VNF
|
||||
software_version: '1.0'
|
||||
descriptor_version: 'VNF_1.0'
|
||||
vnfm_info:
|
||||
- Tacker
|
|
@ -0,0 +1,47 @@
|
|||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Sample template definition
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
|
||||
node_types:
|
||||
SAMPLE.VNF:
|
||||
derived_from: tosca.nodes.nfv.VNF
|
||||
properties:
|
||||
descriptor_id:
|
||||
type: string
|
||||
default: 72700000-0000-0000-0000-202101290004
|
||||
descriptor_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ 'VNF_1.0' ] ]
|
||||
default: 'VNF_1.0'
|
||||
provider:
|
||||
type: string
|
||||
constraints: [ valid_values: [ SAMPLE ] ]
|
||||
default: SAMPLE
|
||||
product_name:
|
||||
type: string
|
||||
constraints: [ valid_values: [ VNF ] ]
|
||||
default: VNF
|
||||
software_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '1.0' ] ]
|
||||
default: '1.0'
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
constraints: [ valid_values: [ 'Tacker' ] ]
|
||||
default: [ 'Tacker' ]
|
||||
flavour_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ default ] ]
|
||||
default: default
|
||||
flavour_description:
|
||||
type: string
|
||||
default: 'n-vnf'
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
type: tosca.interfaces.nfv.Vnflcm
|
|
@ -0,0 +1,7 @@
|
|||
TOSCA-Meta-File-Version: 1.0
|
||||
CSAR-Version: 1.1
|
||||
Created-by: Onboarding portal
|
||||
Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml
|
||||
|
||||
Name: Files/images/cirros-0.5.2-x86_64-disk.img
|
||||
Content-type: application/x-iso9066-image
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# 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 tacker.vnfm.lcm_user_data.utils as UserDataUtil
|
||||
|
||||
from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData
|
||||
|
||||
|
||||
class SampleUserData(AbstractUserData):
|
||||
@staticmethod
|
||||
def instantiate(base_hot_dict=None,
|
||||
vnfd_dict=None,
|
||||
inst_req_info=None,
|
||||
grant_info=None):
|
||||
api_param = UserDataUtil.get_diff_base_hot_param_from_api(
|
||||
base_hot_dict, inst_req_info)
|
||||
initial_param_dict = \
|
||||
UserDataUtil.create_initial_param_server_port_dict(base_hot_dict)
|
||||
vdu_flavor_dict = \
|
||||
UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict)
|
||||
vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict)
|
||||
cpd_vl_dict = UserDataUtil.create_network_dict(inst_req_info,
|
||||
initial_param_dict)
|
||||
final_param_dict = UserDataUtil.create_final_param_dict(
|
||||
initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict)
|
||||
return {**final_param_dict, **api_param}
|
16
tox.ini
16
tox.ini
|
@ -79,6 +79,22 @@ setenv = {[testenv]setenv}
|
|||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_kubernetes_multi_tenant run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-compliance-sol-api]
|
||||
passenv = {[testenv]passenv} *_PROXY
|
||||
commands_pre =
|
||||
git clone https://forge.etsi.org/rep/nfv/api-tests.git
|
||||
git -C api-tests checkout 2.6.1-fix-plu
|
||||
pip install -U -r{envdir}/api-tests/requirements.txt
|
||||
commands =
|
||||
stestr --test-path={toxinidir}/tacker/tests/compliance --top-dir={toxinidir} run --slowest --concurrency 1 {posargs}
|
||||
commands_post =
|
||||
rm -rf api-tests
|
||||
allowlist_externals =
|
||||
git
|
||||
rm
|
||||
|
||||
changedir = {envdir}
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
|
|
Loading…
Reference in New Issue