Revise FT of V2-API
This patch revise the FT of V2-API. The viewpoints of this revision are listed below: * Add some LCM operations in FT(such as Subscriptions and VNFLCM operation occurrences) * Revise VNF Package and request-body * Strengthen the check points by assertion * Fix the response-body related to the attribute that does not have the information to be returned Change-Id: I681800f52b4e2eb29c320c007ed1cf2901b61267
This commit is contained in:
parent
c6b0ca5fe3
commit
ff2e8da445
@ -273,6 +273,12 @@
|
|||||||
Multinodes job for SOL V2 devstack-based functional tests
|
Multinodes job for SOL V2 devstack-based functional tests
|
||||||
host-vars:
|
host-vars:
|
||||||
controller-tacker:
|
controller-tacker:
|
||||||
|
devstack_local_conf:
|
||||||
|
post-config:
|
||||||
|
# Skip notification endpoint testing in create subscription
|
||||||
|
$TACKER_CONF:
|
||||||
|
v2_nfvo:
|
||||||
|
test_callback_uri: False
|
||||||
tox_envlist: dsvm-functional-sol-v2
|
tox_envlist: dsvm-functional-sol-v2
|
||||||
|
|
||||||
- job:
|
- job:
|
||||||
|
@ -81,19 +81,24 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
|||||||
vnfSoftwareVersion=pkg_info.vnfSoftwareVersion,
|
vnfSoftwareVersion=pkg_info.vnfSoftwareVersion,
|
||||||
vnfdVersion=pkg_info.vnfdVersion,
|
vnfdVersion=pkg_info.vnfdVersion,
|
||||||
instantiationState='NOT_INSTANTIATED',
|
instantiationState='NOT_INSTANTIATED',
|
||||||
# optional fields
|
|
||||||
# NOTE: it is OK to absent but fill empty value to make them
|
|
||||||
# handle easy.
|
|
||||||
vnfInstanceName=body.get('vnfInstanceName', ""),
|
|
||||||
vnfInstanceDescription=body.get('vnfInstanceDescription', ""),
|
|
||||||
vnfConfigurableProperties=vnfd_prop['vnfConfigurableProperties'],
|
|
||||||
metadata=metadata,
|
|
||||||
extensions=vnfd_prop['extensions']
|
|
||||||
# not set at the moment. will be set when instantiate.
|
# not set at the moment. will be set when instantiate.
|
||||||
# vimConnectionInfo
|
# vimConnectionInfo
|
||||||
# instantiatedVnfInfo
|
# instantiatedVnfInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# set optional fields
|
||||||
|
if body.get('vnfInstanceName'):
|
||||||
|
inst.vnfInstanceName = body['vnfInstanceName']
|
||||||
|
if body.get('vnfInstanceDescription'):
|
||||||
|
inst.vnfInstanceDescription = body['vnfInstanceDescription']
|
||||||
|
if vnfd_prop.get('vnfConfigurableProperties'):
|
||||||
|
inst.vnfConfigurableProperties = vnfd_prop[
|
||||||
|
'vnfConfigurableProperties']
|
||||||
|
if metadata:
|
||||||
|
inst.metadata = metadata
|
||||||
|
if vnfd_prop.get('extensions'):
|
||||||
|
inst.extensions = vnfd_prop['extensions']
|
||||||
|
|
||||||
inst.create(context)
|
inst.create(context)
|
||||||
|
|
||||||
self.nfvo_client.send_inst_create_notification(context, inst,
|
self.nfvo_client.send_inst_create_notification(context, inst,
|
||||||
|
@ -17,6 +17,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
import urllib
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
@ -38,7 +39,7 @@ VNF_PACKAGE_UPLOAD_TIMEOUT = 300
|
|||||||
|
|
||||||
|
|
||||||
class BaseSolV2Test(base.BaseTestCase):
|
class BaseSolV2Test(base.BaseTestCase):
|
||||||
"""Base test case class for SOL v2 functionl tests."""
|
"""Base test case class for SOL v2 functional tests."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@ -63,6 +64,10 @@ class BaseSolV2Test(base.BaseTestCase):
|
|||||||
cls.tacker_client = http_client.HttpClient(auth)
|
cls.tacker_client = http_client.HttpClient(auth)
|
||||||
cls.neutron_client = http_client.HttpClient(auth,
|
cls.neutron_client = http_client.HttpClient(auth,
|
||||||
service_type='network')
|
service_type='network')
|
||||||
|
cls.glance_client = http_client.HttpClient(auth,
|
||||||
|
service_type='image')
|
||||||
|
cls.nova_client = http_client.HttpClient(auth,
|
||||||
|
service_type='compute')
|
||||||
cls.heat_client = heat_utils.HeatClient(vim_info)
|
cls.heat_client = heat_utils.HeatClient(vim_info)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -138,6 +143,11 @@ class BaseSolV2Test(base.BaseTestCase):
|
|||||||
|
|
||||||
cls.tacker_client.do_request(path, "DELETE")
|
cls.tacker_client.do_request(path, "DELETE")
|
||||||
|
|
||||||
|
def get_vnf_package(self, pkg_id):
|
||||||
|
path = "/vnfpkgm/v1/vnf_packages/{}".format(pkg_id)
|
||||||
|
resp, body = self.tacker_client.do_request(path, "GET")
|
||||||
|
return body
|
||||||
|
|
||||||
def get_network_ids(self, networks):
|
def get_network_ids(self, networks):
|
||||||
path = "/v2.0/networks"
|
path = "/v2.0/networks"
|
||||||
resp, body = self.neutron_client.do_request(path, "GET")
|
resp, body = self.neutron_client.do_request(path, "GET")
|
||||||
@ -156,6 +166,100 @@ class BaseSolV2Test(base.BaseTestCase):
|
|||||||
subnet_ids[subnet['name']] = subnet['id']
|
subnet_ids[subnet['name']] = subnet['id']
|
||||||
return subnet_ids
|
return subnet_ids
|
||||||
|
|
||||||
|
def create_network(self, name):
|
||||||
|
path = "/v2.0/networks"
|
||||||
|
req_body = {
|
||||||
|
"network": {
|
||||||
|
# "admin_state_up": true,
|
||||||
|
"name": name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
resp, resp_body = self.neutron_client.do_request(
|
||||||
|
path, "POST", body=req_body)
|
||||||
|
return resp_body['network']['id']
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Failed, create network for name=<%s>, %s" %
|
||||||
|
(name, e))
|
||||||
|
|
||||||
|
def delete_network(self, net_id):
|
||||||
|
path = "/v2.0/networks/{}".format(net_id)
|
||||||
|
try:
|
||||||
|
self.neutron_client.do_request(path, "DELETE")
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Failed, delete network for id=<%s>, %s" %
|
||||||
|
(net_id, e))
|
||||||
|
|
||||||
|
def create_subnet(self, net_id, sub_name, sub_range, ip_version):
|
||||||
|
path = "/v2.0/subnets"
|
||||||
|
req_body = {
|
||||||
|
"subnet": {
|
||||||
|
"name": sub_name,
|
||||||
|
"network_id": net_id,
|
||||||
|
"cidr": sub_range,
|
||||||
|
"ip_version": ip_version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
resp, resp_body = self.neutron_client.do_request(
|
||||||
|
path, "POST", body=req_body)
|
||||||
|
return resp_body['subnet']['id']
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Failed, create subnet for name=<%s>, %s" %
|
||||||
|
(sub_name, e))
|
||||||
|
|
||||||
|
def delete_subnet(self, sub_id):
|
||||||
|
path = "/v2.0/subnets/{}".format(sub_id)
|
||||||
|
try:
|
||||||
|
self.neutron_client.do_request(path, "DELETE")
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Failed, delete subnet for id=<%s>, %s" %
|
||||||
|
(sub_id, e))
|
||||||
|
|
||||||
|
def create_port(self, network_id, name):
|
||||||
|
path = "/v2.0/ports"
|
||||||
|
req_body = {
|
||||||
|
'port': {
|
||||||
|
'network_id': network_id,
|
||||||
|
'name': name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
resp, resp_body = self.neutron_client.do_request(
|
||||||
|
path, "POST", body=req_body)
|
||||||
|
return resp_body['port']['id']
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Failed, create port for net_id=<%s>, %s" %
|
||||||
|
(network_id, e))
|
||||||
|
|
||||||
|
def delete_port(self, port_id):
|
||||||
|
path = "/v2.0/ports/{}".format(port_id)
|
||||||
|
try:
|
||||||
|
self.neutron_client.do_request(path, "DELETE")
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Failed, delete port for id=<%s>, %s" %
|
||||||
|
(port_id, e))
|
||||||
|
|
||||||
|
def get_image_id(self, image_name):
|
||||||
|
path = "/v2.0/images"
|
||||||
|
resp, resp_body = self.glance_client.do_request(path, "GET")
|
||||||
|
|
||||||
|
image_id = None
|
||||||
|
for image in resp_body.get('images'):
|
||||||
|
if image_name == image['name']:
|
||||||
|
image_id = image['id']
|
||||||
|
return image_id
|
||||||
|
|
||||||
|
def get_server_details(self, server_name):
|
||||||
|
path = "/servers/detail"
|
||||||
|
resp, resp_body = self.nova_client.do_request(path, "GET")
|
||||||
|
|
||||||
|
server_details = None
|
||||||
|
for server in resp_body.get('servers'):
|
||||||
|
if server_name == server['name']:
|
||||||
|
server_details = server
|
||||||
|
return server_details
|
||||||
|
|
||||||
def create_vnf_instance(self, req_body):
|
def create_vnf_instance(self, req_body):
|
||||||
path = "/vnflcm/v2/vnf_instances"
|
path = "/vnflcm/v2/vnf_instances"
|
||||||
return self.tacker_client.do_request(
|
return self.tacker_client.do_request(
|
||||||
@ -171,6 +275,13 @@ class BaseSolV2Test(base.BaseTestCase):
|
|||||||
return self.tacker_client.do_request(
|
return self.tacker_client.do_request(
|
||||||
path, "GET", version="2.0.0")
|
path, "GET", version="2.0.0")
|
||||||
|
|
||||||
|
def list_vnf_instance(self, filter_expr=None):
|
||||||
|
path = "/vnflcm/v2/vnf_instances"
|
||||||
|
if filter_expr:
|
||||||
|
path = "{}?{}".format(path, urllib.parse.urlencode(filter_expr))
|
||||||
|
return self.tacker_client.do_request(
|
||||||
|
path, "GET", version="2.0.0")
|
||||||
|
|
||||||
def instantiate_vnf_instance(self, inst_id, req_body):
|
def instantiate_vnf_instance(self, inst_id, req_body):
|
||||||
path = "/vnflcm/v2/vnf_instances/{}/instantiate".format(inst_id)
|
path = "/vnflcm/v2/vnf_instances/{}/instantiate".format(inst_id)
|
||||||
return self.tacker_client.do_request(
|
return self.tacker_client.do_request(
|
||||||
@ -196,3 +307,92 @@ class BaseSolV2Test(base.BaseTestCase):
|
|||||||
continue
|
continue
|
||||||
else: # FAILED_TEMP or ROLLED_BACK
|
else: # FAILED_TEMP or ROLLED_BACK
|
||||||
raise Exception("Operation failed. state: %s" % state)
|
raise Exception("Operation failed. state: %s" % state)
|
||||||
|
|
||||||
|
def wait_lcmocc_failed_temp(self, lcmocc_id):
|
||||||
|
# NOTE: It is not necessary to set timeout because the operation
|
||||||
|
# itself set timeout and the state will become 'FAILED_TEMP'.
|
||||||
|
path = "/vnflcm/v2/vnf_lcm_op_occs/{}".format(lcmocc_id)
|
||||||
|
while True:
|
||||||
|
time.sleep(5)
|
||||||
|
_, body = self.tacker_client.do_request(
|
||||||
|
path, "GET", expected_status=[200], version="2.0.0")
|
||||||
|
state = body['operationState']
|
||||||
|
if state == 'FAILED_TEMP':
|
||||||
|
return
|
||||||
|
elif state in ['STARTING', 'PROCESSING']:
|
||||||
|
continue
|
||||||
|
elif state == 'COMPLETED':
|
||||||
|
raise Exception("Operation unexpected COMPLETED.")
|
||||||
|
else: # ROLLED_BACK
|
||||||
|
raise Exception("Operation failed. state: %s" % state)
|
||||||
|
|
||||||
|
def show_lcmocc(self, lcmocc_id):
|
||||||
|
path = "/vnflcm/v2/vnf_lcm_op_occs/{}".format(lcmocc_id)
|
||||||
|
return self.tacker_client.do_request(
|
||||||
|
path, "GET", version="2.0.0")
|
||||||
|
|
||||||
|
def list_lcmocc(self, filter_expr=None):
|
||||||
|
path = "/vnflcm/v2/vnf_lcm_op_occs"
|
||||||
|
if filter_expr:
|
||||||
|
path = "{}?{}".format(path, urllib.parse.urlencode(filter_expr))
|
||||||
|
return self.tacker_client.do_request(
|
||||||
|
path, "GET", version="2.0.0")
|
||||||
|
|
||||||
|
def create_subscription(self, req_body):
|
||||||
|
path = "/vnflcm/v2/subscriptions"
|
||||||
|
return self.tacker_client.do_request(
|
||||||
|
path, "POST", body=req_body, version="2.0.0")
|
||||||
|
|
||||||
|
def delete_subscription(self, sub_id):
|
||||||
|
path = "/vnflcm/v2/subscriptions/{}".format(sub_id)
|
||||||
|
return self.tacker_client.do_request(
|
||||||
|
path, "DELETE", version="2.0.0")
|
||||||
|
|
||||||
|
def show_subscription(self, sub_id):
|
||||||
|
path = "/vnflcm/v2/subscriptions/{}".format(sub_id)
|
||||||
|
return self.tacker_client.do_request(
|
||||||
|
path, "GET", version="2.0.0")
|
||||||
|
|
||||||
|
def list_subscriptions(self, filter_expr=None):
|
||||||
|
path = "/vnflcm/v2/subscriptions"
|
||||||
|
if filter_expr:
|
||||||
|
path = "{}?{}".format(path, urllib.parse.urlencode(filter_expr))
|
||||||
|
return self.tacker_client.do_request(
|
||||||
|
path, "GET", version="2.0.0")
|
||||||
|
|
||||||
|
def _check_resp_headers(self, resp, supported_headers):
|
||||||
|
unsupported_headers = ['Link', 'Retry-After',
|
||||||
|
'Content-Range', 'WWW-Authenticate']
|
||||||
|
for s in supported_headers:
|
||||||
|
if s not in resp.headers:
|
||||||
|
raise Exception("Supported header doesn't exist: %s" % s)
|
||||||
|
for u in unsupported_headers:
|
||||||
|
if u in resp.headers:
|
||||||
|
raise Exception("Unsupported header exist: %s" % u)
|
||||||
|
|
||||||
|
def check_resp_headers_in_create(self, resp):
|
||||||
|
# includes location header and response body
|
||||||
|
supported_headers = ['Version', 'Location', 'Content-Type',
|
||||||
|
'Accept-Ranges']
|
||||||
|
self._check_resp_headers(resp, supported_headers)
|
||||||
|
|
||||||
|
def check_resp_headers_in_operation_task(self, resp):
|
||||||
|
# includes location header and no response body
|
||||||
|
supported_headers = ['Version', 'Location']
|
||||||
|
self._check_resp_headers(resp, supported_headers)
|
||||||
|
|
||||||
|
def check_resp_headers_in_get(self, resp):
|
||||||
|
# includes response body and no location header
|
||||||
|
supported_headers = ['Version', 'Content-Type',
|
||||||
|
'Accept-Ranges']
|
||||||
|
self._check_resp_headers(resp, supported_headers)
|
||||||
|
|
||||||
|
def check_resp_headers_in_delete(self, resp):
|
||||||
|
# no location header and response body
|
||||||
|
supported_headers = ['Version']
|
||||||
|
self._check_resp_headers(resp, supported_headers)
|
||||||
|
|
||||||
|
def check_resp_body(self, body, expected_attrs):
|
||||||
|
for attr in expected_attrs:
|
||||||
|
if attr not in body:
|
||||||
|
raise Exception("Expected attribute doesn't exist: %s" % attr)
|
||||||
|
@ -16,226 +16,451 @@
|
|||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
|
||||||
|
def sub1_create():
|
||||||
|
# All attributes are set.
|
||||||
|
# NOTE: All of the following cardinality attributes are set.
|
||||||
|
# In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||||
|
# - 0..1 (1)
|
||||||
|
# - 0..N (2 or more)
|
||||||
|
# - 1
|
||||||
|
# - 1..N (2 or more)
|
||||||
|
vnf_provider_1 = {
|
||||||
|
"vnfProvider": "dummy-vnfProvider-1",
|
||||||
|
"vnfProducts": [
|
||||||
|
{
|
||||||
|
"vnfProductName": "dummy-vnfProductName-1-1",
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.0,
|
||||||
|
"vnfdVersions": [1.0, 2.0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.1,
|
||||||
|
"vnfdVersions": [1.1, 2.1]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vnfProductName": "dummy-vnfProductName-1-2",
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.0,
|
||||||
|
"vnfdVersions": [1.0, 2.0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.1,
|
||||||
|
"vnfdVersions": [1.1, 2.1]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
vnf_provider_2 = {
|
||||||
|
"vnfProvider": "dummy-vnfProvider-2",
|
||||||
|
"vnfProducts": [
|
||||||
|
{
|
||||||
|
"vnfProductName": "dummy-vnfProductName-2-1",
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.0,
|
||||||
|
"vnfdVersions": [1.0, 2.0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.1,
|
||||||
|
"vnfdVersions": [1.1, 2.1]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vnfProductName": "dummy-vnfProductName-2-2",
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.0,
|
||||||
|
"vnfdVersions": [1.0, 2.0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"vnfSoftwareVersion": 1.1,
|
||||||
|
"vnfdVersions": [1.1, 2.1]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# NOTE: The following is omitted because authType is BASIC in this case
|
||||||
|
# - "paramsOauth2ClientCredentials"
|
||||||
|
return {
|
||||||
|
"filter": {
|
||||||
|
"vnfInstanceSubscriptionFilter": {
|
||||||
|
"vnfdIds": [
|
||||||
|
"dummy-vnfdId-1",
|
||||||
|
"dummy-vnfdId-2"
|
||||||
|
],
|
||||||
|
"vnfProductsFromProviders": [
|
||||||
|
vnf_provider_1,
|
||||||
|
vnf_provider_2
|
||||||
|
],
|
||||||
|
"vnfInstanceIds": [
|
||||||
|
"dummy-vnfInstanceId-1",
|
||||||
|
"dummy-vnfInstanceId-2"
|
||||||
|
],
|
||||||
|
"vnfInstanceNames": [
|
||||||
|
"dummy-vnfInstanceName-1",
|
||||||
|
"dummy-vnfInstanceName-2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notificationTypes": [
|
||||||
|
"VnfIdentifierCreationNotification",
|
||||||
|
"VnfLcmOperationOccurrenceNotification"
|
||||||
|
],
|
||||||
|
"operationTypes": [
|
||||||
|
"INSTANTIATE",
|
||||||
|
"TERMINATE"
|
||||||
|
],
|
||||||
|
"operationStates": [
|
||||||
|
"COMPLETED",
|
||||||
|
"FAILED"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"callbackUri": "http://127.0.0.1/",
|
||||||
|
"authentication": {
|
||||||
|
"authType": [
|
||||||
|
"BASIC"
|
||||||
|
],
|
||||||
|
"paramsBasic": {
|
||||||
|
"password": "test_pass",
|
||||||
|
"userName": "test_user"
|
||||||
|
},
|
||||||
|
# "paramsOauth2ClientCredentials": omitted,
|
||||||
|
},
|
||||||
|
"verbosity": "SHORT"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sub2_create():
|
||||||
|
# Omit except for required attributes
|
||||||
|
# NOTE: Only the following cardinality attributes are set.
|
||||||
|
# - 1
|
||||||
|
# - 1..N (1)
|
||||||
|
return {
|
||||||
|
"callbackUri": "http://127.0.0.1/"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def sample1_create(vnfd_id):
|
def sample1_create(vnfd_id):
|
||||||
|
# All attributes are set.
|
||||||
|
# NOTE: All of the following cardinality attributes are set.
|
||||||
|
# In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||||
|
# - 0..1 (1)
|
||||||
|
# - 0..N (2 or more)
|
||||||
|
# - 1
|
||||||
|
# - 1..N (2 or more)
|
||||||
return {
|
return {
|
||||||
"vnfdId": vnfd_id,
|
"vnfdId": vnfd_id,
|
||||||
"vnfInstanceName": "sample1",
|
"vnfInstanceName": "sample1",
|
||||||
"vnfInstanceDescription": "test sample1"
|
"vnfInstanceDescription": "test sample1",
|
||||||
|
"metadata": {"dummy-key": "dummy-val"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def sample1_terminate():
|
def sample1_terminate():
|
||||||
|
# All attributes are set.
|
||||||
|
# NOTE: All of the following cardinality attributes are set.
|
||||||
|
# In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||||
|
# - 0..1 (1)
|
||||||
|
# - 0..N (2 or more)
|
||||||
|
# - 1
|
||||||
|
# - 1..N (2 or more)
|
||||||
|
return {
|
||||||
|
"terminationType": "GRACEFUL",
|
||||||
|
"gracefulTerminationTimeout": 5,
|
||||||
|
"additionalParams": {"dummy-key": "dummy-val"}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sample1_instantiate(net_ids, subnets, ports, auth_url):
|
||||||
|
# All attributes are set.
|
||||||
|
# NOTE: All of the following cardinality attributes are set.
|
||||||
|
# In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||||
|
# - 0..1 (1)
|
||||||
|
# - 0..N (2 or more)
|
||||||
|
# - 1
|
||||||
|
# - 1..N (2 or more)
|
||||||
|
|
||||||
|
vim_id_1 = uuidutils.generate_uuid()
|
||||||
|
vim_id_2 = uuidutils.generate_uuid()
|
||||||
|
link_port_id_1 = uuidutils.generate_uuid()
|
||||||
|
link_port_id_2 = uuidutils.generate_uuid()
|
||||||
|
|
||||||
|
# NOTE: The following is not supported so it is omitted
|
||||||
|
# - "segmentationId"
|
||||||
|
# - "addressRange"
|
||||||
|
# - Multiple "cpProtocolData"
|
||||||
|
# - Multiple "fixedAddresses"
|
||||||
|
ext_vl_1 = {
|
||||||
|
"id": uuidutils.generate_uuid(),
|
||||||
|
"vimConnectionId": vim_id_1,
|
||||||
|
"resourceProviderId": "Company",
|
||||||
|
"resourceId": net_ids['net0'],
|
||||||
|
"extCps": [
|
||||||
|
{
|
||||||
|
"cpdId": "VDU1_CP1",
|
||||||
|
"cpConfig": {
|
||||||
|
"VDU1_CP1": {
|
||||||
|
"parentCpConfigId": uuidutils.generate_uuid(),
|
||||||
|
# "linkPortId": omitted,
|
||||||
|
"cpProtocolData": [{
|
||||||
|
"layerProtocol": "IP_OVER_ETHERNET",
|
||||||
|
"ipOverEthernet": {
|
||||||
|
# "macAddress": omitted,
|
||||||
|
# "segmentationId": omitted,
|
||||||
|
"ipAddresses": [{
|
||||||
|
"type": "IPV4",
|
||||||
|
# "fixedAddresses": omitted,
|
||||||
|
"numDynamicAddresses": 1,
|
||||||
|
# "addressRange": omitted,
|
||||||
|
"subnetId": subnets['subnet0']}]}}]
|
||||||
|
},
|
||||||
|
# { "VDU1_CP1_2": omitted }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cpdId": "VDU2_CP1-1",
|
||||||
|
"cpConfig": {
|
||||||
|
"VDU2_CP1-1": {
|
||||||
|
"parentCpConfigId": uuidutils.generate_uuid(),
|
||||||
|
"linkPortId": link_port_id_1,
|
||||||
|
"cpProtocolData": [{
|
||||||
|
"layerProtocol": "IP_OVER_ETHERNET",
|
||||||
|
"ipOverEthernet": {
|
||||||
|
# "macAddress": omitted,
|
||||||
|
# "segmentationId": omitted,
|
||||||
|
"ipAddresses": [{
|
||||||
|
"type": "IPV4",
|
||||||
|
# "fixedAddresses": omitted,
|
||||||
|
"numDynamicAddresses": 1,
|
||||||
|
# "addressRange": omitted,
|
||||||
|
"subnetId": subnets['subnet0']
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
# { "VDU2_CP1_2": omitted }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cpdId": "VDU2_CP1-2",
|
||||||
|
"cpConfig": {
|
||||||
|
"VDU2_CP1-2": {
|
||||||
|
"parentCpConfigId": uuidutils.generate_uuid(),
|
||||||
|
"linkPortId": link_port_id_2,
|
||||||
|
"cpProtocolData": [{
|
||||||
|
"layerProtocol": "IP_OVER_ETHERNET",
|
||||||
|
"ipOverEthernet": {
|
||||||
|
# "macAddress": omitted,
|
||||||
|
# "segmentationId": omitted,
|
||||||
|
"ipAddresses": [{
|
||||||
|
"type": "IPV4",
|
||||||
|
# "fixedAddresses": omitted,
|
||||||
|
"numDynamicAddresses": 1,
|
||||||
|
# "addressRange": omitted,
|
||||||
|
"subnetId": subnets['subnet0']
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
# { "VDU2_CP1_2": omitted }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extLinkPorts": [
|
||||||
|
{
|
||||||
|
"id": link_port_id_1,
|
||||||
|
"resourceHandle": {
|
||||||
|
"resourceId": ports['VDU2_CP1-1']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
# NOTE: Set dummy value because it is set by "additionalParams"
|
||||||
|
{
|
||||||
|
"id": link_port_id_2,
|
||||||
|
"resourceHandle": {
|
||||||
|
"resourceId": "dummy-id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# NOTE: The following is not supported so it is omitted
|
||||||
|
# - "segmentationId"
|
||||||
|
# - "addressRange"
|
||||||
|
# - Multiple "cpProtocolData"
|
||||||
|
# - Multiple "fixedAddresses"
|
||||||
|
ext_vl_2 = {
|
||||||
|
"id": uuidutils.generate_uuid(),
|
||||||
|
"vimConnectionId": vim_id_1,
|
||||||
|
"resourceProviderId": "Company",
|
||||||
|
"resourceId": net_ids['ft-net0'],
|
||||||
|
"extCps": [
|
||||||
|
{
|
||||||
|
"cpdId": "VDU1_CP2",
|
||||||
|
"cpConfig": {
|
||||||
|
"VDU1_CP2": {
|
||||||
|
"parentCpConfigId": uuidutils.generate_uuid(),
|
||||||
|
# "linkPortId": omitted,
|
||||||
|
"cpProtocolData": [{
|
||||||
|
"layerProtocol": "IP_OVER_ETHERNET",
|
||||||
|
"ipOverEthernet": {
|
||||||
|
# "macAddress": omitted,
|
||||||
|
# "segmentationId": omitted,
|
||||||
|
"ipAddresses": [{
|
||||||
|
"type": "IPV4",
|
||||||
|
# "fixedAddresses": omitted,
|
||||||
|
"numDynamicAddresses": 1,
|
||||||
|
# "addressRange": omitted,
|
||||||
|
"subnetId": subnets['ft-ipv4-subnet0']}
|
||||||
|
]}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
# { "VDU1_CP2_2": omitted }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cpdId": "VDU2_CP2",
|
||||||
|
"cpConfig": {
|
||||||
|
"VDU2_CP2": {
|
||||||
|
"parentCpConfigId": uuidutils.generate_uuid(),
|
||||||
|
# "linkPortId": omitted,
|
||||||
|
"cpProtocolData": [{
|
||||||
|
"layerProtocol": "IP_OVER_ETHERNET",
|
||||||
|
"ipOverEthernet": {
|
||||||
|
"macAddress": "fa:16:3e:fa:22:75",
|
||||||
|
# "segmentationId": omitted,
|
||||||
|
"ipAddresses": [{
|
||||||
|
"type": "IPV4",
|
||||||
|
"fixedAddresses": [
|
||||||
|
"100.100.100.11",
|
||||||
|
# omitted
|
||||||
|
],
|
||||||
|
# "numDynamicAddresses": omitted,
|
||||||
|
# "addressRange": omitted,
|
||||||
|
"subnetId": subnets['ft-ipv4-subnet0']
|
||||||
|
}, {
|
||||||
|
"type": "IPV6",
|
||||||
|
# "fixedAddresses": omitted,
|
||||||
|
# "numDynamicAddresses": omitted,
|
||||||
|
"numDynamicAddresses": 1,
|
||||||
|
# "addressRange": omitted,
|
||||||
|
"subnetId": subnets['ft-ipv6-subnet0']
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
# { "VDU2_CP2_2": omitted }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
# "extLinkPorts": omitted
|
||||||
|
}
|
||||||
|
# NOTE: "vnfLinkPort" is omitted because it is not supported
|
||||||
|
ext_mngd_vl_1 = {
|
||||||
|
"id": uuidutils.generate_uuid(),
|
||||||
|
"vnfVirtualLinkDescId": "internalVL1",
|
||||||
|
"vimConnectionId": vim_id_1,
|
||||||
|
"resourceProviderId": "Company",
|
||||||
|
"resourceId": net_ids['net_mgmt'],
|
||||||
|
# "vnfLinkPort": omitted,
|
||||||
|
"extManagedMultisiteVirtualLinkId": uuidutils.generate_uuid()
|
||||||
|
}
|
||||||
|
# NOTE: "vnfLinkPort" is omitted because it is not supported
|
||||||
|
ext_mngd_vl_2 = {
|
||||||
|
"id": uuidutils.generate_uuid(),
|
||||||
|
"vnfVirtualLinkDescId": "internalVL2",
|
||||||
|
"vimConnectionId": vim_id_1,
|
||||||
|
"resourceProviderId": "Company",
|
||||||
|
"resourceId": net_ids['net1'],
|
||||||
|
# "vnfLinkPort": omitted,
|
||||||
|
"extManagedMultisiteVirtualLinkId": uuidutils.generate_uuid()
|
||||||
|
}
|
||||||
|
vim_1 = {
|
||||||
|
"vimId": vim_id_1,
|
||||||
|
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||||
|
"interfaceInfo": {"endpoint": auth_url},
|
||||||
|
"accessInfo": {
|
||||||
|
"username": "nfv_user",
|
||||||
|
"region": "RegionOne",
|
||||||
|
"password": "devstack",
|
||||||
|
"project": "nfv",
|
||||||
|
"projectDomain": "Default",
|
||||||
|
"userDomain": "Default"
|
||||||
|
},
|
||||||
|
"extra": {"dummy-key": "dummy-val"}
|
||||||
|
}
|
||||||
|
vim_2 = {
|
||||||
|
"vimId": vim_id_2,
|
||||||
|
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||||
|
"interfaceInfo": {"endpoint": auth_url},
|
||||||
|
"accessInfo": {
|
||||||
|
"username": "dummy_user",
|
||||||
|
"region": "RegionOne",
|
||||||
|
"password": "dummy_password",
|
||||||
|
"project": "dummy_project",
|
||||||
|
"projectDomain": "Default",
|
||||||
|
"userDomain": "Default"
|
||||||
|
},
|
||||||
|
"extra": {"dummy-key": "dummy-val"}
|
||||||
|
}
|
||||||
|
addParams = {
|
||||||
|
"lcm-operation-user-data": "./UserData/userdata.py",
|
||||||
|
"lcm-operation-user-data-class": "UserData",
|
||||||
|
"nfv": {"CP": {"VDU2_CP1-2": {"port": ports['VDU2_CP1-2']}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"flavourId": "simple",
|
||||||
|
"instantiationLevelId": "instantiation_level_1",
|
||||||
|
"extVirtualLinks": [
|
||||||
|
ext_vl_1,
|
||||||
|
ext_vl_2
|
||||||
|
],
|
||||||
|
"extManagedVirtualLinks": [
|
||||||
|
ext_mngd_vl_1,
|
||||||
|
ext_mngd_vl_2
|
||||||
|
],
|
||||||
|
"vimConnectionInfo": {
|
||||||
|
"vim1": vim_1,
|
||||||
|
"vim2": vim_2
|
||||||
|
},
|
||||||
|
"localizationLanguage": "ja",
|
||||||
|
"additionalParams": addParams,
|
||||||
|
"extensions": {"dummy-key": "dummy-val"}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sample2_create(vnfd_id):
|
||||||
|
# Omit except for required attributes
|
||||||
|
# NOTE: Only the following cardinality attributes are set.
|
||||||
|
# - 1
|
||||||
|
# - 1..N (1)
|
||||||
|
return {
|
||||||
|
"vnfdId": vnfd_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sample2_terminate():
|
||||||
|
# Omit except for required attributes
|
||||||
|
# NOTE: Only the following cardinality attributes are set.
|
||||||
|
# - 1
|
||||||
|
# - 1..N (1)
|
||||||
return {
|
return {
|
||||||
"terminationType": "FORCEFUL"
|
"terminationType": "FORCEFUL"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def sample1_instantiate(net_ids, subnet_ids, auth_url):
|
def sample2_instantiate():
|
||||||
ext_vl_1 = {
|
# Omit except for required attributes
|
||||||
"id": uuidutils.generate_uuid(),
|
# NOTE: Only the following cardinality attributes are set.
|
||||||
"resourceId": net_ids['net0'],
|
# - 1
|
||||||
"extCps": [
|
# - 1..N (1)
|
||||||
{
|
|
||||||
"cpdId": "VDU1_CP1",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU1_CP1_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"numDynamicAddresses": 1}]}}]}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cpdId": "VDU2_CP1",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU2_CP1_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"fixedAddresses": ["10.10.0.101"]}]}}]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
ext_vl_2 = {
|
|
||||||
"id": uuidutils.generate_uuid(),
|
|
||||||
"resourceId": net_ids['net1'],
|
|
||||||
"extCps": [
|
|
||||||
{
|
|
||||||
"cpdId": "VDU1_CP2",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU1_CP2_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"numDynamicAddresses": 1,
|
|
||||||
"subnetId": subnet_ids['subnet1']}]}}]}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cpdId": "VDU2_CP2",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU2_CP2_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"fixedAddresses": ["10.10.1.101"],
|
|
||||||
"subnetId": subnet_ids['subnet1']}]}}]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"flavourId": "simple",
|
"flavourId": "simple"
|
||||||
"instantiationLevelId": "instantiation_level_1",
|
|
||||||
"extVirtualLinks": [
|
|
||||||
ext_vl_1,
|
|
||||||
ext_vl_2
|
|
||||||
],
|
|
||||||
"extManagedVirtualLinks": [
|
|
||||||
{
|
|
||||||
"id": uuidutils.generate_uuid(),
|
|
||||||
"vnfVirtualLinkDescId": "internalVL1",
|
|
||||||
"resourceId": net_ids['net_mgmt']
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"vimConnectionInfo": {
|
|
||||||
"vim1": {
|
|
||||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
|
||||||
"vimId": uuidutils.generate_uuid(),
|
|
||||||
"interfaceInfo": {"endpoint": auth_url},
|
|
||||||
"accessInfo": {
|
|
||||||
"username": "nfv_user",
|
|
||||||
"region": "RegionOne",
|
|
||||||
"password": "devstack",
|
|
||||||
"project": "nfv",
|
|
||||||
"projectDomain": "Default",
|
|
||||||
"userDomain": "Default"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def sample2_create(vnfd_id):
|
|
||||||
return {
|
|
||||||
"vnfdId": vnfd_id,
|
|
||||||
"vnfInstanceName": "sample2",
|
|
||||||
"vnfInstanceDescription": "test sample2"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def sample2_terminate():
|
|
||||||
return {
|
|
||||||
"terminationType": "GRACEFUL",
|
|
||||||
"gracefulTerminationTimeout": 5
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def sample2_instantiate(net_ids, subnet_ids, auth_url):
|
|
||||||
ext_vl_1 = {
|
|
||||||
"id": uuidutils.generate_uuid(),
|
|
||||||
"resourceId": net_ids['net0'],
|
|
||||||
"extCps": [
|
|
||||||
{
|
|
||||||
"cpdId": "VDU1_CP1",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU1_CP1_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"numDynamicAddresses": 1}]}}]}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cpdId": "VDU2_CP1",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU2_CP1_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"fixedAddresses": ["10.10.0.102"]}]}}]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
ext_vl_2 = {
|
|
||||||
"id": uuidutils.generate_uuid(),
|
|
||||||
"resourceId": net_ids['net1'],
|
|
||||||
"extCps": [
|
|
||||||
{
|
|
||||||
"cpdId": "VDU1_CP2",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU1_CP2_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"numDynamicAddresses": 1,
|
|
||||||
"subnetId": subnet_ids['subnet1']}]}}]}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cpdId": "VDU2_CP2",
|
|
||||||
"cpConfig": {
|
|
||||||
"VDU2_CP2_1": {
|
|
||||||
"cpProtocolData": [{
|
|
||||||
"layerProtocol": "IP_OVER_ETHERNET",
|
|
||||||
"ipOverEthernet": {
|
|
||||||
"ipAddresses": [{
|
|
||||||
"type": "IPV4",
|
|
||||||
"fixedAddresses": ["10.10.1.102"],
|
|
||||||
"subnetId": subnet_ids['subnet1']}]}}]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"flavourId": "simple",
|
|
||||||
"instantiationLevelId": "instantiation_level_1",
|
|
||||||
"extVirtualLinks": [
|
|
||||||
ext_vl_1,
|
|
||||||
ext_vl_2
|
|
||||||
],
|
|
||||||
"extManagedVirtualLinks": [
|
|
||||||
{
|
|
||||||
"id": uuidutils.generate_uuid(),
|
|
||||||
"vnfVirtualLinkDescId": "internalVL1",
|
|
||||||
"resourceId": net_ids['net_mgmt']
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"vimConnectionInfo": {
|
|
||||||
"vim1": {
|
|
||||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
|
||||||
"vimId": uuidutils.generate_uuid(),
|
|
||||||
"interfaceInfo": {"endpoint": auth_url},
|
|
||||||
"accessInfo": {
|
|
||||||
"username": "nfv_user",
|
|
||||||
"region": "RegionOne",
|
|
||||||
"password": "devstack",
|
|
||||||
"project": "nfv",
|
|
||||||
"projectDomain": "Default",
|
|
||||||
"userDomain": "Default"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalParams": {
|
|
||||||
"lcm-operation-user-data": "./UserData/userdata_default.py",
|
|
||||||
"lcm-operation-user-data-class": "DefaultUserData"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ parameters:
|
|||||||
type: string
|
type: string
|
||||||
net5:
|
net5:
|
||||||
type: string
|
type: string
|
||||||
subnet:
|
subnet1:
|
||||||
|
type: string
|
||||||
|
subnet2:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
@ -27,7 +29,7 @@ resources:
|
|||||||
properties:
|
properties:
|
||||||
flavor: { get_param: flavor }
|
flavor: { get_param: flavor }
|
||||||
name: VDU1
|
name: VDU1
|
||||||
block_device_mapping_v2: [{"volume_id": { get_resource: VirtualStorage }}]
|
block_device_mapping_v2: [{"volume_id": { get_resource: VDU1-VirtualStorage }}]
|
||||||
networks:
|
networks:
|
||||||
- port:
|
- port:
|
||||||
get_resource: VDU1_CP1
|
get_resource: VDU1_CP1
|
||||||
@ -44,7 +46,7 @@ resources:
|
|||||||
|
|
||||||
availability_zone: { get_param: zone }
|
availability_zone: { get_param: zone }
|
||||||
|
|
||||||
VirtualStorage:
|
VDU1-VirtualStorage:
|
||||||
type: OS::Cinder::Volume
|
type: OS::Cinder::Volume
|
||||||
properties:
|
properties:
|
||||||
image: { get_param: image }
|
image: { get_param: image }
|
||||||
@ -61,6 +63,8 @@ resources:
|
|||||||
type: OS::Neutron::Port
|
type: OS::Neutron::Port
|
||||||
properties:
|
properties:
|
||||||
network: { get_param: net1 }
|
network: { get_param: net1 }
|
||||||
|
fixed_ips:
|
||||||
|
- subnet: { get_param: subnet1}
|
||||||
|
|
||||||
# extVL with numDynamicAddresses and subnet
|
# extVL with numDynamicAddresses and subnet
|
||||||
VDU1_CP2:
|
VDU1_CP2:
|
||||||
@ -68,7 +72,7 @@ resources:
|
|||||||
properties:
|
properties:
|
||||||
network: { get_param: net2 }
|
network: { get_param: net2 }
|
||||||
fixed_ips:
|
fixed_ips:
|
||||||
- subnet: { get_param: subnet}
|
- subnet: { get_param: subnet2}
|
||||||
|
|
||||||
# delete the following line when extmanagedVLs' Ports are specified in instantiatevnfrequest
|
# delete the following line when extmanagedVLs' Ports are specified in instantiatevnfrequest
|
||||||
VDU1_CP3:
|
VDU1_CP3:
|
||||||
|
@ -16,11 +16,12 @@ resources:
|
|||||||
type: VDU1.yaml
|
type: VDU1.yaml
|
||||||
properties:
|
properties:
|
||||||
flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
|
flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
|
||||||
image: { get_param: [ nfv, VDU, VirtualStorage, vcImageId ] }
|
image: { get_param: [ nfv, VDU, VDU1-VirtualStorage, vcImageId ] }
|
||||||
zone: { get_param: [ nfv, VDU, VDU1, locationConstraints] }
|
zone: { get_param: [ nfv, VDU, VDU1, locationConstraints] }
|
||||||
net1: { get_param: [ nfv, CP, VDU1_CP1, network] }
|
net1: { get_param: [ nfv, CP, VDU1_CP1, network] }
|
||||||
net2: { get_param: [ nfv, CP, VDU1_CP2, network ] }
|
net2: { get_param: [ nfv, CP, VDU1_CP2, network ] }
|
||||||
subnet: { get_param: [nfv, CP, VDU1_CP2, fixed_ips, 0, subnet ]}
|
subnet1: { get_param: [nfv, CP, VDU1_CP1, fixed_ips, 0, subnet ]}
|
||||||
|
subnet2: { get_param: [nfv, CP, VDU1_CP2, fixed_ips, 0, subnet ]}
|
||||||
net3: { get_resource: internalVL1 }
|
net3: { get_resource: internalVL1 }
|
||||||
net4: { get_resource: internalVL2 }
|
net4: { get_resource: internalVL2 }
|
||||||
net5: { get_resource: internalVL3 }
|
net5: { get_resource: internalVL3 }
|
||||||
@ -44,11 +45,12 @@ resources:
|
|||||||
type: OS::Nova::Server
|
type: OS::Nova::Server
|
||||||
properties:
|
properties:
|
||||||
flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
|
flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
|
||||||
image: { get_param: [ nfv, VDU, VDU2, vcImageId] }
|
name: VDU2
|
||||||
availability_zone: { get_param: [ nfv, VDU, VDU2, locationConstraints ] }
|
availability_zone: { get_param: [ nfv, VDU, VDU2, locationConstraints ] }
|
||||||
|
block_device_mapping_v2: [{"volume_id": { get_resource: VDU2-VirtualStorage }}]
|
||||||
networks:
|
networks:
|
||||||
- port:
|
- port: { get_param: [ nfv, CP, VDU2_CP1-1, port ] }
|
||||||
get_resource: VDU2_CP1
|
- port: { get_param: [ nfv, CP, VDU2_CP1-2, port ] }
|
||||||
- port:
|
- port:
|
||||||
get_resource: VDU2_CP2
|
get_resource: VDU2_CP2
|
||||||
- port:
|
- port:
|
||||||
@ -58,13 +60,17 @@ resources:
|
|||||||
- port:
|
- port:
|
||||||
get_resource: VDU2_CP5
|
get_resource: VDU2_CP5
|
||||||
|
|
||||||
# extVL with FixedIP
|
VDU2-VirtualStorage:
|
||||||
VDU2_CP1:
|
type: OS::Cinder::Volume
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
properties:
|
||||||
network: { get_param: [ nfv, CP, VDU2_CP1, network ] }
|
image: { get_param: [ nfv, VDU, VDU2-VirtualStorage, vcImageId] }
|
||||||
fixed_ips:
|
size: 1
|
||||||
- ip_address: { get_param: [nfv, CP, VDU2_CP1, fixed_ips, 0, ip_address]}
|
volume_type: { get_resource: multi }
|
||||||
|
multi:
|
||||||
|
type: OS::Cinder::VolumeType
|
||||||
|
properties:
|
||||||
|
name: VDU2-multi
|
||||||
|
metadata: { multiattach: "<is> True" }
|
||||||
|
|
||||||
# extVL with FixedIP and Subnet
|
# extVL with FixedIP and Subnet
|
||||||
VDU2_CP2:
|
VDU2_CP2:
|
||||||
@ -74,6 +80,7 @@ resources:
|
|||||||
fixed_ips:
|
fixed_ips:
|
||||||
- ip_address: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, ip_address]}
|
- ip_address: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, ip_address]}
|
||||||
subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, subnet]}
|
subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, subnet]}
|
||||||
|
- subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 1, subnet]}
|
||||||
|
|
||||||
VDU2_CP3:
|
VDU2_CP3:
|
||||||
type: OS::Neutron::Port
|
type: OS::Neutron::Port
|
||||||
|
@ -34,7 +34,8 @@ topology_template:
|
|||||||
flavour_id: simple
|
flavour_id: simple
|
||||||
requirements:
|
requirements:
|
||||||
virtual_link_external1_1: [ VDU1_CP1, virtual_link ]
|
virtual_link_external1_1: [ VDU1_CP1, virtual_link ]
|
||||||
virtual_link_external1_2: [ VDU2_CP1, virtual_link ]
|
virtual_link_external1_2: [ VDU2_CP1-1, virtual_link ]
|
||||||
|
virtual_link_external1_3: [ VDU2_CP1-2, virtual_link ]
|
||||||
virtual_link_external2_1: [ VDU1_CP2, virtual_link ]
|
virtual_link_external2_1: [ VDU1_CP2, virtual_link ]
|
||||||
virtual_link_external2_2: [ VDU2_CP2, virtual_link ]
|
virtual_link_external2_2: [ VDU2_CP2, virtual_link ]
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ topology_template:
|
|||||||
virtual_local_storage:
|
virtual_local_storage:
|
||||||
- size_of_storage: 3 GB
|
- size_of_storage: 3 GB
|
||||||
requirements:
|
requirements:
|
||||||
- virtual_storage: VirtualStorage
|
- virtual_storage: VDU1-VirtualStorage
|
||||||
|
|
||||||
VDU2:
|
VDU2:
|
||||||
type: tosca.nodes.nfv.Vdu.Compute
|
type: tosca.nodes.nfv.Vdu.Compute
|
||||||
@ -89,17 +90,6 @@ topology_template:
|
|||||||
vdu_profile:
|
vdu_profile:
|
||||||
min_number_of_instances: 1
|
min_number_of_instances: 1
|
||||||
max_number_of_instances: 1
|
max_number_of_instances: 1
|
||||||
sw_image_data:
|
|
||||||
name: VDU2-image
|
|
||||||
version: '0.5.2'
|
|
||||||
checksum:
|
|
||||||
algorithm: sha-256
|
|
||||||
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
|
||||||
container_format: bare
|
|
||||||
disk_format: qcow2
|
|
||||||
min_disk: 0 GB
|
|
||||||
min_ram: 256 MB
|
|
||||||
size: 12 GB
|
|
||||||
capabilities:
|
capabilities:
|
||||||
virtual_compute:
|
virtual_compute:
|
||||||
properties:
|
properties:
|
||||||
@ -115,19 +105,17 @@ topology_template:
|
|||||||
num_virtual_cpu: 1
|
num_virtual_cpu: 1
|
||||||
virtual_local_storage:
|
virtual_local_storage:
|
||||||
- size_of_storage: 3 GB
|
- size_of_storage: 3 GB
|
||||||
artifacts:
|
requirements:
|
||||||
sw_image:
|
- virtual_storage: VDU2-VirtualStorage
|
||||||
type: tosca.artifacts.nfv.SwImage
|
|
||||||
file: ../Files/images/cirros-0.5.2-x86_64-disk.img
|
|
||||||
|
|
||||||
VirtualStorage:
|
VDU1-VirtualStorage:
|
||||||
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
||||||
properties:
|
properties:
|
||||||
virtual_block_storage_data:
|
virtual_block_storage_data:
|
||||||
size_of_storage: 1 GB
|
size_of_storage: 1 GB
|
||||||
rdma_enabled: true
|
rdma_enabled: true
|
||||||
sw_image_data:
|
sw_image_data:
|
||||||
name: cirros-0.5.2-x86_64-disk
|
name: VDU1-VirtualStorage-image
|
||||||
version: '0.5.2'
|
version: '0.5.2'
|
||||||
checksum:
|
checksum:
|
||||||
algorithm: sha-256
|
algorithm: sha-256
|
||||||
@ -137,6 +125,32 @@ topology_template:
|
|||||||
min_disk: 0 GB
|
min_disk: 0 GB
|
||||||
min_ram: 256 MB
|
min_ram: 256 MB
|
||||||
size: 12 GB
|
size: 12 GB
|
||||||
|
artifacts:
|
||||||
|
sw_image:
|
||||||
|
type: tosca.artifacts.nfv.SwImage
|
||||||
|
file: ../Files/images/cirros-0.5.2-x86_64-disk.img
|
||||||
|
|
||||||
|
VDU2-VirtualStorage:
|
||||||
|
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
||||||
|
properties:
|
||||||
|
virtual_block_storage_data:
|
||||||
|
size_of_storage: 1 GB
|
||||||
|
rdma_enabled: true
|
||||||
|
sw_image_data:
|
||||||
|
name: VDU2-VirtualStorage-image
|
||||||
|
version: '0.5.2'
|
||||||
|
checksum:
|
||||||
|
algorithm: sha-256
|
||||||
|
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
||||||
|
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
|
||||||
|
|
||||||
VDU1_CP1:
|
VDU1_CP1:
|
||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
@ -181,7 +195,7 @@ topology_template:
|
|||||||
- virtual_binding: VDU1
|
- virtual_binding: VDU1
|
||||||
- virtual_link: internalVL3
|
- virtual_link: internalVL3
|
||||||
|
|
||||||
VDU2_CP1:
|
VDU2_CP1-1:
|
||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
properties:
|
properties:
|
||||||
layer_protocols: [ ipv4 ]
|
layer_protocols: [ ipv4 ]
|
||||||
@ -189,7 +203,7 @@ topology_template:
|
|||||||
requirements:
|
requirements:
|
||||||
- virtual_binding: VDU2
|
- virtual_binding: VDU2
|
||||||
|
|
||||||
VDU2_CP2:
|
VDU2_CP1-2:
|
||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
properties:
|
properties:
|
||||||
layer_protocols: [ ipv4 ]
|
layer_protocols: [ ipv4 ]
|
||||||
@ -197,20 +211,28 @@ topology_template:
|
|||||||
requirements:
|
requirements:
|
||||||
- virtual_binding: VDU2
|
- virtual_binding: VDU2
|
||||||
|
|
||||||
VDU2_CP3:
|
VDU2_CP2:
|
||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
properties:
|
properties:
|
||||||
layer_protocols: [ ipv4 ]
|
layer_protocols: [ ipv4 ]
|
||||||
order: 2
|
order: 2
|
||||||
requirements:
|
requirements:
|
||||||
- virtual_binding: VDU2
|
- virtual_binding: VDU2
|
||||||
|
|
||||||
|
VDU2_CP3:
|
||||||
|
type: tosca.nodes.nfv.VduCp
|
||||||
|
properties:
|
||||||
|
layer_protocols: [ ipv4 ]
|
||||||
|
order: 3
|
||||||
|
requirements:
|
||||||
|
- virtual_binding: VDU2
|
||||||
- virtual_link: internalVL1
|
- virtual_link: internalVL1
|
||||||
|
|
||||||
VDU2_CP4:
|
VDU2_CP4:
|
||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
properties:
|
properties:
|
||||||
layer_protocols: [ ipv4 ]
|
layer_protocols: [ ipv4 ]
|
||||||
order: 3
|
order: 4
|
||||||
requirements:
|
requirements:
|
||||||
- virtual_binding: VDU2
|
- virtual_binding: VDU2
|
||||||
- virtual_link: internalVL2
|
- virtual_link: internalVL2
|
||||||
@ -219,7 +241,7 @@ topology_template:
|
|||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
properties:
|
properties:
|
||||||
layer_protocols: [ ipv4 ]
|
layer_protocols: [ ipv4 ]
|
||||||
order: 4
|
order: 5
|
||||||
requirements:
|
requirements:
|
||||||
- virtual_binding: VDU2
|
- virtual_binding: VDU2
|
||||||
- virtual_link: internalVL3
|
- virtual_link: internalVL3
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||||
|
# 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 os
|
||||||
|
import pickle
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class SampleScript(object):
|
||||||
|
|
||||||
|
def __init__(self, req, inst, grant_req, grant, csar_dir):
|
||||||
|
self.req = req
|
||||||
|
self.inst = inst
|
||||||
|
self.grant_req = grant_req
|
||||||
|
self.grant = grant
|
||||||
|
self.csar_dir = csar_dir
|
||||||
|
|
||||||
|
def instantiate_start(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def instantiate_end(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def terminate_start(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def terminate_end(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
script_dict = pickle.load(sys.stdin.buffer)
|
||||||
|
|
||||||
|
operation = script_dict['operation']
|
||||||
|
req = script_dict['request']
|
||||||
|
inst = script_dict['vnf_instance']
|
||||||
|
grant_req = script_dict['grant_request']
|
||||||
|
grant = script_dict['grant_response']
|
||||||
|
csar_dir = script_dict['tmp_csar_dir']
|
||||||
|
|
||||||
|
script = SampleScript(req, inst, grant_req, grant, csar_dir)
|
||||||
|
try:
|
||||||
|
getattr(script, operation)()
|
||||||
|
except AttributeError:
|
||||||
|
raise Exception("{} is not included in the script.".format(operation))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
os._exit(0)
|
||||||
|
except Exception as ex:
|
||||||
|
sys.stderr.write(str(ex))
|
||||||
|
sys.stderr.flush()
|
||||||
|
os._exit(1)
|
@ -19,10 +19,34 @@ from tacker.sol_refactored.common import vnf_instance_utils as inst_utils
|
|||||||
from tacker.sol_refactored.infra_drivers.openstack import userdata_utils
|
from tacker.sol_refactored.infra_drivers.openstack import userdata_utils
|
||||||
|
|
||||||
|
|
||||||
class DefaultUserData(userdata_utils.AbstractUserData):
|
class UserData(userdata_utils.AbstractUserData):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def instantiate(req, inst, grant_req, grant, tmp_csar_dir):
|
def instantiate(req, inst, grant_req, grant, tmp_csar_dir):
|
||||||
|
def _get_param_port(cp_name, grant, req):
|
||||||
|
# see grant first then instantiateVnfRequest
|
||||||
|
vls = grant.get('extVirtualLinks', []) + req.get('extVirtualLinks',
|
||||||
|
[])
|
||||||
|
port_ids = []
|
||||||
|
for vl in vls:
|
||||||
|
link_port_ids = []
|
||||||
|
for extcp in vl['extCps']:
|
||||||
|
if extcp['cpdId'] == cp_name:
|
||||||
|
link_port_ids = _get_link_port_ids_from_extcp(extcp)
|
||||||
|
if 'extLinkPorts' not in vl:
|
||||||
|
continue
|
||||||
|
for extlp in vl['extLinkPorts']:
|
||||||
|
if extlp['id'] in link_port_ids:
|
||||||
|
port_ids.append(extlp['resourceHandle']['resourceId'])
|
||||||
|
return port_ids
|
||||||
|
|
||||||
|
def _get_link_port_ids_from_extcp(extcp):
|
||||||
|
link_port_ids = []
|
||||||
|
for cp_conf in extcp['cpConfig'].values():
|
||||||
|
if 'linkPortId' in cp_conf:
|
||||||
|
link_port_ids.append(cp_conf['linkPortId'])
|
||||||
|
return link_port_ids
|
||||||
|
|
||||||
vnfd = userdata_utils.get_vnfd(inst['vnfdId'], tmp_csar_dir)
|
vnfd = userdata_utils.get_vnfd(inst['vnfdId'], tmp_csar_dir)
|
||||||
flavour_id = req['flavourId']
|
flavour_id = req['flavourId']
|
||||||
|
|
||||||
@ -65,6 +89,16 @@ class DefaultUserData(userdata_utils.AbstractUserData):
|
|||||||
'ip_address')
|
'ip_address')
|
||||||
fixed_ips.append(ips_i)
|
fixed_ips.append(ips_i)
|
||||||
cp_value['fixed_ips'] = fixed_ips
|
cp_value['fixed_ips'] = fixed_ips
|
||||||
|
# NOTE: In the case where multiple cpConfigs corresponding
|
||||||
|
# to a single cpdId are defined, always get the first element
|
||||||
|
# of cpConfig. This is because, according to the current
|
||||||
|
# SOL definitions, the key of cpConfig is the ID managed by
|
||||||
|
# the API consumer, and it is not possible to uniquely determine
|
||||||
|
# which element of cpConfig should be selected by cpdId.
|
||||||
|
# See SOL003 v3.3.1 4.4.1.10 Type: VnfExtCpData.
|
||||||
|
if 'port' in cp_value:
|
||||||
|
cp_value['port'] = _get_param_port(
|
||||||
|
cp_name, grant, req).pop()
|
||||||
|
|
||||||
userdata_utils.apply_ext_managed_vls(top_hot, req, grant)
|
userdata_utils.apply_ext_managed_vls(top_hot, req, grant)
|
||||||
|
|
@ -42,11 +42,22 @@ shutil.rmtree(tmp_dir)
|
|||||||
create_req = paramgen.sample1_create(vnfd_id)
|
create_req = paramgen.sample1_create(vnfd_id)
|
||||||
terminate_req = paramgen.sample1_terminate()
|
terminate_req = paramgen.sample1_terminate()
|
||||||
|
|
||||||
net_ids = utils.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
print('#####################################################################\n'
|
||||||
subnet_ids = utils.get_subnet_ids(['subnet0', 'subnet1'])
|
'# Run pre.py if an error occurs #\n'
|
||||||
|
'# - If an error occurs, run the pre.py script in advance #\n'
|
||||||
|
'# to create the openstack resource required to run this script. #\n'
|
||||||
|
'# Run post.py when you finish tests #\n'
|
||||||
|
'# - When you no longer need these openstack resources #\n'
|
||||||
|
'# after testing, run post.py and delete them. #\n'
|
||||||
|
'#####################################################################')
|
||||||
|
|
||||||
|
net_ids = utils.get_network_ids(['net0', 'net1', 'net_mgmt', 'ft-net0'])
|
||||||
|
subnet_ids = utils.get_subnet_ids(
|
||||||
|
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0'])
|
||||||
|
port_ids = utils.get_port_ids(['VDU2_CP1-1', 'VDU2_CP1-2'])
|
||||||
|
|
||||||
instantiate_req = paramgen.sample1_instantiate(
|
instantiate_req = paramgen.sample1_instantiate(
|
||||||
net_ids, subnet_ids, "http://localhost/identity/v3")
|
net_ids, subnet_ids, port_ids, "http://localhost/identity/v3")
|
||||||
|
|
||||||
with open("create_req", "w") as f:
|
with open("create_req", "w") as f:
|
||||||
f.write(json.dumps(create_req, indent=2))
|
f.write(json.dumps(create_req, indent=2))
|
||||||
|
20
tacker/tests/functional/sol_v2/samples/sample1/post.py
Normal file
20
tacker/tests/functional/sol_v2/samples/sample1/post.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||||
|
# 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.functional.sol_v2 import utils
|
||||||
|
|
||||||
|
utils.delete_network('ft-net0')
|
||||||
|
# NOTE: subnet is automatically deleted by network deletion
|
||||||
|
utils.delete_port('VDU2_CP1-1')
|
||||||
|
utils.delete_port('VDU2_CP1-2')
|
21
tacker/tests/functional/sol_v2/samples/sample1/pre.py
Normal file
21
tacker/tests/functional/sol_v2/samples/sample1/pre.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||||
|
# 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.functional.sol_v2 import utils
|
||||||
|
|
||||||
|
utils.create_network('ft-net0')
|
||||||
|
utils.create_subnet('ft-ipv4-subnet0', 'ft-net0', '100.100.100.0/24', '4')
|
||||||
|
utils.create_subnet('ft-ipv6-subnet0', 'ft-net0', '1111:2222:3333::/64', '6')
|
||||||
|
utils.create_port('VDU2_CP1-1', 'net0')
|
||||||
|
utils.create_port('VDU2_CP1-2', 'net0')
|
@ -6,84 +6,25 @@ parameters:
|
|||||||
type: string
|
type: string
|
||||||
image:
|
image:
|
||||||
type: string
|
type: string
|
||||||
net1:
|
|
||||||
type: string
|
|
||||||
net2:
|
|
||||||
type: string
|
|
||||||
net3:
|
|
||||||
type: string
|
|
||||||
net4:
|
|
||||||
type: string
|
|
||||||
net5:
|
net5:
|
||||||
type: string
|
type: string
|
||||||
subnet:
|
affinity:
|
||||||
type: string
|
type: string
|
||||||
# uncomment when BUG "https://storyboard.openstack.org/#!/story/2009164" fixed
|
|
||||||
# affinity:
|
|
||||||
# type: string
|
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
VDU1:
|
VDU1:
|
||||||
type: OS::Nova::Server
|
type: OS::Nova::Server
|
||||||
properties:
|
properties:
|
||||||
flavor: { get_param: flavor }
|
flavor: { get_param: flavor }
|
||||||
|
image: { get_param: image }
|
||||||
name: VDU1
|
name: VDU1
|
||||||
block_device_mapping_v2: [{"volume_id": { get_resource: VirtualStorage }}]
|
|
||||||
networks:
|
networks:
|
||||||
- port:
|
- port:
|
||||||
get_resource: VDU1_CP1
|
get_resource: VDU1_CP1
|
||||||
- port:
|
scheduler_hints:
|
||||||
get_resource: VDU1_CP2
|
group: {get_param: affinity }
|
||||||
# replace the following line to Port ID when extmanagedVLs' Ports are specified in instantiatevnfrequest
|
|
||||||
- port:
|
|
||||||
get_resource: VDU1_CP3
|
|
||||||
- port:
|
|
||||||
get_resource: VDU1_CP4
|
|
||||||
- port:
|
|
||||||
get_resource: VDU1_CP5
|
|
||||||
|
|
||||||
# uncomment when BUG "https://storyboard.openstack.org/#!/story/2009164" fixed
|
|
||||||
# scheduler_hints:
|
|
||||||
# group: {get_param: affinity }
|
|
||||||
|
|
||||||
VirtualStorage:
|
|
||||||
type: OS::Cinder::Volume
|
|
||||||
properties:
|
|
||||||
image: { get_param: image }
|
|
||||||
size: 1
|
|
||||||
volume_type: { get_resource: multi }
|
|
||||||
multi:
|
|
||||||
type: OS::Cinder::VolumeType
|
|
||||||
properties:
|
|
||||||
name: { get_resource: VDU1_CP1 }
|
|
||||||
metadata: { multiattach: "<is> True" }
|
|
||||||
|
|
||||||
# extVL without FixedIP or with numDynamicAddresses
|
|
||||||
VDU1_CP1:
|
VDU1_CP1:
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
network: { get_param: net1 }
|
|
||||||
|
|
||||||
# extVL with numDynamicAddresses and subnet
|
|
||||||
VDU1_CP2:
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
network: { get_param: net2 }
|
|
||||||
fixed_ips:
|
|
||||||
- subnet: { get_param: subnet}
|
|
||||||
|
|
||||||
# CPs of internal VLs are deleted when extmangaedVLs and port are specified in instantiatevnfrequest
|
|
||||||
VDU1_CP3:
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
network: { get_param: net3 }
|
|
||||||
|
|
||||||
VDU1_CP4:
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
network: { get_param: net4 }
|
|
||||||
|
|
||||||
VDU1_CP5:
|
|
||||||
type: OS::Neutron::Port
|
type: OS::Neutron::Port
|
||||||
properties:
|
properties:
|
||||||
network: { get_param: net5 }
|
network: { get_param: net5 }
|
||||||
|
@ -16,15 +16,9 @@ resources:
|
|||||||
type: VDU1.yaml
|
type: VDU1.yaml
|
||||||
properties:
|
properties:
|
||||||
flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
|
flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
|
||||||
image: { get_param: [ nfv, VDU, VirtualStorage, vcImageId ] }
|
image: { get_param: [ nfv, VDU, VDU1, vcImageId ] }
|
||||||
net1: { get_param: [ nfv, CP, VDU1_CP1, network ] }
|
|
||||||
net2: { get_param: [ nfv, CP, VDU1_CP2, network ] }
|
|
||||||
subnet: { get_param: [nfv, CP, VDU1_CP2, fixed_ips, 0, subnet ]}
|
|
||||||
net3: { get_resource: internalVL1 }
|
|
||||||
net4: { get_resource: internalVL2 }
|
|
||||||
net5: { get_resource: internalVL3 }
|
net5: { get_resource: internalVL3 }
|
||||||
# uncomment when BUG "https://storyboard.openstack.org/#!/story/2009164" fixed
|
affinity: { get_resource: nfvi_node_affinity }
|
||||||
# affinity: { get_resource: nfvi_node_affinity }
|
|
||||||
VDU1_scale_out:
|
VDU1_scale_out:
|
||||||
type: OS::Heat::ScalingPolicy
|
type: OS::Heat::ScalingPolicy
|
||||||
properties:
|
properties:
|
||||||
@ -44,80 +38,23 @@ resources:
|
|||||||
type: OS::Nova::Server
|
type: OS::Nova::Server
|
||||||
properties:
|
properties:
|
||||||
flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
|
flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
|
||||||
|
name: VDU2
|
||||||
image: { get_param: [ nfv, VDU, VDU2, vcImageId] }
|
image: { get_param: [ nfv, VDU, VDU2, vcImageId] }
|
||||||
networks:
|
networks:
|
||||||
- port:
|
- port:
|
||||||
get_resource: VDU2_CP1
|
get_resource: VDU2_CP1
|
||||||
- port:
|
scheduler_hints:
|
||||||
get_resource: VDU2_CP2
|
group: {get_resource: nfvi_node_affinity }
|
||||||
- port:
|
|
||||||
get_resource: VDU2_CP3
|
|
||||||
- port:
|
|
||||||
get_resource: VDU2_CP4
|
|
||||||
- port:
|
|
||||||
get_resource: VDU2_CP5
|
|
||||||
# uncomment when BUG "https://storyboard.openstack.org/#!/story/2009164" fixed
|
|
||||||
# scheduler_hints:
|
|
||||||
# group: {get_resource: nfvi_node_affinity }
|
|
||||||
|
|
||||||
# extVL with FixedIP
|
|
||||||
VDU2_CP1:
|
VDU2_CP1:
|
||||||
type: OS::Neutron::Port
|
type: OS::Neutron::Port
|
||||||
properties:
|
properties:
|
||||||
network: { get_param: [ nfv, CP, VDU2_CP1, network ] }
|
|
||||||
fixed_ips:
|
|
||||||
- ip_address: { get_param: [nfv, CP, VDU2_CP1, fixed_ips, 0, ip_address]}
|
|
||||||
|
|
||||||
# extVL with FixedIP and Subnet
|
|
||||||
VDU2_CP2:
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
network: { get_param: [ nfv, CP, VDU2_CP2, network ] }
|
|
||||||
fixed_ips:
|
|
||||||
- ip_address: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, ip_address]}
|
|
||||||
subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 0, subnet]}
|
|
||||||
|
|
||||||
VDU2_CP3:
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
# replace the following line to VL's ID when extmanagedVLs are specified in instantiatevnfrequest
|
|
||||||
network: { get_resource: internalVL1 }
|
|
||||||
|
|
||||||
VDU2_CP4:
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
# replace the following line to VL's ID when extmanagedVLs are specified in instantiatevnfrequest
|
|
||||||
network: { get_resource: internalVL2 }
|
|
||||||
|
|
||||||
VDU2_CP5:
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
properties:
|
|
||||||
# replace the following line to VL's ID when extmanagedVLs are specified in instantiatevnfrequest
|
|
||||||
network: { get_resource: internalVL3 }
|
network: { get_resource: internalVL3 }
|
||||||
|
|
||||||
# delete the following lines when extmanagedVLs are specified in instantiatevnfrequest
|
|
||||||
internalVL1:
|
|
||||||
type: OS::Neutron::Net
|
|
||||||
internalVL2:
|
|
||||||
type: OS::Neutron::Net
|
|
||||||
internalVL3:
|
internalVL3:
|
||||||
type: OS::Neutron::Net
|
type: OS::Neutron::Net
|
||||||
|
|
||||||
|
|
||||||
internalVL1_subnet:
|
|
||||||
type: OS::Neutron::Subnet
|
|
||||||
properties:
|
|
||||||
ip_version: 4
|
|
||||||
network:
|
|
||||||
get_resource: internalVL1
|
|
||||||
cidr: 192.168.3.0/24
|
|
||||||
internalVL2_subnet:
|
|
||||||
type: OS::Neutron::Subnet
|
|
||||||
properties:
|
|
||||||
ip_version: 4
|
|
||||||
network:
|
|
||||||
get_resource: internalVL2
|
|
||||||
cidr: 192.168.4.0/24
|
|
||||||
internalVL3_subnet:
|
internalVL3_subnet:
|
||||||
type: OS::Neutron::Subnet
|
type: OS::Neutron::Subnet
|
||||||
properties:
|
properties:
|
||||||
@ -126,11 +63,10 @@ resources:
|
|||||||
get_resource: internalVL3
|
get_resource: internalVL3
|
||||||
cidr: 192.168.5.0/24
|
cidr: 192.168.5.0/24
|
||||||
|
|
||||||
# uncomment when BUG "https://storyboard.openstack.org/#!/story/2009164" fixed
|
nfvi_node_affinity:
|
||||||
# nfvi_node_affinity:
|
type: OS::Nova::ServerGroup
|
||||||
# type: OS::Nova::ServerGroup
|
properties:
|
||||||
# properties:
|
name: nfvi_node_affinity
|
||||||
# name: nfvi_node_affinity
|
policies: [ 'affinity' ]
|
||||||
# policies: [ 'affinity' ]
|
|
||||||
|
|
||||||
outputs: {}
|
outputs: {}
|
||||||
|
@ -32,11 +32,6 @@ topology_template:
|
|||||||
node_type: company.provider.VNF
|
node_type: company.provider.VNF
|
||||||
properties:
|
properties:
|
||||||
flavour_id: simple
|
flavour_id: simple
|
||||||
requirements:
|
|
||||||
virtual_link_external1_1: [ VDU1_CP1, virtual_link ]
|
|
||||||
virtual_link_external1_2: [ VDU2_CP1, virtual_link ]
|
|
||||||
virtual_link_external2_1: [ VDU1_CP2, virtual_link ]
|
|
||||||
virtual_link_external2_2: [ VDU2_CP2, virtual_link ]
|
|
||||||
|
|
||||||
node_templates:
|
node_templates:
|
||||||
VNF:
|
VNF:
|
||||||
@ -67,6 +62,17 @@ topology_template:
|
|||||||
vdu_profile:
|
vdu_profile:
|
||||||
min_number_of_instances: 1
|
min_number_of_instances: 1
|
||||||
max_number_of_instances: 3
|
max_number_of_instances: 3
|
||||||
|
sw_image_data:
|
||||||
|
name: cirros-0.5.2-x86_64-disk
|
||||||
|
version: '0.5.2'
|
||||||
|
checksum:
|
||||||
|
algorithm: sha-256
|
||||||
|
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
||||||
|
container_format: bare
|
||||||
|
disk_format: qcow2
|
||||||
|
min_disk: 0 GB
|
||||||
|
min_ram: 256 MB
|
||||||
|
size: 12 GB
|
||||||
capabilities:
|
capabilities:
|
||||||
virtual_compute:
|
virtual_compute:
|
||||||
properties:
|
properties:
|
||||||
@ -82,8 +88,6 @@ topology_template:
|
|||||||
num_virtual_cpu: 1
|
num_virtual_cpu: 1
|
||||||
virtual_local_storage:
|
virtual_local_storage:
|
||||||
- size_of_storage: 3 GB
|
- size_of_storage: 3 GB
|
||||||
requirements:
|
|
||||||
- virtual_storage: VirtualStorage
|
|
||||||
|
|
||||||
VDU2:
|
VDU2:
|
||||||
type: tosca.nodes.nfv.Vdu.Compute
|
type: tosca.nodes.nfv.Vdu.Compute
|
||||||
@ -120,59 +124,7 @@ topology_template:
|
|||||||
virtual_local_storage:
|
virtual_local_storage:
|
||||||
- size_of_storage: 3 GB
|
- size_of_storage: 3 GB
|
||||||
|
|
||||||
VirtualStorage:
|
|
||||||
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
|
||||||
properties:
|
|
||||||
virtual_block_storage_data:
|
|
||||||
size_of_storage: 1 GB
|
|
||||||
rdma_enabled: true
|
|
||||||
sw_image_data:
|
|
||||||
name: cirros-0.5.2-x86_64-disk
|
|
||||||
version: '0.5.2'
|
|
||||||
checksum:
|
|
||||||
algorithm: sha-256
|
|
||||||
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
|
||||||
container_format: bare
|
|
||||||
disk_format: qcow2
|
|
||||||
min_disk: 0 GB
|
|
||||||
min_ram: 256 MB
|
|
||||||
size: 12 GB
|
|
||||||
|
|
||||||
VDU1_CP1:
|
VDU1_CP1:
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 0
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU1
|
|
||||||
|
|
||||||
VDU1_CP2:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 1
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU1
|
|
||||||
|
|
||||||
VDU1_CP3:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 2
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU1
|
|
||||||
- virtual_link: internalVL1
|
|
||||||
|
|
||||||
VDU1_CP4:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 3
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU1
|
|
||||||
- virtual_link: internalVL2
|
|
||||||
|
|
||||||
VDU1_CP5:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
properties:
|
properties:
|
||||||
layer_protocols: [ ipv4 ]
|
layer_protocols: [ ipv4 ]
|
||||||
@ -182,40 +134,6 @@ topology_template:
|
|||||||
- virtual_link: internalVL3
|
- virtual_link: internalVL3
|
||||||
|
|
||||||
VDU2_CP1:
|
VDU2_CP1:
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 0
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU2
|
|
||||||
|
|
||||||
VDU2_CP2:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 1
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU2
|
|
||||||
|
|
||||||
VDU2_CP3:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 2
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU2
|
|
||||||
- virtual_link: internalVL1
|
|
||||||
|
|
||||||
VDU2_CP4:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
|
||||||
properties:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
order: 3
|
|
||||||
requirements:
|
|
||||||
- virtual_binding: VDU2
|
|
||||||
- virtual_link: internalVL2
|
|
||||||
|
|
||||||
VDU2_CP5:
|
|
||||||
type: tosca.nodes.nfv.VduCp
|
type: tosca.nodes.nfv.VduCp
|
||||||
properties:
|
properties:
|
||||||
layer_protocols: [ ipv4 ]
|
layer_protocols: [ ipv4 ]
|
||||||
@ -224,44 +142,6 @@ topology_template:
|
|||||||
- virtual_binding: VDU2
|
- virtual_binding: VDU2
|
||||||
- virtual_link: internalVL3
|
- virtual_link: internalVL3
|
||||||
|
|
||||||
internalVL1:
|
|
||||||
type: tosca.nodes.nfv.VnfVirtualLink
|
|
||||||
properties:
|
|
||||||
connectivity_type:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
description: External Managed Virtual link in the VNF
|
|
||||||
vl_profile:
|
|
||||||
max_bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
min_bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
virtual_link_protocol_data:
|
|
||||||
- associated_layer_protocol: ipv4
|
|
||||||
l3_protocol_data:
|
|
||||||
ip_version: ipv4
|
|
||||||
cidr: 192.168.3.0/24
|
|
||||||
|
|
||||||
internalVL2:
|
|
||||||
type: tosca.nodes.nfv.VnfVirtualLink
|
|
||||||
properties:
|
|
||||||
connectivity_type:
|
|
||||||
layer_protocols: [ ipv4 ]
|
|
||||||
description: External Managed Virtual link in the VNF
|
|
||||||
vl_profile:
|
|
||||||
max_bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
min_bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
virtual_link_protocol_data:
|
|
||||||
- associated_layer_protocol: ipv4
|
|
||||||
l3_protocol_data:
|
|
||||||
ip_version: ipv4
|
|
||||||
cidr: 192.168.4.0/24
|
|
||||||
|
|
||||||
internalVL3:
|
internalVL3:
|
||||||
type: tosca.nodes.nfv.VnfVirtualLink
|
type: tosca.nodes.nfv.VnfVirtualLink
|
||||||
properties:
|
properties:
|
||||||
@ -357,34 +237,6 @@ topology_template:
|
|||||||
number_of_instances: 1
|
number_of_instances: 1
|
||||||
targets: [ VDU2 ]
|
targets: [ VDU2 ]
|
||||||
|
|
||||||
- internalVL1_instantiation_levels:
|
|
||||||
type: tosca.policies.nfv.VirtualLinkInstantiationLevels
|
|
||||||
properties:
|
|
||||||
levels:
|
|
||||||
instantiation_level_1:
|
|
||||||
bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
instantiation_level_2:
|
|
||||||
bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
targets: [ internalVL1 ]
|
|
||||||
|
|
||||||
- internalVL2_instantiation_levels:
|
|
||||||
type: tosca.policies.nfv.VirtualLinkInstantiationLevels
|
|
||||||
properties:
|
|
||||||
levels:
|
|
||||||
instantiation_level_1:
|
|
||||||
bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
instantiation_level_2:
|
|
||||||
bitrate_requirements:
|
|
||||||
root: 1048576
|
|
||||||
leaf: 1048576
|
|
||||||
targets: [ internalVL2 ]
|
|
||||||
|
|
||||||
- internalVL3_instantiation_levels:
|
- internalVL3_instantiation_levels:
|
||||||
type: tosca.policies.nfv.VirtualLinkInstantiationLevels
|
type: tosca.policies.nfv.VirtualLinkInstantiationLevels
|
||||||
properties:
|
properties:
|
||||||
|
@ -34,12 +34,7 @@ shutil.rmtree(tmp_dir)
|
|||||||
|
|
||||||
create_req = paramgen.sample2_create(vnfd_id)
|
create_req = paramgen.sample2_create(vnfd_id)
|
||||||
terminate_req = paramgen.sample2_terminate()
|
terminate_req = paramgen.sample2_terminate()
|
||||||
|
instantiate_req = paramgen.sample2_instantiate()
|
||||||
net_ids = utils.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
|
||||||
subnet_ids = utils.get_subnet_ids(['subnet0', 'subnet1'])
|
|
||||||
|
|
||||||
instantiate_req = paramgen.sample2_instantiate(
|
|
||||||
net_ids, subnet_ids, "http://localhost/identity/v3")
|
|
||||||
|
|
||||||
with open("create_req", "w") as f:
|
with open("create_req", "w") as f:
|
||||||
f.write(json.dumps(create_req, indent=2))
|
f.write(json.dumps(create_req, indent=2))
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import ddt
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ from tacker.tests.functional.sol_v2 import base_v2
|
|||||||
from tacker.tests.functional.sol_v2 import paramgen
|
from tacker.tests.functional.sol_v2 import paramgen
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
class VnfLcmTest(base_v2.BaseSolV2Test):
|
class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -53,10 +55,18 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
|||||||
super(VnfLcmTest, self).setUp()
|
super(VnfLcmTest, self).setUp()
|
||||||
|
|
||||||
def test_api_versions(self):
|
def test_api_versions(self):
|
||||||
|
"""Test version operations
|
||||||
|
|
||||||
|
* About version operations:
|
||||||
|
This test includes the following operations.
|
||||||
|
- 1. List VNFLCM API versions
|
||||||
|
- 2. Show VNFLCM API versions
|
||||||
|
"""
|
||||||
path = "/vnflcm/api_versions"
|
path = "/vnflcm/api_versions"
|
||||||
resp, body = self.tacker_client.do_request(
|
resp, body = self.tacker_client.do_request(
|
||||||
path, "GET", version="2.0.0")
|
path, "GET", version="2.0.0")
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
expected_body = {
|
expected_body = {
|
||||||
"uriPrefix": "/vnflcm",
|
"uriPrefix": "/vnflcm",
|
||||||
"apiVersions": [
|
"apiVersions": [
|
||||||
@ -70,6 +80,7 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
|||||||
resp, body = self.tacker_client.do_request(
|
resp, body = self.tacker_client.do_request(
|
||||||
path, "GET", version="2.0.0")
|
path, "GET", version="2.0.0")
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
expected_body = {
|
expected_body = {
|
||||||
"uriPrefix": "/vnflcm/v2",
|
"uriPrefix": "/vnflcm/v2",
|
||||||
"apiVersions": [
|
"apiVersions": [
|
||||||
@ -78,29 +89,334 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
|||||||
}
|
}
|
||||||
self.assertEqual(body, expected_body)
|
self.assertEqual(body, expected_body)
|
||||||
|
|
||||||
|
@ddt.data(True, False)
|
||||||
|
def test_subscriptions(self, is_all):
|
||||||
|
"""Test subscription operations
|
||||||
|
|
||||||
|
* About attributes:
|
||||||
|
- is_all=True
|
||||||
|
All of the following cardinality attributes are set.
|
||||||
|
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||||
|
- 0..1 (1)
|
||||||
|
- 0..N (2 or more)
|
||||||
|
- 1
|
||||||
|
- 1..N (2 or more)
|
||||||
|
- is_all=False
|
||||||
|
Omit except for required attributes.
|
||||||
|
Only the following cardinality attributes are set.
|
||||||
|
- 1
|
||||||
|
- 1..N (1)
|
||||||
|
|
||||||
|
* About subscription operations:
|
||||||
|
This test includes the following operations.
|
||||||
|
- 0. Pre-setting
|
||||||
|
- 1. Create a new subscription
|
||||||
|
- 2. Show subscription
|
||||||
|
- 3. List subscription with attribute-based filtering
|
||||||
|
- 4. Delete a subscription
|
||||||
|
"""
|
||||||
|
# NOTE: Skip notification endpoint testing in subscription creation
|
||||||
|
# by setting "v2_nfvo.test_callback_uri = False" to 'tacker.conf'
|
||||||
|
# in '.zuul.yaml'.
|
||||||
|
|
||||||
|
# 0. Pre-setting
|
||||||
|
sub_req = paramgen.sub2_create()
|
||||||
|
if is_all:
|
||||||
|
sub_req = paramgen.sub1_create()
|
||||||
|
|
||||||
|
# 1. Create a new subscription
|
||||||
|
resp, body = self.create_subscription(sub_req)
|
||||||
|
self.assertEqual(201, resp.status_code)
|
||||||
|
self.check_resp_headers_in_create(resp)
|
||||||
|
sub_id = body['id']
|
||||||
|
|
||||||
|
# 2. Show subscription
|
||||||
|
expected_attrs = [
|
||||||
|
'id', 'callbackUri', 'verbosity', '_links'
|
||||||
|
]
|
||||||
|
if is_all:
|
||||||
|
additional_attrs = ['filter']
|
||||||
|
expected_attrs.extend(additional_attrs)
|
||||||
|
|
||||||
|
resp, body = self.show_subscription(sub_id)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
self.check_resp_body(body, expected_attrs)
|
||||||
|
|
||||||
|
# 3. List subscription with attribute-based filtering
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % sub_id}
|
||||||
|
resp, body = self.list_subscriptions(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for sbsc in body:
|
||||||
|
self.check_resp_body(sbsc, expected_attrs)
|
||||||
|
|
||||||
|
# 4. Delete a subscription
|
||||||
|
resp, body = self.delete_subscription(sub_id)
|
||||||
|
self.assertEqual(204, resp.status_code)
|
||||||
|
self.check_resp_headers_in_delete(resp)
|
||||||
|
|
||||||
def test_sample1(self):
|
def test_sample1(self):
|
||||||
|
"""Test LCM operations with all attributes set
|
||||||
|
|
||||||
|
* About attributes:
|
||||||
|
All of the following cardinality attributes are set.
|
||||||
|
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||||
|
- 0..1 (1)
|
||||||
|
- 0..N (2 or more)
|
||||||
|
- 1
|
||||||
|
- 1..N (2 or more)
|
||||||
|
|
||||||
|
* About LCM operations:
|
||||||
|
This test includes the following operations.
|
||||||
|
- 0. Pre-setting
|
||||||
|
- 1. Create a new VNF instance resource
|
||||||
|
- 2. Instantiate a VNF instance
|
||||||
|
- 3. Show VNF instance
|
||||||
|
- 4. List VNF instance with attribute-based filtering
|
||||||
|
- 5. Show VNF LCM operation occurrence
|
||||||
|
- 6. List VNF LCM operation occurrence with attribute-based filtering
|
||||||
|
- 7. Terminate a VNF instance
|
||||||
|
- 8. Delete a VNF instance
|
||||||
|
"""
|
||||||
|
# 0. Pre-setting
|
||||||
|
# Create a new network and subnet to check the IP allocation of
|
||||||
|
# IPv4 and IPv6
|
||||||
|
ft_net0_name = 'ft-net0'
|
||||||
|
ft_net0_subs = {
|
||||||
|
'ft-ipv4-subnet0': {
|
||||||
|
'range': '100.100.100.0/24',
|
||||||
|
'ip_version': 4
|
||||||
|
},
|
||||||
|
'ft-ipv6-subnet0': {
|
||||||
|
'range': '1111:2222:3333::/64',
|
||||||
|
'ip_version': 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ft_net0_id = self.create_network(ft_net0_name)
|
||||||
|
self.addCleanup(self.delete_network, ft_net0_id)
|
||||||
|
for sub_name, val in ft_net0_subs.items():
|
||||||
|
# subnet is automatically deleted with network deletion
|
||||||
|
self.create_subnet(
|
||||||
|
ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||||
|
|
||||||
|
net_ids = self.get_network_ids(
|
||||||
|
['net0', 'net1', 'net_mgmt', 'ft-net0'])
|
||||||
|
subnet_ids = self.get_subnet_ids(
|
||||||
|
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0'])
|
||||||
|
|
||||||
|
port_names = ['VDU2_CP1-1', 'VDU2_CP1-2']
|
||||||
|
port_ids = {}
|
||||||
|
for port_name in port_names:
|
||||||
|
port_id = self.create_port(net_ids['net0'], port_name)
|
||||||
|
port_ids[port_name] = port_id
|
||||||
|
self.addCleanup(self.delete_port, port_id)
|
||||||
|
|
||||||
|
# 1. Create a new VNF instance resource
|
||||||
|
# NOTE: extensions and vnfConfigurableProperties are omitted
|
||||||
|
# because they are commented out in etsi_nfv_sol001.
|
||||||
|
expected_inst_attrs = [
|
||||||
|
'id',
|
||||||
|
'vnfInstanceName',
|
||||||
|
'vnfInstanceDescription',
|
||||||
|
'vnfdId',
|
||||||
|
'vnfProvider',
|
||||||
|
'vnfProductName',
|
||||||
|
'vnfSoftwareVersion',
|
||||||
|
'vnfdVersion',
|
||||||
|
# 'vnfConfigurableProperties', # omitted
|
||||||
|
# 'vimConnectionInfo', # omitted
|
||||||
|
'instantiationState',
|
||||||
|
# 'instantiatedVnfInfo', # omitted
|
||||||
|
'metadata',
|
||||||
|
# 'extensions', # omitted
|
||||||
|
'_links'
|
||||||
|
]
|
||||||
create_req = paramgen.sample1_create(self.vnfd_id_1)
|
create_req = paramgen.sample1_create(self.vnfd_id_1)
|
||||||
resp, body = self.create_vnf_instance(create_req)
|
resp, body = self.create_vnf_instance(create_req)
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
self.check_resp_headers_in_create(resp)
|
||||||
|
self.check_resp_body(body, expected_inst_attrs)
|
||||||
inst_id = body['id']
|
inst_id = body['id']
|
||||||
|
|
||||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
# check usageState of VNF Package
|
||||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
usage_state = self.get_vnf_package(self.vnf_pkg_1).get('usageState')
|
||||||
|
self.assertEqual('IN_USE', usage_state)
|
||||||
|
|
||||||
|
# 2. Instantiate a VNF instance
|
||||||
instantiate_req = paramgen.sample1_instantiate(
|
instantiate_req = paramgen.sample1_instantiate(
|
||||||
net_ids, subnet_ids, self.auth_url)
|
net_ids, subnet_ids, port_ids, self.auth_url)
|
||||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||||
self.assertEqual(202, resp.status_code)
|
self.assertEqual(202, resp.status_code)
|
||||||
|
self.check_resp_headers_in_operation_task(resp)
|
||||||
|
|
||||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||||
self.wait_lcmocc_complete(lcmocc_id)
|
self.wait_lcmocc_complete(lcmocc_id)
|
||||||
|
|
||||||
|
# check creation of Heat-stack
|
||||||
|
stack_name = "vnf-{}".format(inst_id)
|
||||||
|
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||||
|
self.assertEqual("CREATE_COMPLETE", stack_status)
|
||||||
|
|
||||||
|
# check creation of Glance-image
|
||||||
|
image_name_list = ['VDU1-VirtualStorage-image',
|
||||||
|
'VDU2-VirtualStorage-image']
|
||||||
|
for image_name in image_name_list:
|
||||||
|
image_id = self.get_image_id(image_name)
|
||||||
|
self.assertIsNotNone(image_id)
|
||||||
|
|
||||||
|
# check that the servers set in "zone:Affinity" are
|
||||||
|
# deployed on 'nova' AZ.
|
||||||
|
# NOTE: local_nfvo returns this AZ
|
||||||
|
vdu1_details = self.get_server_details('VDU1')
|
||||||
|
vdu2_details = self.get_server_details('VDU2')
|
||||||
|
vdu1_az = vdu1_details.get('OS-EXT-AZ:availability_zone')
|
||||||
|
vdu2_az = vdu2_details.get('OS-EXT-AZ:availability_zone')
|
||||||
|
self.assertEqual('nova', vdu1_az)
|
||||||
|
self.assertEqual('nova', vdu2_az)
|
||||||
|
|
||||||
|
# 3. Show VNF instance
|
||||||
|
additional_inst_attrs = [
|
||||||
|
'vimConnectionInfo',
|
||||||
|
'instantiatedVnfInfo'
|
||||||
|
]
|
||||||
|
expected_inst_attrs.extend(additional_inst_attrs)
|
||||||
resp, body = self.show_vnf_instance(inst_id)
|
resp, body = self.show_vnf_instance(inst_id)
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
# TODO(oda-g): check body
|
self.check_resp_headers_in_get(resp)
|
||||||
|
self.check_resp_body(body, expected_inst_attrs)
|
||||||
|
|
||||||
|
# 4. List VNF instance with attribute-based filtering
|
||||||
|
# check attribute-based filtering on VNF instance
|
||||||
|
# NOTE: extensions and vnfConfigurableProperties are omitted
|
||||||
|
# because they are commented out in etsi_nfv_sol001.
|
||||||
|
# * all_fields
|
||||||
|
# -> check the attribute omitted in "exclude_default" is set.
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % inst_id, 'all_fields': ''}
|
||||||
|
resp, body = self.list_vnf_instance(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for inst in body:
|
||||||
|
self.assertIsNotNone(inst.get('vnfInstanceName'))
|
||||||
|
self.assertIsNotNone(inst.get('vnfInstanceDescription'))
|
||||||
|
self.assertIsNotNone(inst.get('vimConnectionInfo'))
|
||||||
|
self.assertIsNotNone(inst.get('instantiatedVnfInfo'))
|
||||||
|
self.assertIsNotNone(inst.get('metadata'))
|
||||||
|
# * fields=<list>
|
||||||
|
# -> check the attribute specified in "fields" is set
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % inst_id,
|
||||||
|
'fields': 'metadata'}
|
||||||
|
resp, body = self.list_vnf_instance(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for inst in body:
|
||||||
|
self.assertIsNone(inst.get('vnfInstanceName'))
|
||||||
|
self.assertIsNone(inst.get('vnfInstanceDescription'))
|
||||||
|
self.assertIsNone(inst.get('vimConnectionInfo'))
|
||||||
|
self.assertIsNone(inst.get('instantiatedVnfInfo'))
|
||||||
|
self.assertIsNotNone(inst.get('metadata'))
|
||||||
|
# * exclude_fields=<list>
|
||||||
|
# -> check the attribute specified in "exclude_fields" is not set
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % inst_id,
|
||||||
|
'exclude_fields': 'vnfInstanceName'}
|
||||||
|
resp, body = self.list_vnf_instance(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for inst in body:
|
||||||
|
self.assertIsNone(inst.get('vnfInstanceName'))
|
||||||
|
self.assertIsNotNone(inst.get('vnfInstanceDescription'))
|
||||||
|
self.assertIsNotNone(inst.get('vimConnectionInfo'))
|
||||||
|
self.assertIsNotNone(inst.get('instantiatedVnfInfo'))
|
||||||
|
self.assertIsNotNone(inst.get('metadata'))
|
||||||
|
# * exclude_default
|
||||||
|
# -> check the attribute omitted in "exclude_default" is not set.
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % inst_id, 'exclude_default': ''}
|
||||||
|
resp, body = self.list_vnf_instance(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for inst in body:
|
||||||
|
self.assertIsNotNone(inst.get('vnfInstanceName'))
|
||||||
|
self.assertIsNotNone(inst.get('vnfInstanceDescription'))
|
||||||
|
self.assertIsNone(inst.get('vimConnectionInfo'))
|
||||||
|
self.assertIsNone(inst.get('instantiatedVnfInfo'))
|
||||||
|
self.assertIsNone(inst.get('metadata'))
|
||||||
|
|
||||||
|
# 5. Show VNF LCM operation occurrence
|
||||||
|
# NOTE: omitted values are not supported at that time
|
||||||
|
expected_attrs = [
|
||||||
|
'id',
|
||||||
|
'operationState',
|
||||||
|
'stateEnteredTime',
|
||||||
|
'startTime',
|
||||||
|
'vnfInstanceId',
|
||||||
|
# 'grantId', # omitted
|
||||||
|
'operation',
|
||||||
|
'isAutomaticInvocation',
|
||||||
|
'operationParams',
|
||||||
|
'isCancelPending',
|
||||||
|
# 'cancelMode', # omitted
|
||||||
|
# 'error', # omitted
|
||||||
|
'resourceChanges',
|
||||||
|
# 'changedInfo', # omitted
|
||||||
|
# 'changedExtConnectivity', # omitted
|
||||||
|
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||||
|
# 'vnfSnapshotInfoId', # omitted
|
||||||
|
'_links'
|
||||||
|
]
|
||||||
|
resp, body = self.show_lcmocc(lcmocc_id)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
self.check_resp_body(body, expected_attrs)
|
||||||
|
|
||||||
|
# 6. List VNF LCM operation occurrence with attribute-based filtering
|
||||||
|
# check attribute-based filtering on vnf_lcm_op_occs
|
||||||
|
# NOTE: error and changedInfo, changedExtConnectivity are omitted
|
||||||
|
# because these values are not supported at that time
|
||||||
|
# * all_fields
|
||||||
|
# -> check the attribute omitted in "exclude_default" is set.
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % lcmocc_id, 'all_fields': ''}
|
||||||
|
resp, body = self.list_lcmocc(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for lcmocc in body:
|
||||||
|
self.assertIsNotNone(lcmocc.get('operationParams'))
|
||||||
|
self.assertIsNotNone(lcmocc.get('resourceChanges'))
|
||||||
|
# * fields=<list>
|
||||||
|
# -> check the attribute specified in "fields" is set
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % lcmocc_id,
|
||||||
|
'fields': 'operationParams'}
|
||||||
|
resp, body = self.list_lcmocc(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for lcmocc in body:
|
||||||
|
self.assertIsNotNone(lcmocc.get('operationParams'))
|
||||||
|
self.assertIsNone(lcmocc.get('resourceChanges'))
|
||||||
|
# * exclude_fields=<list>
|
||||||
|
# -> check the attribute specified in "exclude_fields" is not set
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % inst_id,
|
||||||
|
'exclude_fields': 'operationParams'}
|
||||||
|
resp, body = self.list_lcmocc(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for lcmocc in body:
|
||||||
|
self.assertIsNone(lcmocc.get('operationParams'))
|
||||||
|
self.assertIsNotNone(lcmocc.get('resourceChanges'))
|
||||||
|
# * exclude_default
|
||||||
|
# -> check the attribute omitted in "exclude_default" is not set.
|
||||||
|
filter_expr = {'filter': '(eq,id,%s)' % lcmocc_id,
|
||||||
|
'exclude_default': ''}
|
||||||
|
resp, body = self.list_lcmocc(filter_expr)
|
||||||
|
self.assertEqual(200, resp.status_code)
|
||||||
|
self.check_resp_headers_in_get(resp)
|
||||||
|
for lcmocc in body:
|
||||||
|
self.assertIsNone(lcmocc.get('operationParams'))
|
||||||
|
self.assertIsNone(lcmocc.get('resourceChanges'))
|
||||||
|
|
||||||
|
# 7. Terminate a VNF instance
|
||||||
terminate_req = paramgen.sample1_terminate()
|
terminate_req = paramgen.sample1_terminate()
|
||||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||||
self.assertEqual(202, resp.status_code)
|
self.assertEqual(202, resp.status_code)
|
||||||
|
self.check_resp_headers_in_operation_task(resp)
|
||||||
|
|
||||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||||
self.wait_lcmocc_complete(lcmocc_id)
|
self.wait_lcmocc_complete(lcmocc_id)
|
||||||
@ -109,32 +425,113 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
|||||||
# update and terminate completion.
|
# update and terminate completion.
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
|
# check deletion of Heat-stack
|
||||||
|
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||||
|
self.assertIsNone(stack_status)
|
||||||
|
|
||||||
|
# check deletion of Glance-image
|
||||||
|
for image_name in image_name_list:
|
||||||
|
image_id = self.get_image_id(image_name)
|
||||||
|
self.assertIsNone(image_id)
|
||||||
|
|
||||||
|
# 8. Delete a VNF instance
|
||||||
resp, body = self.delete_vnf_instance(inst_id)
|
resp, body = self.delete_vnf_instance(inst_id)
|
||||||
self.assertEqual(204, resp.status_code)
|
self.assertEqual(204, resp.status_code)
|
||||||
|
self.check_resp_headers_in_delete(resp)
|
||||||
|
|
||||||
|
# check deletion of VNF instance
|
||||||
|
resp, body = self.show_vnf_instance(inst_id)
|
||||||
|
self.assertEqual(404, resp.status_code)
|
||||||
|
|
||||||
|
# check usageState of VNF Package
|
||||||
|
usage_state = self.get_vnf_package(self.vnf_pkg_1).get('usageState')
|
||||||
|
self.assertEqual('NOT_IN_USE', usage_state)
|
||||||
|
|
||||||
def test_sample2(self):
|
def test_sample2(self):
|
||||||
|
"""Test LCM operations with omitting except for required attributes
|
||||||
|
|
||||||
|
* About attributes:
|
||||||
|
Omit except for required attributes.
|
||||||
|
Only the following cardinality attributes are set.
|
||||||
|
- 1
|
||||||
|
- 1..N (1)
|
||||||
|
|
||||||
|
* About LCM operations:
|
||||||
|
This test includes the following operations.
|
||||||
|
- 1. Create a new VNF instance resource
|
||||||
|
- 2. Instantiate a VNF instance
|
||||||
|
- 3. Show VNF instance
|
||||||
|
- 4. Terminate a VNF instance
|
||||||
|
- 5. Delete a VNF instance
|
||||||
|
"""
|
||||||
|
# 1. Create a new VNF instance resource
|
||||||
|
expected_inst_attrs = [
|
||||||
|
'id',
|
||||||
|
# 'vnfInstanceName', # omitted
|
||||||
|
# 'vnfInstanceDescription', # omitted
|
||||||
|
'vnfdId',
|
||||||
|
'vnfProvider',
|
||||||
|
'vnfProductName',
|
||||||
|
'vnfSoftwareVersion',
|
||||||
|
'vnfdVersion',
|
||||||
|
# 'vnfConfigurableProperties', # omitted
|
||||||
|
# 'vimConnectionInfo', # omitted
|
||||||
|
'instantiationState',
|
||||||
|
# 'instantiatedVnfInfo', # omitted
|
||||||
|
# 'metadata', # omitted
|
||||||
|
# 'extensions', # omitted
|
||||||
|
'_links'
|
||||||
|
]
|
||||||
create_req = paramgen.sample2_create(self.vnfd_id_2)
|
create_req = paramgen.sample2_create(self.vnfd_id_2)
|
||||||
resp, body = self.create_vnf_instance(create_req)
|
resp, body = self.create_vnf_instance(create_req)
|
||||||
self.assertEqual(201, resp.status_code)
|
self.assertEqual(201, resp.status_code)
|
||||||
|
self.check_resp_headers_in_create(resp)
|
||||||
|
self.check_resp_body(body, expected_inst_attrs)
|
||||||
inst_id = body['id']
|
inst_id = body['id']
|
||||||
|
|
||||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
# check usageState of VNF Package
|
||||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
usage_state = self.get_vnf_package(self.vnf_pkg_2).get('usageState')
|
||||||
instantiate_req = paramgen.sample2_instantiate(
|
self.assertEqual('IN_USE', usage_state)
|
||||||
net_ids, subnet_ids, self.auth_url)
|
|
||||||
|
# 2. Instantiate a VNF instance
|
||||||
|
instantiate_req = paramgen.sample2_instantiate()
|
||||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||||
self.assertEqual(202, resp.status_code)
|
self.assertEqual(202, resp.status_code)
|
||||||
|
self.check_resp_headers_in_operation_task(resp)
|
||||||
|
|
||||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||||
self.wait_lcmocc_complete(lcmocc_id)
|
self.wait_lcmocc_complete(lcmocc_id)
|
||||||
|
|
||||||
|
# check creation of Heat-stack
|
||||||
|
stack_name = "vnf-{}".format(inst_id)
|
||||||
|
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||||
|
self.assertEqual("CREATE_COMPLETE", stack_status)
|
||||||
|
|
||||||
|
# check that the servers set in "nfvi_node:Affinity" are
|
||||||
|
# deployed on the same host.
|
||||||
|
# NOTE: it's up to heat to decide which host to deploy to
|
||||||
|
vdu1_details = self.get_server_details('VDU1')
|
||||||
|
vdu2_details = self.get_server_details('VDU2')
|
||||||
|
vdu1_host = vdu1_details['hostId']
|
||||||
|
vdu2_host = vdu2_details['hostId']
|
||||||
|
self.assertEqual(vdu1_host, vdu2_host)
|
||||||
|
|
||||||
|
# 3. Show VNF instance
|
||||||
|
additional_inst_attrs = [
|
||||||
|
'vimConnectionInfo',
|
||||||
|
'instantiatedVnfInfo'
|
||||||
|
]
|
||||||
|
expected_inst_attrs.extend(additional_inst_attrs)
|
||||||
resp, body = self.show_vnf_instance(inst_id)
|
resp, body = self.show_vnf_instance(inst_id)
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
# TODO(oda-g): check body
|
self.check_resp_headers_in_get(resp)
|
||||||
|
self.check_resp_body(body, expected_inst_attrs)
|
||||||
|
|
||||||
|
# 4. Terminate a VNF instance
|
||||||
terminate_req = paramgen.sample2_terminate()
|
terminate_req = paramgen.sample2_terminate()
|
||||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||||
self.assertEqual(202, resp.status_code)
|
self.assertEqual(202, resp.status_code)
|
||||||
|
self.check_resp_headers_in_operation_task(resp)
|
||||||
|
|
||||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||||
self.wait_lcmocc_complete(lcmocc_id)
|
self.wait_lcmocc_complete(lcmocc_id)
|
||||||
@ -143,5 +540,19 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
|||||||
# update and terminate completion.
|
# update and terminate completion.
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
|
# check deletion of Heat-stack
|
||||||
|
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||||
|
self.assertIsNone(stack_status)
|
||||||
|
|
||||||
|
# 5. Delete a VNF instance
|
||||||
resp, body = self.delete_vnf_instance(inst_id)
|
resp, body = self.delete_vnf_instance(inst_id)
|
||||||
self.assertEqual(204, resp.status_code)
|
self.assertEqual(204, resp.status_code)
|
||||||
|
self.check_resp_headers_in_delete(resp)
|
||||||
|
|
||||||
|
# check deletion of VNF instance
|
||||||
|
resp, body = self.show_vnf_instance(inst_id)
|
||||||
|
self.assertEqual(404, resp.status_code)
|
||||||
|
|
||||||
|
# check usageState of VNF Package
|
||||||
|
usage_state = self.get_vnf_package(self.vnf_pkg_2).get('usageState')
|
||||||
|
self.assertEqual('NOT_IN_USE', usage_state)
|
||||||
|
@ -50,6 +50,18 @@ def make_zip(sample_dir, tmp_dir, vnfd_id, image_path=None):
|
|||||||
shutil.make_archive(zip_file_path, "zip", tmp_contents)
|
shutil.make_archive(zip_file_path, "zip", tmp_contents)
|
||||||
|
|
||||||
|
|
||||||
|
def create_network(network):
|
||||||
|
# assume OS_* environment variables are already set
|
||||||
|
subprocess.run(
|
||||||
|
["openstack", "net", "create", network])
|
||||||
|
|
||||||
|
|
||||||
|
def delete_network(network):
|
||||||
|
# assume OS_* environment variables are already set
|
||||||
|
subprocess.run(
|
||||||
|
["openstack", "net", "delete", network])
|
||||||
|
|
||||||
|
|
||||||
def get_network_ids(networks):
|
def get_network_ids(networks):
|
||||||
# assume OS_* environment variables are already set
|
# assume OS_* environment variables are already set
|
||||||
net_ids = {}
|
net_ids = {}
|
||||||
@ -61,6 +73,13 @@ def get_network_ids(networks):
|
|||||||
return net_ids
|
return net_ids
|
||||||
|
|
||||||
|
|
||||||
|
def create_subnet(subnet, network, sub_range, version):
|
||||||
|
# assume OS_* environment variables are already set
|
||||||
|
subprocess.run(
|
||||||
|
["openstack", "subnet", "create", subnet, "--network", network,
|
||||||
|
"--subnet-range", sub_range, "--ip-version", version])
|
||||||
|
|
||||||
|
|
||||||
def get_subnet_ids(subnets):
|
def get_subnet_ids(subnets):
|
||||||
# assume OS_* environment variables are already set
|
# assume OS_* environment variables are already set
|
||||||
subnet_ids = {}
|
subnet_ids = {}
|
||||||
@ -70,3 +89,26 @@ def get_subnet_ids(subnets):
|
|||||||
capture_output=True, encoding='utf-8')
|
capture_output=True, encoding='utf-8')
|
||||||
subnet_ids[subnet] = json.loads(p.stdout)['id']
|
subnet_ids[subnet] = json.loads(p.stdout)['id']
|
||||||
return subnet_ids
|
return subnet_ids
|
||||||
|
|
||||||
|
|
||||||
|
def create_port(port, network):
|
||||||
|
# assume OS_* environment variables are already set
|
||||||
|
subprocess.run(
|
||||||
|
["openstack", "port", "create", port, "--network", network])
|
||||||
|
|
||||||
|
|
||||||
|
def delete_port(port):
|
||||||
|
# assume OS_* environment variables are already set
|
||||||
|
subprocess.run(
|
||||||
|
["openstack", "port", "delete", port])
|
||||||
|
|
||||||
|
|
||||||
|
def get_port_ids(ports):
|
||||||
|
# assume OS_* environment variables are already set
|
||||||
|
port_ids = {}
|
||||||
|
for port in ports:
|
||||||
|
p = subprocess.run(
|
||||||
|
["openstack", "port", "show", port, "-c", "id", "-f", "json"],
|
||||||
|
capture_output=True, encoding='utf-8')
|
||||||
|
port_ids[port] = json.loads(p.stdout)['id']
|
||||||
|
return port_ids
|
||||||
|
Loading…
Reference in New Issue
Block a user