Merge "FT of instantiate/scale's ErrorHandling"
This commit is contained in:
commit
17b03eb78f
@ -273,12 +273,6 @@
|
||||
Multinodes job for SOL V2 devstack-based functional tests
|
||||
host-vars:
|
||||
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
|
||||
|
||||
- job:
|
||||
|
@ -28,10 +28,13 @@ from tempest.lib import base
|
||||
from tacker.sol_refactored.common import http_client
|
||||
from tacker.sol_refactored.infra_drivers.openstack import heat_utils
|
||||
from tacker.sol_refactored import objects
|
||||
from tacker.tests.functional.common.fake_server import FakeServerManager
|
||||
from tacker.tests.functional.sol_v2 import utils
|
||||
from tacker.tests import utils as base_utils
|
||||
from tacker import version
|
||||
|
||||
FAKE_SERVER_MANAGER = FakeServerManager.get_instance()
|
||||
MOCK_NOTIFY_CALLBACK_URL = '/notification/callback'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -45,6 +48,9 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
def setUpClass(cls):
|
||||
super(BaseSolV2Test, cls).setUpClass()
|
||||
|
||||
FAKE_SERVER_MANAGER.prepare_http_server()
|
||||
FAKE_SERVER_MANAGER.start_server()
|
||||
|
||||
cfg.CONF(args=['--config-file', '/etc/tacker/tacker.conf'],
|
||||
project='tacker',
|
||||
version='%%prog %s' % version.version_info.release_string())
|
||||
@ -70,6 +76,11 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
service_type='compute')
|
||||
cls.heat_client = heat_utils.HeatClient(vim_info)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(BaseSolV2Test, cls).tearDownClass()
|
||||
FAKE_SERVER_MANAGER.stop_server()
|
||||
|
||||
@classmethod
|
||||
def get_vim_info(cls):
|
||||
vim_params = yaml.safe_load(base_utils.read_file('local-vim.yaml'))
|
||||
@ -143,6 +154,16 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
|
||||
cls.tacker_client.do_request(path, "DELETE")
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
callback_url = os.path.join(
|
||||
MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
FAKE_SERVER_MANAGER.clear_history(callback_url)
|
||||
FAKE_SERVER_MANAGER.set_callback('POST', callback_url, status_code=204)
|
||||
FAKE_SERVER_MANAGER.set_callback('GET', callback_url, status_code=204)
|
||||
|
||||
def get_vnf_package(self, pkg_id):
|
||||
path = "/vnfpkgm/v1/vnf_packages/{}".format(pkg_id)
|
||||
resp, body = self.tacker_client.do_request(path, "GET")
|
||||
@ -287,6 +308,11 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
return self.tacker_client.do_request(
|
||||
path, "POST", body=req_body, version="2.0.0")
|
||||
|
||||
def scale_vnf_instance(self, inst_id, req_body):
|
||||
path = f"/vnflcm/v2/vnf_instances/{inst_id}/scale"
|
||||
return self.tacker_client.do_request(
|
||||
path, "POST", body=req_body, version="2.0.0")
|
||||
|
||||
def terminate_vnf_instance(self, inst_id, req_body):
|
||||
path = "/vnflcm/v2/vnf_instances/{}/terminate".format(inst_id)
|
||||
return self.tacker_client.do_request(
|
||||
@ -326,6 +352,22 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
else: # ROLLED_BACK
|
||||
raise Exception("Operation failed. state: %s" % state)
|
||||
|
||||
def wait_lcmocc_rolled_back(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 = f"/vnflcm/v2/vnf_lcm_op_occs/{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 == 'ROLLED_BACK':
|
||||
return
|
||||
if state in ['ROLLING_BACK']:
|
||||
continue
|
||||
|
||||
raise Exception(f"Operation failed. state: {state}")
|
||||
|
||||
def show_lcmocc(self, lcmocc_id):
|
||||
path = "/vnflcm/v2/vnf_lcm_op_occs/{}".format(lcmocc_id)
|
||||
return self.tacker_client.do_request(
|
||||
@ -338,6 +380,21 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
return self.tacker_client.do_request(
|
||||
path, "GET", version="2.0.0")
|
||||
|
||||
def rollback_lcmocc(self, lcmocc_id):
|
||||
path = f"/vnflcm/v2/vnf_lcm_op_occs/{lcmocc_id}/rollback"
|
||||
return self.tacker_client.do_request(
|
||||
path, "POST", version="2.0.0")
|
||||
|
||||
def retry_lcmocc(self, lcmocc_id):
|
||||
path = f"/vnflcm/v2/vnf_lcm_op_occs/{lcmocc_id}/retry"
|
||||
return self.tacker_client.do_request(
|
||||
path, "POST", version="2.0.0")
|
||||
|
||||
def fail_lcmocc(self, lcmocc_id):
|
||||
path = f"/vnflcm/v2/vnf_lcm_op_occs/{lcmocc_id}/fail"
|
||||
return self.tacker_client.do_request(
|
||||
path, "POST", version="2.0.0")
|
||||
|
||||
def create_subscription(self, req_body):
|
||||
path = "/vnflcm/v2/subscriptions"
|
||||
return self.tacker_client.do_request(
|
||||
@ -396,3 +453,11 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
for attr in expected_attrs:
|
||||
if attr not in body:
|
||||
raise Exception("Expected attribute doesn't exist: %s" % attr)
|
||||
|
||||
def assert_notification_get(self, callback_url):
|
||||
notify_mock_responses = FAKE_SERVER_MANAGER.get_history(
|
||||
callback_url)
|
||||
FAKE_SERVER_MANAGER.clear_history(
|
||||
callback_url)
|
||||
self.assertEqual(1, len(notify_mock_responses))
|
||||
self.assertEqual(204, notify_mock_responses[0].status_code)
|
||||
|
@ -16,7 +16,17 @@
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
|
||||
def sub1_create():
|
||||
def sub_create_min(callback_uri):
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
return {
|
||||
"callbackUri": callback_uri
|
||||
}
|
||||
|
||||
|
||||
def sub_create_max(callback_uri):
|
||||
# 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.
|
||||
@ -110,19 +120,29 @@ def sub1_create():
|
||||
]
|
||||
},
|
||||
"notificationTypes": [
|
||||
"VnfLcmOperationOccurrenceNotification",
|
||||
"VnfIdentifierCreationNotification",
|
||||
"VnfLcmOperationOccurrenceNotification"
|
||||
],
|
||||
"operationTypes": [
|
||||
"INSTANTIATE",
|
||||
"TERMINATE"
|
||||
"SCALE",
|
||||
"TERMINATE",
|
||||
"HEAL",
|
||||
"MODIFY_INFO",
|
||||
"CHANGE_EXT_CONN"
|
||||
],
|
||||
"operationStates": [
|
||||
"COMPLETED",
|
||||
"FAILED"
|
||||
"FAILED",
|
||||
"FAILED_TEMP",
|
||||
"PROCESSING",
|
||||
"ROLLING_BACK",
|
||||
"ROLLED_BACK",
|
||||
"STARTING"
|
||||
]
|
||||
},
|
||||
"callbackUri": "http://127.0.0.1/",
|
||||
"callbackUri": callback_uri,
|
||||
"authentication": {
|
||||
"authType": [
|
||||
"BASIC"
|
||||
@ -137,17 +157,41 @@ def sub1_create():
|
||||
}
|
||||
|
||||
|
||||
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):
|
||||
# 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 create_vnf_max(vnfd_id)
|
||||
|
||||
|
||||
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 terminate_vnf_max()
|
||||
|
||||
|
||||
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)
|
||||
|
||||
return instantiate_vnf_max(net_ids, subnets, ports, auth_url)
|
||||
|
||||
|
||||
def create_vnf_max(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.
|
||||
@ -157,13 +201,13 @@ def sample1_create(vnfd_id):
|
||||
# - 1..N (2 or more)
|
||||
return {
|
||||
"vnfdId": vnfd_id,
|
||||
"vnfInstanceName": "sample1",
|
||||
"vnfInstanceDescription": "test sample1",
|
||||
"vnfInstanceName": "sample",
|
||||
"vnfInstanceDescription": "test sample",
|
||||
"metadata": {"dummy-key": "dummy-val"}
|
||||
}
|
||||
|
||||
|
||||
def sample1_terminate():
|
||||
def terminate_vnf_max():
|
||||
# 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.
|
||||
@ -178,7 +222,7 @@ def sample1_terminate():
|
||||
}
|
||||
|
||||
|
||||
def sample1_instantiate(net_ids, subnets, ports, auth_url):
|
||||
def instantiate_vnf_max(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.
|
||||
@ -409,7 +453,7 @@ def sample1_instantiate(net_ids, subnets, ports, auth_url):
|
||||
},
|
||||
"extra": {"dummy-key": "dummy-val"}
|
||||
}
|
||||
addParams = {
|
||||
add_params = {
|
||||
"lcm-operation-user-data": "./UserData/userdata.py",
|
||||
"lcm-operation-user-data-class": "UserData",
|
||||
"nfv": {"CP": {"VDU2_CP1-2": {"port": ports['VDU2_CP1-2']}}}
|
||||
@ -431,12 +475,37 @@ def sample1_instantiate(net_ids, subnets, ports, auth_url):
|
||||
"vim2": vim_2
|
||||
},
|
||||
"localizationLanguage": "ja",
|
||||
"additionalParams": addParams,
|
||||
"extensions": {"dummy-key": "dummy-val"}
|
||||
"additionalParams": add_params,
|
||||
"extensions": {"dummy-key": "dummy-val"},
|
||||
"vnfConfigurableProperties": {"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 create_vnf_min(vnfd_id)
|
||||
|
||||
|
||||
def sample2_terminate():
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
return terminate_vnf_min()
|
||||
|
||||
|
||||
def sample2_instantiate():
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
return instantiate_vnf_min()
|
||||
|
||||
|
||||
def create_vnf_min(vnfd_id):
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
@ -446,7 +515,7 @@ def sample2_create(vnfd_id):
|
||||
}
|
||||
|
||||
|
||||
def sample2_terminate():
|
||||
def terminate_vnf_min():
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
@ -456,7 +525,7 @@ def sample2_terminate():
|
||||
}
|
||||
|
||||
|
||||
def sample2_instantiate():
|
||||
def instantiate_vnf_min():
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
@ -464,3 +533,19 @@ def sample2_instantiate():
|
||||
return {
|
||||
"flavourId": "simple"
|
||||
}
|
||||
|
||||
|
||||
def scaleout_vnf_max():
|
||||
# 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 {
|
||||
"type": "SCALE_OUT",
|
||||
"aspectId": "VDU1_scale",
|
||||
"numberOfSteps": 1,
|
||||
"additionalParams": {"dummy-key": "dummy-value"}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: 'VDU1 HOT for Sample VNF'
|
||||
|
||||
parameters:
|
||||
flavor:
|
||||
type: string
|
||||
image:
|
||||
type: string
|
||||
net5:
|
||||
type: string
|
||||
affinity:
|
||||
type: string
|
||||
|
||||
resources:
|
||||
VDU1:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: { get_param: flavor }
|
||||
image: { get_param: image }
|
||||
name: VDU1
|
||||
networks:
|
||||
- port:
|
||||
get_resource: VDU1_CP1
|
||||
scheduler_hints:
|
||||
group: {get_param: affinity }
|
||||
|
||||
VDU1_CP1:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: errornetwork
|
@ -0,0 +1,61 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: 'Simple Base HOT for Sample VNF'
|
||||
|
||||
parameters:
|
||||
nfv:
|
||||
type: json
|
||||
|
||||
resources:
|
||||
VDU1_scale_group:
|
||||
type: OS::Heat::AutoScalingGroup
|
||||
properties:
|
||||
min_size: 1
|
||||
max_size: 3
|
||||
desired_capacity: { get_param: [ nfv, VDU, VDU1, desired_capacity ] }
|
||||
resource:
|
||||
type: VDU1.yaml
|
||||
properties:
|
||||
flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
|
||||
image: { get_param: [ nfv, VDU, VDU1, vcImageId ] }
|
||||
net5: { get_resource: internalVL3 }
|
||||
affinity: { get_resource: nfvi_node_affinity }
|
||||
|
||||
# NOTE: Resource definition of OS::Heat::ScalingPolicy is omitted.
|
||||
# It is not used by v2 scale implementation unlike v1.
|
||||
|
||||
VDU2:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
|
||||
name: VDU2
|
||||
image: { get_param: [ nfv, VDU, VDU2, vcImageId] }
|
||||
networks:
|
||||
- port:
|
||||
get_resource: VDU2_CP1
|
||||
scheduler_hints:
|
||||
group: {get_resource: nfvi_node_affinity }
|
||||
|
||||
VDU2_CP1:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: { get_resource: internalVL3 }
|
||||
|
||||
internalVL3:
|
||||
type: OS::Neutron::Net
|
||||
|
||||
|
||||
internalVL3_subnet:
|
||||
type: OS::Neutron::Subnet
|
||||
properties:
|
||||
ip_version: 4
|
||||
network:
|
||||
get_resource: internalVL3
|
||||
cidr: 192.168.5.0/24
|
||||
|
||||
nfvi_node_affinity:
|
||||
type: OS::Nova::ServerGroup
|
||||
properties:
|
||||
name: nfvi_node_affinity
|
||||
policies: [ 'affinity' ]
|
||||
|
||||
outputs: {}
|
@ -0,0 +1,258 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Simple deployment flavour for Sample VNF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- v2_sample2_types.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
descriptor_id:
|
||||
type: string
|
||||
descriptor_version:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
product_name:
|
||||
type: string
|
||||
software_version:
|
||||
type: string
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
flavour_id:
|
||||
type: string
|
||||
flavour_description:
|
||||
type: string
|
||||
|
||||
substitution_mappings:
|
||||
node_type: company.provider.VNF
|
||||
properties:
|
||||
flavour_id: simple
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: company.provider.VNF
|
||||
properties:
|
||||
flavour_description: A simple flavour
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
instantiate_start:
|
||||
implementation: sample-script
|
||||
instantiate_end:
|
||||
implementation: sample-script
|
||||
terminate_start:
|
||||
implementation: sample-script
|
||||
terminate_end:
|
||||
implementation: sample-script
|
||||
artifacts:
|
||||
sample-script:
|
||||
description: Sample script
|
||||
type: tosca.artifacts.Implementation.Python
|
||||
file: ../Scripts/sample_script.py
|
||||
|
||||
VDU1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU1
|
||||
description: VDU1 compute node
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
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:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: m1.tiny
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 3 GB
|
||||
|
||||
VDU2:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU2
|
||||
description: VDU2 compute node
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
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:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: m1.tiny
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 3 GB
|
||||
|
||||
VDU1_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 4
|
||||
requirements:
|
||||
- virtual_binding: VDU1
|
||||
- virtual_link: internalVL3
|
||||
|
||||
VDU2_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 4
|
||||
requirements:
|
||||
- virtual_binding: VDU2
|
||||
- virtual_link: internalVL3
|
||||
|
||||
internalVL3:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
description: Internal 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.5.0/24
|
||||
|
||||
groups:
|
||||
affinityOrAntiAffinityGroup1:
|
||||
type: tosca.groups.nfv.PlacementGroup
|
||||
members: [ VDU1, VDU2 ]
|
||||
|
||||
policies:
|
||||
- scaling_aspects:
|
||||
type: tosca.policies.nfv.ScalingAspects
|
||||
properties:
|
||||
aspects:
|
||||
VDU1_scale:
|
||||
name: VDU1_scale
|
||||
description: VDU1 scaling aspect
|
||||
max_scale_level: 2
|
||||
step_deltas:
|
||||
- delta_1
|
||||
|
||||
- VDU1_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- VDU2_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU2 ]
|
||||
|
||||
- VDU1_scaling_aspect_deltas:
|
||||
type: tosca.policies.nfv.VduScalingAspectDeltas
|
||||
properties:
|
||||
aspect: VDU1_scale
|
||||
deltas:
|
||||
delta_1:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- instantiation_levels:
|
||||
type: tosca.policies.nfv.InstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
description: Smallest size
|
||||
scale_info:
|
||||
VDU1_scale:
|
||||
scale_level: 0
|
||||
instantiation_level_2:
|
||||
description: Largest size
|
||||
scale_info:
|
||||
VDU1_scale:
|
||||
scale_level: 2
|
||||
default_level: instantiation_level_1
|
||||
|
||||
- VDU1_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
number_of_instances: 1
|
||||
instantiation_level_2:
|
||||
number_of_instances: 3
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- VDU2_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
number_of_instances: 1
|
||||
instantiation_level_2:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU2 ]
|
||||
|
||||
- internalVL3_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: [ internalVL3 ]
|
||||
|
||||
- policy_affinity_group:
|
||||
type: tosca.policies.nfv.AffinityRule
|
||||
targets: [ affinityOrAntiAffinityGroup1 ]
|
||||
properties:
|
||||
scope: nfvi_node
|
@ -0,0 +1,31 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Sample VNF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- v2_sample2_types.yaml
|
||||
- v2_sample2_df_simple.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
selected_flavour:
|
||||
type: string
|
||||
description: VNF deployment flavour selected by the consumer. It is provided in the API
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: company.provider.VNF
|
||||
properties:
|
||||
flavour_id: { get_input: selected_flavour }
|
||||
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
|
||||
provider: Company
|
||||
product_name: Sample VNF
|
||||
software_version: '1.0'
|
||||
descriptor_version: '1.0'
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
requirements:
|
||||
#- virtual_link_external # mapped in lower-level templates
|
||||
#- virtual_link_internal # mapped in lower-level templates
|
@ -0,0 +1,55 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: VNF type definition
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
|
||||
node_types:
|
||||
company.provider.VNF:
|
||||
derived_from: tosca.nodes.nfv.VNF
|
||||
properties:
|
||||
descriptor_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d7000000 ] ]
|
||||
default: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
|
||||
descriptor_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '1.0' ] ]
|
||||
default: '1.0'
|
||||
provider:
|
||||
type: string
|
||||
constraints: [ valid_values: [ 'Company' ] ]
|
||||
default: 'Company'
|
||||
product_name:
|
||||
type: string
|
||||
constraints: [ valid_values: [ 'Sample VNF' ] ]
|
||||
default: 'Sample VNF'
|
||||
software_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '1.0' ] ]
|
||||
default: '1.0'
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Tacker ] ]
|
||||
default: [ Tacker ]
|
||||
flavour_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ simple ] ]
|
||||
default: simple
|
||||
flavour_description:
|
||||
type: string
|
||||
default: "flavour"
|
||||
requirements:
|
||||
- virtual_link_external1:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
- virtual_link_external2:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
- virtual_link_internal:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
type: tosca.interfaces.nfv.Vnflcm
|
@ -0,0 +1,67 @@
|
||||
# Copyright (C) 2022 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)
|
@ -0,0 +1,4 @@
|
||||
TOSCA-Meta-File-Version: 1.0
|
||||
CSAR-Version: 1.1
|
||||
Created-by: Onboarding portal
|
||||
Entry-Definitions: Definitions/v2_sample2_top.vnfd.yaml
|
@ -0,0 +1,50 @@
|
||||
# Copyright (C) 2022 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 json
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.tests.functional.sol_v2 import paramgen
|
||||
from tacker.tests.functional.sol_v2 import utils
|
||||
|
||||
|
||||
zip_file_name = os.path.basename(os.path.abspath(".")) + '.zip'
|
||||
tmp_dir = tempfile.mkdtemp()
|
||||
vnfd_id = uuidutils.generate_uuid()
|
||||
utils.make_zip(".", tmp_dir, vnfd_id)
|
||||
|
||||
shutil.copy(os.path.join(tmp_dir, zip_file_name), ".")
|
||||
shutil.rmtree(tmp_dir)
|
||||
|
||||
subscription_req = paramgen.sub_create_min("http://127.0.0.1/")
|
||||
create_req = paramgen.create_vnf_min(vnfd_id)
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
instantiate_req = paramgen.instantiate_vnf_min()
|
||||
|
||||
with open("subscription_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(subscription_req, indent=2))
|
||||
|
||||
with open("create_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(create_req, indent=2))
|
||||
|
||||
with open("terminate_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(terminate_req, indent=2))
|
||||
|
||||
with open("instantiate_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(instantiate_req, indent=2))
|
@ -1,202 +0,0 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
description: ETSI NFV SOL 001 common types definitions version 2.6.1
|
||||
metadata:
|
||||
template_name: etsi_nfv_sol001_common_types
|
||||
template_author: ETSI_NFV
|
||||
template_version: 2.6.1
|
||||
|
||||
data_types:
|
||||
tosca.datatypes.nfv.L2AddressData:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: Describes the information on the MAC addresses to be assigned to a connection point.
|
||||
properties:
|
||||
mac_address_assignment:
|
||||
type: boolean
|
||||
description: Specifies if the address assignment is the responsibility of management and orchestration function or not. If it is set to True, it is the management and orchestration function responsibility
|
||||
required: true
|
||||
|
||||
tosca.datatypes.nfv.L3AddressData:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: Provides information about Layer 3 level addressing scheme and parameters applicable to a CP
|
||||
properties:
|
||||
ip_address_assignment:
|
||||
type: boolean
|
||||
description: Specifies if the address assignment is the responsibility of management and orchestration function or not. If it is set to True, it is the management and orchestration function responsibility
|
||||
required: true
|
||||
floating_ip_activated:
|
||||
type: boolean
|
||||
description: Specifies if the floating IP scheme is activated on the Connection Point or not
|
||||
required: true
|
||||
ip_address_type:
|
||||
type: string
|
||||
description: Defines address type. The address type should be aligned with the address type supported by the layer_protocols properties of the parent VnfExtCp
|
||||
required: false
|
||||
constraints:
|
||||
- valid_values: [ ipv4, ipv6 ]
|
||||
number_of_ip_address:
|
||||
type: integer
|
||||
description: Minimum number of IP addresses to be assigned
|
||||
required: false
|
||||
constraints:
|
||||
- greater_than: 0
|
||||
|
||||
tosca.datatypes.nfv.AddressData:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: Describes information about the addressing scheme and parameters applicable to a CP
|
||||
properties:
|
||||
address_type:
|
||||
type: string
|
||||
description: Describes the type of the address to be assigned to a connection point. The content type shall be aligned with the address type supported by the layerProtocol property of the connection point
|
||||
required: true
|
||||
constraints:
|
||||
- valid_values: [ mac_address, ip_address ]
|
||||
l2_address_data:
|
||||
type: tosca.datatypes.nfv.L2AddressData
|
||||
description: Provides the information on the MAC addresses to be assigned to a connection point.
|
||||
required: false
|
||||
l3_address_data:
|
||||
type: tosca.datatypes.nfv.L3AddressData
|
||||
description: Provides the information on the IP addresses to be assigned to a connection point
|
||||
required: false
|
||||
|
||||
tosca.datatypes.nfv.ConnectivityType:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: describes additional connectivity information of a virtualLink
|
||||
properties:
|
||||
layer_protocols:
|
||||
type: list
|
||||
description: Identifies the protocol a virtualLink gives access to (ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire).The top layer protocol of the virtualLink protocol stack shall always be provided. The lower layer protocols may be included when there are specific requirements on these layers.
|
||||
required: true
|
||||
entry_schema:
|
||||
type: string
|
||||
constraints:
|
||||
- valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
|
||||
flow_pattern:
|
||||
type: string
|
||||
description: Identifies the flow pattern of the connectivity
|
||||
required: false
|
||||
constraints:
|
||||
- valid_values: [ line, tree, mesh ]
|
||||
|
||||
tosca.datatypes.nfv.LinkBitrateRequirements:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: describes the requirements in terms of bitrate for a virtual link
|
||||
properties:
|
||||
root:
|
||||
type: integer # in bits per second
|
||||
description: Specifies the throughput requirement in bits per second of the link (e.g. bitrate of E-Line, root bitrate of E-Tree, aggregate capacity of E-LAN).
|
||||
required: true
|
||||
constraints:
|
||||
- greater_or_equal: 0
|
||||
leaf:
|
||||
type: integer # in bits per second
|
||||
description: Specifies the throughput requirement in bits per second of leaf connections to the link when applicable to the connectivity type (e.g. for E-Tree and E LAN branches).
|
||||
required: false
|
||||
constraints:
|
||||
- greater_or_equal: 0
|
||||
|
||||
tosca.datatypes.nfv.CpProtocolData:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: Describes and associates the protocol layer that a CP uses together with other protocol and connection point information
|
||||
properties:
|
||||
associated_layer_protocol:
|
||||
type: string
|
||||
required: true
|
||||
description: One of the values of the property layer_protocols of the CP
|
||||
constraints:
|
||||
- valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
|
||||
address_data:
|
||||
type: list
|
||||
description: Provides information on the addresses to be assigned to the CP
|
||||
entry_schema:
|
||||
type: tosca.datatypes.nfv.AddressData
|
||||
required: false
|
||||
|
||||
tosca.datatypes.nfv.VnfProfile:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: describes a profile for instantiating VNFs of a particular NS DF according to a specific VNFD and VNF DF.
|
||||
properties:
|
||||
instantiation_level:
|
||||
type: string
|
||||
description: Identifier of the instantiation level of the VNF DF to be used for instantiation. If not present, the default instantiation level as declared in the VNFD shall be used.
|
||||
required: false
|
||||
min_number_of_instances:
|
||||
type: integer
|
||||
description: Minimum number of instances of the VNF based on this VNFD that is permitted to exist for this VnfProfile.
|
||||
required: true
|
||||
constraints:
|
||||
- greater_or_equal: 0
|
||||
max_number_of_instances:
|
||||
type: integer
|
||||
description: Maximum number of instances of the VNF based on this VNFD that is permitted to exist for this VnfProfile.
|
||||
required: true
|
||||
constraints:
|
||||
- greater_or_equal: 0
|
||||
|
||||
tosca.datatypes.nfv.Qos:
|
||||
derived_from: tosca.datatypes.Root
|
||||
description: describes QoS data for a given VL used in a VNF deployment flavour
|
||||
properties:
|
||||
latency:
|
||||
type: scalar-unit.time #Number
|
||||
description: Specifies the maximum latency
|
||||
required: true
|
||||
constraints:
|
||||
- greater_than: 0 s
|
||||
packet_delay_variation:
|
||||
type: scalar-unit.time #Number
|
||||
description: Specifies the maximum jitter
|
||||
required: true
|
||||
constraints:
|
||||
- greater_or_equal: 0 s
|
||||
packet_loss_ratio:
|
||||
type: float
|
||||
description: Specifies the maximum packet loss ratio
|
||||
required: false
|
||||
constraints:
|
||||
- in_range: [ 0.0, 1.0 ]
|
||||
|
||||
capability_types:
|
||||
tosca.capabilities.nfv.VirtualLinkable:
|
||||
derived_from: tosca.capabilities.Node
|
||||
description: A node type that includes the VirtualLinkable capability indicates that it can be pointed by tosca.relationships.nfv.VirtualLinksTo relationship type
|
||||
|
||||
relationship_types:
|
||||
tosca.relationships.nfv.VirtualLinksTo:
|
||||
derived_from: tosca.relationships.DependsOn
|
||||
description: Represents an association relationship between the VduCp and VnfVirtualLink node types
|
||||
valid_target_types: [ tosca.capabilities.nfv.VirtualLinkable ]
|
||||
|
||||
node_types:
|
||||
tosca.nodes.nfv.Cp:
|
||||
derived_from: tosca.nodes.Root
|
||||
description: Provides information regarding the purpose of the connection point
|
||||
properties:
|
||||
layer_protocols:
|
||||
type: list
|
||||
description: Identifies which protocol the connection point uses for connectivity purposes
|
||||
required: true
|
||||
entry_schema:
|
||||
type: string
|
||||
constraints:
|
||||
- valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
|
||||
role: #Name in ETSI NFV IFA011 v0.7.3: cpRole
|
||||
type: string
|
||||
description: Identifies the role of the port in the context of the traffic flow patterns in the VNF or parent NS
|
||||
required: false
|
||||
constraints:
|
||||
- valid_values: [ root, leaf ]
|
||||
description:
|
||||
type: string
|
||||
description: Provides human-readable information on the purpose of the connection point
|
||||
required: false
|
||||
protocol:
|
||||
type: list
|
||||
description: Provides information on the addresses to be assigned to the connection point(s) instantiated from this Connection Point Descriptor
|
||||
required: false
|
||||
entry_schema:
|
||||
type: tosca.datatypes.nfv.CpProtocolData
|
||||
trunk_mode:
|
||||
type: boolean
|
||||
description: Provides information about whether the CP instantiated from this Cp is in Trunk mode (802.1Q or other), When operating in "trunk mode", the Cp is capable of carrying traffic for several VLANs. Absence of this property implies that trunkMode is not configured for the Cp i.e. It is equivalent to boolean value "false".
|
||||
required: false
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,91 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: 'VDU1 HOT for Sample VNF'
|
||||
|
||||
parameters:
|
||||
flavor:
|
||||
type: string
|
||||
image:
|
||||
type: string
|
||||
zone:
|
||||
type: string
|
||||
net1:
|
||||
type: string
|
||||
net2:
|
||||
type: string
|
||||
net3:
|
||||
type: string
|
||||
net4:
|
||||
type: string
|
||||
net5:
|
||||
type: string
|
||||
subnet1:
|
||||
type: string
|
||||
subnet2:
|
||||
type: string
|
||||
|
||||
resources:
|
||||
VDU1:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: { get_param: flavor }
|
||||
name: VDU1
|
||||
block_device_mapping_v2: [{"volume_id": { get_resource: VDU1-VirtualStorage }}]
|
||||
networks:
|
||||
- port:
|
||||
get_resource: VDU1_CP1
|
||||
- port:
|
||||
get_resource: VDU1_CP2
|
||||
# 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
|
||||
|
||||
|
||||
availability_zone: { get_param: zone }
|
||||
|
||||
VDU1-VirtualStorage:
|
||||
type: OS::Cinder::Volume
|
||||
properties:
|
||||
image: { get_param: image }
|
||||
size: 1
|
||||
volume_type: { get_resource: multi }
|
||||
multi:
|
||||
type: OS::Cinder::VolumeType
|
||||
properties:
|
||||
name: multivolume
|
||||
metadata: { multiattach: "<is> True" }
|
||||
|
||||
# extVL without FixedIP or with numDynamicAddresses
|
||||
VDU1_CP1:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: { get_param: net1 }
|
||||
fixed_ips:
|
||||
- subnet: { get_param: subnet1}
|
||||
|
||||
# extVL with numDynamicAddresses and subnet
|
||||
VDU1_CP2:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: { get_param: net2 }
|
||||
fixed_ips:
|
||||
- subnet: { get_param: subnet2}
|
||||
|
||||
# delete the following line when extmanagedVLs' Ports 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
|
||||
properties:
|
||||
network: { get_param: net5 }
|
@ -0,0 +1,120 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: 'Simple Base HOT for Sample VNF'
|
||||
|
||||
parameters:
|
||||
nfv:
|
||||
type: json
|
||||
|
||||
resources:
|
||||
VDU1_scale_group:
|
||||
type: OS::Heat::AutoScalingGroup
|
||||
properties:
|
||||
min_size: 1
|
||||
max_size: 3
|
||||
desired_capacity: { get_param: [ nfv, VDU, VDU1, desired_capacity ] }
|
||||
resource:
|
||||
type: VDU1.yaml
|
||||
properties:
|
||||
flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
|
||||
image: { get_param: [ nfv, VDU, VDU1-VirtualStorage, vcImageId ] }
|
||||
zone: { get_param: [ nfv, VDU, VDU1, locationConstraints] }
|
||||
net1: { get_param: [ nfv, CP, VDU1_CP1, network] }
|
||||
net2: { get_param: [ nfv, CP, VDU1_CP2, network ] }
|
||||
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 }
|
||||
net4: { get_resource: internalVL2 }
|
||||
net5: { get_resource: internalVL3 }
|
||||
|
||||
# NOTE: Resource definition of OS::Heat::ScalingPolicy is omitted.
|
||||
# It is not used by v2 scale implementation unlike v1.
|
||||
|
||||
VDU2:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: { get_param: [ nfv, VDU, VDU2, computeFlavourId ] }
|
||||
name: VDU2
|
||||
availability_zone: { get_param: [ nfv, VDU, VDU2, locationConstraints ] }
|
||||
block_device_mapping_v2: [{"volume_id": { get_resource: VDU2-VirtualStorage }}]
|
||||
networks:
|
||||
- port: { get_param: [ nfv, CP, VDU2_CP1-1, port ] }
|
||||
- port: { get_param: [ nfv, CP, VDU2_CP1-2, port ] }
|
||||
- port:
|
||||
get_resource: VDU2_CP2
|
||||
- port:
|
||||
get_resource: VDU2_CP3
|
||||
- port:
|
||||
get_resource: VDU2_CP4
|
||||
- port:
|
||||
get_resource: VDU2_CP5
|
||||
|
||||
VDU2-VirtualStorage:
|
||||
type: OS::Cinder::Volume
|
||||
properties:
|
||||
image: { get_param: [ nfv, VDU, VDU2-VirtualStorage, vcImageId] }
|
||||
size: 1
|
||||
volume_type: { get_resource: multi }
|
||||
multi:
|
||||
type: OS::Cinder::VolumeType
|
||||
properties:
|
||||
name: VDU2-multi
|
||||
metadata: { multiattach: "<is> True" }
|
||||
|
||||
# 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]}
|
||||
- subnet: { get_param: [nfv, CP, VDU2_CP2, fixed_ips, 1, 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 }
|
||||
|
||||
# delete the following lines when extmanagedVLs are specified in instantiatevnfrequest
|
||||
internalVL1:
|
||||
type: OS::Neutron::Net
|
||||
internalVL2:
|
||||
type: OS::Neutron::Net
|
||||
internalVL3:
|
||||
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:
|
||||
type: OS::Neutron::Subnet
|
||||
properties:
|
||||
ip_version: 4
|
||||
network:
|
||||
get_resource: internalVL3
|
||||
cidr: 192.168.5.0/24
|
||||
outputs: {}
|
@ -0,0 +1,428 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Simple deployment flavour for Sample VNF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- v2_sample1_types.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
descriptor_id:
|
||||
type: string
|
||||
descriptor_version:
|
||||
type: string
|
||||
provider:
|
||||
type: string
|
||||
product_name:
|
||||
type: string
|
||||
software_version:
|
||||
type: string
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
flavour_id:
|
||||
type: string
|
||||
flavour_description:
|
||||
type: string
|
||||
|
||||
substitution_mappings:
|
||||
node_type: company.provider.VNF
|
||||
properties:
|
||||
flavour_id: simple
|
||||
requirements:
|
||||
virtual_link_external1_1: [ VDU1_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_2: [ VDU2_CP2, virtual_link ]
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: company.provider.VNF
|
||||
properties:
|
||||
flavour_description: A simple flavour
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
instantiate: []
|
||||
instantiate_start: []
|
||||
instantiate_end: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
modify_information: []
|
||||
modify_information_start: []
|
||||
modify_information_end: []
|
||||
|
||||
VDU1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU1
|
||||
description: VDU1 compute node
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 3
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: m1.tiny
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 3 GB
|
||||
requirements:
|
||||
- virtual_storage: VDU1-VirtualStorage
|
||||
|
||||
VDU2:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU2
|
||||
description: VDU2 compute node
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: m1.tiny
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 3 GB
|
||||
requirements:
|
||||
- virtual_storage: VDU2-VirtualStorage
|
||||
|
||||
VDU1-VirtualStorage:
|
||||
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
||||
properties:
|
||||
virtual_block_storage_data:
|
||||
size_of_storage: 1 GB
|
||||
rdma_enabled: true
|
||||
sw_image_data:
|
||||
name: VDU1-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
|
||||
|
||||
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:
|
||||
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
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 4
|
||||
requirements:
|
||||
- virtual_binding: VDU1
|
||||
- virtual_link: internalVL3
|
||||
|
||||
VDU2_CP1-1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 0
|
||||
requirements:
|
||||
- virtual_binding: VDU2
|
||||
|
||||
VDU2_CP1-2:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 1
|
||||
requirements:
|
||||
- virtual_binding: VDU2
|
||||
|
||||
VDU2_CP2:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 2
|
||||
requirements:
|
||||
- virtual_binding: VDU2
|
||||
|
||||
VDU2_CP3:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 3
|
||||
requirements:
|
||||
- virtual_binding: VDU2
|
||||
- virtual_link: internalVL1
|
||||
|
||||
VDU2_CP4:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 4
|
||||
requirements:
|
||||
- virtual_binding: VDU2
|
||||
- virtual_link: internalVL2
|
||||
|
||||
VDU2_CP5:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 5
|
||||
requirements:
|
||||
- virtual_binding: VDU2
|
||||
- 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:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ ipv4 ]
|
||||
description: Internal 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.5.0/24
|
||||
|
||||
groups:
|
||||
affinityOrAntiAffinityGroup1:
|
||||
type: tosca.groups.nfv.PlacementGroup
|
||||
members: [ VDU1, VDU2 ]
|
||||
|
||||
policies:
|
||||
- scaling_aspects:
|
||||
type: tosca.policies.nfv.ScalingAspects
|
||||
properties:
|
||||
aspects:
|
||||
VDU1_scale:
|
||||
name: VDU1_scale
|
||||
description: VDU1 scaling aspect
|
||||
max_scale_level: 2
|
||||
step_deltas:
|
||||
- delta_1
|
||||
|
||||
- VDU1_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- VDU2_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU2 ]
|
||||
|
||||
- VDU1_scaling_aspect_deltas:
|
||||
type: tosca.policies.nfv.VduScalingAspectDeltas
|
||||
properties:
|
||||
aspect: VDU1_scale
|
||||
deltas:
|
||||
delta_1:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- instantiation_levels:
|
||||
type: tosca.policies.nfv.InstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
description: Smallest size
|
||||
scale_info:
|
||||
VDU1_scale:
|
||||
scale_level: 0
|
||||
instantiation_level_2:
|
||||
description: Largest size
|
||||
scale_info:
|
||||
VDU1_scale:
|
||||
scale_level: 2
|
||||
default_level: instantiation_level_1
|
||||
|
||||
- VDU1_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
number_of_instances: 1
|
||||
instantiation_level_2:
|
||||
number_of_instances: 3
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- VDU2_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
number_of_instances: 1
|
||||
instantiation_level_2:
|
||||
number_of_instances: 1
|
||||
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:
|
||||
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: [ internalVL3 ]
|
||||
|
||||
- policy_affinity_group:
|
||||
type: tosca.policies.nfv.AffinityRule
|
||||
targets: [ affinityOrAntiAffinityGroup1 ]
|
||||
properties:
|
||||
scope: zone
|
@ -0,0 +1,31 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: Sample VNF
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
- v2_sample1_types.yaml
|
||||
- v2_sample1_df_simple.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
selected_flavour:
|
||||
type: string
|
||||
description: VNF deployment flavour selected by the consumer. It is provided in the API
|
||||
|
||||
node_templates:
|
||||
VNF:
|
||||
type: company.provider.VNF
|
||||
properties:
|
||||
flavour_id: { get_input: selected_flavour }
|
||||
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
|
||||
provider: Company
|
||||
product_name: Sample VNF
|
||||
software_version: '1.0'
|
||||
descriptor_version: '1.0'
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
requirements:
|
||||
#- virtual_link_external # mapped in lower-level templates
|
||||
#- virtual_link_internal # mapped in lower-level templates
|
@ -0,0 +1,55 @@
|
||||
tosca_definitions_version: tosca_simple_yaml_1_2
|
||||
|
||||
description: VNF type definition
|
||||
|
||||
imports:
|
||||
- etsi_nfv_sol001_common_types.yaml
|
||||
- etsi_nfv_sol001_vnfd_types.yaml
|
||||
|
||||
node_types:
|
||||
company.provider.VNF:
|
||||
derived_from: tosca.nodes.nfv.VNF
|
||||
properties:
|
||||
descriptor_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d7000000 ] ]
|
||||
default: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
|
||||
descriptor_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '1.0' ] ]
|
||||
default: '1.0'
|
||||
provider:
|
||||
type: string
|
||||
constraints: [ valid_values: [ 'Company' ] ]
|
||||
default: 'Company'
|
||||
product_name:
|
||||
type: string
|
||||
constraints: [ valid_values: [ 'Sample VNF' ] ]
|
||||
default: 'Sample VNF'
|
||||
software_version:
|
||||
type: string
|
||||
constraints: [ valid_values: [ '1.0' ] ]
|
||||
default: '1.0'
|
||||
vnfm_info:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
constraints: [ valid_values: [ Tacker ] ]
|
||||
default: [ Tacker ]
|
||||
flavour_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ simple ] ]
|
||||
default: simple
|
||||
flavour_description:
|
||||
type: string
|
||||
default: "flavour"
|
||||
requirements:
|
||||
- virtual_link_external1:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
- virtual_link_external2:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
- virtual_link_internal:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
type: tosca.interfaces.nfv.Vnflcm
|
@ -0,0 +1,67 @@
|
||||
# Copyright (C) 2022 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)
|
@ -0,0 +1,4 @@
|
||||
TOSCA-Meta-File-Version: 1.0
|
||||
CSAR-Version: 1.1
|
||||
Created-by: Onboarding portal
|
||||
Entry-Definitions: Definitions/v2_sample1_top.vnfd.yaml
|
@ -0,0 +1,124 @@
|
||||
# Copyright (C) 2022 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 yaml
|
||||
|
||||
from tacker.sol_refactored.common import vnf_instance_utils as inst_utils
|
||||
from tacker.sol_refactored.infra_drivers.openstack import userdata_utils
|
||||
|
||||
|
||||
class UserData(userdata_utils.AbstractUserData):
|
||||
|
||||
@staticmethod
|
||||
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)
|
||||
flavour_id = req['flavourId']
|
||||
|
||||
hot_dict = vnfd.get_base_hot(flavour_id)
|
||||
top_hot = hot_dict['template']
|
||||
|
||||
nfv_dict = userdata_utils.init_nfv_dict(top_hot)
|
||||
|
||||
vdus = nfv_dict.get('VDU', {})
|
||||
for vdu_name, vdu_value in vdus.items():
|
||||
if 'computeFlavourId' in vdu_value:
|
||||
vdu_value['computeFlavourId'] = (
|
||||
userdata_utils.get_param_flavor(
|
||||
vdu_name, flavour_id, vnfd, grant))
|
||||
if 'vcImageId' in vdu_value:
|
||||
vdu_value['vcImageId'] = userdata_utils.get_param_image(
|
||||
vdu_name, flavour_id, vnfd, grant)
|
||||
if 'locationConstraints' in vdu_value:
|
||||
vdu_value['locationConstraints'] = (
|
||||
userdata_utils.get_param_zone(
|
||||
vdu_name, grant_req, grant))
|
||||
if 'desired_capacity' in vdu_value:
|
||||
vdu_value['desired_capacity'] = (
|
||||
userdata_utils.get_param_capacity(
|
||||
vdu_name, inst, grant_req))
|
||||
|
||||
cps = nfv_dict.get('CP', {})
|
||||
for cp_name, cp_value in cps.items():
|
||||
if 'network' in cp_value:
|
||||
cp_value['network'] = userdata_utils.get_param_network(
|
||||
cp_name, grant, req)
|
||||
if 'fixed_ips' in cp_value:
|
||||
ext_fixed_ips = userdata_utils.get_param_fixed_ips(
|
||||
cp_name, grant, req)
|
||||
fixed_ips = []
|
||||
for i in range(len(ext_fixed_ips)):
|
||||
if i not in cp_value['fixed_ips']:
|
||||
break
|
||||
ips_i = cp_value['fixed_ips'][i]
|
||||
if 'subnet' in ips_i:
|
||||
ips_i['subnet'] = ext_fixed_ips[i].get('subnet')
|
||||
if 'ip_address' in ips_i:
|
||||
ips_i['ip_address'] = ext_fixed_ips[i].get(
|
||||
'ip_address')
|
||||
fixed_ips.append(ips_i)
|
||||
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)
|
||||
|
||||
if 'nfv' in req.get('additionalParams', {}):
|
||||
nfv_dict = inst_utils.json_merge_patch(nfv_dict,
|
||||
req['additionalParams']['nfv'])
|
||||
if 'nfv' in grant.get('additionalParams', {}):
|
||||
nfv_dict = inst_utils.json_merge_patch(nfv_dict,
|
||||
grant['additionalParams']['nfv'])
|
||||
|
||||
fields = {
|
||||
'template': yaml.safe_dump(top_hot),
|
||||
'parameters': {'nfv': nfv_dict},
|
||||
'files': {}
|
||||
}
|
||||
for key, value in hot_dict.get('files', {}).items():
|
||||
fields['files'][key] = yaml.safe_dump(value)
|
||||
|
||||
return fields
|
77
tacker/tests/functional/sol_v2/samples/scale_ng/pkggen.py
Normal file
77
tacker/tests/functional/sol_v2/samples/scale_ng/pkggen.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright (C) 2022 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 json
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.tests.functional.sol_v2 import paramgen
|
||||
from tacker.tests.functional.sol_v2 import utils
|
||||
|
||||
|
||||
zip_file_name = os.path.basename(os.path.abspath(".")) + '.zip'
|
||||
tmp_dir = tempfile.mkdtemp()
|
||||
vnfd_id = uuidutils.generate_uuid()
|
||||
|
||||
# tacker/tests/etc...
|
||||
# /functional/sol_v2/samples/smapleX
|
||||
image_dir = "../../../../etc/samples/etsi/nfv/common/Files/images/"
|
||||
image_file = "cirros-0.5.2-x86_64-disk.img"
|
||||
image_path = os.path.abspath(image_dir + image_file)
|
||||
|
||||
utils.make_zip(".", tmp_dir, vnfd_id, image_path)
|
||||
|
||||
shutil.move(os.path.join(tmp_dir, zip_file_name), ".")
|
||||
shutil.rmtree(tmp_dir)
|
||||
|
||||
subscription_req = paramgen.sub_create_max("http://127.0.0.1/")
|
||||
create_req = paramgen.create_vnf_max(vnfd_id)
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
|
||||
print('#####################################################################\n'
|
||||
'# 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.instantiate_vnf_max(
|
||||
net_ids, subnet_ids, port_ids, "http://localhost/identity/v3")
|
||||
|
||||
with open("subscription_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(subscription_req, indent=2))
|
||||
|
||||
with open("create_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(create_req, indent=2))
|
||||
|
||||
with open("terminate_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(terminate_req, indent=2))
|
||||
|
||||
with open("scaleout_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(scaleout_req, indent=2))
|
||||
|
||||
with open("instantiate_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(instantiate_req, indent=2))
|
20
tacker/tests/functional/sol_v2/samples/scale_ng/post.py
Normal file
20
tacker/tests/functional/sol_v2/samples/scale_ng/post.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2022 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/scale_ng/pre.py
Normal file
21
tacker/tests/functional/sol_v2/samples/scale_ng/pre.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (C) 2022 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')
|
@ -97,9 +97,9 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||
- 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 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1
|
||||
- 1..N (2 or more)
|
||||
- is_all=False
|
||||
Omit except for required attributes.
|
||||
@ -115,14 +115,17 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||
- 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()
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_min(callback_uri)
|
||||
if is_all:
|
||||
sub_req = paramgen.sub1_create()
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
|
||||
# 1. Create a new subscription
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
@ -162,9 +165,9 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||
* 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 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
@ -240,7 +243,7 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||
inst_id = body['id']
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1).get('usageState')
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# 2. Instantiate a VNF instance
|
||||
@ -444,7 +447,7 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1).get('usageState')
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
def test_sample2(self):
|
||||
@ -490,7 +493,7 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||
inst_id = body['id']
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2).get('usageState')
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# 2. Instantiate a VNF instance
|
||||
@ -554,5 +557,5 @@ class VnfLcmTest(base_v2.BaseSolV2Test):
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2).get('usageState')
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
686
tacker/tests/functional/sol_v2/test_vnflcm_error_handling.py
Normal file
686
tacker/tests/functional/sol_v2/test_vnflcm_error_handling.py
Normal file
@ -0,0 +1,686 @@
|
||||
# Copyright (C) 2022 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 ddt
|
||||
import os
|
||||
import time
|
||||
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional.sol_v2 import base_v2
|
||||
from tacker.tests.functional.sol_v2 import paramgen
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(VnfLcmErrorHandlingTest, cls).setUpClass()
|
||||
|
||||
cur_dir = os.path.dirname(__file__)
|
||||
# tacker/tests/etc...
|
||||
# /functional/sol_v2
|
||||
image_dir = os.path.join(
|
||||
cur_dir, "../../etc/samples/etsi/nfv/common/Files/images")
|
||||
image_file = "cirros-0.5.2-x86_64-disk.img"
|
||||
image_path = os.path.abspath(os.path.join(image_dir, image_file))
|
||||
|
||||
# Scale operation will fail
|
||||
scale_ng_path = os.path.join(cur_dir, "samples/scale_ng")
|
||||
cls.vnf_pkg_1, cls.vnfd_id_1 = cls.create_vnf_package(
|
||||
scale_ng_path, image_path=image_path)
|
||||
|
||||
# Instantiate VNF will fail
|
||||
error_network_path = os.path.join(cur_dir, "samples/error_network")
|
||||
# no image contained
|
||||
cls.vnf_pkg_2, cls.vnfd_id_2 = cls.create_vnf_package(
|
||||
error_network_path)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(VnfLcmErrorHandlingTest, cls).tearDownClass()
|
||||
|
||||
cls.delete_vnf_package(cls.vnf_pkg_1)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_2)
|
||||
|
||||
def setUp(self):
|
||||
super(VnfLcmErrorHandlingTest, self).setUp()
|
||||
|
||||
def test_retry_rollback_scale_out(self):
|
||||
"""Test retry and rollback scale out operations
|
||||
|
||||
* 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 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Pre-setting
|
||||
- 1. Create subscription
|
||||
- 2. Test notification
|
||||
- 3. Create VNF instance
|
||||
- 4. Instantiate VNF
|
||||
- 5. Show VNF instance
|
||||
- 6. Scale out operation(will fail)
|
||||
- 7. Show VNF instance
|
||||
- 8. Retry operation
|
||||
- 9. Rollback scale out operation
|
||||
- 10. Show VNF LCM operation occurrence
|
||||
- 11. List VNF LCM operation occurrence
|
||||
- 12. Terminate VNF
|
||||
- 13. Delete VNF instance
|
||||
- 14. Delete subscription
|
||||
- 15. Show subscription
|
||||
"""
|
||||
# 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 subscription
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
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. Test notification
|
||||
self.assert_notification_get(callback_url)
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 3. Create VNF instance
|
||||
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.create_vnf_max(self.vnfd_id_1)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
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']
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 4. Instantiate VNF
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
net_ids, subnet_ids, port_ids, self.auth_url)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# 5. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo',
|
||||
'extensions',
|
||||
'vnfConfigurableProperties'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo'].get('vnfState'))
|
||||
|
||||
# 6. Scale out operation(will fail)
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# 7. Show VNF instance
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# 8. Retry scale out operation
|
||||
resp, body = self.retry_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
|
||||
# 9. Rollback scale out operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 10. Show VNF LCM operation occurrence
|
||||
# NOTE: omitted values are not supported at that time
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# '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)
|
||||
|
||||
# 11. List 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', # omitted
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
# 'error', # omitted
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, expected_attrs)
|
||||
|
||||
# 12. Terminate VNF instance
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# wait a bit because there is a bit time lag between vnf instance DB
|
||||
# terminate and delete completion.
|
||||
time.sleep(5)
|
||||
|
||||
# 13. Delete VNF instance
|
||||
resp, body = self.delete_vnf_instance(inst_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_1)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 14. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# 15. Show subscription
|
||||
resp, body = self.show_subscription(sub_id)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
|
||||
def test_rollback_instantiate(self):
|
||||
"""Test rollback instantiate operation
|
||||
|
||||
* 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 subscription
|
||||
- 2. Test notification
|
||||
- 3. Create VNF instance
|
||||
- 4. Instantiate VNF(will fail)
|
||||
- 5. Show VNF instance
|
||||
- 6. Rollback instantiation operation
|
||||
- 7. Show VNF LCM operation occurrence
|
||||
- 8. List VNF LCM operation occurrence
|
||||
- 9. Delete VNF instance
|
||||
- 10. Delete subscription
|
||||
"""
|
||||
|
||||
# 1. Create subscription
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = (f'http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_min(callback_uri)
|
||||
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. Test notification
|
||||
self.assert_notification_get(callback_url)
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 3. Create VNF instance
|
||||
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.create_vnf_min(self.vnfd_id_2)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
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']
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# 4. Instantiate VNF(will fail)
|
||||
instantiate_req = paramgen.instantiate_vnf_min()
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# 5. Show VNF instance
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# 6. Rollback instantiation operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 7. Show VNF LCM operation occurrence
|
||||
# NOTE: omitted values are not supported at that time
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# '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)
|
||||
|
||||
# 8. List 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', # omitted
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
# 'error', # omitted
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, expected_attrs)
|
||||
|
||||
# 9. Delete VNF instance
|
||||
resp, body = self.delete_vnf_instance(inst_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 10. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
def test_fail_instantiate(self):
|
||||
"""Test fail instantiate operation
|
||||
|
||||
* 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 subscription
|
||||
- 2. Test notification
|
||||
- 3. Create VNF instance
|
||||
- 4. Instantiate VNF(will fail)
|
||||
- 5. Show VNF instance
|
||||
- 6. Fail instantiation operation
|
||||
- 7. Show VNF LCM operation occurrence
|
||||
- 8. List VNF LCM operation occurrence
|
||||
- 9. Delete VNF instance
|
||||
- 10. Delete subscription
|
||||
"""
|
||||
|
||||
# 1. Create subscription
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = (f'http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_min(callback_uri)
|
||||
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. Test notification
|
||||
self.assert_notification_get(callback_url)
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 3. Create VNF instance
|
||||
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.create_vnf_min(self.vnfd_id_2)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
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']
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# 4. Instantiate VNF(will fail)
|
||||
instantiate_req = paramgen.instantiate_vnf_min()
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# 5. Show VNF instance
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# 6. Fail instantiation operation
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.fail_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
self.assertEqual('FAILED', body['operationState'])
|
||||
|
||||
# 7. Show VNF LCM operation occurrence
|
||||
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)
|
||||
|
||||
# 8. List 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', # omitted
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
# 'error', # omitted
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, expected_attrs)
|
||||
|
||||
# 9. Delete VNF instance
|
||||
# Delete Stack
|
||||
self.heat_client.delete_stack(f'vnf-{inst_id}')
|
||||
|
||||
resp, body = self.delete_vnf_instance(inst_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_2)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 10. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
@ -31,6 +31,12 @@ def make_zip(sample_dir, tmp_dir, vnfd_id, image_path=None):
|
||||
tmp_contents = os.path.join(tmp_dir, "contents")
|
||||
shutil.copytree(os.path.join(sample_dir, "contents"), tmp_contents)
|
||||
|
||||
# add common vnfd files
|
||||
common_dir = os.path.join(sample_dir, "../common/Definitions/")
|
||||
for entry in os.listdir(common_dir):
|
||||
shutil.copy(os.path.join(common_dir, entry),
|
||||
os.path.join(tmp_contents, "Definitions"))
|
||||
|
||||
# replace vnfd_id
|
||||
def_path = os.path.join(tmp_contents, "Definitions")
|
||||
for entry in os.listdir(def_path):
|
||||
|
Loading…
x
Reference in New Issue
Block a user