From 0d7e6a863faadb30987b1b74cbb5d1921a0c0e68 Mon Sep 17 00:00:00 2001 From: Koichi Edagawa Date: Fri, 11 Sep 2020 16:20:06 +0900 Subject: [PATCH] Support Scale and Rollback function of FT Added Scale Functional tests for Tacker (Victoria). Added Rollback Functional tests for Tacker (Victoria). Changes are the following: - The process of creating a body data about vnfpkg and vnflcm are separated. - Some exception handlings about time out on vnflcm process are improved. - A sleep is added into HTTP server preparation process in a test to reduce CPU usage. - The setting of "network-vif-plugged" is changed to avoid VirtualInterfaceCreateException. Implements: blueprint support-etsi-nfv-specs Change-Id: I9c25cbdf642e73c791a565abda066ce8e98bf802 --- .../BaseHOT/simple/helloworld3.yaml | 98 ++++ .../BaseHOT/simple/nested/VDU1.yaml | 72 +++ .../BaseHOT/simple/nested/VDU2.yaml | 61 +++ .../Definitions/helloworld3_df_simple.yaml | 403 +++++++++++++++ .../Definitions/helloworld3_top.vnfd.yaml | 31 ++ .../Definitions/helloworld3_types.yaml | 55 +++ .../nfv/functional3/TOSCA-Metadata/TOSCA.meta | 4 + .../etsi/nfv/functional3/UserData/__init__.py | 0 .../nfv/functional3/UserData/lcm_user_data.py | 35 ++ .../BaseHOT/simple/helloworld3.yaml | 98 ++++ .../BaseHOT/simple/nested/VDU1.yaml | 72 +++ .../BaseHOT/simple/nested/VDU2.yaml | 61 +++ .../Definitions/helloworld3_df_simple.yaml | 403 +++++++++++++++ .../Definitions/helloworld3_top.vnfd.yaml | 31 ++ .../Definitions/helloworld3_types.yaml | 55 +++ .../nfv/functional4/TOSCA-Metadata/TOSCA.meta | 4 + .../etsi/nfv/functional4/UserData/__init__.py | 0 .../nfv/functional4/UserData/lcm_user_data.py | 35 ++ .../BaseHOT/simple/helloworld3.yaml | 98 ++++ .../BaseHOT/simple/nested/VDU1.yaml | 72 +++ .../BaseHOT/simple/nested/VDU2.yaml | 61 +++ .../Definitions/helloworld3_df_simple.yaml | 403 +++++++++++++++ .../Definitions/helloworld3_top.vnfd.yaml | 31 ++ .../Definitions/helloworld3_types.yaml | 55 +++ .../nfv/functional5/TOSCA-Metadata/TOSCA.meta | 4 + .../etsi/nfv/functional5/UserData/__init__.py | 0 .../nfv/functional5/UserData/lcm_user_data.py | 35 ++ tacker/tests/functional/common/fake_server.py | 19 +- tacker/tests/functional/vnflcm/base.py | 158 +++++- tacker/tests/functional/vnflcm/fake_vnflcm.py | 18 + .../tests/functional/vnflcm/fake_vnfpkgm.py | 105 ++++ .../test_vnf_instance_with_user_data.py | 459 +++++++++++++++--- 32 files changed, 2947 insertions(+), 89 deletions(-) create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/helloworld3.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU1.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU2.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_df_simple.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_top.vnfd.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_types.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/TOSCA-Metadata/TOSCA.meta create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/UserData/__init__.py create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional3/UserData/lcm_user_data.py create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/helloworld3.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU1.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU2.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_df_simple.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_top.vnfd.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_types.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/TOSCA-Metadata/TOSCA.meta create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/UserData/__init__.py create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional4/UserData/lcm_user_data.py create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/helloworld3.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU1.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU2.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_df_simple.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_top.vnfd.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_types.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/TOSCA-Metadata/TOSCA.meta create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/UserData/__init__.py create mode 100644 tacker/tests/etc/samples/etsi/nfv/functional5/UserData/lcm_user_data.py create mode 100644 tacker/tests/functional/vnflcm/fake_vnfpkgm.py diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/helloworld3.yaml b/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/helloworld3.yaml new file mode 100644 index 000000000..7ba4a057b --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/helloworld3.yaml @@ -0,0 +1,98 @@ +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: 1 + resource: + type: VDU1.yaml + properties: + flavor: { get_param: [ nfv, VDU, VDU1, flavor ] } + image: { get_param: [ nfv, VDU, VirtualStorage, image ] } + zone: { get_param: [ nfv, vdu, VDU1, zone ] } + net1: { get_param: [ nfv, CP, VDU1_CP1, network ] } + net2: { get_param: [ nfv, CP, VDU1_CP2, network ] } + net3: { get_resource: extmanageNW_1 } + net4: { get_resource: extmanageNW_2 } + net5: { get_resource: internalNW_1 } + VDU1_scale_scale_out: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: 1 + auto_scaling_group_id: + get_resource: VDU1_scale_group + adjustment_type: change_in_capacity + VDU1_scale_scale_in: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: -1 + auto_scaling_group_id: + get_resource: VDU1_scale_group + adjustment_type: change_in_capacity + VDU2_scale_group: + type: OS::Heat::AutoScalingGroup + properties: + min_size: 2 + max_size: 2 + desired_capacity: 2 + resource: + type: VDU2.yaml + properties: + flavor: { get_param: [ nfv, VDU, VDU2, flavor ] } + image: { get_param: [ nfv, VDU, VDU2, image ] } + zone: { get_param: [ nfv, vdu, VDU2, zone ] } + net1: { get_param: [ nfv, CP, VDU2_CP1, network ] } + net2: { get_param: [ nfv, CP, VDU2_CP2, network ] } + net3: { get_resource: extmanageNW_1 } + net4: { get_resource: extmanageNW_2 } + net5: { get_resource: internalNW_1 } + VDU2_scale_scale_out: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: 1 + auto_scaling_group_id: + get_resource: VDU2_scale_group + adjustment_type: change_in_capacity + VDU2_scale_scale_in: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: -1 + auto_scaling_group_id: + get_resource: VDU2_scale_group + adjustment_type: change_in_capacity + extmanageNW_1: + type: OS::Neutron::Net + extmanageNW_2: + type: OS::Neutron::Net + internalNW_1: + type: OS::Neutron::Net + extmanageNW_1_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: extmanageNW_1 + cidr: 192.168.3.0/24 + extmanageNW_2_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: extmanageNW_2 + cidr: 192.168.4.0/24 + internalNW_1_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: internalNW_1 + cidr: 192.168.5.0/24 +outputs: {} diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU1.yaml b/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU1.yaml new file mode 100644 index 000000000..60fc60313 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU1.yaml @@ -0,0 +1,72 @@ +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 + +resources: + VDU1: + type: OS::Nova::Server + properties: + flavor: { get_param: flavor } + name: VDU1 + block_device_mapping_v2: [{"volume_id": { get_resource: VirtualStorage }}] + networks: + - port: + get_resource: VDU1_CP1 + - port: + get_resource: VDU1_CP2 + - port: + get_resource: VDU1_CP3 + - port: + get_resource: VDU1_CP4 + - port: + get_resource: VDU1_CP5 + availability_zone: { get_param: zone } + + VirtualStorage: + type: OS::Cinder::Volume + properties: + image: { get_param: image } + size: 1 + volume_type: { get_resource: multi } + multi: + type: OS::Cinder::VolumeType + properties: + name: { get_resource: VDU1_CP1 } + metadata: { multiattach: " True" } + VDU1_CP1: + type: OS::Neutron::Port + properties: + network: { get_param: net1 } + VDU1_CP2: + type: OS::Neutron::Port + properties: + network: { get_param: net2 } + 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 } diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU2.yaml b/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU2.yaml new file mode 100644 index 000000000..d777c76ea --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/BaseHOT/simple/nested/VDU2.yaml @@ -0,0 +1,61 @@ +heat_template_version: 2013-05-23 +description: 'VDU2 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 + +resources: + VDU2: + type: OS::Nova::Server + properties: + flavor: { get_param: flavor } + name: VDU2 + image: { get_param: image } + networks: + - port: + get_resource: VDU2_CP1 + - port: + get_resource: VDU2_CP2 + - port: + get_resource: VDU2_CP3 + - port: + get_resource: VDU2_CP4 + - port: + get_resource: VDU2_CP5 + availability_zone: { get_param: zone } + + VDU2_CP1: + type: OS::Neutron::Port + properties: + network: { get_param: net1 } + VDU2_CP2: + type: OS::Neutron::Port + properties: + network: { get_param: net2 } + VDU2_CP3: + type: OS::Neutron::Port + properties: + network: { get_param: net3 } + VDU2_CP4: + type: OS::Neutron::Port + properties: + network: errornetwork + VDU2_CP5: + type: OS::Neutron::Port + properties: + network: errornetwork diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_df_simple.yaml new file mode 100644 index 000000000..b46852223 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_df_simple.yaml @@ -0,0 +1,403 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Simple deployment flavour for Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + - helloworld3_types.yaml + +topology_template: + inputs: + descriptor_id: + type: string + descriptor_version: + type: string + provider: + type: string + product_name: + type: string + software_version: + type: string + vnfm_info: + type: list + entry_schema: + type: string + flavour_id: + type: string + flavour_description: + type: string + + substitution_mappings: + node_type: company.provider.VNF + properties: + flavour_id: simple + requirements: + virtual_link_external1_1: [ VDU1_CP1, virtual_link ] + virtual_link_external1_2: [ VDU2_CP1, virtual_link ] + virtual_link_external2_1: [ VDU1_CP2, virtual_link ] + virtual_link_external2_2: [ VDU2_CP2, virtual_link ] + + node_templates: + 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: VirtualStorage + + VDU2: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: VDU2 + description: VDU2 compute node + vdu_profile: + min_number_of_instances: 2 + max_number_of_instances: 2 + sw_image_data: + name: cirros-0.4.0-x86_64-disk + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: a8dd75ecffd4cdd96072d60c2237b448e0c8b2bc94d57f10fdbc8c481d9005b8 + 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 + + VirtualStorage: + type: tosca.nodes.nfv.Vdu.VirtualBlockStorage + properties: + virtual_block_storage_data: + size_of_storage: 1 GB + rdma_enabled: true + sw_image_data: + name: cirros-0.4.0-x86_64-disk + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: a8dd75ecffd4cdd96072d60c2237b448e0c8b2bc94d57f10fdbc8c481d9005b8 + container_format: bare + disk_format: qcow2 + min_disk: 0 GB + min_ram: 256 MB + size: 12 GB + + 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: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 0 + requirements: + - virtual_binding: VDU2 + + VDU2_CP2: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 1 + requirements: + - virtual_binding: VDU2 + + VDU2_CP3: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 2 + requirements: + - virtual_binding: VDU2 + - virtual_link: internalVL1 + + VDU2_CP4: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 3 + requirements: + - virtual_binding: VDU2 + - virtual_link: internalVL2 + + VDU2_CP5: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 4 + 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: 33.33.0.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: 33.34.0.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: 33.35.0.0/24 + + 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: 2 + 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: 2 + instantiation_level_2: + number_of_instances: 2 + 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_antiaffinity_vdu1: + type: tosca.policies.nfv.AntiAffinityRule + targets: [ VDU1 ] + properties: + scope: zone + + - policy_antiaffinity_vdu2: + type: tosca.policies.nfv.AntiAffinityRule + targets: [ VDU2 ] + properties: + scope: zone diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_top.vnfd.yaml b/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_top.vnfd.yaml new file mode 100644 index 000000000..0be18659b --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_top.vnfd.yaml @@ -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 + - helloworld3_types.yaml + - helloworld3_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 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_types.yaml b/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_types.yaml new file mode 100644 index 000000000..5c026d6a2 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/Definitions/helloworld3_types.yaml @@ -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: "falvour" + 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 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/TOSCA-Metadata/TOSCA.meta b/tacker/tests/etc/samples/etsi/nfv/functional3/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..cfd7444ac --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,4 @@ +TOSCA-Meta-File-Version: 1.0 +CSAR-Version: 1.1 +Created-by: Onboarding portal +Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/UserData/__init__.py b/tacker/tests/etc/samples/etsi/nfv/functional3/UserData/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tacker/tests/etc/samples/etsi/nfv/functional3/UserData/lcm_user_data.py b/tacker/tests/etc/samples/etsi/nfv/functional3/UserData/lcm_user_data.py new file mode 100644 index 000000000..725c5430a --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional3/UserData/lcm_user_data.py @@ -0,0 +1,35 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData +import tacker.vnfm.lcm_user_data.utils as UserDataUtil + + +class SampleUserData(AbstractUserData): + @staticmethod + def instantiate(base_hot_dict=None, + vnfd_dict=None, + inst_req_info=None, + grant_info=None): + api_param = UserDataUtil.get_diff_base_hot_param_from_api( + base_hot_dict, inst_req_info) + initial_param_dict = \ + UserDataUtil.create_initial_param_server_port_dict( + base_hot_dict) + vdu_flavor_dict = \ + UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict) + vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict) + cpd_vl_dict = UserDataUtil.create_network_dict( + inst_req_info, initial_param_dict) + final_param_dict = UserDataUtil.create_final_param_dict( + initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict) + return {**final_param_dict, **api_param} diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/helloworld3.yaml b/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/helloworld3.yaml new file mode 100644 index 000000000..a8f5f2a48 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/helloworld3.yaml @@ -0,0 +1,98 @@ +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: 1 + resource: + type: VDU1.yaml + properties: + flavor: { get_param: [ nfv, VDU, VDU1, flavor ] } + image: { get_param: [ nfv, VDU, VirtualStorage, image ] } + zone: { get_param: [ nfv, vdu, VDU1, zone ] } + net1: { get_param: [ nfv, CP, VDU1_CP1, network ] } + net2: { get_param: [ nfv, CP, VDU1_CP2, network ] } + net3: { get_resource: extmanageNW_1 } + net4: { get_resource: extmanageNW_2 } + net5: { get_resource: internalNW_1 } + VDU1_scale_scale_out: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: 1 + auto_scaling_group_id: + get_resource: VDU1_scale_group + adjustment_type: change_in_capacity + VDU1_scale_scale_in: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: -1 + auto_scaling_group_id: + get_resource: VDU1_scale_group + adjustment_type: change_in_capacity + VDU2_scale_group: + type: OS::Heat::AutoScalingGroup + properties: + min_size: 2 + max_size: 2 + desired_capacity: 2 + resource: + type: VDU2.yaml + properties: + flavor: { get_param: [ nfv, VDU, VDU2, flavor ] } + image: { get_param: [ nfv, VDU, VDU2, image ] } + zone: { get_param: [ nfv, vdu, VDU2, zone ] } + net1: { get_param: [ nfv, CP, VDU2_CP1, network ] } + net2: { get_param: [ nfv, CP, VDU2_CP2, network ] } + net3: { get_resource: extmanageNW_1 } + net4: { get_resource: extmanageNW_2 } + net5: { get_resource: internalNW_1 } + VDU2_scale_scale_out: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: 99 + auto_scaling_group_id: + get_resource: VDU2_scale_group + adjustment_type: change_in_capacity + VDU2_scale_scale_in: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: -99 + auto_scaling_group_id: + get_resource: VDU2_scale_group + adjustment_type: change_in_capacity + extmanageNW_1: + type: OS::Neutron::Net + extmanageNW_2: + type: OS::Neutron::Net + internalNW_1: + type: OS::Neutron::Net + extmanageNW_1_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: extmanageNW_1 + cidr: 192.168.3.0/24 + extmanageNW_2_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: extmanageNW_2 + cidr: 192.168.4.0/24 + internalNW_1_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: internalNW_1 + cidr: 192.168.5.0/24 +outputs: {} diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU1.yaml b/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU1.yaml new file mode 100644 index 000000000..c6874d60f --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU1.yaml @@ -0,0 +1,72 @@ +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 + +resources: + VDU1: + type: OS::Nova::Server + properties: + flavor: { get_param: flavor } + name: VDU1 + block_device_mapping_v2: [{"volume_id": { get_resource: VirtualStorage }}] + networks: + - port: + get_resource: VDU1_CP1 + - port: + get_resource: VDU1_CP2 + - port: + get_resource: VDU1_CP3 + - port: + get_resource: VDU1_CP4 + - port: + get_resource: VDU1_CP5 + availability_zone: { get_param: zone } + + 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: " True" } + VDU1_CP1: + type: OS::Neutron::Port + properties: + network: { get_param: net1 } + VDU1_CP2: + type: OS::Neutron::Port + properties: + network: { get_param: net2 } + 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 } diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU2.yaml b/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU2.yaml new file mode 100644 index 000000000..c4772dad6 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/BaseHOT/simple/nested/VDU2.yaml @@ -0,0 +1,61 @@ +heat_template_version: 2013-05-23 +description: 'VDU2 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 + +resources: + VDU2: + type: OS::Nova::Server + properties: + flavor: { get_param: flavor } + name: VDU2 + image: { get_param: image } + networks: + - port: + get_resource: VDU2_CP1 + - port: + get_resource: VDU2_CP2 + - port: + get_resource: VDU2_CP3 + - port: + get_resource: VDU2_CP4 + - port: + get_resource: VDU2_CP5 + availability_zone: { get_param: zone } + + VDU2_CP1: + type: OS::Neutron::Port + properties: + network: { get_param: net1 } + VDU2_CP2: + type: OS::Neutron::Port + properties: + network: { get_param: net2 } + VDU2_CP3: + type: OS::Neutron::Port + properties: + network: { get_param: net3 } + VDU2_CP4: + type: OS::Neutron::Port + properties: + network: { get_param: net4 } + VDU2_CP5: + type: OS::Neutron::Port + properties: + network: { get_param: net5 } diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_df_simple.yaml new file mode 100644 index 000000000..b46852223 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_df_simple.yaml @@ -0,0 +1,403 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Simple deployment flavour for Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + - helloworld3_types.yaml + +topology_template: + inputs: + descriptor_id: + type: string + descriptor_version: + type: string + provider: + type: string + product_name: + type: string + software_version: + type: string + vnfm_info: + type: list + entry_schema: + type: string + flavour_id: + type: string + flavour_description: + type: string + + substitution_mappings: + node_type: company.provider.VNF + properties: + flavour_id: simple + requirements: + virtual_link_external1_1: [ VDU1_CP1, virtual_link ] + virtual_link_external1_2: [ VDU2_CP1, virtual_link ] + virtual_link_external2_1: [ VDU1_CP2, virtual_link ] + virtual_link_external2_2: [ VDU2_CP2, virtual_link ] + + node_templates: + 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: VirtualStorage + + VDU2: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: VDU2 + description: VDU2 compute node + vdu_profile: + min_number_of_instances: 2 + max_number_of_instances: 2 + sw_image_data: + name: cirros-0.4.0-x86_64-disk + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: a8dd75ecffd4cdd96072d60c2237b448e0c8b2bc94d57f10fdbc8c481d9005b8 + 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 + + VirtualStorage: + type: tosca.nodes.nfv.Vdu.VirtualBlockStorage + properties: + virtual_block_storage_data: + size_of_storage: 1 GB + rdma_enabled: true + sw_image_data: + name: cirros-0.4.0-x86_64-disk + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: a8dd75ecffd4cdd96072d60c2237b448e0c8b2bc94d57f10fdbc8c481d9005b8 + container_format: bare + disk_format: qcow2 + min_disk: 0 GB + min_ram: 256 MB + size: 12 GB + + 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: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 0 + requirements: + - virtual_binding: VDU2 + + VDU2_CP2: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 1 + requirements: + - virtual_binding: VDU2 + + VDU2_CP3: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 2 + requirements: + - virtual_binding: VDU2 + - virtual_link: internalVL1 + + VDU2_CP4: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 3 + requirements: + - virtual_binding: VDU2 + - virtual_link: internalVL2 + + VDU2_CP5: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 4 + 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: 33.33.0.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: 33.34.0.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: 33.35.0.0/24 + + 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: 2 + 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: 2 + instantiation_level_2: + number_of_instances: 2 + 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_antiaffinity_vdu1: + type: tosca.policies.nfv.AntiAffinityRule + targets: [ VDU1 ] + properties: + scope: zone + + - policy_antiaffinity_vdu2: + type: tosca.policies.nfv.AntiAffinityRule + targets: [ VDU2 ] + properties: + scope: zone diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_top.vnfd.yaml b/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_top.vnfd.yaml new file mode 100644 index 000000000..0be18659b --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_top.vnfd.yaml @@ -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 + - helloworld3_types.yaml + - helloworld3_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 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_types.yaml b/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_types.yaml new file mode 100644 index 000000000..5c026d6a2 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/Definitions/helloworld3_types.yaml @@ -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: "falvour" + 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 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/TOSCA-Metadata/TOSCA.meta b/tacker/tests/etc/samples/etsi/nfv/functional4/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..cfd7444ac --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,4 @@ +TOSCA-Meta-File-Version: 1.0 +CSAR-Version: 1.1 +Created-by: Onboarding portal +Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/UserData/__init__.py b/tacker/tests/etc/samples/etsi/nfv/functional4/UserData/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tacker/tests/etc/samples/etsi/nfv/functional4/UserData/lcm_user_data.py b/tacker/tests/etc/samples/etsi/nfv/functional4/UserData/lcm_user_data.py new file mode 100644 index 000000000..725c5430a --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional4/UserData/lcm_user_data.py @@ -0,0 +1,35 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData +import tacker.vnfm.lcm_user_data.utils as UserDataUtil + + +class SampleUserData(AbstractUserData): + @staticmethod + def instantiate(base_hot_dict=None, + vnfd_dict=None, + inst_req_info=None, + grant_info=None): + api_param = UserDataUtil.get_diff_base_hot_param_from_api( + base_hot_dict, inst_req_info) + initial_param_dict = \ + UserDataUtil.create_initial_param_server_port_dict( + base_hot_dict) + vdu_flavor_dict = \ + UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict) + vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict) + cpd_vl_dict = UserDataUtil.create_network_dict( + inst_req_info, initial_param_dict) + final_param_dict = UserDataUtil.create_final_param_dict( + initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict) + return {**final_param_dict, **api_param} diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/helloworld3.yaml b/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/helloworld3.yaml new file mode 100644 index 000000000..7ba4a057b --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/helloworld3.yaml @@ -0,0 +1,98 @@ +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: 1 + resource: + type: VDU1.yaml + properties: + flavor: { get_param: [ nfv, VDU, VDU1, flavor ] } + image: { get_param: [ nfv, VDU, VirtualStorage, image ] } + zone: { get_param: [ nfv, vdu, VDU1, zone ] } + net1: { get_param: [ nfv, CP, VDU1_CP1, network ] } + net2: { get_param: [ nfv, CP, VDU1_CP2, network ] } + net3: { get_resource: extmanageNW_1 } + net4: { get_resource: extmanageNW_2 } + net5: { get_resource: internalNW_1 } + VDU1_scale_scale_out: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: 1 + auto_scaling_group_id: + get_resource: VDU1_scale_group + adjustment_type: change_in_capacity + VDU1_scale_scale_in: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: -1 + auto_scaling_group_id: + get_resource: VDU1_scale_group + adjustment_type: change_in_capacity + VDU2_scale_group: + type: OS::Heat::AutoScalingGroup + properties: + min_size: 2 + max_size: 2 + desired_capacity: 2 + resource: + type: VDU2.yaml + properties: + flavor: { get_param: [ nfv, VDU, VDU2, flavor ] } + image: { get_param: [ nfv, VDU, VDU2, image ] } + zone: { get_param: [ nfv, vdu, VDU2, zone ] } + net1: { get_param: [ nfv, CP, VDU2_CP1, network ] } + net2: { get_param: [ nfv, CP, VDU2_CP2, network ] } + net3: { get_resource: extmanageNW_1 } + net4: { get_resource: extmanageNW_2 } + net5: { get_resource: internalNW_1 } + VDU2_scale_scale_out: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: 1 + auto_scaling_group_id: + get_resource: VDU2_scale_group + adjustment_type: change_in_capacity + VDU2_scale_scale_in: + type: OS::Heat::ScalingPolicy + properties: + scaling_adjustment: -1 + auto_scaling_group_id: + get_resource: VDU2_scale_group + adjustment_type: change_in_capacity + extmanageNW_1: + type: OS::Neutron::Net + extmanageNW_2: + type: OS::Neutron::Net + internalNW_1: + type: OS::Neutron::Net + extmanageNW_1_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: extmanageNW_1 + cidr: 192.168.3.0/24 + extmanageNW_2_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: extmanageNW_2 + cidr: 192.168.4.0/24 + internalNW_1_subnet: + type: OS::Neutron::Subnet + properties: + ip_version: 4 + network: + get_resource: internalNW_1 + cidr: 192.168.5.0/24 +outputs: {} diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU1.yaml b/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU1.yaml new file mode 100644 index 000000000..60fc60313 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU1.yaml @@ -0,0 +1,72 @@ +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 + +resources: + VDU1: + type: OS::Nova::Server + properties: + flavor: { get_param: flavor } + name: VDU1 + block_device_mapping_v2: [{"volume_id": { get_resource: VirtualStorage }}] + networks: + - port: + get_resource: VDU1_CP1 + - port: + get_resource: VDU1_CP2 + - port: + get_resource: VDU1_CP3 + - port: + get_resource: VDU1_CP4 + - port: + get_resource: VDU1_CP5 + availability_zone: { get_param: zone } + + VirtualStorage: + type: OS::Cinder::Volume + properties: + image: { get_param: image } + size: 1 + volume_type: { get_resource: multi } + multi: + type: OS::Cinder::VolumeType + properties: + name: { get_resource: VDU1_CP1 } + metadata: { multiattach: " True" } + VDU1_CP1: + type: OS::Neutron::Port + properties: + network: { get_param: net1 } + VDU1_CP2: + type: OS::Neutron::Port + properties: + network: { get_param: net2 } + 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 } diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU2.yaml b/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU2.yaml new file mode 100644 index 000000000..c4772dad6 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/BaseHOT/simple/nested/VDU2.yaml @@ -0,0 +1,61 @@ +heat_template_version: 2013-05-23 +description: 'VDU2 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 + +resources: + VDU2: + type: OS::Nova::Server + properties: + flavor: { get_param: flavor } + name: VDU2 + image: { get_param: image } + networks: + - port: + get_resource: VDU2_CP1 + - port: + get_resource: VDU2_CP2 + - port: + get_resource: VDU2_CP3 + - port: + get_resource: VDU2_CP4 + - port: + get_resource: VDU2_CP5 + availability_zone: { get_param: zone } + + VDU2_CP1: + type: OS::Neutron::Port + properties: + network: { get_param: net1 } + VDU2_CP2: + type: OS::Neutron::Port + properties: + network: { get_param: net2 } + VDU2_CP3: + type: OS::Neutron::Port + properties: + network: { get_param: net3 } + VDU2_CP4: + type: OS::Neutron::Port + properties: + network: { get_param: net4 } + VDU2_CP5: + type: OS::Neutron::Port + properties: + network: { get_param: net5 } diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_df_simple.yaml new file mode 100644 index 000000000..b46852223 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_df_simple.yaml @@ -0,0 +1,403 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Simple deployment flavour for Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + - helloworld3_types.yaml + +topology_template: + inputs: + descriptor_id: + type: string + descriptor_version: + type: string + provider: + type: string + product_name: + type: string + software_version: + type: string + vnfm_info: + type: list + entry_schema: + type: string + flavour_id: + type: string + flavour_description: + type: string + + substitution_mappings: + node_type: company.provider.VNF + properties: + flavour_id: simple + requirements: + virtual_link_external1_1: [ VDU1_CP1, virtual_link ] + virtual_link_external1_2: [ VDU2_CP1, virtual_link ] + virtual_link_external2_1: [ VDU1_CP2, virtual_link ] + virtual_link_external2_2: [ VDU2_CP2, virtual_link ] + + node_templates: + 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: VirtualStorage + + VDU2: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: VDU2 + description: VDU2 compute node + vdu_profile: + min_number_of_instances: 2 + max_number_of_instances: 2 + sw_image_data: + name: cirros-0.4.0-x86_64-disk + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: a8dd75ecffd4cdd96072d60c2237b448e0c8b2bc94d57f10fdbc8c481d9005b8 + 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 + + VirtualStorage: + type: tosca.nodes.nfv.Vdu.VirtualBlockStorage + properties: + virtual_block_storage_data: + size_of_storage: 1 GB + rdma_enabled: true + sw_image_data: + name: cirros-0.4.0-x86_64-disk + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: a8dd75ecffd4cdd96072d60c2237b448e0c8b2bc94d57f10fdbc8c481d9005b8 + container_format: bare + disk_format: qcow2 + min_disk: 0 GB + min_ram: 256 MB + size: 12 GB + + 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: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 0 + requirements: + - virtual_binding: VDU2 + + VDU2_CP2: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 1 + requirements: + - virtual_binding: VDU2 + + VDU2_CP3: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 2 + requirements: + - virtual_binding: VDU2 + - virtual_link: internalVL1 + + VDU2_CP4: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 3 + requirements: + - virtual_binding: VDU2 + - virtual_link: internalVL2 + + VDU2_CP5: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 4 + 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: 33.33.0.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: 33.34.0.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: 33.35.0.0/24 + + 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: 2 + 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: 2 + instantiation_level_2: + number_of_instances: 2 + 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_antiaffinity_vdu1: + type: tosca.policies.nfv.AntiAffinityRule + targets: [ VDU1 ] + properties: + scope: zone + + - policy_antiaffinity_vdu2: + type: tosca.policies.nfv.AntiAffinityRule + targets: [ VDU2 ] + properties: + scope: zone diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_top.vnfd.yaml b/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_top.vnfd.yaml new file mode 100644 index 000000000..0be18659b --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_top.vnfd.yaml @@ -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 + - helloworld3_types.yaml + - helloworld3_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 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_types.yaml b/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_types.yaml new file mode 100644 index 000000000..5c026d6a2 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/Definitions/helloworld3_types.yaml @@ -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: "falvour" + 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 \ No newline at end of file diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/TOSCA-Metadata/TOSCA.meta b/tacker/tests/etc/samples/etsi/nfv/functional5/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..cfd7444ac --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,4 @@ +TOSCA-Meta-File-Version: 1.0 +CSAR-Version: 1.1 +Created-by: Onboarding portal +Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/UserData/__init__.py b/tacker/tests/etc/samples/etsi/nfv/functional5/UserData/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tacker/tests/etc/samples/etsi/nfv/functional5/UserData/lcm_user_data.py b/tacker/tests/etc/samples/etsi/nfv/functional5/UserData/lcm_user_data.py new file mode 100644 index 000000000..725c5430a --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/functional5/UserData/lcm_user_data.py @@ -0,0 +1,35 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData +import tacker.vnfm.lcm_user_data.utils as UserDataUtil + + +class SampleUserData(AbstractUserData): + @staticmethod + def instantiate(base_hot_dict=None, + vnfd_dict=None, + inst_req_info=None, + grant_info=None): + api_param = UserDataUtil.get_diff_base_hot_param_from_api( + base_hot_dict, inst_req_info) + initial_param_dict = \ + UserDataUtil.create_initial_param_server_port_dict( + base_hot_dict) + vdu_flavor_dict = \ + UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict) + vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict) + cpd_vl_dict = UserDataUtil.create_network_dict( + inst_req_info, initial_param_dict) + final_param_dict = UserDataUtil.create_final_param_dict( + initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict) + return {**final_param_dict, **api_param} diff --git a/tacker/tests/functional/common/fake_server.py b/tacker/tests/functional/common/fake_server.py index f6caf7013..6042bd3d2 100644 --- a/tacker/tests/functional/common/fake_server.py +++ b/tacker/tests/functional/common/fake_server.py @@ -19,6 +19,7 @@ import json import os import threading import time +from urllib.parse import urlparse from oslo_log import log as logging @@ -115,12 +116,13 @@ class DummyRequestHander(http.server.CGIHTTPRequestHandler): return False - def _returned_callback(self, mock_info): + def _returned_callback(self, path, mock_info): """Send responses to client. Called in do_* methods. This method do not handle message when error is occured. Args: + path (str): URI path mock_info (tuple): callback informations from caller. """ request_headers = dict(self.headers._headers) @@ -146,7 +148,7 @@ class DummyRequestHander(http.server.CGIHTTPRequestHandler): if len(response_body_str) > 0: self.wfile.write(response_body_str) - FakeServerManager.get_instance().add_history(self.path, RequestHistory( + FakeServerManager.get_instance().add_history(path, RequestHistory( status_code=status_code, request_headers=request_headers, request_body=request_body, @@ -207,8 +209,9 @@ class DummyRequestHander(http.server.CGIHTTPRequestHandler): # Check URI in request. if self._is_match_with_list(): # Request is registered in our list. - self._returned_callback( - FakeServerManager.get_instance()._funcs_gets[self.path]) + tplUri = urlparse(self.path) + self._returned_callback(tplUri.path, + FakeServerManager.get_instance()._funcs_gets[tplUri.path]) else: # Unregistered URI is requested LOG.debug('GET Recv. Unknown URL: "%s"' % self.path) @@ -229,8 +232,9 @@ class DummyRequestHander(http.server.CGIHTTPRequestHandler): # URI might have trailing uuid or not. if self._is_match_with_list(): # Request is registered in our list. - self._returned_callback( - FakeServerManager.get_instance()._funcs_posts[self.path]) + tplUri = urlparse(self.path) + self._returned_callback(tplUri.path, + FakeServerManager.get_instance()._funcs_posts[tplUri.path]) else: # Unregistered URI is requested LOG.debug('POST Recv. Unknown URL: "%s"' % self.path) @@ -268,6 +272,7 @@ class FakeServerManager(SingletonMixin): """Manager class to manage dummy server setting and control""" SERVER_PORT = 9990 + SERVER_INVOKE_CHECK_INTERVAL = 10 def __init__(self): # Initialize class-specific variables. @@ -397,7 +402,7 @@ class FakeServerManager(SingletonMixin): self.objHttpd = http.server.HTTPServer( (address, port), DummyRequestHander) except OSError: - time.sleep(10) + time.sleep(self.SERVER_INVOKE_CHECK_INTERVAL) continue else: break diff --git a/tacker/tests/functional/vnflcm/base.py b/tacker/tests/functional/vnflcm/base.py index 0f9da1996..f6a68d563 100644 --- a/tacker/tests/functional/vnflcm/base.py +++ b/tacker/tests/functional/vnflcm/base.py @@ -128,7 +128,7 @@ def _create_and_upload_vnf_package( break if ((int(time.time()) - start_time) > timeout): - raise Exception("Failed to onboard vnf package") + raise TimeoutError("Failed to onboard vnf package") time.sleep(1) @@ -159,7 +159,7 @@ def _show_vnf_package(tacker_client, vnf_package_id): return resp, body if ((int(time.time()) - start_time) > timeout): - raise Exception("Failed to onboard vnf package") + raise TimeoutError("Failed to onboard vnf package") time.sleep(1) @@ -175,7 +175,7 @@ def _list_vnf_package(tacker_client, **kwargs): return resp, body if ((int(time.time()) - start_time) > timeout): - raise Exception("Failed to onboard vnf package") + raise TimeoutError("Failed to onboard vnf package") time.sleep(1) @@ -228,8 +228,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): if self.is_setup_error: self.fail("Faild, not exists pre-registered image.") - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) FAKE_SERVER_MANAGER.clear_history(callback_url) FAKE_SERVER_MANAGER.set_callback( 'POST', @@ -417,8 +418,20 @@ class BaseVnfLcmTest(base.BaseTackerTest): return resp, body def _heal_vnf_instance(self, vnf_instance_id, request_body): - url = \ - os.path.join(self.base_vnf_instances_url, vnf_instance_id, "heal") + url = os.path.join( + self.base_vnf_instances_url, + vnf_instance_id, + "heal") + resp, body = self.http_client.do_request(url, "POST", + body=jsonutils.dumps(request_body)) + + return resp, body + + def _scale_vnf_instance(self, vnf_instance_id, request_body): + url = os.path.join( + self.base_vnf_instances_url, + vnf_instance_id, + "scale") resp, body = self.http_client.do_request(url, "POST", body=jsonutils.dumps(request_body)) @@ -438,6 +451,24 @@ class BaseVnfLcmTest(base.BaseTackerTest): return resp, body + def _rollback_op_occs(self, vnf_lcm_op_occs_id): + rollback_url = os.path.join( + self.base_vnf_lcm_op_occs_url, + vnf_lcm_op_occs_id, 'rollback') + resp, response_body = self.http_client.do_request( + rollback_url, "POST") + + return resp, response_body + + def _show_op_occs(self, vnf_lcm_op_occs_id): + show_url = os.path.join( + self.base_vnf_lcm_op_occs_url, + vnf_lcm_op_occs_id) + resp, response_body = self.http_client.do_request( + show_url, "GET") + + return resp, response_body + def _wait_terminate_vnf_instance(self, id, timeout=None): start_time = int(time.time()) @@ -631,8 +662,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): expected_operation_status=None, vnf_instance_id=None): start_time = int(time.time()) - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) while True: actual_status = None @@ -700,8 +732,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): fields.VnfInstanceState.NOT_INSTANTIATED) # FT-checkpoint: Notification - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) notify_mock_responses = self._filter_notify_history(callback_url, vnf_instance.get('id')) @@ -717,8 +750,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): self.assertEqual(404, resp.status_code) # FT-checkpoint: Notification - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) notify_mock_responses = self._filter_notify_history(callback_url, vnf_instance_id) @@ -742,8 +776,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): expected_resource_status='CREATE_COMPLETE') # FT-checkpoint: Notification - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) notify_mock_responses = self._filter_notify_history(callback_url, vnf_instance_id) @@ -779,8 +814,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): expected_stack_status=expected_stack_status) # FT-checkpoint: Notification - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) notify_mock_responses = self._filter_notify_history(callback_url, vnf_instance_id) @@ -824,8 +860,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): glance_image_id_list=glance_image_id_list) # FT-checkpoint: Notification - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) notify_mock_responses = self._filter_notify_history(callback_url, vnf_instance_id) @@ -845,6 +882,84 @@ class BaseVnfLcmTest(base.BaseTackerTest): 'VnfLcmOperationOccurrenceNotification', 'COMPLETED') + def assert_scale_vnf( + self, + resp, + vnf_instance_id, + pre_stack_resource_list, + post_stack_resource_list, + scale_type='SCALE_OUT', + expected_stack_status='CREATE_COMPLETE'): + self.assertEqual(202, resp.status_code) + self.assert_http_header_location_for_lcm_op_occs(resp.headers) + + resp, vnf_instance = self._show_vnf_instance(vnf_instance_id) + self.assert_vnf_state(vnf_instance) + self.assert_instantiation_state(vnf_instance) + + # check: scaling stack resource count + if scale_type == 'SCALE_OUT': + self.assertTrue(len(pre_stack_resource_list) < + len(post_stack_resource_list)) + else: + self.assertTrue(len(pre_stack_resource_list) > + len(post_stack_resource_list)) + + # check scaleStatus + scale_status = vnf_instance['instantiatedVnfInfo']['scaleStatus'] + self.assertTrue(len(scale_status) > 0) + for status in scale_status: + self.assertIsNotNone(status.get('aspectId')) + self.assertIsNotNone(status.get('scaleLevel')) + + self.assert_heat_stack_status( + vnf_instance['id'], + expected_stack_status=expected_stack_status) + + # FT-checkpoint: Notification + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) + notify_mock_responses = self._filter_notify_history(callback_url, + vnf_instance_id) + + self.assertEqual(3, len(notify_mock_responses)) + self.assert_notification_mock_response( + notify_mock_responses[0], + 'VnfLcmOperationOccurrenceNotification', + 'STARTING') + + self.assert_notification_mock_response( + notify_mock_responses[1], + 'VnfLcmOperationOccurrenceNotification', + 'PROCESSING') + + self.assert_notification_mock_response( + notify_mock_responses[2], + 'VnfLcmOperationOccurrenceNotification', + 'COMPLETED') + + def assert_rollback_vnf(self, resp, vnf_instance_id): + self.assertEqual(202, resp.status_code) + + # FT-checkpoint: Notification + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) + notify_mock_responses = self._filter_notify_history(callback_url, + vnf_instance_id) + + self.assertEqual(2, len(notify_mock_responses)) + self.assert_notification_mock_response( + notify_mock_responses[0], + 'VnfLcmOperationOccurrenceNotification', + 'ROLLING_BACK') + + self.assert_notification_mock_response( + notify_mock_responses[1], + 'VnfLcmOperationOccurrenceNotification', + 'ROLLED_BACK') + def assert_update_vnf( self, resp, @@ -864,8 +979,9 @@ class BaseVnfLcmTest(base.BaseTackerTest): expected_stack_status=expected_stack_status) # FT-checkpoint: Notification - callback_url = \ - os.path.join(MOCK_NOTIFY_CALLBACK_URL, self._testMethodName) + callback_url = os.path.join( + MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) notify_mock_responses = self._filter_notify_history(callback_url, vnf_instance_id) diff --git a/tacker/tests/functional/vnflcm/fake_vnflcm.py b/tacker/tests/functional/vnflcm/fake_vnflcm.py index b23356c12..519f2287e 100644 --- a/tacker/tests/functional/vnflcm/fake_vnflcm.py +++ b/tacker/tests/functional/vnflcm/fake_vnflcm.py @@ -239,3 +239,21 @@ class VnfInstances: data["vnfPkgId"] = vnf_package_id return data + + def make_scale_request_body(scale_type): + """Parameter selection policy. + + numberOfSteps specifies 1 + + Args: + scale_type (str): SCALE_OUT or SCALE_IN + """ + + return { + "type": scale_type, + "aspectId": "VDU1_scale", + "numberOfSteps": 1, + "additionalParams": { + "samplekey": "samplevalue" + } + } diff --git a/tacker/tests/functional/vnflcm/fake_vnfpkgm.py b/tacker/tests/functional/vnflcm/fake_vnfpkgm.py new file mode 100644 index 000000000..1f124ce3b --- /dev/null +++ b/tacker/tests/functional/vnflcm/fake_vnfpkgm.py @@ -0,0 +1,105 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +from oslo_utils import uuidutils + + +class VnfPackage: + VNF_PACKAGE_REQ_PATH = "/vnfpkgm/v1/vnf_packages" + + @staticmethod + def make_list_response_body(): + return [VnfPackage.make_individual_response] + + @staticmethod + def make_individual_response_body(vnfd_id, vnf_package_hash): + add_artifact_hash = ( + "6513f21e44aa3da349f248188a44" + + "bc304a3653a04122d8fb4535423c8" + + "e1d14cd6a153f735bb0982e2" + + "161b5b5186106570c17a9" + + "e58b64dd39390617cd5a350f78") + + sw_image_hash = ( + "6513f21e44aa3da349" + + "f248188a44bc304a3653a04" + + "122d8fb4535423c8e1d14c" + + "d6a153f735bb0982e2161b5" + + "b5186106570c17a9e58b6" + + "4dd39390617cd5a350f78") + + data = { + "id": uuidutils.generate_uuid(), + "vnfdId": vnfd_id, + "vnfProvider": "Company", + "vnfProductName": "Sample VNF", + "vnfSoftwareVersion": "1.0", + "vnfdVersion": "1.0", + "checksum": { + "algorithm": "SHA-512", + "hash": vnf_package_hash + }, + "softwareImages": [ + { + "id": "sw_image", + "name": "cirros-0.4.0-x86_64-disk", + "provider": "Company", + "version": "0.4.0", + "checksum": { + "algorithm": "SHA-512", + "hash": sw_image_hash + }, + "containerFormat": "BARE", + "diskFormat": "QCOW2", + "createdAt": "2020-09-01T12:34:56Z", + "minDisk": "2147483648", + "minRam": "268435456", + "size": "1073741824", + "userMetadata": { + "key": "value" + }, + "imagePath": "Files/images/cirros-0.4.0-x86_64-disk.img" + } + ], + "additionalArtifacts": [ + { + "artifactPath": + "Files/images/cirros-0.4.0-x86_64-disk.img", + "checksum": { + "algorithm": "SHA-512", + "hash": add_artifact_hash + }, + "metadata": { + "key": "value" + } + } + ], + "onboardingState": "ONBOARDED", + "operationalState": "ENABLED", + "usageState": "NOT_IN_USE", + "userDefinedData": { + "key": "value" + }, + "_links": { + "self": { + "href": "GetPackageのURI" + }, + "vnfd": { + "href": "GetVNFDのURI" + }, + "packageContent": { + "href": "GetPackageContentのURI" + } + } + } + + return data diff --git a/tacker/tests/functional/vnflcm/test_vnf_instance_with_user_data.py b/tacker/tests/functional/vnflcm/test_vnf_instance_with_user_data.py index 643572cd0..23a987d4a 100644 --- a/tacker/tests/functional/vnflcm/test_vnf_instance_with_user_data.py +++ b/tacker/tests/functional/vnflcm/test_vnf_instance_with_user_data.py @@ -89,12 +89,134 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): if ((int(time.time()) - start_time) > timeout): if resp: resp.raise_for_status() - raise Exception("Failed to show_subscription") + raise TimeoutError("Failed to show_subscription") time.sleep(1) + def test_inst_scaling_term(self): + """Test basic life cycle operations with sample VNFD. + + In this test case, we do following steps. + - Create subscription. + - Create VNF package. + - Upload VNF package. + - Create VNF instance. + - Instantiate VNF. + - Get VNF informations. + - Scale-Out VNF + - Scale-In VNF + - Terminate VNF + - Delete VNF + - Delete subscription + """ + # Create subscription and register it. + request_body = fake_vnflcm.Subscription.make_create_request_body( + 'http://localhost:{}{}'.format( + vnflcm_base.FAKE_SERVER_MANAGER.SERVER_PORT, + os.path.join(vnflcm_base.MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName))) + resp, response_body = self._register_subscription(request_body) + self.assertEqual(201, resp.status_code) + self.assert_http_header_location_for_subscription(resp.headers) + subscription_id = response_body.get('id') + self.addCleanup( + self._delete_subscription, + subscription_id) + + # Pre Setting: Create vnf package. + sample_name = 'functional5' + csar_package_path = os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "../../etc/samples/etsi/nfv", + sample_name)) + tempname, _ = vnflcm_base._create_csar_with_unique_vnfd_id( + csar_package_path) + # upload vnf package + vnf_package_id, vnfd_id = vnflcm_base._create_and_upload_vnf_package( + self.tacker_client, user_defined_data={ + "key": sample_name}, temp_csar_path=tempname) + + # Post Setting: Reserve deleting vnf package. + self.addCleanup(vnflcm_base._delete_vnf_package, self.tacker_client, + vnf_package_id) + + # Create vnf instance + resp, vnf_instance = self._create_vnf_instance_from_body( + fake_vnflcm.VnfInstances.make_create_request_body(vnfd_id)) + vnf_instance_id = vnf_instance['id'] + self._wait_lcm_done(vnf_instance_id=vnf_instance_id) + self.assert_create_vnf(resp, vnf_instance, vnf_package_id) + self.addCleanup(self._delete_vnf_instance, vnf_instance_id) + + # Instantiate vnf instance + request_body = fake_vnflcm.VnfInstances.make_inst_request_body( + self.vim['tenant_id'], self.ext_networks, self.ext_mngd_networks, + self.ext_link_ports, self.ext_subnets) + resp, _ = self._instantiate_vnf_instance(vnf_instance_id, request_body) + self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) + self.assert_instantiate_vnf(resp, vnf_instance_id, vnf_package_id) + + # Show vnf instance + resp, vnf_instance = self._show_vnf_instance(vnf_instance_id) + self.assertEqual(200, resp.status_code) + + # Scale-out vnf instance + stack = self._get_heat_stack(vnf_instance_id) + pre_stack_resource_list = self._get_heat_resource_list(stack.id, 2) + + request_body = fake_vnflcm.VnfInstances.make_scale_request_body( + 'SCALE_OUT') + resp, _ = self._scale_vnf_instance(vnf_instance_id, request_body) + self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) + + post_stack_resource_list = self._get_heat_resource_list(stack.id, 2) + self._assert_scale_vnf(resp, vnf_instance_id, vnf_package_id, + pre_stack_resource_list, post_stack_resource_list, + scale_type='SCALE_OUT') + + # Scale-in vnf instance + stack = self._get_heat_stack(vnf_instance_id) + pre_stack_resource_list = self._get_heat_resource_list(stack.id, 2) + + request_body = fake_vnflcm.VnfInstances.make_scale_request_body( + 'SCALE_IN') + resp, _ = self._scale_vnf_instance(vnf_instance_id, request_body) + self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) + + post_stack_resource_list = self._get_heat_resource_list(stack.id, 2) + self._assert_scale_vnf(resp, vnf_instance_id, vnf_package_id, + pre_stack_resource_list, post_stack_resource_list, + scale_type='SCALE_IN') + + # Terminate VNF + stack = self._get_heat_stack(vnf_instance_id) + resources_list = self._get_heat_resource_list(stack.id) + resource_name_list = [r.resource_name for r in resources_list] + glance_image_id_list = self._get_glance_image_list_from_stack_resource( + stack.id, resource_name_list) + + terminate_req_body = fake_vnflcm.VnfInstances.make_term_request_body() + resp, _ = self._terminate_vnf_instance( + vnf_instance_id, terminate_req_body) + self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) + self.assert_terminate_vnf(resp, vnf_instance_id, stack.id, + resource_name_list, glance_image_id_list, vnf_package_id) + + # Delete VNF + resp, _ = self._delete_vnf_instance(vnf_instance_id) + self._wait_lcm_done(vnf_instance_id=vnf_instance_id) + self.assert_delete_vnf(resp, vnf_instance_id, vnf_package_id) + + # Subscription delete + resp, response_body = self._delete_subscription(subscription_id) + self.assertEqual(204, resp.status_code) + + resp, _ = self._show_subscription(subscription_id) + self.assertEqual(404, resp.status_code) + def test_inst_update_heal_term(self): - """Test base life cycle operations. + """Test basic life cycle operations. In this test case, we do following steps. - Create subscription. @@ -123,9 +245,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): self.assertEqual(201, resp.status_code) self.assert_http_header_location_for_subscription(resp.headers) subscription_id = response_body.get('id') - self.addCleanup( - self._delete_subscription, - subscription_id) + self.addCleanup(self._delete_subscription, subscription_id) # Subscription show resp, body = self._wait_show_subscription(subscription_id) @@ -150,9 +270,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): "key": sample_name}, temp_csar_path=tempname) # Post Setting: Reserve deleting vnf package. - self.addCleanup( - vnflcm_base._delete_vnf_package, - self.tacker_client, + self.addCleanup(vnflcm_base._delete_vnf_package, self.tacker_client, vnf_package_id) # Create vnf instance @@ -162,17 +280,12 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): self._wait_lcm_done(vnf_instance_id=vnf_instance_id) self.assert_create_vnf(resp, vnf_instance, vnf_package_id) vnf_instance_name = vnf_instance['vnfInstanceName'] - self.addCleanup( - self._delete_vnf_instance, - vnf_instance_id) + self.addCleanup(self._delete_vnf_instance, vnf_instance_id) # Instantiate vnf instance request_body = fake_vnflcm.VnfInstances.make_inst_request_body( - self.vim['tenant_id'], - self.ext_networks, - self.ext_mngd_networks, - self.ext_link_ports, - self.ext_subnets) + self.vim['tenant_id'], self.ext_networks, self.ext_mngd_networks, + self.ext_link_ports, self.ext_subnets) resp, _ = self._instantiate_vnf_instance(vnf_instance_id, request_body) self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) self.assert_instantiate_vnf(resp, vnf_instance_id, vnf_package_id) @@ -209,12 +322,8 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): vnfd_id=update_vnfd_id) resp, _ = self._update_vnf_instance(vnf_instance_id, request_body) self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) - self.assert_update_vnf( - resp, - vnf_instance_id, - after_id=request_body['vnfdId'], - old_id=vnfd_id) - + self.assert_update_vnf(resp, vnf_instance_id, + after_id=request_body['vnfdId'], old_id=vnfd_id) vnf_package_id = update_vnf_package_id # Heal vnf (exists vnfc_instace_id) @@ -287,9 +396,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): self.assertEqual(201, resp.status_code) self.assert_http_header_location_for_subscription(resp.headers) subscription_id = response_body.get('id') - self.addCleanup( - self._delete_subscription, - subscription_id) + self.addCleanup(self._delete_subscription, subscription_id) # Pre Setting: Create vnf package. sample_name = 'functional' @@ -306,9 +413,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): "key": sample_name}, temp_csar_path=tempname) # Post Setting: Reserve deleting vnf package. - self.addCleanup( - vnflcm_base._delete_vnf_package, - self.tacker_client, + self.addCleanup(vnflcm_base._delete_vnf_package, self.tacker_client, vnf_package_id) # Create vnf instance @@ -317,17 +422,12 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): vnf_instance_id = vnf_instance['id'] self._wait_lcm_done(vnf_instance_id=vnf_instance_id) self.assert_create_vnf(resp, vnf_instance, vnf_package_id) - self.addCleanup( - self._delete_vnf_instance, - vnf_instance_id) + self.addCleanup(self._delete_vnf_instance, vnf_instance_id) # Instantiate vnf instance request_body = fake_vnflcm.VnfInstances.make_inst_request_body( - self.vim['tenant_id'], - self.ext_networks, - self.ext_mngd_networks, - self.ext_link_ports, - self.ext_subnets) + self.vim['tenant_id'], self.ext_networks, self.ext_mngd_networks, + self.ext_link_ports, self.ext_subnets) resp, _ = self._instantiate_vnf_instance(vnf_instance_id, request_body) self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) self.assert_instantiate_vnf(resp, vnf_instance_id, vnf_package_id) @@ -365,12 +465,8 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): vnf_package_id=update_vnf_package_id) resp, _ = self._update_vnf_instance(vnf_instance_id, request_body) self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) - self.assert_update_vnf( - resp, - vnf_instance_id, - is_vnfd=False, - after_id=request_body['vnfPkgId'], - old_id=vnf_package_id) + self.assert_update_vnf(resp, vnf_instance_id, is_vnfd=False, + after_id=request_body['vnfPkgId'], old_id=vnf_package_id) vnf_package_id = update_vnf_package_id # Terminate VNF @@ -426,9 +522,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): "key": sample_name}, temp_csar_path=tempname) # Reserve deleting vnf package - self.addCleanup( - vnflcm_base._delete_vnf_package, - self.tacker_client, + self.addCleanup(vnflcm_base._delete_vnf_package, self.tacker_client, vnf_package_id) # Settings @@ -449,11 +543,9 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): # Reserve deleting vnf instance self.addCleanup(self._delete_vnf_instance, vnf_instance['id']) - request_body = \ - vnflcm_base._create_instantiate_vnf_request_body("simple", - vim_id=self.vim['id'], - ext_vl=self.ext_vl, - add_params=add_params) + request_body = vnflcm_base._create_instantiate_vnf_request_body( + "simple", vim_id=self.vim['id'], ext_vl=self.ext_vl, + add_params=add_params) self._instantiate_vnf_instance_fail(vnf_instance['id'], request_body) @@ -481,9 +573,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): "key": sample_name}, temp_csar_path=tempname) # Reserve deleting vnf package - self.addCleanup( - vnflcm_base._delete_vnf_package, - self.tacker_client, + self.addCleanup(vnflcm_base._delete_vnf_package, self.tacker_client, vnf_package_id) # Settings @@ -536,9 +626,7 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): "key": sample_name}, temp_csar_path=tempname) # Reserve deleting vnf package - self.addCleanup( - vnflcm_base._delete_vnf_package, - self.tacker_client, + self.addCleanup(vnflcm_base._delete_vnf_package, self.tacker_client, vnf_package_id) # Settings @@ -671,14 +759,224 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): # Reserve deleting vnf instance self.addCleanup(self._delete_vnf_instance, vnf_instance['id']) - request_body = \ - vnflcm_base._create_instantiate_vnf_request_body("simple", - vim_id=self.vim['id'], - ext_vl=self.ext_vl, - add_params=add_params) + request_body = vnflcm_base._create_instantiate_vnf_request_body( + "simple", vim_id=self.vim['id'], ext_vl=self.ext_vl, + add_params=add_params) self._instantiate_vnf_instance_fail(vnf_instance['id'], request_body) + def test_rollback_instantiate(self): + """Test rollback operation for instantiation. + + In this test case, we do following steps. + - Create subscription. + - Create VNF package. + - Upload VNF package. + - Create VNF instance. + - Instantiate VNF(Will fail). + - Get vnflcmOpOccId to rollback. + - Rollback instantiation operation. + - Get opOccs information. + - Delete subscription. + """ + # Create subscription and register it. + request_body = fake_vnflcm.Subscription.make_create_request_body( + 'http://localhost:{}{}'.format( + vnflcm_base.FAKE_SERVER_MANAGER.SERVER_PORT, + os.path.join(vnflcm_base.MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName))) + resp, response_body = self._register_subscription(request_body) + self.assertEqual(201, resp.status_code) + self.assert_http_header_location_for_subscription(resp.headers) + subscription_id = response_body.get('id') + self.addCleanup(self._delete_subscription, subscription_id) + + # Pre Setting: Create vnf package. + sample_name = 'functional3' + csar_package_path = os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "../../etc/samples/etsi/nfv", + sample_name)) + tempname, _ = vnflcm_base._create_csar_with_unique_vnfd_id( + csar_package_path) + # upload vnf package + vnf_package_id, vnfd_id = vnflcm_base._create_and_upload_vnf_package( + self.tacker_client, user_defined_data={ + "key": sample_name}, temp_csar_path=tempname) + + # Post Setting: Reserve deleting vnf package. + self.addCleanup( + vnflcm_base._delete_vnf_package, + self.tacker_client, + vnf_package_id) + + # Create vnf instance + resp, vnf_instance = self._create_vnf_instance_from_body( + fake_vnflcm.VnfInstances.make_create_request_body(vnfd_id)) + vnf_instance_id = vnf_instance['id'] + self._wait_lcm_done(vnf_instance_id=vnf_instance_id) + self.assert_create_vnf(resp, vnf_instance, vnf_package_id) + self.addCleanup(self._delete_vnf_instance, vnf_instance_id) + + # Failed instantiate VNF + request_body = fake_vnflcm.VnfInstances.make_inst_request_body( + self.vim['tenant_id'], self.ext_networks, self.ext_mngd_networks, + self.ext_link_ports, self.ext_subnets) + resp, _ = self._instantiate_vnf_instance(vnf_instance_id, request_body) + self._wait_lcm_done('FAILED_TEMP', vnf_instance_id=vnf_instance_id) + + callback_url = os.path.join( + vnflcm_base.MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) + notify_mock_responses = vnflcm_base.FAKE_SERVER_MANAGER.get_history( + callback_url) + vnflcm_base.FAKE_SERVER_MANAGER.clear_history( + callback_url) + + # get vnflcm_op_occ_id + vnflcm_op_occ_id = notify_mock_responses[0].request_body.get( + 'vnfLcmOpOccId') + self.assertIsNotNone(vnflcm_op_occ_id) + + # rollback + resp, _ = self._rollback_op_occs(vnflcm_op_occ_id) + self._wait_lcm_done('ROLLING_BACK', vnf_instance_id=vnf_instance_id) + self._wait_lcm_done('ROLLED_BACK', vnf_instance_id=vnf_instance_id) + self.assert_rollback_vnf(resp, vnf_instance_id) + + # occ-show + resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id) + self._assert_occ_show(resp, op_occs_info) + + # Delete VNF + resp, _ = self._delete_vnf_instance(vnf_instance_id) + self._wait_lcm_done(vnf_instance_id=vnf_instance_id) + self.assert_delete_vnf(resp, vnf_instance_id, vnf_package_id) + + # Subscription delete + resp, response_body = self._delete_subscription(subscription_id) + self.assertEqual(204, resp.status_code) + + def test_rollback_scale_out(self): + """Test rollback operation for Scale-Out operation. + + In this test case, we do following steps. + - Create subscription. + - Create VNF package. + - Upload VNF package. + - Create VNF instance. + - Instantiate VNF. + - Scale-Out(Will fail). + - Get vnfcmOpOccId to rollback. + - Rollback Scale-Out operation. + - Get opOccs information. + - Terminate VNF. + - Delete subscription. + """ + # Create subscription and register it. + request_body = fake_vnflcm.Subscription.make_create_request_body( + 'http://localhost:{}{}'.format( + vnflcm_base.FAKE_SERVER_MANAGER.SERVER_PORT, + os.path.join(vnflcm_base.MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName))) + resp, response_body = self._register_subscription(request_body) + self.assertEqual(201, resp.status_code) + self.assert_http_header_location_for_subscription(resp.headers) + subscription_id = response_body.get('id') + self.addCleanup(self._delete_subscription, subscription_id) + + # Pre Setting: Create vnf package. + sample_name = 'functional4' + csar_package_path = os.path.abspath( + os.path.join( + os.path.dirname(__file__), + "../../etc/samples/etsi/nfv", + sample_name)) + tempname, _ = vnflcm_base._create_csar_with_unique_vnfd_id( + csar_package_path) + # upload vnf package + vnf_package_id, vnfd_id = vnflcm_base._create_and_upload_vnf_package( + self.tacker_client, user_defined_data={ + "key": sample_name}, temp_csar_path=tempname) + + # Post Setting: Reserve deleting vnf package. + self.addCleanup( + vnflcm_base._delete_vnf_package, + self.tacker_client, + vnf_package_id) + + # Create vnf instance + resp, vnf_instance = self._create_vnf_instance_from_body( + fake_vnflcm.VnfInstances.make_create_request_body(vnfd_id)) + vnf_instance_id = vnf_instance['id'] + self._wait_lcm_done(vnf_instance_id=vnf_instance_id) + self.assert_create_vnf(resp, vnf_instance, vnf_package_id) + self.addCleanup(self._delete_vnf_instance, vnf_instance_id) + + # instantiate VNF + request_body = fake_vnflcm.VnfInstances.make_inst_request_body( + self.vim['tenant_id'], self.ext_networks, self.ext_mngd_networks, + self.ext_link_ports, self.ext_subnets) + self._instantiate_vnf_instance(vnf_instance_id, request_body) + self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) + vnflcm_base.FAKE_SERVER_MANAGER.clear_history( + os.path.join(vnflcm_base.MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName)) + + # Fail Scale-out vnf instance + request_body = fake_vnflcm.VnfInstances.make_scale_request_body( + 'SCALE_OUT') + resp, _ = self._scale_vnf_instance(vnf_instance_id, request_body) + self._wait_lcm_done('FAILED_TEMP', vnf_instance_id=vnf_instance_id) + + callback_url = os.path.join( + vnflcm_base.MOCK_NOTIFY_CALLBACK_URL, + self._testMethodName) + notify_mock_responses = vnflcm_base.FAKE_SERVER_MANAGER.get_history( + callback_url) + vnflcm_base.FAKE_SERVER_MANAGER.clear_history( + callback_url) + + # get vnflcm_op_occ_id + vnflcm_op_occ_id = notify_mock_responses[0].request_body.get( + 'vnfLcmOpOccId') + self.assertIsNotNone(vnflcm_op_occ_id) + + # rollback + resp, _ = self._rollback_op_occs(vnflcm_op_occ_id) + self._wait_lcm_done('ROLLING_BACK', vnf_instance_id=vnf_instance_id) + self._wait_lcm_done('ROLLED_BACK', vnf_instance_id=vnf_instance_id) + self.assert_rollback_vnf(resp, vnf_instance_id) + + # occ-show + resp, op_occs_info = self._show_op_occs(vnflcm_op_occ_id) + self._assert_occ_show(resp, op_occs_info) + + # Terminate VNF + stack = self._get_heat_stack(vnf_instance_id) + resources_list = self._get_heat_resource_list(stack.id) + resource_name_list = [r.resource_name for r in resources_list] + glance_image_id_list = self._get_glance_image_list_from_stack_resource( + stack.id, + resource_name_list) + + terminate_req_body = fake_vnflcm.VnfInstances.make_term_request_body() + resp, _ = self._terminate_vnf_instance(vnf_instance_id, + terminate_req_body) + self._wait_lcm_done('COMPLETED', vnf_instance_id=vnf_instance_id) + self.assert_terminate_vnf(resp, vnf_instance_id, stack.id, + resource_name_list, glance_image_id_list, vnf_package_id) + + # Delete VNF + resp, _ = self._delete_vnf_instance(vnf_instance_id) + self._wait_lcm_done(vnf_instance_id=vnf_instance_id) + self.assert_delete_vnf(resp, vnf_instance_id, vnf_package_id) + + # Subscription delete + resp, response_body = self._delete_subscription(subscription_id) + self.assertEqual(204, resp.status_code) + def assert_create_vnf(self, resp, vnf_instance, vnf_pkg_id): super().assert_create_vnf(resp, vnf_instance) @@ -738,6 +1036,25 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): self.tacker_client, vnf_pkg_id) self.assert_vnf_package_usage_state(vnf_pkg_info) + def _assert_scale_vnf( + self, + resp, + vnf_instance_id, + vnf_pkg_id, + pre_stack_resource_list, + post_stack_resource_list, + scale_type): + super().assert_scale_vnf( + resp, + vnf_instance_id, + pre_stack_resource_list, + post_stack_resource_list, + scale_type=scale_type) + + resp, vnf_pkg_info = vnflcm_base._show_vnf_package( + self.tacker_client, vnf_pkg_id) + self.assert_vnf_package_usage_state(vnf_pkg_info) + def assert_update_vnf(self, resp, vnf_instance_id, is_vnfd=True, after_id=None, old_id=None, expected_stack_status='CREATE_COMPLETE'): @@ -788,3 +1105,23 @@ class VnfLcmWithUserDataTest(vnflcm_base.BaseVnfLcmTest): self.assertEqual( expected_usage_state, vnf_package_info['usageState']) + + def _assert_occ_show(self, resp, op_occs_info): + self.assertEqual(200, resp.status_code) + + # Only check required parameters. + self.assertIsNotNone(op_occs_info.get('id')) + self.assertIsNotNone(op_occs_info.get('operationState')) + self.assertIsNotNone(op_occs_info.get('stateEnteredTime')) + self.assertIsNotNone(op_occs_info.get('vnfInstanceId')) + self.assertIsNotNone(op_occs_info.get('operation')) + self.assertIsNotNone(op_occs_info.get('isAutomaticInvocation')) + self.assertIsNotNone(op_occs_info.get('isCancelPending')) + + _links = op_occs_info.get('_links') + self.assertIsNotNone(_links.get('self')) + self.assertIsNotNone(_links.get('self').get('href')) + self.assertIsNotNone(_links.get('vnfInstance')) + self.assertIsNotNone(_links.get('vnfInstance').get('href')) + self.assertIsNotNone(_links.get('grant')) + self.assertIsNotNone(_links.get('grant').get('href'))