FT of scale/modify v2 APIs
This patch add scale/modify functional tests of v2 APIs to the following test cases: * Test basic lcms for v2 api Max pattern. * Test basic lcms for v2 api Min pattern. * Test rollback update VNF for v2 api. * Test update and scale out's before/after for v2 api. Implements: blueprint support-nfv-solv3-scale-vnf Implements: blueprint support-nfv-solv3-modify-vnf Closes-bug: #1962564 Change-Id: I0826f1c580a56cec860d59ae0eeb197e8d30f344
This commit is contained in:
parent
55a16877c8
commit
3635aa1476
|
@ -98,12 +98,12 @@ The following is sample Base HOT corresponding to above sample userdata script.
|
|||
|
||||
**top Base HOT**
|
||||
|
||||
.. literalinclude:: ../../../tacker/tests/functional/sol_v2/samples/sample1/contents/BaseHOT/simple/sample1.yaml
|
||||
.. literalinclude:: ../../../tacker/tests/functional/sol_v2/samples/basic_lcms_max/contents/BaseHOT/simple/sample1.yaml
|
||||
:language: yaml
|
||||
|
||||
**nested Base HOT**
|
||||
|
||||
.. literalinclude:: ../../../tacker/tests/functional/sol_v2/samples/sample1/contents/BaseHOT/simple/nested/VDU1.yaml
|
||||
.. literalinclude:: ../../../tacker/tests/functional/sol_v2/samples/basic_lcms_max/contents/BaseHOT/simple/nested/VDU1.yaml
|
||||
:language: yaml
|
||||
|
||||
|
||||
|
|
|
@ -102,8 +102,10 @@ class VnfLcmDriverV2(object):
|
|||
'operation': operation,
|
||||
'request': req.to_dict(),
|
||||
'vnf_instance': inst.to_dict(),
|
||||
'grant_request': grant_req.to_dict(),
|
||||
'grant_response': grant.to_dict(),
|
||||
'grant_request': (grant_req.to_dict()
|
||||
if grant_req is not None else None),
|
||||
'grant_response': (grant.to_dict()
|
||||
if grant is not None else None),
|
||||
'tmp_csar_dir': tmp_csar_dir
|
||||
}
|
||||
# script is relative path to Definitions/xxx.yaml
|
||||
|
|
|
@ -313,6 +313,11 @@ class BaseSolV2Test(base.BaseTestCase):
|
|||
return self.tacker_client.do_request(
|
||||
path, "POST", body=req_body, version="2.0.0")
|
||||
|
||||
def update_vnf_instance(self, inst_id, req_body):
|
||||
path = f"/vnflcm/v2/vnf_instances/{inst_id}"
|
||||
return self.tacker_client.do_request(
|
||||
path, "PATCH", 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(
|
||||
|
|
|
@ -157,40 +157,6 @@ def sub_create_max(callback_uri):
|
|||
}
|
||||
|
||||
|
||||
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.
|
||||
|
@ -481,30 +447,6 @@ def instantiate_vnf_max(net_ids, subnets, ports, auth_url):
|
|||
}
|
||||
|
||||
|
||||
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.
|
||||
|
@ -549,3 +491,109 @@ def scaleout_vnf_max():
|
|||
"numberOfSteps": 1,
|
||||
"additionalParams": {"dummy-key": "dummy-value"}
|
||||
}
|
||||
|
||||
|
||||
def scaleout_vnf_min():
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
return {
|
||||
"type": "SCALE_OUT",
|
||||
"aspectId": "VDU1_scale"
|
||||
}
|
||||
|
||||
|
||||
def scalein_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_IN",
|
||||
"aspectId": "VDU1_scale",
|
||||
"numberOfSteps": 1,
|
||||
"additionalParams": {"dummy-key": "dummy-value"}
|
||||
}
|
||||
|
||||
|
||||
def scalein_vnf_min():
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
return {
|
||||
"type": "SCALE_IN",
|
||||
"aspectId": "VDU1_scale"
|
||||
}
|
||||
|
||||
|
||||
def update_vnf_max(vnfd_id, vnfc_id_1, vnfc_id_2):
|
||||
# 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 {
|
||||
"vnfInstanceName": "new name",
|
||||
"vnfInstanceDescription": "new description",
|
||||
"vnfdId": vnfd_id,
|
||||
"vnfConfigurableProperties": {"dummy-key": "dummy-value"},
|
||||
"metadata": {"dummy-key": "dummy-value"},
|
||||
"extensions": {"dummy-key": "dummy-value"},
|
||||
"vimConnectionInfo": {
|
||||
"vim2": {
|
||||
"vimId": "ac2d2ece-5e49-4b15-b92d-b681e9c096d8",
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity/v3"
|
||||
},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"password": "dummy_password",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {
|
||||
"dummy-key": "dummy-val"
|
||||
}
|
||||
}
|
||||
},
|
||||
"vnfcInfoModifications": [
|
||||
{
|
||||
"id": vnfc_id_1,
|
||||
"vnfcConfigurableProperties": {"dummy-key": "dummy-value"}
|
||||
},
|
||||
{
|
||||
"id": vnfc_id_2,
|
||||
"vnfcConfigurableProperties": {"dummy-key": "dummy-value"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def update_vnf_min():
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
return {
|
||||
"vnfInstanceName": "new name"
|
||||
}
|
||||
|
||||
|
||||
def update_vnf_min_with_parameter(vnfd_id):
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
return {
|
||||
"vnfdId": vnfd_id
|
||||
}
|
||||
|
|
|
@ -421,8 +421,8 @@ topology_template:
|
|||
leaf: 1048576
|
||||
targets: [ internalVL3 ]
|
||||
|
||||
- policy_antiaffinity_group:
|
||||
type: tosca.policies.nfv.AntiAffinityRule
|
||||
- policy_affinity_group:
|
||||
type: tosca.policies.nfv.AffinityRule
|
||||
targets: [ affinityOrAntiAffinityGroup1 ]
|
||||
properties:
|
||||
scope: zone
|
|
@ -39,8 +39,10 @@ utils.make_zip(".", tmp_dir, vnfd_id, image_path)
|
|||
shutil.move(os.path.join(tmp_dir, zip_file_name), ".")
|
||||
shutil.rmtree(tmp_dir)
|
||||
|
||||
create_req = paramgen.sample1_create(vnfd_id)
|
||||
terminate_req = paramgen.sample1_terminate()
|
||||
create_req = paramgen.create_vnf_max(vnfd_id)
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
scalein_req = paramgen.scalein_vnf_max()
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
|
||||
print('#####################################################################\n'
|
||||
'# Run pre.py if an error occurs #\n'
|
||||
|
@ -56,14 +58,20 @@ subnet_ids = utils.get_subnet_ids(
|
|||
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0'])
|
||||
port_ids = utils.get_port_ids(['VDU2_CP1-1', 'VDU2_CP1-2'])
|
||||
|
||||
instantiate_req = paramgen.sample1_instantiate(
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
net_ids, subnet_ids, port_ids, "http://localhost/identity/v3")
|
||||
|
||||
with open("create_req", "w") as f:
|
||||
with open("create_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(create_req, indent=2))
|
||||
|
||||
with open("terminate_req", "w") as f:
|
||||
with open("terminate_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(terminate_req, indent=2))
|
||||
|
||||
with open("instantiate_req", "w") as f:
|
||||
with open("scaleout_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(scaleout_req, indent=2))
|
||||
|
||||
with open("scalein_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(scalein_req, indent=2))
|
||||
|
||||
with open("instantiate_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(instantiate_req, indent=2))
|
|
@ -0,0 +1,262 @@
|
|||
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
|
||||
change_external_connectivity_start:
|
||||
implementation: sample-script
|
||||
modify_information_start:
|
||||
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,77 @@
|
|||
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import pickle
|
||||
import sys
|
||||
|
||||
|
||||
class SampleScript(object):
|
||||
|
||||
def __init__(self, req, inst, grant_req, grant, csar_dir):
|
||||
self.req = req
|
||||
self.inst = inst
|
||||
self.grant_req = grant_req
|
||||
self.grant = grant
|
||||
self.csar_dir = csar_dir
|
||||
|
||||
def instantiate_start(self):
|
||||
pass
|
||||
|
||||
def instantiate_end(self):
|
||||
pass
|
||||
|
||||
def terminate_start(self):
|
||||
pass
|
||||
|
||||
def terminate_end(self):
|
||||
pass
|
||||
|
||||
def change_external_connectivity_start(self):
|
||||
if os.path.exists('/tmp/change_external_connectivity_start'):
|
||||
raise Exception("test change_external_connectivity_start error")
|
||||
pass
|
||||
|
||||
def modify_information_start(self):
|
||||
if os.path.exists('/tmp/modify_information_start'):
|
||||
raise Exception("test modify_information_start error")
|
||||
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,58 @@
|
|||
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import 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)
|
||||
|
||||
create_req = paramgen.create_vnf_min(vnfd_id)
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
instantiate_req = paramgen.instantiate_vnf_min()
|
||||
scaleout_req = paramgen.scaleout_vnf_min()
|
||||
scalein_req = paramgen.scalein_vnf_min()
|
||||
update_seq = paramgen.update_vnf_min()
|
||||
|
||||
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))
|
||||
|
||||
with open("scaleout_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(scaleout_req, indent=2))
|
||||
|
||||
with open("scalein_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(scalein_req, indent=2))
|
||||
|
||||
with open("update_seq", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(update_seq, indent=2))
|
|
@ -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: { get_param: net5 }
|
|
@ -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: {}
|
|
@ -98,7 +98,7 @@ topology_template:
|
|||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: cirros-0.5.2-x86_64-disk
|
||||
name: cirros-0.5.2-x86_64-disk2
|
||||
version: '0.5.2'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
|
@ -251,8 +251,8 @@ topology_template:
|
|||
leaf: 1048576
|
||||
targets: [ internalVL3 ]
|
||||
|
||||
- policy_antiaffinity_group:
|
||||
type: tosca.policies.nfv.AntiAffinityRule
|
||||
- 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,4 @@
|
|||
TOSCA-Meta-File-Version: 1.0
|
||||
CSAR-Version: 1.1
|
||||
Created-by: Onboarding portal
|
||||
Entry-Definitions: Definitions/v2_sample2_top.vnfd.yaml
|
|
@ -32,15 +32,14 @@ utils.make_zip(".", tmp_dir, vnfd_id)
|
|||
shutil.copy(os.path.join(tmp_dir, zip_file_name), ".")
|
||||
shutil.rmtree(tmp_dir)
|
||||
|
||||
create_req = paramgen.sample2_create(vnfd_id)
|
||||
terminate_req = paramgen.sample2_terminate()
|
||||
instantiate_req = paramgen.sample2_instantiate()
|
||||
update_min_req = paramgen.update_vnf_min_with_parameter(vnfd_id)
|
||||
# fake vnfc id, shoule be get from show vnf
|
||||
vnfc_id_1 = "VDU1-9300a3cb-bd3b-45e4-9967-095040caf827"
|
||||
vnfc_id_2 = "VDU2-39681281-e6e6-4179-8898-d9ec70f1642a"
|
||||
update_max_req = paramgen.update_vnf_max(vnfd_id, vnfc_id_1, vnfc_id_2)
|
||||
|
||||
with open("create_req", "w") as f:
|
||||
f.write(json.dumps(create_req, indent=2))
|
||||
with open("update_min_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(update_min_req, indent=2))
|
||||
|
||||
with open("terminate_req", "w") as f:
|
||||
f.write(json.dumps(terminate_req, indent=2))
|
||||
|
||||
with open("instantiate_req", "w") as f:
|
||||
f.write(json.dumps(instantiate_req, indent=2))
|
||||
with open("update_max_req", "w", encoding='utf-8') as f:
|
||||
f.write(json.dumps(update_max_req, indent=2))
|
File diff suppressed because it is too large
Load Diff
|
@ -48,15 +48,23 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
cls.vnf_pkg_2, cls.vnfd_id_2 = cls.create_vnf_package(
|
||||
error_network_path)
|
||||
|
||||
# update VNF or change external VNF connectivity will fail
|
||||
update_change_ng_path = os.path.join(cur_dir,
|
||||
"samples/basic_lcms_min")
|
||||
# no image contained
|
||||
cls.vnf_pkg_3, cls.vnfd_id_3 = cls.create_vnf_package(
|
||||
update_change_ng_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)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_3)
|
||||
|
||||
def setUp(self):
|
||||
super(VnfLcmErrorHandlingTest, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
def test_retry_rollback_scale_out(self):
|
||||
"""Test retry and rollback scale out operations
|
||||
|
@ -141,6 +149,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 3. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
|
@ -206,7 +215,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo'].get('vnfState'))
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# 6. Scale out operation(will fail)
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
|
@ -221,7 +230,6 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
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)
|
||||
|
@ -240,6 +248,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 10. Show VNF LCM operation occurrence
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.13 VnfLcmOpOcc
|
||||
# NOTE: omitted values are not supported at that time
|
||||
expected_attrs = [
|
||||
'id',
|
||||
|
@ -362,7 +371,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
# 1. Create subscription
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = (f'http://localhost:'
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
|
@ -379,6 +388,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 3. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
# 'vnfInstanceName', # omitted
|
||||
|
@ -441,6 +451,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 7. Show VNF LCM operation occurrence
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.13 VnfLcmOpOcc
|
||||
# NOTE: omitted values are not supported at that time
|
||||
expected_attrs = [
|
||||
'id',
|
||||
|
@ -535,7 +546,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
# 1. Create subscription
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = (f'http://localhost:'
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
|
@ -552,6 +563,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 3. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
# 'vnfInstanceName', # omitted
|
||||
|
@ -635,6 +647,7 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
self.assertEqual('FAILED', body['operationState'])
|
||||
|
||||
# 7. Show VNF LCM operation occurrence
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.13 VnfLcmOpOcc
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
|
@ -684,3 +697,205 @@ class VnfLcmErrorHandlingTest(base_v2.BaseSolV2Test):
|
|||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
def test_rollback_update(self):
|
||||
"""Test rollback update VNF 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
|
||||
- 5. Show VNF instance
|
||||
- 6. Update VNF(will fail)
|
||||
- 7. Rollback update operation
|
||||
- 8. Show VNF LCM operation occurrence
|
||||
- 9. List VNF LCM operation occurrence
|
||||
- 10. Terminate VNF
|
||||
- 11. Delete VNF instance
|
||||
- 12. Delete subscription
|
||||
"""
|
||||
|
||||
# 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_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_3)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 3. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
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_3)
|
||||
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_3)['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_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_complete(lcmocc_id)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_3)['usageState']
|
||||
self.assertEqual('IN_USE', usage_state)
|
||||
|
||||
# 5. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
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['instantiationState'])
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# 6. Update VNF(will fail)
|
||||
# NOTE: Create a file so that an error occurs in mgmtDriver
|
||||
path = '/tmp/modify_information_start'
|
||||
with open(path, 'w', encoding='utf-8') as f:
|
||||
f.write('')
|
||||
self.addCleanup(os.remove, path)
|
||||
update_req = paramgen.update_vnf_min()
|
||||
resp, body = self.update_vnf_instance(inst_id, update_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)
|
||||
|
||||
# 7. Rollback update 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)
|
||||
|
||||
# 8. Show VNF LCM operation occurrence
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.13 VnfLcmOpOcc
|
||||
# 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.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 9. List VNF LCM operation occurrence
|
||||
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)
|
||||
|
||||
# 10. Terminate a VNF instance
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
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)
|
||||
|
||||
# wait a bit because there is a bit time lag between lcmocc DB
|
||||
# update and terminate completion.
|
||||
time.sleep(10)
|
||||
|
||||
# check usageState of VNF Package
|
||||
usage_state = self.get_vnf_package(self.vnf_pkg_3)['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['instantiationState'])
|
||||
|
||||
# 11. 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_3)['usageState']
|
||||
self.assertEqual('NOT_IN_USE', usage_state)
|
||||
|
||||
# 12. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
|
Loading…
Reference in New Issue