Merge "FT for multi tenant policy in LCM"
This commit is contained in:
commit
61cb57a8b9
10
.zuul.yaml
10
.zuul.yaml
|
@ -275,6 +275,15 @@
|
|||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol-v2
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-multi-tenant
|
||||
parent: tacker-functional-devstack-multinode-sol
|
||||
description: |
|
||||
Multinodes job for SOL Multi tenant devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol-multi-tenant
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-separated-nfvo
|
||||
parent: tacker-functional-devstack-multinode-sol
|
||||
|
@ -522,3 +531,4 @@
|
|||
- tacker-functional-devstack-multinode-sol-kubernetes
|
||||
- tacker-functional-devstack-multinode-libs-master
|
||||
- tacker-functional-devstack-multinode-sol-v2
|
||||
- tacker-functional-devstack-multinode-sol-multi-tenant
|
||||
|
|
|
@ -163,7 +163,7 @@ def _vnf_lcm_subscriptions_show(context, subscriptionId):
|
|||
|
||||
sql = text(
|
||||
"select "
|
||||
"t1.id,t1.callback_uri,t2.filter "
|
||||
"t1.id,t1.callback_uri,t1.tenant_id,t2.filter "
|
||||
"from vnf_lcm_subscriptions t1, "
|
||||
"(select distinct subscription_uuid,filter from vnf_lcm_filters) t2 "
|
||||
"where t1.id = t2.subscription_uuid "
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
heat_template_version: 2013-05-23
|
||||
description: 'Simple Base HOT for Sample VNF'
|
||||
|
||||
parameters:
|
||||
nfv:
|
||||
type: json
|
||||
|
||||
resources:
|
||||
VDU1_scale:
|
||||
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
|
||||
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
|
||||
adjustment_type: change_in_capacity
|
||||
VDU2_scale:
|
||||
type: OS::Heat::AutoScalingGroup
|
||||
depends_on: VDU1_scale
|
||||
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
|
||||
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
|
||||
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: {}
|
|
@ -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: "<is> 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 }
|
|
@ -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
|
|
@ -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.5.2-x86_64-disk
|
||||
version: '0.5.2'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
min_ram: 256 MB
|
||||
size: 12 GB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: m1.tiny
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 3 GB
|
||||
|
||||
VirtualStorage:
|
||||
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
||||
properties:
|
||||
virtual_block_storage_data:
|
||||
size_of_storage: 1 GB
|
||||
rdma_enabled: true
|
||||
sw_image_data:
|
||||
name: cirros-0.5.2-x86_64-disk
|
||||
version: '0.5.2'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
min_ram: 256 MB
|
||||
size: 12 GB
|
||||
|
||||
VDU1_CP1:
|
||||
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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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}
|
|
@ -454,10 +454,12 @@ class BaseTackerTest(base.BaseTestCase):
|
|||
|
||||
return vnf_instance, tosca_dict
|
||||
|
||||
def _list_op_occs(self, filter_string=''):
|
||||
def _list_op_occs(self, filter_string='', http_client=None):
|
||||
if http_client is None:
|
||||
http_client = self.http_client
|
||||
show_url = os.path.join(
|
||||
self.base_vnf_lcm_op_occs_url)
|
||||
resp, response_body = self.http_client.do_request(
|
||||
resp, response_body = http_client.do_request(
|
||||
show_url + filter_string, "GET")
|
||||
return resp, response_body
|
||||
|
||||
|
|
|
@ -206,6 +206,8 @@ class FakeServerManager(object):
|
|||
"""Manager class to manage dummy server setting and control"""
|
||||
|
||||
SERVER_PORT = 9990
|
||||
SERVER_PORT_T1 = 9995
|
||||
SERVER_PORT_T2 = 9996
|
||||
SERVER_INVOKE_CHECK_INTERVAL = 10
|
||||
|
||||
def __init__(self):
|
||||
|
|
|
@ -209,6 +209,12 @@ def _create_instantiate_vnf_request_body(flavour_id,
|
|||
class BaseVnfLcmTest(base.BaseTackerTest):
|
||||
|
||||
is_setup_error = False
|
||||
# NOTE: If prepare_fake_server is set(by default) then this base
|
||||
# class will prepare(create and start) the fake http server which
|
||||
# takes time and can add up more time in gate CI. Any child class
|
||||
# can set it false. For example, BaseVnfLcmMultiTenantTest which
|
||||
# create their own servers for two different tenants.
|
||||
prepare_fake_server = True
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -217,12 +223,14 @@ class BaseVnfLcmTest(base.BaseTackerTest):
|
|||
we set up fake NFVO server for test at here.
|
||||
'''
|
||||
super(BaseVnfLcmTest, cls).setUpClass()
|
||||
if cls.prepare_fake_server:
|
||||
cls._prepare_start_fake_server(FAKE_SERVER_MANAGER,
|
||||
FAKE_SERVER_PORT)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(BaseVnfLcmTest, cls).tearDownClass()
|
||||
if cls.prepare_fake_server:
|
||||
FAKE_SERVER_MANAGER.stop_server()
|
||||
|
||||
def setUp(self):
|
||||
|
@ -231,8 +239,8 @@ 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,
|
||||
if self.prepare_fake_server:
|
||||
callback_url = os.path.join(MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
self._clear_history_and_set_callback(FAKE_SERVER_MANAGER,
|
||||
callback_url)
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import os
|
||||
|
||||
from tacker.tests.functional import base
|
||||
from tacker.tests.functional.common.fake_server import FakeServerManager
|
||||
from tacker.tests.functional.sol.vnflcm import base as vnflcm_base
|
||||
|
||||
|
||||
FAKE_SERVER_MANAGER_T1 = FakeServerManager()
|
||||
FAKE_SERVER_PORT_T1 = 9995
|
||||
FAKE_SERVER_MANAGER_T2 = FakeServerManager()
|
||||
FAKE_SERVER_PORT_T2 = 9996
|
||||
|
||||
|
||||
class BaseVnfLcmMultiTenantTest(vnflcm_base.BaseVnfLcmTest):
|
||||
|
||||
prepare_fake_server = False
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(BaseVnfLcmMultiTenantTest, cls).setUpClass()
|
||||
|
||||
result = cls.get_openstack_client_session(
|
||||
vim_conf_file='local-tenant1-vim.yaml')
|
||||
cls.client_tenant1 = result.get('client')
|
||||
cls.http_client_tenant1 = result.get('http_client')
|
||||
cls.h_client_tenant1 = result.get('h_client')
|
||||
cls.glance_client_tenant1 = result.get('glance_client')
|
||||
|
||||
result = cls.get_openstack_client_session(
|
||||
vim_conf_file='local-tenant2-vim.yaml')
|
||||
cls.client_tenant2 = result.get('client')
|
||||
cls.http_client_tenant2 = result.get('http_client')
|
||||
cls.h_client_tenant2 = result.get('h_client')
|
||||
cls.glance_client_tenant2 = result.get('glance_client')
|
||||
|
||||
cls.tacker_client_t1 = base.BaseTackerTest.tacker_http_client(
|
||||
'local-tenant1-vim.yaml')
|
||||
cls.tacker_client_t2 = base.BaseTackerTest.tacker_http_client(
|
||||
'local-tenant2-vim.yaml')
|
||||
|
||||
# Set up fake NFVO server for tenant1 and tenant2
|
||||
cls.servers = {FAKE_SERVER_PORT_T1: FAKE_SERVER_MANAGER_T1,
|
||||
FAKE_SERVER_PORT_T2: FAKE_SERVER_MANAGER_T2}
|
||||
# NOTE: Create both server in parallel, otherwise they can
|
||||
# cause (especially server start) job timeout.
|
||||
for port, manager in cls.servers.items():
|
||||
cls._prepare_start_fake_server(manager, port)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(BaseVnfLcmMultiTenantTest, cls).tearDownClass()
|
||||
for _, manager in cls.servers.items():
|
||||
manager.stop_server()
|
||||
|
||||
def setUp(self):
|
||||
super(BaseVnfLcmMultiTenantTest, self).setUp()
|
||||
self.base_url = "/vnfpkgm/v1/vnf_packages"
|
||||
|
||||
callback_url = os.path.join(
|
||||
vnflcm_base.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
self._clear_history_and_set_callback(FAKE_SERVER_MANAGER_T1,
|
||||
callback_url)
|
||||
self._clear_history_and_set_callback(FAKE_SERVER_MANAGER_T2,
|
||||
callback_url)
|
||||
|
||||
vim_list = self.client.list_vims()
|
||||
self.vim_tenant1 = self.get_vim(vim_list, 'VIM_TEST')
|
||||
if not self.vim_tenant1:
|
||||
assert False, "vim_list is Empty: Tenant VIM is missing"
|
||||
self.vim_tenant2 = self.get_vim(vim_list, 'VIM_DEMO')
|
||||
if not self.vim_tenant2:
|
||||
assert False, "vim_list is Empty: Tenant VIM is missing"
|
||||
|
||||
result = self._create_network_settings()
|
||||
self.ext_networks_tenant1 = result.get('ext_networks')
|
||||
self.ext_vl_tenant1 = result.get('ext_vl')
|
||||
self.ext_mngd_networks_tenant1 = result.get('ext_mngd_networks')
|
||||
self.ext_link_ports_tenant1 = result.get('ext_link_ports')
|
||||
self.ext_subnets_tenant1 = result.get('ext_subnets')
|
||||
self.changed_ext_networks_tenant1 = result.get(
|
||||
'changed_ext_networks')
|
||||
self.changed_ext_subnets_tenant1 = result.get(
|
||||
'changed_ext_subnets')
|
||||
|
||||
result = self._create_network_settings()
|
||||
self.ext_networks_tenant2 = result.get('ext_networks')
|
||||
self.ext_vl_tenant2 = result.get('ext_vl')
|
||||
self.ext_mngd_networks_tenant2 = result.get('ext_mngd_networks')
|
||||
self.ext_link_ports_tenant2 = result.get('ext_link_ports')
|
||||
self.ext_subnets_tenant2 = result.get('ext_subnets')
|
||||
self.changed_ext_networks_tenant2 = result.get(
|
||||
'changed_ext_networks')
|
||||
self.changed_ext_subnets_tenant2 = result.get(
|
||||
'changed_ext_subnets')
|
||||
|
||||
@classmethod
|
||||
def get_openstack_client_session(cls, vim_conf_file):
|
||||
client = base.BaseTackerTest.tackerclient(vim_conf_file)
|
||||
http_client = base.BaseTackerTest.tacker_http_client(vim_conf_file)
|
||||
h_client = base.BaseTackerTest.heatclient(vim_conf_file)
|
||||
glance_client = base.BaseTackerTest.glanceclient(vim_conf_file)
|
||||
return {'client': client,
|
||||
'http_client': http_client,
|
||||
'h_client': h_client,
|
||||
'glance_client': glance_client}
|
|
@ -0,0 +1,252 @@
|
|||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from tacker.tests import uuidsentinel
|
||||
|
||||
|
||||
class Subscription:
|
||||
|
||||
@staticmethod
|
||||
def make_create_request_body(callback_uri):
|
||||
"""Parameter selection policy.
|
||||
|
||||
Set all Notification types and all life cycle types for filter.
|
||||
Specify OAuth2 for authentication → do not set authentication.
|
||||
|
||||
Args:
|
||||
callback_uri (str): Notification URI.
|
||||
|
||||
Returns:
|
||||
dict: Request body
|
||||
"""
|
||||
return {
|
||||
"filter": {
|
||||
"vnfInstanceSubscriptionFilter": {
|
||||
"vnfdIds": ["b1bb0ce7-ebca-4fa7-95ed-4840d7000000"],
|
||||
"vnfProductsFromProviders": [{
|
||||
"vnfProvider": "Company",
|
||||
"vnfProducts": [
|
||||
{
|
||||
"vnfProductName": "Sample VNF",
|
||||
"versions": [
|
||||
{
|
||||
"vnfSoftwareVersion": "1.0",
|
||||
"vnfdVersions": ["1.0"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
"notificationTypes": [
|
||||
"VnfLcmOperationOccurrenceNotification",
|
||||
"VnfIdentifierCreationNotification",
|
||||
"VnfIdentifierDeletionNotification"
|
||||
],
|
||||
"operationTypes": [
|
||||
"INSTANTIATE",
|
||||
"SCALE",
|
||||
"TERMINATE",
|
||||
"HEAL",
|
||||
"MODIFY_INFO",
|
||||
"CHANGE_EXT_CONN"
|
||||
],
|
||||
"operationStates": ["STARTING"]
|
||||
},
|
||||
"callbackUri": callback_uri
|
||||
}
|
||||
|
||||
|
||||
ext_vdu1_cp1 = {
|
||||
"cpdId": "VDU1_CP1",
|
||||
"cpConfig": [{
|
||||
"linkPortId": uuidsentinel.elp1_id
|
||||
}],
|
||||
}
|
||||
ext_vdu2_cp1 = {
|
||||
"cpdId": "VDU2_CP1",
|
||||
"cpConfig": [{
|
||||
"linkPortId": uuidsentinel.elp2_id
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
def _set_ext_link_port1(external_ports_id):
|
||||
ext_link_port1 = {
|
||||
"id": uuidsentinel.elp1_id,
|
||||
"resourceHandle": {
|
||||
"vimConnectionId": uuidsentinel.vim_connection_id,
|
||||
"resourceId": external_ports_id[0]
|
||||
}
|
||||
}
|
||||
return ext_link_port1
|
||||
|
||||
|
||||
def _set_ext_link_port2(external_ports_id):
|
||||
ext_link_port2 = {
|
||||
"id": uuidsentinel.elp2_id,
|
||||
"resourceHandle": {
|
||||
"vimConnectionId": uuidsentinel.vim_connection_id,
|
||||
"resourceId": external_ports_id[1]
|
||||
}
|
||||
}
|
||||
return ext_link_port2
|
||||
|
||||
|
||||
def _set_ext_virtual_link_cp1(networks_id, external_ports_id):
|
||||
ext_virtual_link_cp1 = {
|
||||
"id": uuidsentinel.evl1_id,
|
||||
"resourceId": networks_id[0],
|
||||
"vimConnectionId": uuidsentinel.vim_connection_id,
|
||||
"extCps": [ext_vdu1_cp1, ext_vdu2_cp1],
|
||||
"extLinkPorts": [
|
||||
_set_ext_link_port1(external_ports_id),
|
||||
_set_ext_link_port2(external_ports_id)]
|
||||
}
|
||||
return ext_virtual_link_cp1
|
||||
|
||||
|
||||
def _set_ext_cps_vdu1_cp2(external_subnets_id):
|
||||
ext_cps_vdu1_cp2 = {
|
||||
"cpdId": "VDU1_CP2",
|
||||
"cpConfig": [{
|
||||
"cpProtocolData": [{
|
||||
"layerProtocol": "IP_OVER_ETHERNET",
|
||||
"ipOverEthernet": {
|
||||
"ipAddresses": [{
|
||||
"type": "IPV4",
|
||||
"fixedAddresses": ["22.22.1.10"],
|
||||
"subnetId": external_subnets_id[1]
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}
|
||||
return ext_cps_vdu1_cp2
|
||||
|
||||
|
||||
def _set_ext_cps_vdu2_cp2(external_subnets_id):
|
||||
ext_cps_vdu2_cp2 = {
|
||||
"cpdId": "VDU2_CP2",
|
||||
"cpConfig": [{
|
||||
"cpProtocolData": [{
|
||||
"layerProtocol": "IP_OVER_ETHERNET",
|
||||
"ipOverEthernet": {
|
||||
"ipAddresses": [{
|
||||
"type": "IPV4",
|
||||
"fixedAddresses": ["22.22.1.20"],
|
||||
"subnetId": external_subnets_id[1]
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}
|
||||
return ext_cps_vdu2_cp2
|
||||
|
||||
|
||||
def _set_ext_virtual_link_cp2(networks_id, external_subnets_id):
|
||||
ext_virtual_link_cp2 = {
|
||||
"id": uuidsentinel.evl2_id,
|
||||
"resourceId": networks_id[1],
|
||||
"vimConnectionId": uuidsentinel.vim_connection_id,
|
||||
"extCps": [
|
||||
_set_ext_cps_vdu1_cp2(external_subnets_id),
|
||||
_set_ext_cps_vdu2_cp2(external_subnets_id)
|
||||
]
|
||||
}
|
||||
return ext_virtual_link_cp2
|
||||
|
||||
|
||||
def _set_ext_mng_vtl_lnks(ext_mngd_networks_id):
|
||||
ext_mng_vtl_lnks = [{
|
||||
"id": uuidsentinel.emvl1_id,
|
||||
"vnfVirtualLinkDescId": "internalVL1",
|
||||
"resourceId": ext_mngd_networks_id[0]
|
||||
}, {
|
||||
"id": uuidsentinel.emvl2_id,
|
||||
"vnfVirtualLinkDescId": "internalVL2",
|
||||
"resourceId": ext_mngd_networks_id[1]
|
||||
}]
|
||||
return ext_mng_vtl_lnks
|
||||
|
||||
|
||||
class VnfInstances:
|
||||
|
||||
@staticmethod
|
||||
def make_create_request_body(vnfd_id):
|
||||
return {
|
||||
"vnfdId": vnfd_id,
|
||||
"vnfInstanceName": "",
|
||||
"vnfInstanceDescription": "Sample VNF",
|
||||
"metadata": {
|
||||
"samplekey": "samplevalue"
|
||||
}
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def make_inst_request_body(
|
||||
user_name,
|
||||
tenant_id,
|
||||
networks_id,
|
||||
ext_mngd_networks_id,
|
||||
external_ports_id,
|
||||
external_subnets_id):
|
||||
data = {
|
||||
"flavourId": "simple",
|
||||
"instantiationLevelId": "instantiation_level_1",
|
||||
"extVirtualLinks": [
|
||||
_set_ext_virtual_link_cp1(
|
||||
networks_id, external_ports_id),
|
||||
_set_ext_virtual_link_cp2(
|
||||
networks_id, external_subnets_id)
|
||||
],
|
||||
"extManagedVirtualLinks": _set_ext_mng_vtl_lnks(
|
||||
ext_mngd_networks_id),
|
||||
"vimConnectionInfo": [{
|
||||
"id": uuidsentinel.vim_connection_id,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.v_2",
|
||||
"vimConnectionId": uuidsentinel.vim_connection_id,
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity"
|
||||
},
|
||||
"accessInfo": {
|
||||
"username": user_name,
|
||||
"region": "RegionOne",
|
||||
"password": "devstack",
|
||||
"tenant": tenant_id
|
||||
}
|
||||
}],
|
||||
"additionalParams": {
|
||||
"lcm-operation-user-data": "./UserData/lcm_user_data.py",
|
||||
"lcm-operation-user-data-class": "SampleUserData"
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def make_term_request_body():
|
||||
"""Parameter selection policy.
|
||||
|
||||
As all parameters are set, GRACEFUL is specified for terminationType.
|
||||
(to specify gracefulTerminationTimeout)
|
||||
|
||||
Returns:
|
||||
dict: Request body
|
||||
"""
|
||||
return {
|
||||
"terminationType": "GRACEFUL",
|
||||
"gracefulTerminationTimeout": 1,
|
||||
"additionalParams": {
|
||||
"samplekey": "samplevalue"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,455 @@
|
|||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional.sol.vnflcm import base as vnflcm_base
|
||||
from tacker.tests.functional.sol_multi_tenant.vnflcm import base
|
||||
from tacker.tests.functional.sol_multi_tenant.vnflcm import fake_vnflcm
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
|
||||
class VnfLcmWithMultiTenant(base.BaseVnfLcmMultiTenantTest):
|
||||
|
||||
VNF_PACKAGE_DELETE_TIMEOUT = 120
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(VnfLcmWithMultiTenant, cls).setUpClass()
|
||||
|
||||
# ModifyVNF specific image create.
|
||||
is_setup_error_tenant1 = cls._modify_vnf_specific_image_create(
|
||||
cls.glance_client_tenant1)
|
||||
if is_setup_error_tenant1:
|
||||
cls.is_setup_error = True
|
||||
return
|
||||
|
||||
is_setup_error_tenant2 = cls._modify_vnf_specific_image_create(
|
||||
cls.glance_client_tenant2)
|
||||
if is_setup_error_tenant2:
|
||||
cls.is_setup_error = True
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def _modify_vnf_specific_image_create(cls, glance_clt):
|
||||
is_setup_error = False
|
||||
images = cls._list_glance_image()
|
||||
if len(images) == 0:
|
||||
is_setup_error = True
|
||||
return is_setup_error
|
||||
|
||||
for image in images:
|
||||
specific_image_name = f'{image.name}{2}'
|
||||
image_data = {
|
||||
"min_disk": image.min_disk,
|
||||
"min_ram": image.min_ram,
|
||||
"disk_format": image.disk_format,
|
||||
"container_format": image.container_format,
|
||||
"visibility": image.visibility,
|
||||
"name": specific_image_name}
|
||||
|
||||
try:
|
||||
images = cls._list_glance_image(specific_image_name)
|
||||
if len(images) == 1:
|
||||
break
|
||||
|
||||
_, body = glance_clt.http_client.get(
|
||||
f'{glance_clt.http_client.get_endpoint()}{image.file}')
|
||||
|
||||
with tempfile.TemporaryFile('w+b') as f:
|
||||
for content in body:
|
||||
f.write(content)
|
||||
cls._create_glance_image(image_data, f.read())
|
||||
except Exception as e:
|
||||
print("Fail, Modify-VNF specific image create.", e, flush=True)
|
||||
is_setup_error = True
|
||||
return is_setup_error
|
||||
|
||||
return is_setup_error
|
||||
|
||||
def _wait_show_subscription(self, subscription_id, tacker_client):
|
||||
# wait for subscription creation
|
||||
timeout = vnflcm_base.VNF_SUBSCRIPTION_TIMEOUT
|
||||
start_time = int(time.time())
|
||||
while True:
|
||||
resp, body = self._show_subscription(subscription_id,
|
||||
tacker_client)
|
||||
if resp.ok or resp.status_code == 404:
|
||||
return resp, body
|
||||
|
||||
if ((int(time.time()) - start_time) > timeout):
|
||||
if resp:
|
||||
resp.raise_for_status()
|
||||
raise TimeoutError("Failed to show_subscription")
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
def _delete_vnf_package(self, package_uuid, http_client):
|
||||
url = os.path.join(self.base_url, package_uuid)
|
||||
resp, _ = http_client.do_request(url, "DELETE")
|
||||
self.assertEqual(204, resp.status_code)
|
||||
|
||||
def _wait_for_delete(self, package_uuid, http_client):
|
||||
show_url = os.path.join(self.base_url, package_uuid)
|
||||
timeout = self.VNF_PACKAGE_DELETE_TIMEOUT
|
||||
start_time = int(time.time())
|
||||
while True:
|
||||
resp, body = http_client.do_request(show_url, "GET")
|
||||
if (404 == resp.status_code):
|
||||
return resp, body
|
||||
|
||||
if (int(time.time()) - start_time) > timeout:
|
||||
raise Exception("Failed to delete package")
|
||||
time.sleep(1)
|
||||
|
||||
def _disable_operational_state(self, package_uuid, http_client):
|
||||
update_req_body = jsonutils.dumps({
|
||||
"operationalState": "DISABLED"})
|
||||
|
||||
resp, _ = http_client.do_request(
|
||||
'{base_path}/{id}'.format(id=package_uuid,
|
||||
base_path=self.base_url),
|
||||
"PATCH", content_type='application/json',
|
||||
body=update_req_body)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def assert_vnf_package_usage_state(
|
||||
self,
|
||||
vnf_package_info,
|
||||
expected_usage_state=fields.PackageUsageStateType.IN_USE):
|
||||
self.assertEqual(
|
||||
expected_usage_state,
|
||||
vnf_package_info['usageState'])
|
||||
|
||||
def assert_create_vnf(self, resp, vnf_instance, vnf_pkg_id,
|
||||
tacker_client, fake_server_manager):
|
||||
super().assert_create_vnf(resp, vnf_instance,
|
||||
fake_server_manager)
|
||||
|
||||
resp, vnf_pkg_info = vnflcm_base._show_vnf_package(
|
||||
tacker_client, vnf_pkg_id)
|
||||
self.assert_vnf_package_usage_state(vnf_pkg_info)
|
||||
|
||||
def _vnf_instance_wait_until_fail_detected(self, id,
|
||||
instantiation_state=fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
timeout=vnflcm_base.VNF_INSTANTIATE_ERROR_WAIT):
|
||||
time.sleep(timeout)
|
||||
_, body = self._show_vnf_instance(id)
|
||||
if body['instantiationState'] != instantiation_state:
|
||||
error = ("Vnf instance %(id)s status is %(current)s, "
|
||||
"expected status should be %(expected)s")
|
||||
self.fail(error % {"id": id,
|
||||
"current": body['instantiationState'],
|
||||
"expected": instantiation_state})
|
||||
|
||||
def test_subscription_functionality(self):
|
||||
"""Test subscription operations with member role users.
|
||||
|
||||
In this test case, we do following steps.
|
||||
Note: User A belongs to Tenant 1(t1).
|
||||
User B belongs to Tenant 2(t2).
|
||||
- Create subscription.
|
||||
- User A registers Subscription A(Notification Server A).
|
||||
- User B registers Subscription B(Notification Server B).
|
||||
- Show Subscription
|
||||
- User A only gets information about Subscription A.
|
||||
- User B only gets information about Subscription B.
|
||||
- List Subscription
|
||||
- User A gets subscription list and confirms only
|
||||
Subscription A is output.
|
||||
- User B gets subscription list and confirms only
|
||||
Subscription B is output.
|
||||
- Delete Subscription
|
||||
- User A deletes Subscription A.
|
||||
- User B deletes Subscription B.
|
||||
TODO(manpreetk): Only positive test cases are validated in
|
||||
Y-release.
|
||||
Negative test cases
|
||||
- User A fails to delete Subscription B.
|
||||
- User B fails to delete Subscription A.
|
||||
Validation of negative test cases would require design changes
|
||||
in Fake NFVO server, which could be implemented in the upcoming
|
||||
cycle.
|
||||
"""
|
||||
# Create subscription
|
||||
# User A registers Subscription A.
|
||||
callback_url = os.path.join(vnflcm_base.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
req_body = fake_vnflcm.Subscription.make_create_request_body(
|
||||
'http://localhost:{}{}'.format(
|
||||
base.FAKE_SERVER_MANAGER_T1.SERVER_PORT_T1,
|
||||
callback_url))
|
||||
resp_t1, resp_body_t1 = self._register_subscription(req_body,
|
||||
self.http_client_tenant1)
|
||||
self.assertEqual(201, resp_t1.status_code)
|
||||
self.assert_http_header_location_for_subscription(
|
||||
resp_t1.headers)
|
||||
self.assert_notification_get(callback_url,
|
||||
base.FAKE_SERVER_MANAGER_T1)
|
||||
subscription_id_t1 = resp_body_t1.get('id')
|
||||
|
||||
# User B registers Subscription B
|
||||
callback_url = os.path.join(vnflcm_base.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
req_body_t2 = fake_vnflcm.Subscription.make_create_request_body(
|
||||
'http://localhost:{}{}'.format(
|
||||
base.FAKE_SERVER_MANAGER_T2.SERVER_PORT_T2,
|
||||
callback_url))
|
||||
resp_t2, resp_body_t2 = self._register_subscription(
|
||||
req_body_t2, self.http_client_tenant2)
|
||||
self.assertEqual(201, resp_t2.status_code)
|
||||
self.assert_http_header_location_for_subscription(
|
||||
resp_t2.headers)
|
||||
self.assert_notification_get(callback_url,
|
||||
base.FAKE_SERVER_MANAGER_T2)
|
||||
subscription_id_t2 = resp_body_t2.get('id')
|
||||
|
||||
# Show Subscription
|
||||
# User A gets information for Subscription A
|
||||
resp_t1, resp_body_show_t1 = self._wait_show_subscription(
|
||||
subscription_id_t1, self.tacker_client_t1)
|
||||
self.assert_subscription_show(resp_t1, resp_body_show_t1)
|
||||
|
||||
# User B gets information for Subscription B
|
||||
resp_t2, resp_body_show_t2 = self._wait_show_subscription(
|
||||
subscription_id_t2, self.tacker_client_t2)
|
||||
self.assert_subscription_show(resp_t2, resp_body_show_t2)
|
||||
|
||||
# List Subscription
|
||||
# User A gets subscription list
|
||||
resp, _ = self._list_subscription(self.tacker_client_t1)
|
||||
self.assertEqual(200, resp_t1.status_code)
|
||||
|
||||
# Confirm subscription A
|
||||
filter_expr = {
|
||||
'filter': "filter=(eq,id,{})".format(
|
||||
resp_body_show_t1.get('id'))}
|
||||
resp, subscription_body_t1 = self._list_subscription_filter(
|
||||
self.http_client_tenant1,
|
||||
params=filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(1, len(subscription_body_t1))
|
||||
|
||||
# User B gets subscription list
|
||||
resp_t2, _ = self._list_subscription(
|
||||
self.tacker_client_t2)
|
||||
self.assertEqual(200, resp_t2.status_code)
|
||||
|
||||
# Confirm subscription B
|
||||
filter_expr = {
|
||||
'filter': "filter=(eq,id,{})".format(
|
||||
resp_body_show_t2.get('id'))}
|
||||
resp, subscription_body_t2 = self._list_subscription_filter(
|
||||
self.http_client_tenant2,
|
||||
params=filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(1, len(subscription_body_t2))
|
||||
|
||||
# Delete subscription
|
||||
# User A deletes Subscription A
|
||||
self.addCleanup(self._delete_subscription,
|
||||
subscription_id_t1, self.tacker_client_t1)
|
||||
|
||||
# User B deletes Subscription B
|
||||
self.addCleanup(self._delete_subscription,
|
||||
subscription_id_t2, self.tacker_client_t2)
|
||||
|
||||
def test_vnf_package_functionality(self):
|
||||
"""Test VNF package operations with member role users.
|
||||
|
||||
In this test case, we do following steps.
|
||||
Note: User A belongs to Tenant 1.
|
||||
User B belongs to Tenant 2.
|
||||
- Create and Upload VNF Package
|
||||
- User A creates VNF Package A.
|
||||
- User A uploads VNF Package A.
|
||||
- User B creates VNF Package B.
|
||||
- User B uploads VNF Package B.
|
||||
- List VNF Package
|
||||
- User A gets VNF package list and confirms only
|
||||
VNF Package A is output.
|
||||
- User B gets VNF package list and confirms only
|
||||
VNF Package B is output.
|
||||
- Show VNF Package
|
||||
- User A only gets information about VNF Package A.
|
||||
- User B only gets information about VNF Package B.
|
||||
- Delete VNF Package
|
||||
- User A deletes VNF Package A.
|
||||
- User B deletes VNF Package B.
|
||||
TODO(manpreetk): Only positive test cases are validated in
|
||||
Y-release.
|
||||
Negative test cases
|
||||
- User A fails to delete VNF Package B.
|
||||
- User B fails to delete VNF Package A.
|
||||
Validation of negative test cases would require design changes
|
||||
in Fake NFVO server, which could be implemented in the upcoming
|
||||
cycle.
|
||||
"""
|
||||
# Create and Upload VNF Package
|
||||
# User A creates VNF Package A
|
||||
sample_name = 'mt_functional1'
|
||||
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)
|
||||
|
||||
# User A uploads VNF Package A
|
||||
vnf_pkg_id, vnfd_id = vnflcm_base._create_and_upload_vnf_package(
|
||||
self.tacker_client_t1, user_defined_data={
|
||||
"key": sample_name}, temp_csar_path=tempname)
|
||||
|
||||
# User B creates VNF Package B
|
||||
sample_name_t2 = 'mt_functional1'
|
||||
csar_package_path_t2 = os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"../../../etc/samples/etsi/nfv",
|
||||
sample_name_t2))
|
||||
tempname_t2, _ = vnflcm_base._create_csar_with_unique_vnfd_id(
|
||||
csar_package_path_t2)
|
||||
|
||||
# User B uploads VNF Package B
|
||||
vnf_pkg_id2, vnfd_id2 = vnflcm_base._create_and_upload_vnf_package(
|
||||
self.tacker_client_t2, user_defined_data={
|
||||
"key": sample_name_t2}, temp_csar_path=tempname_t2)
|
||||
|
||||
# List VNF Package
|
||||
# User A gets VNF package list and confirms only VNF Package A
|
||||
# is output.
|
||||
resp, body = self.http_client_tenant1.do_request(
|
||||
self.base_url, "GET")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
package_id = [obj['id'] for obj in body]
|
||||
self.assertIn(vnf_pkg_id, package_id)
|
||||
|
||||
# User B gets VNF package list and confirms only VNF Package B
|
||||
# is output.
|
||||
resp_t2, body_t2 = self.http_client_tenant2.do_request(
|
||||
self.base_url, "GET")
|
||||
self.assertEqual(200, resp_t2.status_code)
|
||||
|
||||
package_id = [obj['id'] for obj in body_t2]
|
||||
self.assertIn(vnf_pkg_id2, package_id)
|
||||
|
||||
# Show VNF Package
|
||||
# User A only gets information about VNF Package A
|
||||
show_url = os.path.join(self.base_url, vnf_pkg_id)
|
||||
resp, body = self.http_client_tenant1.do_request(
|
||||
show_url, "GET")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# User B only gets information about VNF Package B
|
||||
show_url_t2 = os.path.join(self.base_url, vnf_pkg_id2)
|
||||
resp_t2, body_t2 = self.http_client_tenant2.do_request(
|
||||
show_url_t2, "GET")
|
||||
self.assertEqual(200, resp_t2.status_code)
|
||||
|
||||
# Delete VNF Package
|
||||
# User A deletes VNF Package A
|
||||
self._disable_operational_state(vnf_pkg_id,
|
||||
self.http_client_tenant1)
|
||||
self._delete_vnf_package(vnf_pkg_id, self.http_client_tenant1)
|
||||
self._wait_for_delete(vnf_pkg_id, self.http_client_tenant1)
|
||||
|
||||
# User B deletes VNF Package B
|
||||
self._disable_operational_state(vnf_pkg_id2,
|
||||
self.http_client_tenant2)
|
||||
self._delete_vnf_package(vnf_pkg_id2, self.http_client_tenant2)
|
||||
self._wait_for_delete(vnf_pkg_id2, self.http_client_tenant2)
|
||||
|
||||
def test_vnf_instantiation_by_vim_of_different_tenant_and_role(self):
|
||||
"""Test VNF instantiation by VIM of differnt tenant.
|
||||
|
||||
In this test case, we do following steps.
|
||||
Note: User A is an admin role user belongs to Tenant 1.
|
||||
User B is a non-admin role user belongs to Tenant 2.
|
||||
- Create VNF Instance
|
||||
- User B creates VNF Instance B using VNF Package B.
|
||||
- Instantiate VNF
|
||||
- User A fails to instantiates VNF Instance B, both
|
||||
VNF and VIM belong to different tenant.
|
||||
"""
|
||||
# Pre-Setting
|
||||
# User B registers Subscription B.
|
||||
callback_url = os.path.join(vnflcm_base.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
req_body_t2 = fake_vnflcm.Subscription.make_create_request_body(
|
||||
'http://localhost:{}{}'.format(
|
||||
base.FAKE_SERVER_MANAGER_T2.SERVER_PORT_T2,
|
||||
callback_url))
|
||||
resp_t2, resp_body_t2 = self._register_subscription(
|
||||
req_body_t2, self.http_client_tenant2)
|
||||
self.assertEqual(201, resp_t2.status_code)
|
||||
self.assert_http_header_location_for_subscription(
|
||||
resp_t2.headers)
|
||||
self.assert_notification_get(callback_url,
|
||||
base.FAKE_SERVER_MANAGER_T2)
|
||||
subscription_id_t2 = resp_body_t2.get('id')
|
||||
self.addCleanup(
|
||||
self._delete_subscription,
|
||||
subscription_id_t2,
|
||||
self.tacker_client_t2)
|
||||
|
||||
# Create and Upload VNF Package
|
||||
# User B creates VNF Package B
|
||||
sample_name_t2 = 'mt_functional1'
|
||||
csar_package_path_t2 = os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"../../../etc/samples/etsi/nfv",
|
||||
sample_name_t2))
|
||||
tempname_t2, _ = vnflcm_base._create_csar_with_unique_vnfd_id(
|
||||
csar_package_path_t2)
|
||||
|
||||
# User B uploads VNF Package B
|
||||
vnf_pkg_id, vnfd_id = vnflcm_base._create_and_upload_vnf_package(
|
||||
self.tacker_client_t2, user_defined_data={
|
||||
"key": sample_name_t2}, temp_csar_path=tempname_t2)
|
||||
|
||||
# Post Setting: Reserve deleting VNF package.
|
||||
self.addCleanup(vnflcm_base._delete_vnf_package,
|
||||
self.tacker_client_t2, vnf_pkg_id)
|
||||
|
||||
# Create VNF Instance
|
||||
# User B creates VNF Instance B using VNF Package B
|
||||
resp_t2, vnf_instance_t2 = self._create_vnf_instance_from_body(
|
||||
fake_vnflcm.VnfInstances.make_create_request_body(vnfd_id),
|
||||
self.http_client_tenant2)
|
||||
vnf_instance_id_t2 = vnf_instance_t2.get('id')
|
||||
self._wait_lcm_done(vnf_instance_id=vnf_instance_id_t2,
|
||||
fake_server_manager=base.FAKE_SERVER_MANAGER_T2)
|
||||
self.assert_create_vnf(resp_t2, vnf_instance_t2,
|
||||
vnf_pkg_id,
|
||||
self.tacker_client_t2,
|
||||
base.FAKE_SERVER_MANAGER_T2)
|
||||
|
||||
# Instantiate VNF instance
|
||||
# User A fails to instantiate VNF Instance B as both VIM and VNF
|
||||
# belongs to differernt tenants
|
||||
request_body = fake_vnflcm.VnfInstances.make_inst_request_body(
|
||||
'nfv_user',
|
||||
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_t2,
|
||||
request_body, self.http_client)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self._vnf_instance_wait_until_fail_detected(vnf_instance_id_t2)
|
|
@ -88,6 +88,7 @@ auth_url: "${VIMC_ENDPOINT}"
|
|||
username: "${VIMC_OS_USER}"
|
||||
password: "${VIMC_OS_PASSWORD}"
|
||||
project_name: "${VIMC_PROJ}"
|
||||
domain_name: "${VIMC_OS_PROJ_DOMAIN}"
|
||||
project_domain_name: "${VIMC_OS_PROJ_DOMAIN}"
|
||||
user_domain_name: "${VIMC_OS_USER_DOMAIN}"
|
||||
cert_verify: "${_cert_verify}"
|
||||
|
|
6
tox.ini
6
tox.ini
|
@ -61,6 +61,12 @@ setenv = {[testenv]setenv}
|
|||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2 run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-multi-tenant]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_multi_tenant run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
|
|
Loading…
Reference in New Issue