Reduce the amount of time of Tacker v2 functional tests
This fix is for improving v2 functional tests by reducing the cost of tests on zuul. It implements (1), (2) and (4) as proposed in the following Spec: * https://review.opendev.org/c/openstack/tacker-specs/+/932974 * (1)Divide time consuming tests * tacker-functional-devstack-multinode-sol-v2-basic * tacker-ft-v2-df-userdata-ccvp * tacker-ft-v2-st-userdata-basic * tacker-ft-v2-st-userdata-ccvp * tacker-functional-devstack-multinode-sol-v2-vnflcm * tacker-ft-v2-df-userdata-basic-max * tacker-ft-v2-df-userdata-basic-min * tacker-ft-v2-df-userdata-update * tacker-ft-v2-df-userdata-scale * tacker-ft-v2-df-userdata-err-handling * tacker-functional-devstack-multinode-sol-v2-individual-vnfc-mgmt * tacker-ft-v2-st-userdata-basic-max * tacker-ft-v2-st-userdata-basic-min * tacker-ft-v2-st-userdata-err-handling * tacker-ft-v2-st-userdata-various-lcm * (2)Move tests less frequently updated to move to non-voting * tacker-functional-devstack-multinode-sol-v2-notification * tacker-functional-devstack-multinode-sol-v2-prometheus * tacker-functional-devstack-multinode-sol-separated-nfvo-v2 * tacker-functional-devstack-multinode-sol-https-v2 * tacker-functional-devstack-multinode-sol-encrypt-cred-barbican * tacker-functional-devstack-multinode-sol-encrypt-cred-local * tacker-functional-devstack-kubernetes-oidc-auth * tacker-functional-devstack-multinode-sol-v2-az-retry * tacker-functional-devstack-enhanced-policy-sol * tacker-functional-devstack-enhanced-policy-sol-kubernetes * tacker-functional-devstack-multinode-sol-terraform-v2 * (4)Rename each test scenarios and revise directory structure Implements: blueprint reduce-ft-time Change-Id: I98efef94b779a6a07a8841a85f6b7ba877f50444 Depends-On: I2deb71242f555bbae5ee7c798add18490cb38344
This commit is contained in:
parent
f41acdc698
commit
5c29fafc5f
846
.zuul.yaml
846
.zuul.yaml
@ -1,846 +0,0 @@
|
||||
- nodeset:
|
||||
name: openstack-4-nodes-jammy
|
||||
nodes:
|
||||
- name: controller
|
||||
label: ubuntu-jammy
|
||||
- name: controller-tacker
|
||||
label: ubuntu-jammy
|
||||
- name: compute1
|
||||
label: ubuntu-jammy
|
||||
- name: compute2
|
||||
label: ubuntu-jammy
|
||||
groups:
|
||||
# Nodes running the compute service
|
||||
- name: compute
|
||||
nodes:
|
||||
- compute1
|
||||
- compute2
|
||||
# Nodes that are not the controller
|
||||
- name: subnode
|
||||
nodes:
|
||||
- controller-tacker
|
||||
- compute1
|
||||
- compute2
|
||||
# Switch node for multinode networking setup
|
||||
- name: switch
|
||||
nodes:
|
||||
- controller
|
||||
# Peer nodes for multinode networking setup
|
||||
- name: peers
|
||||
nodes:
|
||||
- controller-tacker
|
||||
- compute1
|
||||
- compute2
|
||||
|
||||
- nodeset:
|
||||
name: openstack-k8s-3-nodes-jammy
|
||||
nodes:
|
||||
- name: controller
|
||||
label: ubuntu-jammy
|
||||
- name: controller-tacker
|
||||
label: ubuntu-jammy
|
||||
- name: controller-k8s
|
||||
label: ubuntu-jammy
|
||||
groups:
|
||||
- name: subnode
|
||||
nodes:
|
||||
- controller-tacker
|
||||
- controller-k8s
|
||||
- name: switch
|
||||
nodes:
|
||||
- controller
|
||||
- name: peers
|
||||
nodes:
|
||||
- controller-tacker
|
||||
- controller-k8s
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-parent
|
||||
parent: devstack
|
||||
description: |
|
||||
Abstraction multinodes job for SOL devstack-based functional tests
|
||||
nodeset: openstack-4-nodes-jammy
|
||||
pre-run: playbooks/devstack/pre.yaml
|
||||
run: playbooks/devstack/run.yaml
|
||||
post-run: playbooks/devstack/post.yaml
|
||||
roles:
|
||||
- zuul: openstack-infra/devstack
|
||||
timeout: 10800
|
||||
required-projects:
|
||||
- openstack/cinder
|
||||
- openstack/glance
|
||||
- openstack/keystone
|
||||
- openstack/neutron
|
||||
- openstack/nova
|
||||
- openstack/placement
|
||||
- openstack/aodh
|
||||
- openstack/horizon
|
||||
- openstack/barbican
|
||||
- openstack/heat
|
||||
- openstack/networking-sfc
|
||||
- openstack/python-barbicanclient
|
||||
- openstack/python-tackerclient
|
||||
- openstack/tacker
|
||||
- openstack/tacker-horizon
|
||||
vars:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
DATABASE_TYPE: mysql
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
GNOCCHI_SERVICE_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
Q_SERVICE_PLUGIN_CLASSES: ovn-router,networking_sfc.services.flowclassifier.plugin.FlowClassifierPlugin,neutron.services.qos.qos_plugin.QoSPlugin,qos
|
||||
L2_AGENT_EXTENSIONS: qos
|
||||
DEVSTACK_PARALLEL: True
|
||||
OVN_L3_CREATE_PUBLIC_NETWORK: true
|
||||
OVN_DBS_LOG_LEVEL: dbg
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
test_matrix_configs: [neutron]
|
||||
zuul_work_dir: src/opendev.org/openstack/tacker
|
||||
host-vars:
|
||||
controller:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
# NOTE: workaround for Heat timeout due to communication
|
||||
# problem between nova and neutron.
|
||||
$NEUTRON_CONF:
|
||||
DEFAULT:
|
||||
client_socket_timeout: 60
|
||||
$NEUTRON_DHCP_CONF:
|
||||
DEFAULT:
|
||||
enable_isolated_metadata: True
|
||||
# NOTE: workaround for Cinder image volume cache problem.
|
||||
# https://bugs.launchpad.net/cinder/+bug/1953704
|
||||
$CINDER_CONF:
|
||||
lvmdriver-1:
|
||||
image_volume_cache_enabled: False
|
||||
devstack_plugins:
|
||||
heat: https://opendev.org/openstack/heat
|
||||
networking-sfc: https://opendev.org/openstack/networking-sfc
|
||||
aodh: https://opendev.org/openstack/aodh
|
||||
barbican: https://opendev.org/openstack/barbican
|
||||
devstack_services:
|
||||
# Core services enabled for this branch.
|
||||
# This list replaces the test-matrix.
|
||||
# Shared services
|
||||
mysql: true
|
||||
rabbit: true
|
||||
tls-proxy: false
|
||||
# Keystone services
|
||||
key: true
|
||||
# Glance services
|
||||
g-api: true
|
||||
# Nova services
|
||||
n-api: true
|
||||
n-api-meta: true
|
||||
n-cond: true
|
||||
n-cpu: false
|
||||
n-novnc: true
|
||||
n-sch: true
|
||||
placement-api: true
|
||||
# OVN services
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
# Neutron services
|
||||
q-svc: true
|
||||
q-qos: true
|
||||
q-ovn-metadata-agent: true
|
||||
# Cinder services
|
||||
c-api: true
|
||||
c-sch: true
|
||||
c-vol: true
|
||||
cinder: true
|
||||
# Services we don't need.
|
||||
# This section is not really needed, it's for readability.
|
||||
horizon: false
|
||||
tempest: false
|
||||
swift: false
|
||||
s-account: false
|
||||
s-container: false
|
||||
s-object: false
|
||||
s-proxy: false
|
||||
c-bak: false
|
||||
tox_install_siblings: false
|
||||
controller-tacker:
|
||||
devstack_plugins:
|
||||
tacker: https://opendev.org/openstack/tacker
|
||||
devstack_services:
|
||||
# OVN services
|
||||
ovn-controller: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
# Neutron services
|
||||
q-ovn-metadata-agent: true
|
||||
# Tacker services
|
||||
tacker: true
|
||||
tacker-conductor: true
|
||||
group-vars:
|
||||
compute:
|
||||
# Since a VirtualInterfaceCreateException occurs during a test,
|
||||
# the setting of network-vif-plugged is changed by the reference of
|
||||
# the following URL.
|
||||
# https://bugs.launchpad.net/heat/+bug/1694371
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$NOVA_CONF:
|
||||
DEFAULT:
|
||||
vif_plugging_is_fatal: False
|
||||
subnode:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
DATABASE_TYPE: mysql
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
GNOCCHI_SERVICE_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_MODE: standalone
|
||||
IS_ZUUL_FT: True
|
||||
Q_SERVICE_PLUGIN_CLASSES: "qos,\
|
||||
networking_sfc.services.flowclassifier.plugin.FlowClassifierPlugin,\
|
||||
neutron.services.qos.qos_plugin.QoSPlugin,\
|
||||
ovn-router"
|
||||
L2_AGENT_EXTENSIONS: qos
|
||||
ENABLE_CHASSIS_AS_GW: false
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
devstack_services:
|
||||
# To override the parent job's definitions.
|
||||
tls-proxy: false
|
||||
# OVN services
|
||||
ovn-controller: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
# Neutron services
|
||||
q-ovn-metadata-agent: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-legacy-nfvo
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests for legacy_nfvo
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol-legacy-nfvo
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-vnflcm
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests for vnflcm
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
database:
|
||||
max_pool_size: 0
|
||||
tox_envlist: dsvm-functional-sol-vnflcm
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-vnflcm-userdata
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests for vnflcm with userdata
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
database:
|
||||
max_pool_size: 0
|
||||
tox_envlist: dsvm-functional-sol-vnflcm-userdata
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-vnfpkgm
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests for vnfpkgm
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol-vnfpkgm
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-v2-basic
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL V2 devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
server_notification:
|
||||
server_notification: true
|
||||
prometheus_plugin:
|
||||
auto_scaling: true
|
||||
auto_healing: true
|
||||
v2_vnfm:
|
||||
# Notes: The List API will return 'Link' Header in response
|
||||
# body only if page_size is not 0. This job will check 'Link'
|
||||
# Header, so these page_size parameters are set to 1.
|
||||
vnf_instance_page_size: 1
|
||||
lcm_op_occ_page_size: 1
|
||||
tox_envlist: dsvm-functional-sol-v2-basic
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-v2-vnflcm
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL V2 devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
server_notification:
|
||||
server_notification: true
|
||||
prometheus_plugin:
|
||||
auto_scaling: true
|
||||
auto_healing: true
|
||||
tox_envlist: dsvm-functional-sol-v2-vnflcm
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-v2-notification
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL V2 devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
server_notification:
|
||||
server_notification: true
|
||||
tox_envlist: dsvm-functional-sol-v2-notification
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-v2-prometheus
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL V2 devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
prometheus_plugin:
|
||||
auto_scaling: true
|
||||
auto_healing: true
|
||||
tox_envlist: dsvm-functional-sol-v2-prometheus
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-multi-tenant
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL Multi tenant devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol-multi-tenant
|
||||
vars:
|
||||
setup_multi_tenant: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-separated-nfvo
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests
|
||||
with separated NFVO
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
connect_vnf_packages:
|
||||
base_url: http://127.0.0.1:9990/vnfpkgm/v1/vnf_packages
|
||||
pipeline: package_content,vnfd,artifacts
|
||||
connect_grant:
|
||||
base_url: http://127.0.0.1:9990/grant/v1/grants
|
||||
openstack_vim:
|
||||
stack_retries: 120
|
||||
tox_envlist: dsvm-functional-sol-separated-nfvo
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-separated-nfvo-v2
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests
|
||||
with separated V2 NFVO
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_nfvo:
|
||||
use_external_nfvo: True
|
||||
endpoint: http://127.0.0.1:9990
|
||||
token_endpoint: http://127.0.0.1:9990/token
|
||||
client_id: 229ec984de7547b2b662e968961af5a4
|
||||
client_password: devstack
|
||||
use_client_secret_basic: True
|
||||
tox_envlist: dsvm-functional-sol-separated-nfvo-v2
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-v2-individual-vnfc-mgmt
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinode job for SOL V2 devstack-based individual vnfc mgmt functional
|
||||
tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_vnfm:
|
||||
# Notes: The List API will return 'Link' Header in response
|
||||
# body only if page_size is not 0. This job will check 'Link'
|
||||
# Header, so these page_size parameters are set to 1.
|
||||
vnf_instance_page_size: 1
|
||||
lcm_op_occ_page_size: 1
|
||||
tox_envlist: dsvm-functional-sol-v2-individual-vnfc-mgmt
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-kubernetes-parent
|
||||
parent: devstack
|
||||
description: |
|
||||
Abstraction multinodes job for SOL devstack-based kubernetes functional
|
||||
tests
|
||||
nodeset: openstack-k8s-3-nodes-jammy
|
||||
pre-run: playbooks/devstack/pre.yaml
|
||||
run: playbooks/devstack/run.yaml
|
||||
post-run: playbooks/devstack/post.yaml
|
||||
roles:
|
||||
- zuul: openstack-infra/devstack
|
||||
timeout: 10800
|
||||
required-projects:
|
||||
- openstack/barbican
|
||||
- openstack/cinder
|
||||
- openstack/devstack-plugin-container
|
||||
- openstack/glance
|
||||
- openstack/heat
|
||||
- openstack/horizon
|
||||
- openstack/keystone
|
||||
- openstack/neutron
|
||||
- openstack/nova
|
||||
- openstack/placement
|
||||
- openstack/python-barbicanclient
|
||||
- openstack/python-tackerclient
|
||||
- openstack/tacker
|
||||
- openstack/tacker-horizon
|
||||
host-vars:
|
||||
controller:
|
||||
devstack_plugins:
|
||||
barbican: https://opendev.org/openstack/barbican
|
||||
heat: https://opendev.org/openstack/heat
|
||||
neutron: https://opendev.org/openstack/neutron
|
||||
devstack_services:
|
||||
base: false
|
||||
c-api: true
|
||||
c-bak: false
|
||||
c-sch: true
|
||||
c-vol: true
|
||||
cinder: true
|
||||
coredns: false
|
||||
etcd3: true
|
||||
g-api: true
|
||||
g-reg: true
|
||||
horizon: false
|
||||
key: true
|
||||
mysql: true
|
||||
n-api-meta: true
|
||||
n-api: true
|
||||
n-cond: true
|
||||
n-cpu: false
|
||||
n-novnc: true
|
||||
n-sch: true
|
||||
neutron: true
|
||||
placement-api: true
|
||||
placement-client: true
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-qos: true
|
||||
q-svc: true
|
||||
q-ovn-metadata-agent: true
|
||||
rabbit: true
|
||||
s-account: false
|
||||
s-container: false
|
||||
s-object: false
|
||||
s-proxy: false
|
||||
swift: false
|
||||
tempest: false
|
||||
tls-proxy: false
|
||||
tox_install_siblings: false
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
kubernetes_vim:
|
||||
stack_retries: 120
|
||||
devstack_services:
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-ovn-metadata-agent: true
|
||||
tacker: true
|
||||
tacker-conductor: true
|
||||
devstack_plugins:
|
||||
tacker: https://opendev.org/openstack/tacker
|
||||
controller-k8s:
|
||||
devstack_local_conf: {}
|
||||
devstack_plugins:
|
||||
devstack-plugin-container: https://opendev.org/openstack/devstack-plugin-container
|
||||
devstack_services:
|
||||
etcd3: false
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-ovn-metadata-agent: true
|
||||
container: true
|
||||
k8s-master: true
|
||||
tox_install_siblings: false
|
||||
group-vars:
|
||||
subnode:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
DATABASE_TYPE: mysql
|
||||
IS_ZUUL_FT: True
|
||||
K8S_API_SERVER_IP: "{{ hostvars['controller-k8s']['nodepool']['private_ipv4'] }}"
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
CONTAINER_ENGINE: crio
|
||||
K8S_VERSION: "1.30.5"
|
||||
CRIO_VERSION: "1.30.5"
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
TACKER_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_MODE: standalone
|
||||
USE_PYTHON3: true
|
||||
ENABLE_CHASSIS_AS_GW: false
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
# TODO(ueha): Remove this workarround if the Zuul jobs succeed with GLOBAL_VENV=true
|
||||
GLOBAL_VENV: false
|
||||
K8S_TOKEN: "9agf12.zsu5uh2m4pzt3qba"
|
||||
devstack_services:
|
||||
dstat: false
|
||||
horizon: false
|
||||
n-api-meta: false
|
||||
n-api: false
|
||||
n-cauth: false
|
||||
n-cond: false
|
||||
n-cpu: true
|
||||
n-novnc: false
|
||||
n-obj: false
|
||||
n-sch: false
|
||||
ovn-controller: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-ovn-metadata-agent: true
|
||||
tls-proxy: false
|
||||
vars:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
DATABASE_TYPE: mysql
|
||||
ETCD_USE_RAMDISK: true
|
||||
IS_ZUUL_FT: True
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
L2_AGENT_EXTENSIONS: qos
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
Q_SERVICE_PLUGIN_CLASSES: ovn-router,neutron.services.qos.qos_plugin.QoSPlugin,qos
|
||||
TACKER_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_MODE: standalone
|
||||
USE_PYTHON3: true
|
||||
DEVSTACK_PARALLEL: True
|
||||
OVN_L3_CREATE_PUBLIC_NETWORK: true
|
||||
OVN_DBS_LOG_LEVEL: dbg
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
# TODO(ueha): Remove this workarround if the Zuul jobs succeed with GLOBAL_VENV=true
|
||||
GLOBAL_VENV: false
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$NEUTRON_DHCP_CONF:
|
||||
DEFAULT:
|
||||
enable_isolated_metadata: True
|
||||
k8s_api_url: "https://{{ hostvars['controller-k8s']['nodepool']['private_ipv4'] }}:6443"
|
||||
k8s_ssl_verify: true
|
||||
helm_version: "3.15.4"
|
||||
test_matrix_configs: [neutron]
|
||||
zuul_work_dir: src/opendev.org/openstack/tacker
|
||||
zuul_copy_output:
|
||||
'{{ devstack_log_dir }}/kubernetes': 'logs'
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-kubernetes
|
||||
parent: tacker-functional-devstack-multinode-sol-kubernetes-parent
|
||||
description: |
|
||||
Multinodes job for SOL Kubernetes Multi tenant devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
database:
|
||||
max_pool_size: 0
|
||||
tox_envlist: dsvm-functional-sol-kubernetes
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-kubernetes-multi-tenant
|
||||
parent: tacker-functional-devstack-multinode-sol-kubernetes-parent
|
||||
description: |
|
||||
Multinodes job for SOL Kubernetes Multi tenant devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol-kubernetes-multi-tenant
|
||||
vars:
|
||||
setup_multi_tenant: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-kubernetes-v2
|
||||
parent: tacker-functional-devstack-multinode-sol-kubernetes-parent
|
||||
description: |
|
||||
Multinodes job for SOL Kubernetes V2 devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_vnfm:
|
||||
kubernetes_vim_rsc_wait_timeout: 800
|
||||
prometheus_plugin:
|
||||
fault_management: true
|
||||
performance_management: true
|
||||
auto_scaling: true
|
||||
auto_healing: true
|
||||
test_rule_with_promtool: true
|
||||
tox_envlist: dsvm-functional-sol-kubernetes-v2
|
||||
vars:
|
||||
prometheus_setup: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-https-v2
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests
|
||||
with https request
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_vnfm:
|
||||
notification_verify_cert: true
|
||||
notification_ca_cert_file: /etc/https_server/ssl/ca.crt
|
||||
use_oauth2_mtls_for_heat: false
|
||||
heat_verify_cert: true
|
||||
heat_ca_cert_file: /etc/https_server/ssl/ca.crt
|
||||
prometheus_plugin:
|
||||
fault_management: true
|
||||
performance_management: true
|
||||
auto_scaling: true
|
||||
performance_management_package: tacker.sol_refactored.common.monitoring_plugin_base
|
||||
performance_management_class: MonitoringPluginStub
|
||||
v2_nfvo:
|
||||
use_external_nfvo: true
|
||||
endpoint: https://localhost:9990
|
||||
token_endpoint: https://localhost:9990/token
|
||||
client_id: 229ec984de7547b2b662e968961af5a4
|
||||
client_password: devstack
|
||||
nfvo_verify_cert: true
|
||||
nfvo_ca_cert_file: /etc/https_server/ssl/ca.crt
|
||||
use_client_secret_basic: true
|
||||
tox_envlist: dsvm-functional-sol-https-v2
|
||||
vars:
|
||||
https_setup: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-encrypt-cred-barbican
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests
|
||||
with encrypt credentials
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
DEFAULT:
|
||||
use_credential_encryption: true
|
||||
keymanager_type: "barbican"
|
||||
v2_nfvo:
|
||||
use_external_nfvo: true
|
||||
endpoint: https://localhost:9990
|
||||
token_endpoint: https://localhost:9990/token
|
||||
client_id: 229ec984de7547b2b662e968961af5a4
|
||||
client_password: devstack
|
||||
nfvo_ca_cert_file: /etc/https_server/ssl/ca.crt
|
||||
nfvo_verify_cert: true
|
||||
use_client_secret_basic: true
|
||||
tox_envlist: dsvm-functional-sol-encrypt-cred-barbican
|
||||
vars:
|
||||
https_setup: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-encrypt-cred-local
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based functional tests
|
||||
with encrypt credentials
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
DEFAULT:
|
||||
use_credential_encryption: true
|
||||
keymanager_type: "local"
|
||||
crypt_key_dir: "/etc/tacker/crypt/fernet_keys"
|
||||
v2_nfvo:
|
||||
use_external_nfvo: true
|
||||
endpoint: https://localhost:9990
|
||||
token_endpoint: https://localhost:9990/token
|
||||
client_id: 229ec984de7547b2b662e968961af5a4
|
||||
client_password: devstack
|
||||
nfvo_ca_cert_file: /etc/https_server/ssl/ca.crt
|
||||
nfvo_verify_cert: true
|
||||
use_client_secret_basic: true
|
||||
tox_envlist: dsvm-functional-sol-encrypt-cred-local
|
||||
vars:
|
||||
https_setup: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-kubernetes-oidc-auth
|
||||
parent: tacker-functional-devstack-multinode-sol-kubernetes-v2
|
||||
description: |
|
||||
Multinodes job for Kubernetes OIDC Auth tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol_kubernetes_oidc_auth
|
||||
vars:
|
||||
keycloak_host: "{{ hostvars['controller-k8s']['nodepool']['private_ipv4'] }}"
|
||||
keycloak_http_port: 8080
|
||||
keycloak_https_port: 8443
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-v2-az-retry
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for retry of AZ selection in SOL V2 devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_nfvo:
|
||||
test_grant_zone_list: az-1
|
||||
v2_vnfm:
|
||||
placement_fallback_best_effort: true
|
||||
enable_rollback_stack: true
|
||||
devstack_services:
|
||||
n-cpu: true
|
||||
placement-client: true
|
||||
tox_envlist: dsvm-functional-sol-v2-az-retry
|
||||
vars:
|
||||
setup_multi_az: true
|
||||
controller_tacker_hostname: "{{ hostvars['controller-tacker']['ansible_hostname'] }}"
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-enhanced-policy-sol
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Enhanced policy job for SOL devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-enhanced-policy-sol
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
oslo_policy:
|
||||
enhanced_tacker_policy: True
|
||||
vars:
|
||||
config_enhanced_policy: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-enhanced-policy-sol-kubernetes
|
||||
parent: tacker-functional-devstack-multinode-sol-kubernetes-v2
|
||||
description: |
|
||||
Enhanced policy job for SOL Kubernetes devstack-based functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-enhanced-policy-sol-kubernetes
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
oslo_policy:
|
||||
enhanced_tacker_policy: True
|
||||
vars:
|
||||
config_enhanced_policy: true
|
||||
|
||||
- job:
|
||||
name: tacker-functional-devstack-multinode-sol-terraform-v2
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL Terraform devstack-based functional tests
|
||||
attempts: 1
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-functional-sol-terraform-v2
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_vnfm:
|
||||
tf_file_dir: /tmp/tacker/terraform
|
||||
vars:
|
||||
terraform_setup: true
|
||||
|
||||
- job:
|
||||
name: tacker-compliance-devstack-multinode-sol
|
||||
parent: tacker-functional-devstack-multinode-sol-parent
|
||||
description: |
|
||||
Multinodes job for SOL devstack-based compliance tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: dsvm-compliance-sol-api
|
||||
voting: false
|
||||
|
||||
- project:
|
||||
templates:
|
||||
- check-requirements
|
||||
- openstack-cover-jobs
|
||||
- openstack-python3-jobs
|
||||
- publish-openstack-docs-pti
|
||||
- release-notes-jobs-python3
|
||||
check:
|
||||
jobs:
|
||||
- tacker-functional-devstack-multinode-sol-legacy-nfvo
|
||||
- tacker-functional-devstack-multinode-sol-vnflcm
|
||||
- tacker-functional-devstack-multinode-sol-vnflcm-userdata
|
||||
- tacker-functional-devstack-multinode-sol-vnfpkgm
|
||||
- tacker-functional-devstack-multinode-sol-separated-nfvo
|
||||
- tacker-functional-devstack-multinode-sol-kubernetes
|
||||
- tacker-functional-devstack-multinode-sol-v2-basic
|
||||
- tacker-functional-devstack-multinode-sol-v2-vnflcm
|
||||
- tacker-functional-devstack-multinode-sol-v2-notification
|
||||
- tacker-functional-devstack-multinode-sol-v2-prometheus
|
||||
- tacker-functional-devstack-multinode-sol-separated-nfvo-v2
|
||||
- tacker-functional-devstack-multinode-sol-v2-individual-vnfc-mgmt
|
||||
- tacker-functional-devstack-multinode-sol-kubernetes-v2
|
||||
- tacker-functional-devstack-multinode-sol-multi-tenant
|
||||
- tacker-functional-devstack-multinode-sol-https-v2
|
||||
- tacker-functional-devstack-multinode-sol-encrypt-cred-barbican
|
||||
- tacker-functional-devstack-multinode-sol-encrypt-cred-local
|
||||
- tacker-functional-devstack-multinode-sol-kubernetes-multi-tenant
|
||||
- tacker-functional-devstack-kubernetes-oidc-auth
|
||||
- tacker-functional-devstack-multinode-sol-v2-az-retry
|
||||
- tacker-functional-devstack-enhanced-policy-sol
|
||||
- tacker-functional-devstack-enhanced-policy-sol-kubernetes
|
||||
- tacker-compliance-devstack-multinode-sol
|
||||
- tacker-functional-devstack-multinode-sol-terraform-v2
|
@ -173,7 +173,7 @@ To change the version execute the below steps:
|
||||
|
||||
1. Open ``<tacker_route_directory>/tacker/tox.ini`` file in any editor.
|
||||
|
||||
2. Under [testenv:dsvm-compliance-sol-api] section in **commands_pre** while
|
||||
2. Under [testenv:ft-v1-compliance-sol] section in **commands_pre** while
|
||||
doing checkout of api-tests mention desired TST's code version.
|
||||
|
||||
.. code-block:: console
|
||||
@ -217,14 +217,14 @@ Execution of testcase
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tox -e dsvm-compliance-sol-api
|
||||
tox -e ft-v1-compliance-sol
|
||||
|
||||
* Or from tacker directory, specific testcases can be executed using
|
||||
the following command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tox -e dsvm-compliance-sol-api tacker.tests.compliance.xxx.yyy.<testcase>
|
||||
tox -e ft-v1-compliance-sol tacker.tests.compliance.xxx.yyy.<testcase>
|
||||
|
||||
|
||||
How to proceed when the test fails
|
||||
@ -237,7 +237,7 @@ How to proceed when the test fails
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker/.tox/dsvm-compliance-sol-api/log/SOL003/VNFLifecycleManagement-API
|
||||
tacker/.tox/ft-v1-compliance-sol/log/SOL003/VNFLifecycleManagement-API
|
||||
/VNFInstances/GET_information_about_multiple_VNF_instances
|
||||
|
||||
* Compliance test may also get failed due to code problem at
|
||||
|
@ -0,0 +1,53 @@
|
||||
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
|
||||
from tacker.tests.functional.sol_v2_common import test_vnflcm_basic_common
|
||||
from tacker.tests import utils
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VnfLcmMaxTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(VnfLcmMaxTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
# for basic lcms tests max pattern
|
||||
basic_lcms_max_path = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_max")
|
||||
cls.max_pkg, cls.max_vnfd_id = cls.create_vnf_package(
|
||||
basic_lcms_max_path, image_path=image_path)
|
||||
|
||||
# for update vnf test
|
||||
update_vnf_path = utils.test_sample("functional/sol_v2_common",
|
||||
"update_vnf")
|
||||
# no image contained
|
||||
cls.upd_pkg, cls.upd_vnfd_id = cls.create_vnf_package(update_vnf_path)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(VnfLcmMaxTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.max_pkg)
|
||||
cls.delete_vnf_package(cls.upd_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
def test_basic_lcms_max(self):
|
||||
self.basic_lcms_max_common_test()
|
@ -0,0 +1,157 @@
|
||||
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
import os
|
||||
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests.functional.sol_v2_common import test_vnflcm_basic_common
|
||||
from tacker.tests import utils
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VnfLcmMinTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(VnfLcmMinTest, cls).setUpClass()
|
||||
|
||||
# for basic lcms tests min pattern
|
||||
basic_lcms_min_path = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_min")
|
||||
# no image contained
|
||||
cls.min_pkg, cls.min_vnfd_id = cls.create_vnf_package(
|
||||
basic_lcms_min_path)
|
||||
|
||||
# for update vnf test
|
||||
update_vnf_path = utils.test_sample("functional/sol_v2_common",
|
||||
"update_vnf")
|
||||
# no image contained
|
||||
cls.upd_pkg, cls.upd_vnfd_id = cls.create_vnf_package(update_vnf_path)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(VnfLcmMinTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.min_pkg)
|
||||
cls.delete_vnf_package(cls.upd_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
def test_api_versions(self):
|
||||
"""Test version operations
|
||||
|
||||
* About version operations:
|
||||
This test includes the following operations.
|
||||
- 1. List VNFLCM API versions
|
||||
- 2. Show VNFLCM API versions
|
||||
"""
|
||||
path = "/vnflcm/api_versions"
|
||||
resp, body = self.tacker_client.do_request(path, "GET")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
expected_body = {
|
||||
"uriPrefix": "/vnflcm",
|
||||
"apiVersions": [
|
||||
{'version': '1.3.0', 'isDeprecated': False},
|
||||
{'version': '2.0.0', 'isDeprecated': False}
|
||||
]
|
||||
}
|
||||
self.assertEqual(body, expected_body)
|
||||
|
||||
path = "/vnflcm/v2/api_versions"
|
||||
resp, body = self.tacker_client.do_request(path, "GET")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
expected_body = {
|
||||
"uriPrefix": "/vnflcm/v2",
|
||||
"apiVersions": [
|
||||
{'version': '2.0.0', 'isDeprecated': False}
|
||||
]
|
||||
}
|
||||
self.assertEqual(body, expected_body)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_subscriptions(self, is_all):
|
||||
"""Test subscription operations
|
||||
|
||||
* About attributes:
|
||||
- is_all=True
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
- is_all=False
|
||||
Omit except for required attributes.
|
||||
Only the following cardinality attributes are set.
|
||||
- 1
|
||||
- 1..N (1)
|
||||
|
||||
* About subscription operations:
|
||||
This test includes the following operations.
|
||||
- 0. Pre-setting
|
||||
- 1. Create a new subscription
|
||||
- 2. Show subscription
|
||||
- 3. List subscription with attribute-based filtering
|
||||
- 4. Delete a subscription
|
||||
"""
|
||||
|
||||
# 0. Pre-setting
|
||||
callback_url = os.path.join(self.get_notify_callback_url(),
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{self.get_server_port()}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_min(callback_uri)
|
||||
if is_all:
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
|
||||
# 1. Create a new subscription
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# 2. Show subscription
|
||||
expected_attrs = [
|
||||
'id', 'callbackUri', 'verbosity', '_links'
|
||||
]
|
||||
if is_all:
|
||||
additional_attrs = ['filter']
|
||||
expected_attrs.extend(additional_attrs)
|
||||
|
||||
resp, body = self.show_subscription(sub_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 3. List subscription with attribute-based filtering
|
||||
filter_expr = {'filter': '(eq,id,%s)' % sub_id}
|
||||
resp, body = self.list_subscriptions(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for sbsc in body:
|
||||
self.check_resp_body(sbsc, expected_attrs)
|
||||
|
||||
# 4. Delete a subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
def test_basic_lcms_min(self):
|
||||
self.basic_lcms_min_common_test()
|
@ -22,11 +22,11 @@ from tacker.tests import utils
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class ChangeVnfPkgVnfLcmTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
class VnfLcmCcvpTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(ChangeVnfPkgVnfLcmTest, cls).setUpClass()
|
||||
super(VnfLcmCcvpTest, cls).setUpClass()
|
||||
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
@ -57,7 +57,7 @@ class ChangeVnfPkgVnfLcmTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(ChangeVnfPkgVnfLcmTest, cls).tearDownClass()
|
||||
super(VnfLcmCcvpTest, cls).tearDownClass()
|
||||
|
||||
cls.delete_vnf_package(cls.old_pkg)
|
||||
cls.delete_vnf_package(cls.new_image_pkg)
|
||||
@ -65,7 +65,7 @@ class ChangeVnfPkgVnfLcmTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
cls.delete_vnf_package(cls.failed_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super(ChangeVnfPkgVnfLcmTest, self).setUp()
|
||||
super(VnfLcmCcvpTest, self).setUp()
|
||||
|
||||
def test_change_vnfpkg_from_image_to_image(self):
|
||||
self.change_vnfpkg_from_image_to_image_common_test()
|
@ -23,11 +23,11 @@ from tacker.tests import utils
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VnfLcmTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
class VnfLcmScaleTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(VnfLcmTest, cls).setUpClass()
|
||||
super(VnfLcmScaleTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
@ -37,787 +37,14 @@ class VnfLcmTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
cls.max_pkg, cls.max_vnfd_id = cls.create_vnf_package(
|
||||
basic_lcms_max_path, image_path=image_path)
|
||||
|
||||
# for basic lcms tests min pattern
|
||||
basic_lcms_min_path = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_min")
|
||||
# no image contained
|
||||
cls.min_pkg, cls.min_vnfd_id = cls.create_vnf_package(
|
||||
basic_lcms_min_path)
|
||||
|
||||
# for update vnf test
|
||||
update_vnf_path = utils.test_sample("functional/sol_v2_common",
|
||||
"update_vnf")
|
||||
# no image contained
|
||||
cls.upd_pkg, cls.upd_vnfd_id = cls.create_vnf_package(update_vnf_path)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(VnfLcmTest, cls).tearDownClass()
|
||||
super(VnfLcmScaleTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.max_pkg)
|
||||
cls.delete_vnf_package(cls.min_pkg)
|
||||
cls.delete_vnf_package(cls.upd_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
def test_api_versions(self):
|
||||
"""Test version operations
|
||||
|
||||
* About version operations:
|
||||
This test includes the following operations.
|
||||
- 1. List VNFLCM API versions
|
||||
- 2. Show VNFLCM API versions
|
||||
"""
|
||||
path = "/vnflcm/api_versions"
|
||||
resp, body = self.tacker_client.do_request(path, "GET")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
expected_body = {
|
||||
"uriPrefix": "/vnflcm",
|
||||
"apiVersions": [
|
||||
{'version': '1.3.0', 'isDeprecated': False},
|
||||
{'version': '2.0.0', 'isDeprecated': False}
|
||||
]
|
||||
}
|
||||
self.assertEqual(body, expected_body)
|
||||
|
||||
path = "/vnflcm/v2/api_versions"
|
||||
resp, body = self.tacker_client.do_request(path, "GET")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
expected_body = {
|
||||
"uriPrefix": "/vnflcm/v2",
|
||||
"apiVersions": [
|
||||
{'version': '2.0.0', 'isDeprecated': False}
|
||||
]
|
||||
}
|
||||
self.assertEqual(body, expected_body)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_subscriptions(self, is_all):
|
||||
"""Test subscription operations
|
||||
|
||||
* About attributes:
|
||||
- is_all=True
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
- is_all=False
|
||||
Omit except for required attributes.
|
||||
Only the following cardinality attributes are set.
|
||||
- 1
|
||||
- 1..N (1)
|
||||
|
||||
* About subscription operations:
|
||||
This test includes the following operations.
|
||||
- 0. Pre-setting
|
||||
- 1. Create a new subscription
|
||||
- 2. Show subscription
|
||||
- 3. List subscription with attribute-based filtering
|
||||
- 4. Delete a subscription
|
||||
"""
|
||||
|
||||
# 0. Pre-setting
|
||||
callback_url = os.path.join(self.get_notify_callback_url(),
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{self.get_server_port()}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_min(callback_uri)
|
||||
if is_all:
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
|
||||
# 1. Create a new subscription
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# 2. Show subscription
|
||||
expected_attrs = [
|
||||
'id', 'callbackUri', 'verbosity', '_links'
|
||||
]
|
||||
if is_all:
|
||||
additional_attrs = ['filter']
|
||||
expected_attrs.extend(additional_attrs)
|
||||
|
||||
resp, body = self.show_subscription(sub_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 3. List subscription with attribute-based filtering
|
||||
filter_expr = {'filter': '(eq,id,%s)' % sub_id}
|
||||
resp, body = self.list_subscriptions(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for sbsc in body:
|
||||
self.check_resp_body(sbsc, expected_attrs)
|
||||
|
||||
# 4. Delete a subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
def test_basic_lcms_max(self):
|
||||
self.basic_lcms_max_common_test()
|
||||
|
||||
def test_basic_lcms_min(self):
|
||||
self.basic_lcms_min_common_test()
|
||||
|
||||
def test_update_scale_lcm(self):
|
||||
"""Test the sequence of update VNF and scale out
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Pre-setting
|
||||
- 1. Create subscription
|
||||
- 2. Create VNF instance
|
||||
- 3. Instantiate VNF
|
||||
- 4. Show VNF instance
|
||||
- 5. Update VNF
|
||||
- 6. Show VNF instance
|
||||
- 7. Scale out operation
|
||||
- 8. Terminate VNF
|
||||
- 9. Delete VNF instance
|
||||
- 10. Delete subscription
|
||||
"""
|
||||
# 0. Pre-setting
|
||||
# Create a new network and subnet to check the IP allocation of
|
||||
# IPv4 and IPv6
|
||||
ft_net0_name = 'ft-net0'
|
||||
ft_net0_subs = {
|
||||
'ft-ipv4-subnet0': {
|
||||
'range': '100.100.100.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet0': {
|
||||
'range': '1111:2222:3333::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net0_id = self.create_network(ft_net0_name)
|
||||
self.addCleanup(self.delete_network, ft_net0_id)
|
||||
for sub_name, val in ft_net0_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
self.create_subnet(
|
||||
ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
net_ids = self.get_network_ids(
|
||||
['net0', 'net1', 'net_mgmt', 'ft-net0'])
|
||||
subnet_ids = self.get_subnet_ids(
|
||||
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0'])
|
||||
|
||||
port_names = ['VDU2_CP1-1', 'VDU2_CP1-2']
|
||||
port_ids = {}
|
||||
for port_name in port_names:
|
||||
port_id = self.create_port(net_ids['net0'], port_name)
|
||||
port_ids[port_name] = port_id
|
||||
self.addCleanup(self.delete_port, port_id)
|
||||
|
||||
# 1. Create subscription
|
||||
callback_url = os.path.join(self.get_notify_callback_url(),
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{self.get_server_port()}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# 2. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
# NOTE: extensions and vnfConfigurableProperties are omitted
|
||||
# because they are commented out in etsi_nfv_sol001.
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
# 'vimConnectionInfo', # omitted
|
||||
'instantiationState',
|
||||
# 'instantiatedVnfInfo', # omitted
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
create_req = paramgen.create_vnf_max(self.max_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
inst_id = body['id']
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 3. Instantiate VNF instance
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
net_ids, subnet_ids, port_ids, self.auth_url)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 4. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# 5. Update VNF
|
||||
# check attribute value before update VNF
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
|
||||
# check usageState of update VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check vnfd id
|
||||
self.assertEqual(self.max_vnfd_id, body['vnfdId'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertGreater(len(vnfc_info), 1)
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
for vnfc in vnfc_info:
|
||||
self.assertIn('id', vnfc)
|
||||
self.assertIn('vduId', vnfc)
|
||||
self.assertIsNotNone(vnfc.get('vnfcState'))
|
||||
self.assertIsNone(vnfc.get('vnfcConfigurableProperties'))
|
||||
|
||||
update_req = paramgen.update_vnf_max(self.upd_vnfd_id, vnfc_ids)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 6. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check usageState of update pattern VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'IN_USE')
|
||||
|
||||
# check the specified attribute after update VNF
|
||||
self.assertEqual(self.upd_vnfd_id, body['vnfdId'])
|
||||
self.assertEqual('new name', body['vnfInstanceName'])
|
||||
self.assertEqual('new description', body['vnfInstanceDescription'])
|
||||
dummy_key_value = {'dummy-key': 'dummy-value'}
|
||||
self.assertEqual(dummy_key_value, body['metadata'])
|
||||
self.assertEqual(dummy_key_value, body['extensions'])
|
||||
self.assertEqual(dummy_key_value, body['vnfConfigurableProperties'])
|
||||
vim_connection_info = {
|
||||
"vim2": {
|
||||
"vimId": "ac2d2ece-5e49-4b15-b92d-b681e9c096d8",
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity/v3"
|
||||
},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {
|
||||
"dummy-key": "dummy-val"
|
||||
}
|
||||
}
|
||||
}
|
||||
self.assertEqual(vim_connection_info['vim2'],
|
||||
body['vimConnectionInfo']['vim2'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertEqual(vnfc_ids[0], vnfc_info[0]['id'])
|
||||
self.assertEqual(vnfc_ids[1], vnfc_info[1]['id'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[0]['vnfcConfigurableProperties'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[1]['vnfcConfigurableProperties'])
|
||||
|
||||
# 7. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 8. Terminate a VNF instance
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 9. Delete a VNF instance
|
||||
resp, body = self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# 10. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
def test_update_heal_lcm(self):
|
||||
"""Test the sequence of update VNF and heal VNF
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Pre-setting
|
||||
- 1. Create subscription
|
||||
- 2. Create VNF instance
|
||||
- 3. Instantiate VNF
|
||||
- 4. Show VNF instance
|
||||
- 5. Update VNF
|
||||
- 6. Show VNF instance
|
||||
- 7. Heal VNF(all with omit all parameter)
|
||||
- 8. Heal VNF(all with all=False parameter)
|
||||
- 9. Heal VNF(all with all=True parameter)
|
||||
- 10. Terminate VNF
|
||||
- 11. Delete VNF instance
|
||||
- 12. Delete subscription
|
||||
"""
|
||||
# 0. Pre-setting
|
||||
# Create a new network and subnet to check the IP allocation of
|
||||
# IPv4 and IPv6
|
||||
ft_net0_name = 'ft-net0'
|
||||
ft_net0_subs = {
|
||||
'ft-ipv4-subnet0': {
|
||||
'range': '100.100.100.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet0': {
|
||||
'range': '1111:2222:3333::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net0_id = self.create_network(ft_net0_name)
|
||||
self.addCleanup(self.delete_network, ft_net0_id)
|
||||
for sub_name, val in ft_net0_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
self.create_subnet(
|
||||
ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
net_ids = self.get_network_ids(
|
||||
['net0', 'net1', 'net_mgmt', 'ft-net0'])
|
||||
subnet_ids = self.get_subnet_ids(
|
||||
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0'])
|
||||
|
||||
port_names = ['VDU2_CP1-1', 'VDU2_CP1-2']
|
||||
port_ids = {}
|
||||
for port_name in port_names:
|
||||
port_id = self.create_port(net_ids['net0'], port_name)
|
||||
port_ids[port_name] = port_id
|
||||
self.addCleanup(self.delete_port, port_id)
|
||||
|
||||
# 1. Create subscription
|
||||
callback_url = os.path.join(self.get_notify_callback_url(),
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{self.get_server_port()}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# 2. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
# NOTE: extensions and vnfConfigurableProperties are omitted
|
||||
# because they are commented out in etsi_nfv_sol001.
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
# 'vimConnectionInfo', # omitted
|
||||
'instantiationState',
|
||||
# 'instantiatedVnfInfo', # omitted
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
create_req = paramgen.create_vnf_max(self.max_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
inst_id = body['id']
|
||||
|
||||
# check usageState of VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 3. Instantiate VNF instance
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
net_ids, subnet_ids, port_ids, self.auth_url)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 4. Show VNF instance
|
||||
# check creation of Heat-stack
|
||||
stack_name = f'vnf-{inst_id}'
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("CREATE_COMPLETE", stack_status)
|
||||
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# 5. Update VNF
|
||||
# check attribute value before update VNF
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
|
||||
# check usageState of update VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check vnfd id
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(self.max_vnfd_id, body['vnfdId'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertGreater(len(vnfc_info), 1)
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
for vnfc in vnfc_info:
|
||||
self.assertIn('id', vnfc)
|
||||
self.assertIn('vduId', vnfc)
|
||||
self.assertIsNotNone(vnfc.get('vnfcState'))
|
||||
self.assertIsNone(vnfc.get('vnfcConfigurableProperties'))
|
||||
|
||||
update_req = paramgen.update_vnf_max(self.upd_vnfd_id, vnfc_ids)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 6. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check usageState of update VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'IN_USE')
|
||||
|
||||
# check the specified attribute after update VNF
|
||||
self.assertEqual(self.upd_vnfd_id, body['vnfdId'])
|
||||
self.assertEqual('new name', body['vnfInstanceName'])
|
||||
self.assertEqual('new description', body['vnfInstanceDescription'])
|
||||
dummy_key_value = {'dummy-key': 'dummy-value'}
|
||||
self.assertEqual(dummy_key_value, body['metadata'])
|
||||
self.assertEqual(dummy_key_value, body['extensions'])
|
||||
self.assertEqual(dummy_key_value, body['vnfConfigurableProperties'])
|
||||
vim_connection_info = {
|
||||
"vim2": {
|
||||
"vimId": "ac2d2ece-5e49-4b15-b92d-b681e9c096d8",
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity/v3"
|
||||
},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {
|
||||
"dummy-key": "dummy-val"
|
||||
}
|
||||
}
|
||||
}
|
||||
self.assertEqual(vim_connection_info['vim2'],
|
||||
body['vimConnectionInfo']['vim2'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertEqual(vnfc_ids[0], vnfc_info[0]['id'])
|
||||
self.assertEqual(vnfc_ids[1], vnfc_info[1]['id'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[0]['vnfcConfigurableProperties'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[1]['vnfcConfigurableProperties'])
|
||||
|
||||
# 7. Heal VNF(all with omit all parameter)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter()
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("UPDATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
|
||||
self.assertNotEqual(vdu1_stack_before_heal['physical_resource_id'],
|
||||
vdu1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(vdu2_stack_before_heal['physical_resource_id'],
|
||||
vdu2_stack_after_heal['physical_resource_id'])
|
||||
|
||||
# 8. Heal VNF(all with all=False parameter)
|
||||
vdu1_stack_before_heal = vdu1_stack_after_heal
|
||||
vdu2_stack_before_heal = vdu2_stack_after_heal
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(False)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("UPDATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
|
||||
self.assertNotEqual(vdu1_stack_before_heal['physical_resource_id'],
|
||||
vdu1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(vdu2_stack_before_heal['physical_resource_id'],
|
||||
vdu2_stack_after_heal['physical_resource_id'])
|
||||
|
||||
# 9. Heal VNF(all with all=True parameter)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2', 'VDU1-VirtualStorage',
|
||||
'VDU2-VirtualStorage', 'internalVL3'])]
|
||||
vdu1_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
storage1_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1-VirtualStorage')][0]
|
||||
storage2_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2-VirtualStorage')][0]
|
||||
network_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'internalVL3')][0]
|
||||
|
||||
stack_id_before_heal = self.heat_client.get_stack_id(stack_name)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(True)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_id_after_heal = self.heat_client.get_stack_id(stack_name)
|
||||
self.assertNotEqual(stack_id_before_heal, stack_id_after_heal)
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("CREATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2', 'VDU1-VirtualStorage',
|
||||
'VDU2-VirtualStorage', 'internalVL3'])]
|
||||
vdu1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
storage1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1-VirtualStorage')][0]
|
||||
storage2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2-VirtualStorage')][0]
|
||||
network_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'internalVL3')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
storage1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
storage2_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
network_stack_after_heal['resource_status'])
|
||||
|
||||
self.assertNotEqual(vdu1_stack_before_heal['physical_resource_id'],
|
||||
vdu1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(vdu2_stack_before_heal['physical_resource_id'],
|
||||
vdu2_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(storage1_stack_before_heal['physical_resource_id'],
|
||||
storage1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(storage2_stack_before_heal['physical_resource_id'],
|
||||
storage2_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(network_stack_before_heal['physical_resource_id'],
|
||||
network_stack_after_heal['physical_resource_id'])
|
||||
|
||||
# 10. Terminate VNF
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 11. Delete VNF instance
|
||||
resp, body = self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# 12. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
def test_scale_heal_lcm(self):
|
||||
"""Test the sequence of scale out/in and heal VNF
|
||||
|
@ -0,0 +1,702 @@
|
||||
# Copyright (C) 2021 Nippon Telegraph and Telephone Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
import os
|
||||
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests.functional.sol_v2_common import test_vnflcm_basic_common
|
||||
from tacker.tests import utils
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VnfLcmUpdateTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(VnfLcmUpdateTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
# for basic lcms tests max pattern
|
||||
basic_lcms_max_path = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_max")
|
||||
cls.max_pkg, cls.max_vnfd_id = cls.create_vnf_package(
|
||||
basic_lcms_max_path, image_path=image_path)
|
||||
|
||||
# for update vnf test
|
||||
update_vnf_path = utils.test_sample("functional/sol_v2_common",
|
||||
"update_vnf")
|
||||
# no image contained
|
||||
cls.upd_pkg, cls.upd_vnfd_id = cls.create_vnf_package(update_vnf_path)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(VnfLcmUpdateTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.max_pkg)
|
||||
cls.delete_vnf_package(cls.upd_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
def test_update_scale_lcm(self):
|
||||
"""Test the sequence of update VNF and scale out
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Pre-setting
|
||||
- 1. Create subscription
|
||||
- 2. Create VNF instance
|
||||
- 3. Instantiate VNF
|
||||
- 4. Show VNF instance
|
||||
- 5. Update VNF
|
||||
- 6. Show VNF instance
|
||||
- 7. Scale out operation
|
||||
- 8. Terminate VNF
|
||||
- 9. Delete VNF instance
|
||||
- 10. Delete subscription
|
||||
"""
|
||||
# 0. Pre-setting
|
||||
# Create a new network and subnet to check the IP allocation of
|
||||
# IPv4 and IPv6
|
||||
ft_net0_name = 'ft-net0'
|
||||
ft_net0_subs = {
|
||||
'ft-ipv4-subnet0': {
|
||||
'range': '100.100.100.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet0': {
|
||||
'range': '1111:2222:3333::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net0_id = self.create_network(ft_net0_name)
|
||||
self.addCleanup(self.delete_network, ft_net0_id)
|
||||
for sub_name, val in ft_net0_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
self.create_subnet(
|
||||
ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
net_ids = self.get_network_ids(
|
||||
['net0', 'net1', 'net_mgmt', 'ft-net0'])
|
||||
subnet_ids = self.get_subnet_ids(
|
||||
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0'])
|
||||
|
||||
port_names = ['VDU2_CP1-1', 'VDU2_CP1-2']
|
||||
port_ids = {}
|
||||
for port_name in port_names:
|
||||
port_id = self.create_port(net_ids['net0'], port_name)
|
||||
port_ids[port_name] = port_id
|
||||
self.addCleanup(self.delete_port, port_id)
|
||||
|
||||
# 1. Create subscription
|
||||
callback_url = os.path.join(self.get_notify_callback_url(),
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{self.get_server_port()}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# 2. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
# NOTE: extensions and vnfConfigurableProperties are omitted
|
||||
# because they are commented out in etsi_nfv_sol001.
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
# 'vimConnectionInfo', # omitted
|
||||
'instantiationState',
|
||||
# 'instantiatedVnfInfo', # omitted
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
create_req = paramgen.create_vnf_max(self.max_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
inst_id = body['id']
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 3. Instantiate VNF instance
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
net_ids, subnet_ids, port_ids, self.auth_url)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 4. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# 5. Update VNF
|
||||
# check attribute value before update VNF
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
|
||||
# check usageState of update VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check vnfd id
|
||||
self.assertEqual(self.max_vnfd_id, body['vnfdId'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertGreater(len(vnfc_info), 1)
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
for vnfc in vnfc_info:
|
||||
self.assertIn('id', vnfc)
|
||||
self.assertIn('vduId', vnfc)
|
||||
self.assertIsNotNone(vnfc.get('vnfcState'))
|
||||
self.assertIsNone(vnfc.get('vnfcConfigurableProperties'))
|
||||
|
||||
update_req = paramgen.update_vnf_max(self.upd_vnfd_id, vnfc_ids)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 6. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check usageState of update pattern VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'IN_USE')
|
||||
|
||||
# check the specified attribute after update VNF
|
||||
self.assertEqual(self.upd_vnfd_id, body['vnfdId'])
|
||||
self.assertEqual('new name', body['vnfInstanceName'])
|
||||
self.assertEqual('new description', body['vnfInstanceDescription'])
|
||||
dummy_key_value = {'dummy-key': 'dummy-value'}
|
||||
self.assertEqual(dummy_key_value, body['metadata'])
|
||||
self.assertEqual(dummy_key_value, body['extensions'])
|
||||
self.assertEqual(dummy_key_value, body['vnfConfigurableProperties'])
|
||||
vim_connection_info = {
|
||||
"vim2": {
|
||||
"vimId": "ac2d2ece-5e49-4b15-b92d-b681e9c096d8",
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity/v3"
|
||||
},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {
|
||||
"dummy-key": "dummy-val"
|
||||
}
|
||||
}
|
||||
}
|
||||
self.assertEqual(vim_connection_info['vim2'],
|
||||
body['vimConnectionInfo']['vim2'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertEqual(vnfc_ids[0], vnfc_info[0]['id'])
|
||||
self.assertEqual(vnfc_ids[1], vnfc_info[1]['id'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[0]['vnfcConfigurableProperties'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[1]['vnfcConfigurableProperties'])
|
||||
|
||||
# 7. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 8. Terminate a VNF instance
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 9. Delete a VNF instance
|
||||
resp, body = self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# 10. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
def test_update_heal_lcm(self):
|
||||
"""Test the sequence of update VNF and heal VNF
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Pre-setting
|
||||
- 1. Create subscription
|
||||
- 2. Create VNF instance
|
||||
- 3. Instantiate VNF
|
||||
- 4. Show VNF instance
|
||||
- 5. Update VNF
|
||||
- 6. Show VNF instance
|
||||
- 7. Heal VNF(all with omit all parameter)
|
||||
- 8. Heal VNF(all with all=False parameter)
|
||||
- 9. Heal VNF(all with all=True parameter)
|
||||
- 10. Terminate VNF
|
||||
- 11. Delete VNF instance
|
||||
- 12. Delete subscription
|
||||
"""
|
||||
# 0. Pre-setting
|
||||
# Create a new network and subnet to check the IP allocation of
|
||||
# IPv4 and IPv6
|
||||
ft_net0_name = 'ft-net0'
|
||||
ft_net0_subs = {
|
||||
'ft-ipv4-subnet0': {
|
||||
'range': '100.100.100.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet0': {
|
||||
'range': '1111:2222:3333::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net0_id = self.create_network(ft_net0_name)
|
||||
self.addCleanup(self.delete_network, ft_net0_id)
|
||||
for sub_name, val in ft_net0_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
self.create_subnet(
|
||||
ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
net_ids = self.get_network_ids(
|
||||
['net0', 'net1', 'net_mgmt', 'ft-net0'])
|
||||
subnet_ids = self.get_subnet_ids(
|
||||
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0'])
|
||||
|
||||
port_names = ['VDU2_CP1-1', 'VDU2_CP1-2']
|
||||
port_ids = {}
|
||||
for port_name in port_names:
|
||||
port_id = self.create_port(net_ids['net0'], port_name)
|
||||
port_ids[port_name] = port_id
|
||||
self.addCleanup(self.delete_port, port_id)
|
||||
|
||||
# 1. Create subscription
|
||||
callback_url = os.path.join(self.get_notify_callback_url(),
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{self.get_server_port()}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_max(callback_uri)
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# 2. Create VNF instance
|
||||
# ETSI NFV SOL003 v3.3.1 5.5.2.2 VnfInstance
|
||||
# NOTE: extensions and vnfConfigurableProperties are omitted
|
||||
# because they are commented out in etsi_nfv_sol001.
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
# 'vimConnectionInfo', # omitted
|
||||
'instantiationState',
|
||||
# 'instantiatedVnfInfo', # omitted
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
create_req = paramgen.create_vnf_max(self.max_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
inst_id = body['id']
|
||||
|
||||
# check usageState of VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 3. Instantiate VNF instance
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
net_ids, subnet_ids, port_ids, self.auth_url)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 4. Show VNF instance
|
||||
# check creation of Heat-stack
|
||||
stack_name = f'vnf-{inst_id}'
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("CREATE_COMPLETE", stack_status)
|
||||
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# 5. Update VNF
|
||||
# check attribute value before update VNF
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
|
||||
# check usageState of update VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check vnfd id
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(self.max_vnfd_id, body['vnfdId'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertGreater(len(vnfc_info), 1)
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
for vnfc in vnfc_info:
|
||||
self.assertIn('id', vnfc)
|
||||
self.assertIn('vduId', vnfc)
|
||||
self.assertIsNotNone(vnfc.get('vnfcState'))
|
||||
self.assertIsNone(vnfc.get('vnfcConfigurableProperties'))
|
||||
|
||||
update_req = paramgen.update_vnf_max(self.upd_vnfd_id, vnfc_ids)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 6. Show VNF instance
|
||||
additional_inst_attrs = [
|
||||
'vimConnectionInfo',
|
||||
'instantiatedVnfInfo'
|
||||
]
|
||||
expected_inst_attrs.extend(additional_inst_attrs)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'NOT_IN_USE')
|
||||
|
||||
# check usageState of update VNF Package
|
||||
self.check_package_usage(self.upd_pkg, 'IN_USE')
|
||||
|
||||
# check the specified attribute after update VNF
|
||||
self.assertEqual(self.upd_vnfd_id, body['vnfdId'])
|
||||
self.assertEqual('new name', body['vnfInstanceName'])
|
||||
self.assertEqual('new description', body['vnfInstanceDescription'])
|
||||
dummy_key_value = {'dummy-key': 'dummy-value'}
|
||||
self.assertEqual(dummy_key_value, body['metadata'])
|
||||
self.assertEqual(dummy_key_value, body['extensions'])
|
||||
self.assertEqual(dummy_key_value, body['vnfConfigurableProperties'])
|
||||
vim_connection_info = {
|
||||
"vim2": {
|
||||
"vimId": "ac2d2ece-5e49-4b15-b92d-b681e9c096d8",
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity/v3"
|
||||
},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {
|
||||
"dummy-key": "dummy-val"
|
||||
}
|
||||
}
|
||||
}
|
||||
self.assertEqual(vim_connection_info['vim2'],
|
||||
body['vimConnectionInfo']['vim2'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertEqual(vnfc_ids[0], vnfc_info[0]['id'])
|
||||
self.assertEqual(vnfc_ids[1], vnfc_info[1]['id'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[0]['vnfcConfigurableProperties'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[1]['vnfcConfigurableProperties'])
|
||||
|
||||
# 7. Heal VNF(all with omit all parameter)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter()
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("UPDATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
|
||||
self.assertNotEqual(vdu1_stack_before_heal['physical_resource_id'],
|
||||
vdu1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(vdu2_stack_before_heal['physical_resource_id'],
|
||||
vdu2_stack_after_heal['physical_resource_id'])
|
||||
|
||||
# 8. Heal VNF(all with all=False parameter)
|
||||
vdu1_stack_before_heal = vdu1_stack_after_heal
|
||||
vdu2_stack_before_heal = vdu2_stack_after_heal
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(False)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("UPDATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
|
||||
self.assertNotEqual(vdu1_stack_before_heal['physical_resource_id'],
|
||||
vdu1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(vdu2_stack_before_heal['physical_resource_id'],
|
||||
vdu2_stack_after_heal['physical_resource_id'])
|
||||
|
||||
# 9. Heal VNF(all with all=True parameter)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2', 'VDU1-VirtualStorage',
|
||||
'VDU2-VirtualStorage', 'internalVL3'])]
|
||||
vdu1_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
storage1_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1-VirtualStorage')][0]
|
||||
storage2_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2-VirtualStorage')][0]
|
||||
network_stack_before_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'internalVL3')][0]
|
||||
|
||||
stack_id_before_heal = self.heat_client.get_stack_id(stack_name)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(True)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_id_after_heal = self.heat_client.get_stack_id(stack_name)
|
||||
self.assertNotEqual(stack_id_before_heal, stack_id_after_heal)
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("CREATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2', 'VDU1-VirtualStorage',
|
||||
'VDU2-VirtualStorage', 'internalVL3'])]
|
||||
vdu1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
storage1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1-VirtualStorage')][0]
|
||||
storage2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2-VirtualStorage')][0]
|
||||
network_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'internalVL3')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
storage1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
storage2_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
network_stack_after_heal['resource_status'])
|
||||
|
||||
self.assertNotEqual(vdu1_stack_before_heal['physical_resource_id'],
|
||||
vdu1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(vdu2_stack_before_heal['physical_resource_id'],
|
||||
vdu2_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(storage1_stack_before_heal['physical_resource_id'],
|
||||
storage1_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(storage2_stack_before_heal['physical_resource_id'],
|
||||
storage2_stack_after_heal['physical_resource_id'])
|
||||
self.assertNotEqual(network_stack_before_heal['physical_resource_id'],
|
||||
network_stack_after_heal['physical_resource_id'])
|
||||
|
||||
# 10. Terminate VNF
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 11. Delete VNF instance
|
||||
resp, body = self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# 12. Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
@ -71,26 +71,11 @@ class IndividualVnfcMgmtTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
subprocess.run(["sudo", "cp", os.path.join(pkg_path_2, source_path),
|
||||
os.path.join(csar_dir, dest_path)])
|
||||
|
||||
# for change_vnfpkg network/flavor change test
|
||||
pkg_path_3 = utils.test_sample("functional/sol_v2_common",
|
||||
"userdata_standard_change_vnfpkg_nw")
|
||||
cls.new_nw_pkg, cls.new_nw_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_3, image_path=image_path, userdata_path=userdata_path)
|
||||
|
||||
# for attach non-boot volume to VDU test
|
||||
pkg_path_4 = utils.test_sample("functional/sol_v2_common",
|
||||
"userdata_standard_with_non_boot_volume")
|
||||
cls.non_boot_volume_pkg, cls.non_boot_volume_vnfd_id = (
|
||||
cls.create_vnf_package(pkg_path_4, image_path=image_path,
|
||||
userdata_path=userdata_path))
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(IndividualVnfcMgmtTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.standard_pkg)
|
||||
cls.delete_vnf_package(cls.new_pkg)
|
||||
cls.delete_vnf_package(cls.new_nw_pkg)
|
||||
cls.delete_vnf_package(cls.non_boot_volume_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
@ -118,10 +103,6 @@ class IndividualVnfcMgmtTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
if vnfc_info['vnfcResourceInfoId'] == vnfc['id']:
|
||||
return vnfc_info['id']
|
||||
|
||||
def _get_vnfc_cps(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return {cp_info['cpdId'] for cp_info in vnfc['vnfcCpInfo']}
|
||||
|
||||
def _get_vnfc_cp_net_id(self, inst, vdu, index, cp):
|
||||
# this is for external CPs
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
@ -136,20 +117,6 @@ class IndividualVnfcMgmtTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
# must be found
|
||||
return ext_vl['resourceHandle']['resourceId']
|
||||
|
||||
def _get_vnfc_cp_net_name(self, inst, vdu, index, cp):
|
||||
# this is for internal CPs
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
link_port_id = cp_info['vnfLinkPortId']
|
||||
break
|
||||
for vl in inst['instantiatedVnfInfo']['vnfVirtualLinkResourceInfo']:
|
||||
for port in vl['vnfLinkPorts']:
|
||||
if port['id'] == link_port_id:
|
||||
# must be found
|
||||
return vl['vnfVirtualLinkDescId']
|
||||
|
||||
def _get_vnfc_image(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for key, value in vnfc['metadata'].items():
|
||||
@ -157,16 +124,6 @@ class IndividualVnfcMgmtTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
# must be found
|
||||
return value
|
||||
|
||||
def _get_vnfc_flavor(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
# must exist
|
||||
return vnfc['metadata']['flavor']
|
||||
|
||||
def _get_vnfc_storage_ids(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
storage_res_ids = vnfc.get('storageResourceIds', [])
|
||||
return sorted(storage_res_ids)
|
||||
|
||||
def _get_server_name(self, inst, vdu, index):
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if (vnfc['vduId'] == vdu and
|
||||
@ -695,328 +652,3 @@ class IndividualVnfcMgmtTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
# Delete VNF instance
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_change_vnfpkg_nw(self):
|
||||
"""Test change_vnfpkg with additional functions
|
||||
|
||||
* Note:
|
||||
This test focuses change_vnfpkg with the following changes.
|
||||
- adding external CP
|
||||
- change internal network
|
||||
- change flavor
|
||||
|
||||
TODO: add anoter patterns (ex. change extMgdVLs)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- Create VNF instance
|
||||
- 1. Instantiate VNF instance
|
||||
- Show VNF instance / check
|
||||
- 2. Change_vnfpkg operation
|
||||
- Show VNF instance / check
|
||||
- Terminate VNF instance
|
||||
- Delete VNF instance
|
||||
"""
|
||||
|
||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
||||
|
||||
# Create VNF instance
|
||||
create_req = paramgen.sample3_create(self.standard_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF instance
|
||||
instantiate_req = paramgen.sample3_instantiate(
|
||||
net_ids, subnet_ids, self.auth_url)
|
||||
instantiate_req['instantiationLevelId'] = "instantiation_level_2"
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_1 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check number of VDUs and indexes
|
||||
self.assertEqual({0, 1}, self._get_vdu_indexes(inst_1, 'VDU1'))
|
||||
self.assertEqual({0}, self._get_vdu_indexes(inst_1, 'VDU2'))
|
||||
|
||||
# 2. Change_vnfpkg operation
|
||||
change_vnfpkg_req = paramgen.sample5_change_vnfpkg(self.new_nw_vnfd_id,
|
||||
net_ids, subnet_ids)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnfpkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_2 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check vnfdId is changed
|
||||
self.assertEqual(self.new_nw_vnfd_id, inst_2['vnfdId'])
|
||||
# check images are changed
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_1, 'VDU1', 1),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 1))
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU2', 0))
|
||||
# check flavor is changed (VDU2 only)
|
||||
self.assertNotEqual(self._get_vnfc_flavor(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_flavor(inst_2, 'VDU2', 0))
|
||||
# check external CPs; VDU1_CP4 and VDU2_CP4 are added
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_1, 'VDU1', 0))
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_1, 'VDU1', 1))
|
||||
self.assertFalse('VDU2_CP4' in self._get_vnfc_cps(inst_1, 'VDU2', 0))
|
||||
self.assertTrue('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 0))
|
||||
self.assertTrue('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 1))
|
||||
self.assertTrue('VDU2_CP4' in self._get_vnfc_cps(inst_2, 'VDU2', 0))
|
||||
self.assertEqual(net_ids['net0'],
|
||||
self._get_vnfc_cp_net_id(inst_2, 'VDU1', 0, 'VDU1_CP4'))
|
||||
self.assertEqual(net_ids['net0'],
|
||||
self._get_vnfc_cp_net_id(inst_2, 'VDU1', 1, 'VDU1_CP4'))
|
||||
self.assertEqual(net_ids['net0'],
|
||||
self._get_vnfc_cp_net_id(inst_2, 'VDU2', 0, 'VDU2_CP4'))
|
||||
# check internal CPs; VDU1_CP3 and VDU2_CP3 are changed
|
||||
self.assertEqual("internalVL2",
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 0, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL2",
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 1, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL2",
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU2', 0, 'VDU2_CP3'))
|
||||
self.assertEqual("internalVL3",
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 0, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL3",
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 1, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL3",
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU2', 0, 'VDU2_CP3'))
|
||||
|
||||
# Terminate VNF instance
|
||||
terminate_req = paramgen.sample5_terminate()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Delete VNF instance
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_change_vnfpkg_nw_rollback(self):
|
||||
"""Test rollback of change_vnfpkg with additional functions
|
||||
|
||||
* Note:
|
||||
This test focuses rollback of change_vnfpkg with the following
|
||||
changes.
|
||||
- adding external CP
|
||||
- change internal network
|
||||
- change flavor
|
||||
|
||||
TODO: add anoter patterns (ex. change extMgdVLs)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- Create VNF instance
|
||||
- 1. Instantiate VNF instance
|
||||
- Show VNF instance / check
|
||||
- 2. Change_vnfpkg operation => FAILED_TEMP
|
||||
- Rollback
|
||||
- Show VNF instance / check
|
||||
- Terminate VNF instance
|
||||
- Delete VNF instance
|
||||
"""
|
||||
|
||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
||||
|
||||
# Create VNF instance
|
||||
create_req = paramgen.sample3_create(self.standard_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF instance
|
||||
instantiate_req = paramgen.sample3_instantiate(
|
||||
net_ids, subnet_ids, self.auth_url)
|
||||
instantiate_req['instantiationLevelId'] = "instantiation_level_2"
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_1 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check number of VDUs and indexes
|
||||
self.assertEqual({0, 1}, self._get_vdu_indexes(inst_1, 'VDU1'))
|
||||
self.assertEqual({0}, self._get_vdu_indexes(inst_1, 'VDU2'))
|
||||
|
||||
# 2. Change_vnfpkg operation
|
||||
self.put_fail_file('change_vnfpkg')
|
||||
change_vnfpkg_req = paramgen.sample5_change_vnfpkg(self.new_nw_vnfd_id,
|
||||
net_ids, subnet_ids)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnfpkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
self.rm_fail_file('change_vnfpkg')
|
||||
|
||||
# Rollback
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_2 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check vnfdId is not changed
|
||||
self.assertEqual(self.standard_vnfd_id, inst_2['vnfdId'])
|
||||
# check images are not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_image(inst_1, 'VDU1', 1),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 1))
|
||||
self.assertEqual(self._get_vnfc_image(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU2', 0))
|
||||
# check flavor is not changed (VDU2 only)
|
||||
self.assertEqual(self._get_vnfc_flavor(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_flavor(inst_2, 'VDU2', 0))
|
||||
# check external CPs; VDU1_CP4 and VDU2_CP4 are not added
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 0))
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 1))
|
||||
self.assertFalse('VDU2_CP4' in self._get_vnfc_cps(inst_2, 'VDU2', 0))
|
||||
# check internal CPs; VDU1_CP3 and VDU2_CP3 are not changed
|
||||
self.assertEqual(
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 0, 'VDU1_CP3'),
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 0, 'VDU1_CP3'))
|
||||
self.assertEqual(
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 1, 'VDU1_CP3'),
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 1, 'VDU1_CP3'))
|
||||
self.assertEqual(
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU2', 0, 'VDU2_CP3'),
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU2', 0, 'VDU2_CP3'))
|
||||
|
||||
# Terminate VNF instance
|
||||
terminate_req = paramgen.sample3_terminate()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Delete VNF instance
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_instantiate_attach_non_boot_volume(self):
|
||||
"""Test Instantiate with non-boot volume attached to VDU
|
||||
|
||||
* Note:
|
||||
This test focuses on the non-boot volume attached by
|
||||
OS::Cinder::VolumeAttachment in HOT being registered to
|
||||
storageResourceIds.
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- Create VNF instance
|
||||
- 1. Instantiate VNF instance
|
||||
- Show VNF instance / check
|
||||
- 2. Heal operation("all"=True)
|
||||
- Show VNF instance / check
|
||||
- 3. Heal operation("all" is not specified)
|
||||
- Show VNF instance / check
|
||||
- Terminate VNF instance
|
||||
- Delete VNF instance
|
||||
"""
|
||||
|
||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
||||
|
||||
# Create VNF instance
|
||||
create_req = paramgen.sample7_create(self.non_boot_volume_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF instance
|
||||
instantiate_req = paramgen.sample7_instantiate(
|
||||
net_ids, subnet_ids, self.auth_url)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_1 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check number of VDUs and indexes
|
||||
self.assertEqual({0}, self._get_vdu_indexes(inst_1, 'VDU1'))
|
||||
|
||||
# check storageResourceIds of attached non-boot volume
|
||||
self.assertNotEqual([], self._get_vnfc_storage_ids(inst_1, 'VDU1', 0))
|
||||
|
||||
# 2. Heal operation("all"=True)
|
||||
# VDU1-0 to heal
|
||||
heal_req = paramgen.sample7_heal('a-001')
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_2 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check id of VDU1-0 is changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_2, 'VDU1', 0))
|
||||
|
||||
# check storageResourceIds of VDU1-0 is changed
|
||||
self.assertNotEqual([], self._get_vnfc_storage_ids(inst_2, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_2, 'VDU1', 0))
|
||||
|
||||
# 3. Heal operation("all" is not specified)
|
||||
# VDU1-0 to heal
|
||||
heal_req['vnfcInstanceId'] = ['a-001']
|
||||
del heal_req['additionalParams']['all']
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_3 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check id of VDU1-0 is changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_3, 'VDU1', 0))
|
||||
|
||||
# check storageResourceIds of VDU1-0 is not changed
|
||||
self.assertEqual(self._get_vnfc_storage_ids(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_3, 'VDU1', 0))
|
||||
|
||||
# Terminate VNF instance
|
||||
terminate_req = paramgen.sample7_terminate()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Delete VNF instance
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
@ -0,0 +1,828 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import string
|
||||
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional.sol_v2_common import base_v2
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests import utils
|
||||
|
||||
SUPPORT_STRING_FOR_VNFD_ID = f"{string.ascii_letters}{string.digits}-._ "
|
||||
MAX_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}max_vnfd_id"
|
||||
MIN_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}min_vnfd_id"
|
||||
UPD_MAX_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}upd_max_vnfd_id"
|
||||
NEW_MAX_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}new_max_vnfd_id"
|
||||
|
||||
|
||||
class IndividualVnfcMgmtBasicMaxTest(base_v2.BaseSolV2Test):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(IndividualVnfcMgmtBasicMaxTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
userdata_path = utils.userdata("userdata_standard.py")
|
||||
|
||||
# vnf package for basic lcms tests max pattern
|
||||
pkg_path_1 = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_max_individual_vnfc")
|
||||
cls.max_pkg, cls.max_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_1, image_path=image_path,
|
||||
userdata_path=userdata_path, vnfd_id=MAX_VNFD_ID)
|
||||
|
||||
# vnf package for basic lcms tests min pattern
|
||||
pkg_path_2 = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_min_individual_vnfc")
|
||||
cls.min_pkg, cls.min_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_2, userdata_path=userdata_path,
|
||||
vnfd_id=MIN_VNFD_ID)
|
||||
|
||||
# vnf package for update vnf max pattern
|
||||
pkg_path_3 = utils.test_sample("functional/sol_v2_common",
|
||||
"update_vnf_max_individual_vnfc")
|
||||
cls.upd_max_pkg, cls.upd_max_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_3, image_path=image_path,
|
||||
userdata_path=userdata_path, vnfd_id=UPD_MAX_VNFD_ID)
|
||||
|
||||
# vnf package for change vnf package max pattern
|
||||
pkg_path_4 = utils.test_sample("functional/sol_v2_common",
|
||||
"change_vnfpkg_max_individual_vnfc")
|
||||
cls.new_max_pkg, cls.new_max_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_4, userdata_path=userdata_path,
|
||||
vnfd_id=NEW_MAX_VNFD_ID)
|
||||
|
||||
cls._pre_setting()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(IndividualVnfcMgmtBasicMaxTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.max_pkg)
|
||||
cls.delete_vnf_package(cls.min_pkg)
|
||||
cls.delete_vnf_package(cls.upd_max_pkg)
|
||||
cls.delete_vnf_package(cls.new_max_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@classmethod
|
||||
def _pre_setting(cls):
|
||||
# Create a new network and subnet to check the IP allocation of
|
||||
# IPv4 and IPv6
|
||||
ft_net0_name = 'ft-net0'
|
||||
ft_net0_subs = {
|
||||
'ft-ipv4-subnet0': {
|
||||
'range': '100.100.100.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet0': {
|
||||
'range': '1111:2222:3333::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net0_id = cls.create_network(cls, ft_net0_name)
|
||||
cls.addClassCleanup(cls.delete_network, cls, ft_net0_id)
|
||||
for sub_name, val in ft_net0_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
cls.create_subnet(
|
||||
cls, ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
# Create a new network for change external connectivity
|
||||
ft_net1_name = 'ft-net1'
|
||||
ft_net1_subs = {
|
||||
'ft-ipv4-subnet1': {
|
||||
'range': '22.22.22.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet1': {
|
||||
'range': '1111:2222:4444::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net1_id = cls.create_network(cls, ft_net1_name)
|
||||
cls.addClassCleanup(cls.delete_network, cls, ft_net1_id)
|
||||
for sub_name, val in ft_net1_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
cls.create_subnet(
|
||||
cls, ft_net1_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
cls.net_ids = cls.get_network_ids(
|
||||
cls, ['net0', 'net1', 'net_mgmt', 'ft-net0', 'ft-net1'])
|
||||
cls.subnet_ids = cls.get_subnet_ids(
|
||||
cls, ['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0',
|
||||
'ft-ipv4-subnet1', 'ft-ipv6-subnet1'])
|
||||
|
||||
def _get_vdu_indexes(self, inst, vdu):
|
||||
return {
|
||||
vnfc['metadata'].get('vdu_idx')
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']
|
||||
if vnfc['vduId'] == vdu
|
||||
}
|
||||
|
||||
def _get_vnfc_metadata_keys(self, inst, vdu):
|
||||
vnfc_metadata_keys = set()
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if vnfc['vduId'] == vdu:
|
||||
vnfc_metadata_keys.update(set(vnfc['metadata'].keys()))
|
||||
return vnfc_metadata_keys
|
||||
|
||||
def _add_additional_params(self, req):
|
||||
if not req.get('additionalParams'):
|
||||
req['additionalParams'] = {}
|
||||
req['additionalParams']['lcm-operation-user-data'] = (
|
||||
'./UserData/userdata_standard.py')
|
||||
req['additionalParams']['lcm-operation-user-data-class'] = (
|
||||
'StandardUserData')
|
||||
|
||||
def _get_vnfc_by_vdu_index(self, inst, vdu, index):
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if (vnfc['vduId'] == vdu and
|
||||
vnfc['metadata'].get('vdu_idx') == index):
|
||||
return vnfc
|
||||
|
||||
def _get_vnfc_id(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return vnfc['id']
|
||||
|
||||
def _get_vnfc_image(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for key, value in vnfc['metadata'].items():
|
||||
if key.startswith('image-'):
|
||||
# must be found
|
||||
return value
|
||||
|
||||
def _get_vnfc_storage_ids(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return vnfc['storageResourceIds']
|
||||
|
||||
def _get_vnf_ext_cp_id(self, inst, vdu, index, cp):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
ext_cp_id = cp_info['vnfExtCpId']
|
||||
break
|
||||
return ext_cp_id
|
||||
|
||||
def _get_vnf_link_port_id(self, inst, vdu, index, cp):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
link_port_id = cp_info['vnfLinkPortId']
|
||||
break
|
||||
return link_port_id
|
||||
|
||||
def _get_vnfc_flavor(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
# must exist
|
||||
return vnfc['metadata']['flavor']
|
||||
|
||||
def _get_vnfc_cps(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return {cp_info['cpdId'] for cp_info in vnfc['vnfcCpInfo']}
|
||||
|
||||
def _get_vnfc_cp_net_name(self, inst, vdu, index, cp):
|
||||
# this is for internal CPs
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
link_port_id = cp_info['vnfLinkPortId']
|
||||
break
|
||||
for vl in inst['instantiatedVnfInfo']['vnfVirtualLinkResourceInfo']:
|
||||
for port in vl['vnfLinkPorts']:
|
||||
if port['id'] == link_port_id:
|
||||
# must be found
|
||||
return vl['vnfVirtualLinkDescId']
|
||||
|
||||
def _check_for_show_operation(
|
||||
self, operation, expected_inst_attrs, inst_id,
|
||||
vdu_result=None, image_result=None):
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
if operation == 'INSTANTIATE':
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
if operation == 'SCALE':
|
||||
# check scaleStatus
|
||||
scale_status = body['instantiatedVnfInfo']['scaleStatus']
|
||||
self.assertGreater(len(scale_status), 0)
|
||||
for status in scale_status:
|
||||
self.assertIn('aspectId', status)
|
||||
self.assertIn('scaleLevel', status)
|
||||
|
||||
# check instantiatedVnfInfo's information
|
||||
# check number of VDU, and index
|
||||
if vdu_result:
|
||||
self.assertEqual(vdu_result['VDU1'],
|
||||
self._get_vdu_indexes(body, 'VDU1'))
|
||||
self.assertEqual(vdu_result['VDU2'],
|
||||
self._get_vdu_indexes(body, 'VDU2'))
|
||||
# check exist of VDU-image
|
||||
if image_result:
|
||||
for result_1 in image_result['VDU1']:
|
||||
self.assertIn(
|
||||
result_1,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU1'))
|
||||
for result_2 in image_result['VDU2']:
|
||||
self.assertIn(
|
||||
result_2,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU2'))
|
||||
|
||||
return body
|
||||
|
||||
def test_basic_lcms_max(self):
|
||||
"""Test LCM operations for individual vnfc mgmt with all attributes set
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Create VNF
|
||||
- 1. Instantiate VNF
|
||||
- 2. Show VNF instance(check for instantiate)
|
||||
- 3. List VNF instance with attribute-based filtering
|
||||
- 4. Show VNF LCM operation occurrence
|
||||
- 5. Heal VNF(all with omit all parameter)
|
||||
- 6. Show VNF instance(check for heal)
|
||||
- 7. List VNF LCM operation occurrence with attribute-based
|
||||
filtering
|
||||
- 8. Heal VNF(all with all=True parameter)
|
||||
- 9. Show VNF instance(check for heal)
|
||||
- 10. Scale out operation
|
||||
- 11. Show VNF instance(check for scale)
|
||||
- 12. Scale in operation
|
||||
- 13. Show VNF instance(check for scale)
|
||||
- 14. Heal VNF(vnfc)
|
||||
- 15. Show VNF instance(check for heal)
|
||||
- 16. Change external connectivity
|
||||
- 17. Show VNF instance(check for change-ext-conn)
|
||||
- 18. Heal VNF(vnfc with omit all parameter)
|
||||
- 19. Show VNF instance(check for heal)
|
||||
- 20. Heal VNF(vnfc with all=False parameter)
|
||||
- 21. Show VNF instance(check for heal)
|
||||
- 22. Heal VNF(vnfc with all=True parameter)
|
||||
- 23. Show VNF instance(check for heal)
|
||||
- 24. Update VNF
|
||||
- 25. Show VNF instance(check for update)
|
||||
- 26. Update VNF(again)
|
||||
- 27. Change current VNF Package
|
||||
- 28. Show VNF instance(check for change-vnfpkg)
|
||||
- 29. Terminate VNF
|
||||
- 30. Delete VNF
|
||||
"""
|
||||
# 0. Create VNF
|
||||
create_req = paramgen.create_vnf_max(
|
||||
self.max_vnfd_id,
|
||||
description="test for basic_lcms_max_individual_vnfc")
|
||||
_, body = self.create_vnf_instance(create_req)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
self.net_ids, self.subnet_ids, None, self.auth_url,
|
||||
user_data=True)
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check that the servers set in "zone:Affinity" are
|
||||
# deployed on 'nova' AZ.
|
||||
# NOTE: local_nfvo returns this AZ
|
||||
vdu1_details = self.get_server_details('VDU1')
|
||||
vdu2_details = self.get_server_details('VDU2')
|
||||
vdu1_az = vdu1_details.get('OS-EXT-AZ:availability_zone')
|
||||
vdu2_az = vdu2_details.get('OS-EXT-AZ:availability_zone')
|
||||
self.assertEqual('nova', vdu1_az)
|
||||
self.assertEqual('nova', vdu2_az)
|
||||
|
||||
# 2. Show VNF instance(check for instantiate)
|
||||
# NOTE: extensions and vnfConfigurableProperties are omitted
|
||||
# because they are commented out in etsi_nfv_sol001.
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
'vimConnectionInfo',
|
||||
'instantiationState',
|
||||
'instantiatedVnfInfo',
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
inst_2 = self._check_for_show_operation(
|
||||
'INSTANTIATE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 3. List VNF instance with attribute-based filtering
|
||||
# check Link in 'list_vnf_instance'
|
||||
# The Response Header will contain a 'Link' Header only when there
|
||||
# are at least two vnf instance data in the database, so it needs to
|
||||
# create an unused data.
|
||||
create_req = paramgen.create_vnf_min(self.min_vnfd_id)
|
||||
_, tmp_body = self.create_vnf_instance(create_req)
|
||||
resp, body = self.list_vnf_instance()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_index(resp)
|
||||
# * all_fields
|
||||
# -> check the attribute omitted in "exclude_default" is set.
|
||||
filter_expr = {'filter': f'(eq,id,{inst_id})', 'all_fields': ''}
|
||||
resp, body = self.list_vnf_instance(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for inst in body:
|
||||
self.assertIn('vimConnectionInfo', inst)
|
||||
self.assertIn('instantiatedVnfInfo', inst)
|
||||
self.assertIn('metadata', inst)
|
||||
# * fields=<list>
|
||||
# -> check the attribute specified in "fields" is set
|
||||
filter_expr = {'filter': f'(eq,id,{inst_id})',
|
||||
'fields': 'metadata'}
|
||||
resp, body = self.list_vnf_instance(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for inst in body:
|
||||
self.assertNotIn('vimConnectionInfo', inst)
|
||||
self.assertNotIn('instantiatedVnfInfo', inst)
|
||||
self.assertIn('metadata', inst)
|
||||
# * exclude_fields=<list>
|
||||
# -> check the attribute specified in "exclude_fields" is not set
|
||||
filter_expr = {'filter': f'(eq,id,{inst_id})',
|
||||
'exclude_fields': 'metadata'}
|
||||
resp, body = self.list_vnf_instance(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for inst in body:
|
||||
self.assertIn('vimConnectionInfo', inst)
|
||||
self.assertIn('instantiatedVnfInfo', inst)
|
||||
self.assertNotIn('metadata', inst)
|
||||
# * exclude_default
|
||||
# -> check the attribute omitted in "exclude_default" is not set.
|
||||
filter_expr = {'filter': f'(eq,id,{inst_id})',
|
||||
'exclude_default': ''}
|
||||
resp, body = self.list_vnf_instance(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for inst in body:
|
||||
self.assertNotIn('vimConnectionInfo', inst)
|
||||
self.assertNotIn('instantiatedVnfInfo', inst)
|
||||
self.assertNotIn('metadata', inst)
|
||||
self.delete_vnf_instance(tmp_body['id'])
|
||||
|
||||
# 4. Show VNF LCM operation occurrence
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
# 'error', # omitted
|
||||
'resourceChanges',
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 5. Heal VNF(all with omit all parameter)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter()
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 6. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_6 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_6, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_2, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_6, 'VDU2', 0))
|
||||
# check images are not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_6, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_image(inst_2, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_6, 'VDU2', 0))
|
||||
|
||||
# 7. List VNF LCM operation occurrence with attribute-based filtering
|
||||
# * all_fields
|
||||
# -> check the attribute omitted in "exclude_default" is set.
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_index(resp)
|
||||
filter_expr = {'filter': f'(eq,id,{lcmocc_id})', 'all_fields': ''}
|
||||
resp, body = self.list_lcmocc(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for lcmocc in body:
|
||||
self.assertIn('operationParams', lcmocc)
|
||||
self.assertIn('resourceChanges', lcmocc)
|
||||
# * fields=<list>
|
||||
# -> check the attribute specified in "fields" is set
|
||||
filter_expr = {'filter': f'(eq,id,{lcmocc_id})',
|
||||
'fields': 'operationParams'}
|
||||
resp, body = self.list_lcmocc(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for lcmocc in body:
|
||||
self.assertIn('operationParams', lcmocc)
|
||||
self.assertNotIn('resourceChanges', lcmocc)
|
||||
# * exclude_fields=<list>
|
||||
# -> check the attribute specified in "exclude_fields" is not set
|
||||
filter_expr = {'filter': f'(eq,id,{lcmocc_id})',
|
||||
'exclude_fields': 'operationParams'}
|
||||
resp, body = self.list_lcmocc(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for lcmocc in body:
|
||||
self.assertNotIn('operationParams', lcmocc)
|
||||
self.assertIn('resourceChanges', lcmocc)
|
||||
# * exclude_default
|
||||
# -> check the attribute omitted in "exclude_default" is not set.
|
||||
filter_expr = {'filter': f'(eq,id,{lcmocc_id})',
|
||||
'exclude_default': ''}
|
||||
resp, body = self.list_lcmocc(filter_expr)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
for lcmocc in body:
|
||||
self.assertNotIn('operationParams', lcmocc)
|
||||
self.assertNotIn('resourceChanges', lcmocc)
|
||||
|
||||
# 8. Heal VNF(all with all=True parameter)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(True)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 9. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_9 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_6, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_9, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_6, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_9, 'VDU2', 0))
|
||||
# check storage ids are changed
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_6, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_9, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_6, 'VDU2', 0),
|
||||
self._get_vnfc_storage_ids(inst_9, 'VDU2', 0))
|
||||
# check cps are changed
|
||||
for cp_1 in ['VDU1_CP1', 'VDU1_CP2', 'VDU2_CP2']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(inst_6, cp_1.split('_')[0], 0, cp_1),
|
||||
self._get_vnf_ext_cp_id(inst_9, cp_1.split('_')[0], 0, cp_1))
|
||||
for cp_2 in ['VDU1_CP3', 'VDU1_CP4', 'VDU1_CP5',
|
||||
'VDU2_CP3', 'VDU2_CP4', 'VDU2_CP5']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_link_port_id(inst_6,
|
||||
cp_2.split('_')[0], 0, cp_2),
|
||||
self._get_vnf_link_port_id(inst_9,
|
||||
cp_2.split('_')[0], 0, cp_2))
|
||||
|
||||
# 10. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
self._add_additional_params(scaleout_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 11. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0',
|
||||
'image-VDU1-VirtualStorage-1'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
_ = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 12. Scale in operation
|
||||
scalein_req = paramgen.scalein_vnf_max()
|
||||
self._add_additional_params(scalein_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scalein_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 13. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
inst_13 = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 14. Heal VNF(vnfc)
|
||||
vnfc_info = inst_13['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_id = [vnfc['id'] for vnfc in vnfc_info
|
||||
if ("VDU2" == vnfc['vduId'])][0]
|
||||
heal_req = paramgen.heal_vnf_vnfc_max(vnfc_id)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 15. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_15 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check id of VDU2 is changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_13, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_15, 'VDU2', 0))
|
||||
# check image of VDU2 is not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_13, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_15, 'VDU2', 0))
|
||||
|
||||
# 16. Change external connectivity
|
||||
change_ext_conn_req = paramgen.change_ext_conn_max(
|
||||
self.net_ids, self.subnet_ids, self.auth_url)
|
||||
self._add_additional_params(change_ext_conn_req)
|
||||
resp, body = self.change_ext_conn(inst_id, change_ext_conn_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 17. Show VNF instance(check for change-ext-conn)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_17 = self._check_for_show_operation(
|
||||
'CHANGE_EXT_CONN', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check vnfExtCPIds of VDU are changed
|
||||
for ext_cp in ['VDU1_CP1', 'VDU2_CP2']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_15, ext_cp.split('_')[0], 0, ext_cp),
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_17, ext_cp.split('_')[0], 0, ext_cp))
|
||||
|
||||
# 18. Heal VNF(vnfc with omit all parameter)
|
||||
vnfc_info = inst_17['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
heal_req = paramgen.heal_vnf_vnfc_max_with_parameter(vnfc_ids)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 19. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_19 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_17, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_19, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_17, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_19, 'VDU2', 0))
|
||||
# check images are not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_17, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_19, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_image(inst_17, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_19, 'VDU2', 0))
|
||||
|
||||
# 20. Heal VNF(vnfc with all=False parameter)
|
||||
vnfc_info = inst_19['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
heal_req = paramgen.heal_vnf_vnfc_max_with_parameter(vnfc_ids, False)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 21. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_21 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_19, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_21, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_19, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_21, 'VDU2', 0))
|
||||
# check images are not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_19, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_21, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_image(inst_19, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_21, 'VDU2', 0))
|
||||
|
||||
# 22. Heal VNF(vnfc with all=True parameter)
|
||||
vnfc_info = inst_21['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
heal_req = paramgen.heal_vnf_vnfc_max_with_parameter(vnfc_ids, True)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 23. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_23 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_21, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_23, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_21, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_23, 'VDU2', 0))
|
||||
# check storage ids are changed
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_21, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_23, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_21, 'VDU2', 0),
|
||||
self._get_vnfc_storage_ids(inst_23, 'VDU2', 0))
|
||||
# 24. Update VNF
|
||||
# check attribute value before update VNF
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
# check usageState of update VNF Package
|
||||
self.check_package_usage(self.upd_max_pkg)
|
||||
# check vnfd id
|
||||
self.assertEqual(self.max_vnfd_id, inst_23['vnfdId'])
|
||||
|
||||
vnfc_info = inst_23['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
update_req = paramgen.update_vnf_max(self.upd_max_vnfd_id, vnfc_ids)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 25. Show VNF instance(check for update)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_25 = self._check_for_show_operation(
|
||||
'MODIFY_INFO', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg)
|
||||
# check usageState of update max pattern VNF Package
|
||||
self.check_package_usage(self.upd_max_pkg, 'IN_USE')
|
||||
self.assertEqual(self.upd_max_vnfd_id, inst_25['vnfdId'])
|
||||
self.assertEqual('new name', inst_25['vnfInstanceName'])
|
||||
self.assertEqual('new description', inst_25['vnfInstanceDescription'])
|
||||
dummy_key_value = {'dummy-key': 'dummy-value'}
|
||||
self.assertEqual(dummy_key_value, inst_25['metadata'])
|
||||
self.assertEqual(dummy_key_value, inst_25['extensions'])
|
||||
self.assertEqual(dummy_key_value, inst_25['vnfConfigurableProperties'])
|
||||
|
||||
# 26. Update VNF(again)
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg)
|
||||
# check usageState of update max pattern VNF Package
|
||||
self.check_package_usage(self.upd_max_pkg, 'IN_USE')
|
||||
# check vnfd id
|
||||
self.assertEqual(self.upd_max_vnfd_id, inst_25['vnfdId'])
|
||||
|
||||
update_req = paramgen.update_vnf_min_with_parameter(self.max_vnfd_id)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 27. Change current VNF Package
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
# check usageState of update max pattern VNF Package
|
||||
self.check_package_usage(self.upd_max_pkg)
|
||||
# check usageState of new max pattern VNF Package
|
||||
self.check_package_usage(self.new_max_pkg)
|
||||
change_vnf_pkg_req = paramgen.change_vnf_pkg_individual_vnfc_max(
|
||||
self.new_max_vnfd_id, self.net_ids, self.subnet_ids)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnf_pkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 28. Show VNF instance(check for change-vnfpkg)
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg)
|
||||
# check usageState of new max pattern VNF Package
|
||||
self.check_package_usage(self.new_max_pkg, 'IN_USE')
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_28 = self._check_for_show_operation(
|
||||
'CHANGE_VNFPKG', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check vnfdId
|
||||
self.assertEqual(self.new_max_vnfd_id, inst_28['vnfdId'])
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_25, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_28, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_25, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_28, 'VDU2', 0))
|
||||
# check images of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_25, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_28, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_25, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_28, 'VDU2', 0))
|
||||
self.assertEqual('cirros-0.5.2-x86_64-disk',
|
||||
self._get_vnfc_image(inst_28, 'VDU1', 0))
|
||||
self.assertEqual('cirros-0.5.2-x86_64-disk',
|
||||
self._get_vnfc_image(inst_28, 'VDU2', 0))
|
||||
# check flavor is changed (VDU2 only)
|
||||
self.assertNotEqual(self._get_vnfc_flavor(inst_25, 'VDU2', 0),
|
||||
self._get_vnfc_flavor(inst_28, 'VDU2', 0))
|
||||
# check vnfExtCPId of VDU1_CP1 is changed
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(inst_25, 'VDU1', 0, 'VDU1_CP1'),
|
||||
self._get_vnf_ext_cp_id(inst_28, 'VDU1', 0, 'VDU1_CP1'))
|
||||
# check external CPs, VDU1_CP6 and VDU2_CP6 are added
|
||||
self.assertFalse('VDU1_CP6' in self._get_vnfc_cps(inst_25, 'VDU1', 0))
|
||||
self.assertFalse('VDU2_CP6' in self._get_vnfc_cps(inst_25, 'VDU2', 0))
|
||||
self.assertTrue('VDU1_CP6' in self._get_vnfc_cps(inst_28, 'VDU1', 0))
|
||||
self.assertTrue('VDU2_CP6' in self._get_vnfc_cps(inst_28, 'VDU2', 0))
|
||||
# check internal CPs, VDU1_CP5 and VDU2_CP5 are changed
|
||||
self.assertEqual("internalVL3", self._get_vnfc_cp_net_name(
|
||||
inst_25, 'VDU1', 0, 'VDU1_CP5'))
|
||||
self.assertEqual("internalVL3", self._get_vnfc_cp_net_name(
|
||||
inst_25, 'VDU2', 0, 'VDU2_CP5'))
|
||||
self.assertEqual("internalVL4", self._get_vnfc_cp_net_name(
|
||||
inst_28, 'VDU1', 0, 'VDU1_CP5'))
|
||||
self.assertEqual("internalVL4", self._get_vnfc_cp_net_name(
|
||||
inst_28, 'VDU2', 0, 'VDU2_CP5'))
|
||||
|
||||
# 29. Terminate VNF
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 30. Delete VNF
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
@ -0,0 +1,425 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import string
|
||||
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional.sol_v2_common import base_v2
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests import utils
|
||||
|
||||
SUPPORT_STRING_FOR_VNFD_ID = f"{string.ascii_letters}{string.digits}-._ "
|
||||
MIN_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}min_vnfd_id"
|
||||
UPD_NEW_MIN_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}upd_new_min_vnfd_id"
|
||||
|
||||
|
||||
class IndividualVnfcMgmtBasicMinTest(base_v2.BaseSolV2Test):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(IndividualVnfcMgmtBasicMinTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
userdata_path = utils.userdata("userdata_standard.py")
|
||||
|
||||
# vnf package for basic lcms tests min pattern
|
||||
pkg_path_1 = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_min_individual_vnfc")
|
||||
cls.min_pkg, cls.min_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_1, userdata_path=userdata_path,
|
||||
vnfd_id=MIN_VNFD_ID)
|
||||
|
||||
# vnf package for change vnf package or update min pattern
|
||||
pkg_path_2 = utils.test_sample("functional/sol_v2_common",
|
||||
"change_vnfpkg_or_update_min_individual_vnfc")
|
||||
cls.upd_new_min_pkg, cls.upd_new_min_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_2, image_path=image_path, userdata_path=userdata_path,
|
||||
vnfd_id=UPD_NEW_MIN_VNFD_ID)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(IndividualVnfcMgmtBasicMinTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.min_pkg)
|
||||
cls.delete_vnf_package(cls.upd_new_min_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
def _get_vdu_indexes(self, inst, vdu):
|
||||
return {
|
||||
vnfc['metadata'].get('vdu_idx')
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']
|
||||
if vnfc['vduId'] == vdu
|
||||
}
|
||||
|
||||
def _get_vnfc_metadata_keys(self, inst, vdu):
|
||||
vnfc_metadata_keys = set()
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if vnfc['vduId'] == vdu:
|
||||
vnfc_metadata_keys.update(set(vnfc['metadata'].keys()))
|
||||
return vnfc_metadata_keys
|
||||
|
||||
def _add_additional_params(self, req):
|
||||
if not req.get('additionalParams'):
|
||||
req['additionalParams'] = {}
|
||||
req['additionalParams']['lcm-operation-user-data'] = (
|
||||
'./UserData/userdata_standard.py')
|
||||
req['additionalParams']['lcm-operation-user-data-class'] = (
|
||||
'StandardUserData')
|
||||
|
||||
def _get_vnfc_by_vdu_index(self, inst, vdu, index):
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if (vnfc['vduId'] == vdu and
|
||||
vnfc['metadata'].get('vdu_idx') == index):
|
||||
return vnfc
|
||||
|
||||
def _get_vnfc_id(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return vnfc['id']
|
||||
|
||||
def _get_vnfc_image(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for key, value in vnfc['metadata'].items():
|
||||
if key.startswith('image-'):
|
||||
# must be found
|
||||
return value
|
||||
|
||||
def _get_vnfc_flavor(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
# must exist
|
||||
return vnfc['metadata']['flavor']
|
||||
|
||||
def _check_for_show_operation(
|
||||
self, operation, expected_inst_attrs, inst_id,
|
||||
vdu_result=None, image_result=None):
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
if operation == 'INSTANTIATE':
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
if operation == 'SCALE':
|
||||
# check scaleStatus
|
||||
scale_status = body['instantiatedVnfInfo']['scaleStatus']
|
||||
self.assertGreater(len(scale_status), 0)
|
||||
for status in scale_status:
|
||||
self.assertIn('aspectId', status)
|
||||
self.assertIn('scaleLevel', status)
|
||||
|
||||
# check instantiatedVnfInfo's information
|
||||
# check number of VDU, and index
|
||||
if vdu_result:
|
||||
self.assertEqual(vdu_result['VDU1'],
|
||||
self._get_vdu_indexes(body, 'VDU1'))
|
||||
self.assertEqual(vdu_result['VDU2'],
|
||||
self._get_vdu_indexes(body, 'VDU2'))
|
||||
# check exist of VDU-image
|
||||
if image_result:
|
||||
for result_1 in image_result['VDU1']:
|
||||
self.assertIn(
|
||||
result_1,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU1'))
|
||||
for result_2 in image_result['VDU2']:
|
||||
self.assertIn(
|
||||
result_2,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU2'))
|
||||
|
||||
return body
|
||||
|
||||
def test_basic_lcms_min(self):
|
||||
"""Test LCM operations with omitting except for required attributes
|
||||
|
||||
The change_ext_conn can't be tested here because min pattern VNF
|
||||
package 2 don't have external connectivity. So moved it to the
|
||||
test_various_lcm_operations_before_and_after().
|
||||
|
||||
* About attributes:
|
||||
Omit except for required attributes.
|
||||
Only the following cardinality attributes are set.
|
||||
- 1
|
||||
- 1..N (1)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Create VNF
|
||||
- 1. Instantiate VNF
|
||||
- 2. Show VNF instance(check for instantiate)
|
||||
- 3. Heal VNF(all with omit all parameter)
|
||||
- 4. Show VNF instance(check for heal)
|
||||
- 5. Scale out operation
|
||||
- 6. Show VNF instance(check for scale)
|
||||
- 7. Update VNF
|
||||
- 8. Show VNF instance(check for update)
|
||||
- 9. Heal VNF(vnfc)
|
||||
- 10. Show VNF instance(check for heal)
|
||||
- 11. Scale in operation
|
||||
- 12. Show VNF instance(check for scale)
|
||||
- 13. Terminate VNF
|
||||
- 14. Update VNF again
|
||||
- 15. Instantiate VNF again
|
||||
- 16. Change current VNF Package
|
||||
- 17. Show VNF instance(check for change-vnfpkg)
|
||||
- 18. Terminate VNF again
|
||||
- 19. Delete VNF
|
||||
"""
|
||||
# 0. Create VNF
|
||||
create_req = paramgen.create_vnf_min(self.min_vnfd_id)
|
||||
_, body = self.create_vnf_instance(create_req)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF
|
||||
instantiate_req = paramgen.instantiate_vnf_min()
|
||||
self._add_additional_params(instantiate_req)
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check that the servers set in "nfvi_node:Affinity" are
|
||||
# deployed on the same host.
|
||||
# NOTE: it's up to heat to decide which host to deploy to
|
||||
vdu1_details = self.get_server_details('VDU1')
|
||||
vdu2_details = self.get_server_details('VDU2')
|
||||
vdu1_host = vdu1_details['hostId']
|
||||
vdu2_host = vdu2_details['hostId']
|
||||
self.assertEqual(vdu1_host, vdu2_host)
|
||||
|
||||
# 2. Show VNF instance(check for instantiate)
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
# 'vnfInstanceName', # omitted
|
||||
# 'vnfInstanceDescription', # omitted
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
'vimConnectionInfo',
|
||||
'instantiationState',
|
||||
'instantiatedVnfInfo',
|
||||
# 'metadata', # omitted
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-0'},
|
||||
'VDU2': {'image-VDU2-0'}}
|
||||
inst_2 = self._check_for_show_operation(
|
||||
'INSTANTIATE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 3. Heal VNF(all with omit all parameter)
|
||||
heal_req = paramgen.heal_vnf_all_min()
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 4. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_4 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_4, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_2, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_4, 'VDU2', 0))
|
||||
|
||||
# 5. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_min()
|
||||
self._add_additional_params(scaleout_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 6. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-0', 'image-VDU1-1'},
|
||||
'VDU2': {'image-VDU2-0'}}
|
||||
_ = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 7. Update VNF
|
||||
update_req = paramgen.update_vnf_min_with_parameter(
|
||||
self.upd_new_min_vnfd_id)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
# check usageState of min pattern VNF Package
|
||||
self.check_package_usage(self.min_pkg)
|
||||
# check usageState of update or new min pattern VNF Package
|
||||
self.check_package_usage(self.upd_new_min_pkg, 'IN_USE')
|
||||
|
||||
# 8. Show VNF instance(check for update)
|
||||
inst_8 = self._check_for_show_operation(
|
||||
'MODIFY_INFO', expected_inst_attrs, inst_id)
|
||||
self.assertEqual(self.upd_new_min_vnfd_id, inst_8['vnfdId'])
|
||||
|
||||
# 9. Heal VNF(vnfc)
|
||||
vnfc_info = inst_8['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_id = [vnfc['id'] for vnfc in vnfc_info
|
||||
if (vnfc['vnfcResourceInfoId'] ==
|
||||
self._get_vnfc_id(inst_8, 'VDU1', 1))][0]
|
||||
heal_req = paramgen.heal_vnf_vnfc_min(vnfc_id)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 10. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
inst_10 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check id of VDU1 with index 1 is changed, with index 0 is not changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_8, 'VDU1', 1),
|
||||
self._get_vnfc_id(inst_10, 'VDU1', 1))
|
||||
self.assertEqual(self._get_vnfc_id(inst_8, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_10, 'VDU1', 0))
|
||||
# check image value of image-VDU1-1 is changed, others are not changed
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_8, 'VDU1', 1),
|
||||
self._get_vnfc_image(inst_10, 'VDU1', 1))
|
||||
self.assertEqual(self._get_vnfc_image(inst_8, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_10, 'VDU1', 0))
|
||||
|
||||
# 11. Scale in operation
|
||||
scalein_req = paramgen.scalein_vnf_min()
|
||||
self._add_additional_params(scalein_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scalein_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 12. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-0'},
|
||||
'VDU2': {'image-VDU2-0'}}
|
||||
_ = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 13. Terminate VNF
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 14. Update VNF again
|
||||
update_req = paramgen.update_vnf_min_with_parameter(self.min_vnfd_id)
|
||||
resp, body = self.exec_lcm_operation(self.update_vnf_instance,
|
||||
inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
# check usageState of min pattern VNF Package
|
||||
self.check_package_usage(self.min_pkg, 'IN_USE')
|
||||
# check usageState of update or new min pattern VNF Package
|
||||
self.check_package_usage(self.upd_new_min_pkg)
|
||||
|
||||
# 15. Instantiate VNF again
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
inst_15 = self._check_for_show_operation(
|
||||
'INSTANTIATE', expected_inst_attrs, inst_id)
|
||||
|
||||
# 16. Change current VNF Package
|
||||
change_vnf_pkg_req = paramgen.change_vnf_pkg_individual_vnfc_min(
|
||||
self.upd_new_min_vnfd_id)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnf_pkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 17. Show VNF instance(check for change-vnfpkg)
|
||||
# check usageState of min pattern VNF Package
|
||||
self.check_package_usage(self.min_pkg)
|
||||
# check usageState of update or new min pattern VNF Package
|
||||
self.check_package_usage(self.upd_new_min_pkg, 'IN_USE')
|
||||
inst_17 = self._check_for_show_operation(
|
||||
'CHANGE_VNFPKG', expected_inst_attrs, inst_id)
|
||||
# check vnfdId
|
||||
self.assertEqual(self.upd_new_min_vnfd_id, inst_17['vnfdId'])
|
||||
# check ids of VDU are not changed
|
||||
self.assertEqual(self._get_vnfc_id(inst_15, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_17, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_id(inst_15, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_17, 'VDU2', 0))
|
||||
# check image of VDU1 is changed
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_15, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_17, 'VDU1', 0))
|
||||
# check flavors of VDU are not changed
|
||||
self.assertEqual(self._get_vnfc_flavor(inst_15, 'VDU1', 0),
|
||||
self._get_vnfc_flavor(inst_17, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_flavor(inst_15, 'VDU2', 0),
|
||||
self._get_vnfc_flavor(inst_17, 'VDU2', 0))
|
||||
|
||||
# 18. Terminate VNF again
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 19. Delete VNF
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
@ -0,0 +1,454 @@
|
||||
# Copyright (C) 2022 Nippon Telegraph and Telephone Corporation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
import tacker.conf
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests.functional.sol_v2_common import test_vnflcm_basic_common
|
||||
from tacker.tests.functional.sol_v2_common import zipgen
|
||||
from tacker.tests import utils
|
||||
|
||||
|
||||
CONF = tacker.conf.CONF
|
||||
|
||||
|
||||
class IndividualVnfcMgmtCcvpTest(test_vnflcm_basic_common.CommonVnfLcmTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(IndividualVnfcMgmtCcvpTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
userdata_path = utils.userdata("userdata_standard.py")
|
||||
|
||||
# main vnf package for StandardUserData test
|
||||
cls.standard_vnfd_id, zip_path = zipgen.userdata_standard()
|
||||
cls.standard_pkg = cls.upload_vnf_package(zip_path)
|
||||
|
||||
# for change_vnfpkg network/flavor change test
|
||||
pkg_path_2 = utils.test_sample("functional/sol_v2_common",
|
||||
"userdata_standard_change_vnfpkg_nw")
|
||||
cls.new_nw_pkg, cls.new_nw_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_2, image_path=image_path, userdata_path=userdata_path)
|
||||
|
||||
# for attach non-boot volume to VDU test
|
||||
pkg_path_3 = utils.test_sample("functional/sol_v2_common",
|
||||
"userdata_standard_with_non_boot_volume")
|
||||
cls.non_boot_volume_pkg, cls.non_boot_volume_vnfd_id = (
|
||||
cls.create_vnf_package(pkg_path_3, image_path=image_path,
|
||||
userdata_path=userdata_path))
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(IndividualVnfcMgmtCcvpTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.standard_pkg)
|
||||
cls.delete_vnf_package(cls.new_nw_pkg)
|
||||
cls.delete_vnf_package(cls.non_boot_volume_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
def _get_vdu_indexes(self, inst, vdu):
|
||||
return {
|
||||
vnfc['metadata'].get('vdu_idx')
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']
|
||||
if vnfc['vduId'] == vdu
|
||||
}
|
||||
|
||||
def _get_vnfc_by_vdu_index(self, inst, vdu, index):
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if (vnfc['vduId'] == vdu and
|
||||
vnfc['metadata'].get('vdu_idx') == index):
|
||||
return vnfc
|
||||
|
||||
def _get_vnfc_id(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return vnfc['id']
|
||||
|
||||
def _get_vnfc_cps(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return {cp_info['cpdId'] for cp_info in vnfc['vnfcCpInfo']}
|
||||
|
||||
def _get_vnfc_cp_net_id(self, inst, vdu, index, cp):
|
||||
# this is for external CPs
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
ext_cp_id = cp_info['vnfExtCpId']
|
||||
break
|
||||
for ext_vl in inst['instantiatedVnfInfo']['extVirtualLinkInfo']:
|
||||
for port in ext_vl['extLinkPorts']:
|
||||
if port['cpInstanceId'] == ext_cp_id:
|
||||
# must be found
|
||||
return ext_vl['resourceHandle']['resourceId']
|
||||
|
||||
def _get_vnfc_cp_net_name(self, inst, vdu, index, cp):
|
||||
# this is for internal CPs
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
link_port_id = cp_info['vnfLinkPortId']
|
||||
break
|
||||
for vl in inst['instantiatedVnfInfo']['vnfVirtualLinkResourceInfo']:
|
||||
for port in vl['vnfLinkPorts']:
|
||||
if port['id'] == link_port_id:
|
||||
# must be found
|
||||
return vl['vnfVirtualLinkDescId']
|
||||
|
||||
def _get_vnfc_image(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for key, value in vnfc['metadata'].items():
|
||||
if key.startswith('image-'):
|
||||
# must be found
|
||||
return value
|
||||
|
||||
def _get_vnfc_flavor(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
# must exist
|
||||
return vnfc['metadata']['flavor']
|
||||
|
||||
def _get_vnfc_storage_ids(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
storage_res_ids = vnfc.get('storageResourceIds', [])
|
||||
return sorted(storage_res_ids)
|
||||
|
||||
def test_change_vnfpkg_nw(self):
|
||||
"""Test change_vnfpkg with additional functions
|
||||
|
||||
* Note:
|
||||
This test focuses change_vnfpkg with the following changes.
|
||||
- adding external CP
|
||||
- change internal network
|
||||
- change flavor
|
||||
|
||||
TODO: add another patterns (ex. change extMgdVLs)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- Create VNF instance
|
||||
- 1. Instantiate VNF instance
|
||||
- Show VNF instance / check
|
||||
- 2. Change_vnfpkg operation
|
||||
- Show VNF instance / check
|
||||
- Terminate VNF instance
|
||||
- Delete VNF instance
|
||||
"""
|
||||
|
||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
||||
|
||||
# Create VNF instance
|
||||
create_req = paramgen.sample3_create(self.standard_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF instance
|
||||
instantiate_req = paramgen.sample3_instantiate(
|
||||
net_ids, subnet_ids, self.auth_url)
|
||||
instantiate_req['instantiationLevelId'] = "instantiation_level_2"
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_1 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check number of VDUs and indexes
|
||||
self.assertEqual({0, 1}, self._get_vdu_indexes(inst_1, 'VDU1'))
|
||||
self.assertEqual({0}, self._get_vdu_indexes(inst_1, 'VDU2'))
|
||||
|
||||
# 2. Change_vnfpkg operation
|
||||
change_vnfpkg_req = paramgen.sample5_change_vnfpkg(self.new_nw_vnfd_id,
|
||||
net_ids, subnet_ids)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnfpkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_2 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check vnfdId is changed
|
||||
self.assertEqual(self.new_nw_vnfd_id, inst_2['vnfdId'])
|
||||
# check images are changed
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_1, 'VDU1', 1),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 1))
|
||||
self.assertNotEqual(self._get_vnfc_image(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU2', 0))
|
||||
# check flavor is changed (VDU2 only)
|
||||
self.assertNotEqual(self._get_vnfc_flavor(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_flavor(inst_2, 'VDU2', 0))
|
||||
# check external CPs; VDU1_CP4 and VDU2_CP4 are added
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_1, 'VDU1', 0))
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_1, 'VDU1', 1))
|
||||
self.assertFalse('VDU2_CP4' in self._get_vnfc_cps(inst_1, 'VDU2', 0))
|
||||
self.assertTrue('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 0))
|
||||
self.assertTrue('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 1))
|
||||
self.assertTrue('VDU2_CP4' in self._get_vnfc_cps(inst_2, 'VDU2', 0))
|
||||
self.assertEqual(net_ids['net0'],
|
||||
self._get_vnfc_cp_net_id(inst_2, 'VDU1', 0, 'VDU1_CP4'))
|
||||
self.assertEqual(net_ids['net0'],
|
||||
self._get_vnfc_cp_net_id(inst_2, 'VDU1', 1, 'VDU1_CP4'))
|
||||
self.assertEqual(net_ids['net0'],
|
||||
self._get_vnfc_cp_net_id(inst_2, 'VDU2', 0, 'VDU2_CP4'))
|
||||
# check internal CPs; VDU1_CP3 and VDU2_CP3 are changed
|
||||
self.assertEqual("internalVL2",
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 0, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL2",
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 1, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL2",
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU2', 0, 'VDU2_CP3'))
|
||||
self.assertEqual("internalVL3",
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 0, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL3",
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 1, 'VDU1_CP3'))
|
||||
self.assertEqual("internalVL3",
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU2', 0, 'VDU2_CP3'))
|
||||
|
||||
# Terminate VNF instance
|
||||
terminate_req = paramgen.sample5_terminate()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Delete VNF instance
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_change_vnfpkg_nw_rollback(self):
|
||||
"""Test rollback of change_vnfpkg with additional functions
|
||||
|
||||
* Note:
|
||||
This test focuses rollback of change_vnfpkg with the following
|
||||
changes.
|
||||
- adding external CP
|
||||
- change internal network
|
||||
- change flavor
|
||||
|
||||
TODO: add another patterns (ex. change extMgdVLs)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- Create VNF instance
|
||||
- 1. Instantiate VNF instance
|
||||
- Show VNF instance / check
|
||||
- 2. Change_vnfpkg operation => FAILED_TEMP
|
||||
- Rollback
|
||||
- Show VNF instance / check
|
||||
- Terminate VNF instance
|
||||
- Delete VNF instance
|
||||
"""
|
||||
|
||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
||||
|
||||
# Create VNF instance
|
||||
create_req = paramgen.sample3_create(self.standard_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF instance
|
||||
instantiate_req = paramgen.sample3_instantiate(
|
||||
net_ids, subnet_ids, self.auth_url)
|
||||
instantiate_req['instantiationLevelId'] = "instantiation_level_2"
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_1 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check number of VDUs and indexes
|
||||
self.assertEqual({0, 1}, self._get_vdu_indexes(inst_1, 'VDU1'))
|
||||
self.assertEqual({0}, self._get_vdu_indexes(inst_1, 'VDU2'))
|
||||
|
||||
# 2. Change_vnfpkg operation
|
||||
self.put_fail_file('change_vnfpkg')
|
||||
change_vnfpkg_req = paramgen.sample5_change_vnfpkg(self.new_nw_vnfd_id,
|
||||
net_ids, subnet_ids)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnfpkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
self.rm_fail_file('change_vnfpkg')
|
||||
|
||||
# Rollback
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_2 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check vnfdId is not changed
|
||||
self.assertEqual(self.standard_vnfd_id, inst_2['vnfdId'])
|
||||
# check images are not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_image(inst_1, 'VDU1', 1),
|
||||
self._get_vnfc_image(inst_2, 'VDU1', 1))
|
||||
self.assertEqual(self._get_vnfc_image(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_2, 'VDU2', 0))
|
||||
# check flavor is not changed (VDU2 only)
|
||||
self.assertEqual(self._get_vnfc_flavor(inst_1, 'VDU2', 0),
|
||||
self._get_vnfc_flavor(inst_2, 'VDU2', 0))
|
||||
# check external CPs; VDU1_CP4 and VDU2_CP4 are not added
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 0))
|
||||
self.assertFalse('VDU1_CP4' in self._get_vnfc_cps(inst_2, 'VDU1', 1))
|
||||
self.assertFalse('VDU2_CP4' in self._get_vnfc_cps(inst_2, 'VDU2', 0))
|
||||
# check internal CPs; VDU1_CP3 and VDU2_CP3 are not changed
|
||||
self.assertEqual(
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 0, 'VDU1_CP3'),
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 0, 'VDU1_CP3'))
|
||||
self.assertEqual(
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU1', 1, 'VDU1_CP3'),
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU1', 1, 'VDU1_CP3'))
|
||||
self.assertEqual(
|
||||
self._get_vnfc_cp_net_name(inst_1, 'VDU2', 0, 'VDU2_CP3'),
|
||||
self._get_vnfc_cp_net_name(inst_2, 'VDU2', 0, 'VDU2_CP3'))
|
||||
|
||||
# Terminate VNF instance
|
||||
terminate_req = paramgen.sample3_terminate()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Delete VNF instance
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_instantiate_attach_non_boot_volume(self):
|
||||
"""Test Instantiate with non-boot volume attached to VDU
|
||||
|
||||
* Note:
|
||||
This test focuses on the non-boot volume attached by
|
||||
OS::Cinder::VolumeAttachment in HOT being registered to
|
||||
storageResourceIds.
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- Create VNF instance
|
||||
- 1. Instantiate VNF instance
|
||||
- Show VNF instance / check
|
||||
- 2. Heal operation("all"=True)
|
||||
- Show VNF instance / check
|
||||
- 3. Heal operation("all" is not specified)
|
||||
- Show VNF instance / check
|
||||
- Terminate VNF instance
|
||||
- Delete VNF instance
|
||||
"""
|
||||
|
||||
net_ids = self.get_network_ids(['net0', 'net1', 'net_mgmt'])
|
||||
subnet_ids = self.get_subnet_ids(['subnet0', 'subnet1'])
|
||||
|
||||
# Create VNF instance
|
||||
create_req = paramgen.sample7_create(self.non_boot_volume_vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF instance
|
||||
instantiate_req = paramgen.sample7_instantiate(
|
||||
net_ids, subnet_ids, self.auth_url)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_1 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check number of VDUs and indexes
|
||||
self.assertEqual({0}, self._get_vdu_indexes(inst_1, 'VDU1'))
|
||||
|
||||
# check storageResourceIds of attached non-boot volume
|
||||
self.assertNotEqual([], self._get_vnfc_storage_ids(inst_1, 'VDU1', 0))
|
||||
|
||||
# 2. Heal operation("all"=True)
|
||||
# VDU1-0 to heal
|
||||
heal_req = paramgen.sample7_heal('a-001')
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_2 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check id of VDU1-0 is changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_2, 'VDU1', 0))
|
||||
|
||||
# check storageResourceIds of VDU1-0 is changed
|
||||
self.assertNotEqual([], self._get_vnfc_storage_ids(inst_2, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_1, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_2, 'VDU1', 0))
|
||||
|
||||
# 3. Heal operation("all" is not specified)
|
||||
# VDU1-0 to heal
|
||||
heal_req['vnfcInstanceId'] = ['a-001']
|
||||
del heal_req['additionalParams']['all']
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Show VNF instance
|
||||
resp, inst_3 = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
# check id of VDU1-0 is changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_3, 'VDU1', 0))
|
||||
|
||||
# check storageResourceIds of VDU1-0 is not changed
|
||||
self.assertEqual(self._get_vnfc_storage_ids(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_3, 'VDU1', 0))
|
||||
|
||||
# Terminate VNF instance
|
||||
terminate_req = paramgen.sample7_terminate()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# Delete VNF instance
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
@ -0,0 +1,917 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import string
|
||||
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional.sol_v2_common import base_v2
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests import utils
|
||||
|
||||
SUPPORT_STRING_FOR_VNFD_ID = f"{string.ascii_letters}{string.digits}-._ "
|
||||
MAX_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}max_vnfd_id"
|
||||
MIN_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}min_vnfd_id"
|
||||
NEW_MAX_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}new_max_vnfd_id"
|
||||
UPD_NEW_MIN_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}upd_new_min_vnfd_id"
|
||||
|
||||
|
||||
class IndividualVnfcMgmtErrorHandlingTest(base_v2.BaseSolV2Test):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(IndividualVnfcMgmtErrorHandlingTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
userdata_path = utils.userdata("userdata_standard.py")
|
||||
|
||||
# vnf package for basic lcms tests max pattern
|
||||
pkg_path_1 = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_max_individual_vnfc")
|
||||
cls.max_pkg, cls.max_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_1, image_path=image_path,
|
||||
userdata_path=userdata_path, vnfd_id=MAX_VNFD_ID)
|
||||
|
||||
# vnf package for basic lcms tests min pattern
|
||||
pkg_path_2 = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_min_individual_vnfc")
|
||||
cls.min_pkg, cls.min_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_2, userdata_path=userdata_path,
|
||||
vnfd_id=MIN_VNFD_ID)
|
||||
|
||||
# vnf package for change vnf package max pattern
|
||||
pkg_path_3 = utils.test_sample("functional/sol_v2_common",
|
||||
"change_vnfpkg_max_individual_vnfc")
|
||||
cls.new_max_pkg, cls.new_max_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_3, userdata_path=userdata_path,
|
||||
vnfd_id=NEW_MAX_VNFD_ID)
|
||||
|
||||
# vnf package for change vnf package or update min pattern
|
||||
pkg_path_4 = utils.test_sample("functional/sol_v2_common",
|
||||
"change_vnfpkg_or_update_min_individual_vnfc")
|
||||
cls.upd_new_min_pkg, cls.upd_new_min_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_4, image_path=image_path, userdata_path=userdata_path,
|
||||
vnfd_id=UPD_NEW_MIN_VNFD_ID)
|
||||
|
||||
cls.expected_list_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
# 'grantId', # omitted
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
# 'operationParams', # omitted
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
# 'error', # omitted
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
|
||||
cls._pre_setting()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(IndividualVnfcMgmtErrorHandlingTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.max_pkg)
|
||||
cls.delete_vnf_package(cls.min_pkg)
|
||||
cls.delete_vnf_package(cls.new_max_pkg)
|
||||
cls.delete_vnf_package(cls.upd_new_min_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@classmethod
|
||||
def _pre_setting(cls):
|
||||
# Create a new network and subnet to check the IP allocation of
|
||||
# IPv4 and IPv6
|
||||
ft_net0_name = 'ft-net0'
|
||||
ft_net0_subs = {
|
||||
'ft-ipv4-subnet0': {
|
||||
'range': '100.100.100.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet0': {
|
||||
'range': '1111:2222:3333::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net0_id = cls.create_network(cls, ft_net0_name)
|
||||
cls.addClassCleanup(cls.delete_network, cls, ft_net0_id)
|
||||
for sub_name, val in ft_net0_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
cls.create_subnet(
|
||||
cls, ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
# Create a new network for change external connectivity
|
||||
ft_net1_name = 'ft-net1'
|
||||
ft_net1_subs = {
|
||||
'ft-ipv4-subnet1': {
|
||||
'range': '22.22.22.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet1': {
|
||||
'range': '1111:2222:4444::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net1_id = cls.create_network(cls, ft_net1_name)
|
||||
cls.addClassCleanup(cls.delete_network, cls, ft_net1_id)
|
||||
for sub_name, val in ft_net1_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
cls.create_subnet(
|
||||
cls, ft_net1_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
cls.net_ids = cls.get_network_ids(
|
||||
cls, ['net0', 'net1', 'net_mgmt', 'ft-net0', 'ft-net1'])
|
||||
cls.subnet_ids = cls.get_subnet_ids(
|
||||
cls, ['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0',
|
||||
'ft-ipv4-subnet1', 'ft-ipv6-subnet1'])
|
||||
|
||||
def _get_vdu_indexes(self, inst, vdu):
|
||||
return {
|
||||
vnfc['metadata'].get('vdu_idx')
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']
|
||||
if vnfc['vduId'] == vdu
|
||||
}
|
||||
|
||||
def _get_vnfc_metadata_keys(self, inst, vdu):
|
||||
vnfc_metadata_keys = set()
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if vnfc['vduId'] == vdu:
|
||||
vnfc_metadata_keys.update(set(vnfc['metadata'].keys()))
|
||||
return vnfc_metadata_keys
|
||||
|
||||
def _add_additional_params(self, req):
|
||||
if not req.get('additionalParams'):
|
||||
req['additionalParams'] = {}
|
||||
req['additionalParams']['lcm-operation-user-data'] = (
|
||||
'./UserData/userdata_standard.py')
|
||||
req['additionalParams']['lcm-operation-user-data-class'] = (
|
||||
'StandardUserData')
|
||||
|
||||
def _get_vnfc_by_vdu_index(self, inst, vdu, index):
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if (vnfc['vduId'] == vdu and
|
||||
vnfc['metadata'].get('vdu_idx') == index):
|
||||
return vnfc
|
||||
|
||||
def _get_vnfc_image(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for key, value in vnfc['metadata'].items():
|
||||
if key.startswith('image-'):
|
||||
# must be found
|
||||
return value
|
||||
|
||||
def _get_vnfc_flavor(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
# must exist
|
||||
return vnfc['metadata']['flavor']
|
||||
|
||||
def _get_vnfc_cps(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return {cp_info['cpdId'] for cp_info in vnfc['vnfcCpInfo']}
|
||||
|
||||
def _get_vnfc_cp_net_name(self, inst, vdu, index, cp):
|
||||
# this is for internal CPs
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
link_port_id = cp_info['vnfLinkPortId']
|
||||
break
|
||||
for vl in inst['instantiatedVnfInfo']['vnfVirtualLinkResourceInfo']:
|
||||
for port in vl['vnfLinkPorts']:
|
||||
if port['id'] == link_port_id:
|
||||
# must be found
|
||||
return vl['vnfVirtualLinkDescId']
|
||||
|
||||
def _check_for_show_operation(
|
||||
self, operation, expected_inst_attrs, inst_id,
|
||||
vdu_result=None, image_result=None):
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
if operation == 'INSTANTIATE':
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
if operation == 'SCALE':
|
||||
# check scaleStatus
|
||||
scale_status = body['instantiatedVnfInfo']['scaleStatus']
|
||||
self.assertGreater(len(scale_status), 0)
|
||||
for status in scale_status:
|
||||
self.assertIn('aspectId', status)
|
||||
self.assertIn('scaleLevel', status)
|
||||
|
||||
# check instantiatedVnfInfo's information
|
||||
# check number of VDU, and index
|
||||
if vdu_result:
|
||||
self.assertEqual(vdu_result['VDU1'],
|
||||
self._get_vdu_indexes(body, 'VDU1'))
|
||||
self.assertEqual(vdu_result['VDU2'],
|
||||
self._get_vdu_indexes(body, 'VDU2'))
|
||||
# check exist of VDU-image
|
||||
if image_result:
|
||||
for result_1 in image_result['VDU1']:
|
||||
self.assertIn(
|
||||
result_1,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU1'))
|
||||
for result_2 in image_result['VDU2']:
|
||||
self.assertIn(
|
||||
result_2,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU2'))
|
||||
|
||||
return body
|
||||
|
||||
def test_retry_rollback_scale_out(self):
|
||||
"""Test retry and rollback scale out operations
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Create VNF
|
||||
- 1. Instantiate VNF
|
||||
- 2. Show VNF instance
|
||||
- 3. Scale out operation(will fail)
|
||||
- 4. Show VNF instance
|
||||
- 5. Retry operation
|
||||
- 6. Rollback scale out operation
|
||||
- 7. Show VNF LCM operation occurrence
|
||||
- 8. List VNF LCM operation occurrence
|
||||
- 9. Terminate VNF
|
||||
- 10. Delete VNF
|
||||
"""
|
||||
# 0. Create VNF
|
||||
create_req = paramgen.create_vnf_max(
|
||||
self.max_vnfd_id,
|
||||
description="test for retry and rollback scale out")
|
||||
_, body = self.create_vnf_instance(create_req)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF instance
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
self.net_ids, self.subnet_ids, None, self.auth_url,
|
||||
user_data=True)
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 2. Show VNF instance(check for instantiate)
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
'vimConnectionInfo',
|
||||
'instantiationState',
|
||||
'instantiatedVnfInfo',
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
_ = self._check_for_show_operation(
|
||||
'INSTANTIATE', expected_inst_attrs, inst_id)
|
||||
|
||||
# 3. Scale out operation(will fail)
|
||||
self.put_fail_file('scale_end')
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
self._add_additional_params(scaleout_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
|
||||
# 4. Show VNF instance
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# 5. Retry scale out operation
|
||||
resp, body = self.retry_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
self.rm_fail_file('scale_end')
|
||||
|
||||
# 6. Rollback scale out operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 7. Show VNF LCM operation occurrence
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 8. List VNF LCM operation occurrence
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_index(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, self.expected_list_attrs)
|
||||
|
||||
# 9. Terminate VNF instance
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# 10. Delete VNF
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_rollback_instantiate(self):
|
||||
"""Test rollback instantiate operation
|
||||
|
||||
* About attributes:
|
||||
Omit except for required attributes.
|
||||
Only the following cardinality attributes are set.
|
||||
- 1
|
||||
- 1..N (1)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Create VNF
|
||||
- 1. Instantiate VNF(will fail)
|
||||
- 2. Show VNF instance
|
||||
- 3. Rollback instantiation operation
|
||||
- 4. Show VNF LCM operation occurrence
|
||||
- 5. List VNF LCM operation occurrence
|
||||
- 6. Delete VNF
|
||||
"""
|
||||
# 0. Create VNF
|
||||
create_req = paramgen.create_vnf_min(self.min_vnfd_id)
|
||||
_, body = self.create_vnf_instance(create_req)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF(will fail)
|
||||
self.put_fail_file('instantiate_end')
|
||||
instantiate_req = paramgen.instantiate_vnf_min()
|
||||
self._add_additional_params(instantiate_req)
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
self.rm_fail_file('instantiate_end')
|
||||
|
||||
# 2. Show VNF instance
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
# 'vnfInstanceName', # omitted
|
||||
# 'vnfInstanceDescription', # omitted
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
# 'vimConnectionInfo', # omitted
|
||||
'instantiationState',
|
||||
# 'instantiatedVnfInfo', # omitted
|
||||
# 'metadata', # omitted
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body.get('instantiationState'))
|
||||
|
||||
# 3. Rollback instantiation operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 4. Show VNF LCM operation occurrence
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 5. List VNF LCM operation occurrence
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_index(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, self.expected_list_attrs)
|
||||
|
||||
# 6. Delete VNF
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_rollback_chgextconn_and_update(self):
|
||||
"""Test rollback change_ext_conn and update operation
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Create VNF
|
||||
- 1. Instantiate VNF
|
||||
- 2. Show VNF instance
|
||||
- 3. Change external connectivity(will fail)
|
||||
- 4. Rollback change_ext_conn operation
|
||||
- 5. Show VNF LCM operation occurrence
|
||||
- 6. List VNF LCM operation occurrence
|
||||
- 7. Update VNF(will fail)
|
||||
- 8. Rollback update operation
|
||||
- 9. Show VNF LCM operation occurrence
|
||||
- 10. List VNF LCM operation occurrence
|
||||
- 11. Terminate VNF
|
||||
- 12. Delete VNF
|
||||
"""
|
||||
# 0. Create VNF
|
||||
create_req = paramgen.create_vnf_max(self.max_vnfd_id)
|
||||
_, body = self.create_vnf_instance(create_req)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
self.net_ids, self.subnet_ids, None, self.auth_url,
|
||||
user_data=True)
|
||||
self._add_additional_params(instantiate_req)
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 2. Show VNF instance
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
# 'vnfInstanceName', # omitted
|
||||
# 'vnfInstanceDescription', # omitted
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
'vimConnectionInfo',
|
||||
'instantiationState',
|
||||
'instantiatedVnfInfo',
|
||||
# 'metadata', # omitted
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
_ = self._check_for_show_operation(
|
||||
'INSTANTIATE', expected_inst_attrs, inst_id)
|
||||
|
||||
# 3. Change external connectivity(will fail)
|
||||
self.put_fail_file('change_external_connectivity_end')
|
||||
change_ext_conn_req = paramgen.change_ext_conn_min(
|
||||
self.net_ids, self.subnet_ids)
|
||||
self._add_additional_params(change_ext_conn_req)
|
||||
resp, body = self.change_ext_conn(inst_id, change_ext_conn_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
self.rm_fail_file('change_external_connectivity_end')
|
||||
|
||||
# 4. Rollback change_ext_conn operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 5. Show VNF LCM operation occurrence
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# Confirm that the operation failed in change_ext_conn_end after
|
||||
# change_ext_conn.
|
||||
self.assertIn(
|
||||
'change_external_connectivity_end failed', body['error']['detail'])
|
||||
|
||||
# 6. List VNF LCM operation occurrence
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_index(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, self.expected_list_attrs)
|
||||
|
||||
# 7. Update VNF(will fail)
|
||||
self.put_fail_file('modify_information_start')
|
||||
update_req = paramgen.update_vnf_min()
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
self.rm_fail_file('modify_information_start')
|
||||
|
||||
# 8. Rollback update operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 9. Show VNF LCM operation occurrence
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
# 'grantId', # omitted
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 10. List VNF LCM operation occurrence
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_index(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, self.expected_list_attrs)
|
||||
|
||||
# 11. Terminate VNF
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 12. Delete VNF
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
||||
|
||||
def test_rollback_change_vnfpkg(self):
|
||||
"""Test rollback change_vnfpkg operation
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Create VNF
|
||||
- 1. Instantiate VNF
|
||||
- 2. Show VNF instance
|
||||
- 3. Change Current VNF Package(will fail)
|
||||
- 4. Rollback change_vnfpkg operation
|
||||
- 5. Show VNF LCM operation occurrence
|
||||
- 6. Show VNF instance
|
||||
- 7. Change Current VNF Package(will fail)
|
||||
- 8. Rollback change_vnfpkg operation
|
||||
- 9. Show VNF LCM operation occurrence
|
||||
- 10. List VNF LCM operation occurrence
|
||||
- 11. Show VNF instance
|
||||
- 12. Terminate VNF
|
||||
- 13. Delete VNF
|
||||
"""
|
||||
# 0. Create VNF
|
||||
create_req = paramgen.create_vnf_max(
|
||||
self.max_vnfd_id,
|
||||
description="test for rollback change vnf package")
|
||||
_, body = self.create_vnf_instance(create_req)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
self.net_ids, self.subnet_ids, None, self.auth_url,
|
||||
user_data=True)
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 2. Show VNF instance(check for instantiate)
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
'vimConnectionInfo',
|
||||
'instantiationState',
|
||||
'instantiatedVnfInfo',
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
inst_2 = self._check_for_show_operation(
|
||||
'INSTANTIATE', expected_inst_attrs, inst_id)
|
||||
|
||||
# 3. Change Current VNF Package(will fail)
|
||||
self.put_fail_file('change_vnfpkg')
|
||||
change_vnf_pkg_req = paramgen.change_vnf_pkg_individual_vnfc_max(
|
||||
self.new_max_vnfd_id, self.net_ids, self.subnet_ids)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnf_pkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
self.rm_fail_file('change_vnfpkg')
|
||||
|
||||
# 4. Rollback change_vnfpkg operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 5. Show VNF LCM operation occurrence
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# 6. Show VNF instance
|
||||
_, inst_6 = self.show_vnf_instance(inst_id)
|
||||
# check vnfdId
|
||||
self.assertEqual(self.max_vnfd_id, inst_6['vnfdId'])
|
||||
# check images of VDU are not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_6, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_image(inst_2, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_6, 'VDU2', 0))
|
||||
# check flavor of VDU2 is not changed
|
||||
self.assertEqual(self._get_vnfc_flavor(inst_2, 'VDU2', 0),
|
||||
self._get_vnfc_flavor(inst_6, 'VDU2', 0))
|
||||
# check external CPs, VDU1_CP6 and VDU2_CP6 are not added
|
||||
self.assertFalse('VDU1_CP6' in self._get_vnfc_cps(inst_2, 'VDU1', 0))
|
||||
self.assertFalse('VDU2_CP6' in self._get_vnfc_cps(inst_2, 'VDU2', 0))
|
||||
self.assertFalse('VDU1_CP6' in self._get_vnfc_cps(inst_6, 'VDU1', 0))
|
||||
self.assertFalse('VDU2_CP6' in self._get_vnfc_cps(inst_6, 'VDU2', 0))
|
||||
# check internal CPs, VDU1_CP5 and VDU2_CP5 are not changed
|
||||
self.assertEqual("internalVL3", self._get_vnfc_cp_net_name(
|
||||
inst_2, 'VDU1', 0, 'VDU1_CP5'))
|
||||
self.assertEqual("internalVL3", self._get_vnfc_cp_net_name(
|
||||
inst_2, 'VDU2', 0, 'VDU2_CP5'))
|
||||
self.assertEqual("internalVL3", self._get_vnfc_cp_net_name(
|
||||
inst_6, 'VDU1', 0, 'VDU1_CP5'))
|
||||
self.assertEqual("internalVL3", self._get_vnfc_cp_net_name(
|
||||
inst_6, 'VDU2', 0, 'VDU2_CP5'))
|
||||
|
||||
# 7. Change Current VNF Package(will fail)
|
||||
# This operation intentionally performs an operation outside the
|
||||
# supported range, making it in the FAILED_TEMP state to test the
|
||||
# rollback operation in this case.
|
||||
# supported cases:
|
||||
# 1. change VM created by image to VM created by new image
|
||||
# 2. change VM created by volume to VM created by new volume
|
||||
change_vnf_pkg_req = paramgen.change_vnf_pkg_individual_vnfc_min(
|
||||
self.upd_new_min_vnfd_id, vdu2_old_vnfc='VDU2_CP2')
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnf_pkg_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_failed_temp(lcmocc_id)
|
||||
|
||||
# 8. Rollback change_vnfpkg operation
|
||||
resp, body = self.rollback_lcmocc(lcmocc_id)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
self.wait_lcmocc_rolled_back(lcmocc_id)
|
||||
|
||||
# 9. Show VNF LCM operation occurrence
|
||||
expected_attrs = [
|
||||
'id',
|
||||
'operationState',
|
||||
'stateEnteredTime',
|
||||
'startTime',
|
||||
'vnfInstanceId',
|
||||
'grantId',
|
||||
'operation',
|
||||
'isAutomaticInvocation',
|
||||
'operationParams',
|
||||
'isCancelPending',
|
||||
# 'cancelMode', # omitted
|
||||
'error',
|
||||
# 'resourceChanges', # omitted
|
||||
# 'changedInfo', # omitted
|
||||
# 'changedExtConnectivity', # omitted
|
||||
# 'modificationsTriggeredByVnfPkgChange', # omitted
|
||||
# 'vnfSnapshotInfoId', # omitted
|
||||
'_links'
|
||||
]
|
||||
resp, body = self.show_lcmocc(lcmocc_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_attrs)
|
||||
|
||||
# Confirm that the operation failed in change vnf package progress
|
||||
# while executing update_stack operation
|
||||
|
||||
self.assertIn('StackValidationFailed', body['error']['detail'])
|
||||
|
||||
# 10. List VNF LCM operation occurrence
|
||||
resp, body = self.list_lcmocc()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_index(resp)
|
||||
for lcmocc in body:
|
||||
self.check_resp_body(lcmocc, self.expected_list_attrs)
|
||||
|
||||
# 11. Show VNF instance
|
||||
_, inst_11 = self.show_vnf_instance(inst_id)
|
||||
# check vnfdId
|
||||
self.assertEqual(self.max_vnfd_id, inst_11['vnfdId'])
|
||||
# check images of VDU are not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_2, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_11, 'VDU1', 0))
|
||||
self.assertEqual(self._get_vnfc_image(inst_2, 'VDU2', 0),
|
||||
self._get_vnfc_image(inst_11, 'VDU2', 0))
|
||||
|
||||
# 12. Terminate VNF
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 13. Delete VNF
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
@ -0,0 +1,801 @@
|
||||
# Copyright (C) 2023 Fujitsu
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import string
|
||||
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional.sol_v2_common import base_v2
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests import utils
|
||||
|
||||
SUPPORT_STRING_FOR_VNFD_ID = f"{string.ascii_letters}{string.digits}-._ "
|
||||
MAX_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}max_vnfd_id"
|
||||
UPD_MAX_VNFD_ID = f"{SUPPORT_STRING_FOR_VNFD_ID}upd_max_vnfd_id"
|
||||
|
||||
|
||||
class IndividualVnfcMgmtVariousLcmTest(base_v2.BaseSolV2Test):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(IndividualVnfcMgmtVariousLcmTest, cls).setUpClass()
|
||||
image_path = utils.test_etc_sample("etsi/nfv/common/Files/images",
|
||||
"cirros-0.5.2-x86_64-disk.img")
|
||||
|
||||
userdata_path = utils.userdata("userdata_standard.py")
|
||||
|
||||
# vnf package for basic lcms tests max pattern
|
||||
pkg_path_1 = utils.test_sample("functional/sol_v2_common",
|
||||
"basic_lcms_max_individual_vnfc")
|
||||
cls.max_pkg, cls.max_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_1, image_path=image_path,
|
||||
userdata_path=userdata_path, vnfd_id=MAX_VNFD_ID)
|
||||
|
||||
# vnf package for update vnf max pattern
|
||||
pkg_path_2 = utils.test_sample("functional/sol_v2_common",
|
||||
"update_vnf_max_individual_vnfc")
|
||||
cls.upd_max_pkg, cls.upd_max_vnfd_id = cls.create_vnf_package(
|
||||
pkg_path_2, image_path=image_path,
|
||||
userdata_path=userdata_path, vnfd_id=UPD_MAX_VNFD_ID)
|
||||
|
||||
cls._pre_setting()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(IndividualVnfcMgmtVariousLcmTest, cls).tearDownClass()
|
||||
cls.delete_vnf_package(cls.max_pkg)
|
||||
cls.delete_vnf_package(cls.upd_max_pkg)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@classmethod
|
||||
def _pre_setting(cls):
|
||||
# Create a new network and subnet to check the IP allocation of
|
||||
# IPv4 and IPv6
|
||||
ft_net0_name = 'ft-net0'
|
||||
ft_net0_subs = {
|
||||
'ft-ipv4-subnet0': {
|
||||
'range': '100.100.100.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet0': {
|
||||
'range': '1111:2222:3333::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net0_id = cls.create_network(cls, ft_net0_name)
|
||||
cls.addClassCleanup(cls.delete_network, cls, ft_net0_id)
|
||||
for sub_name, val in ft_net0_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
cls.create_subnet(
|
||||
cls, ft_net0_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
# Create a new network for change external connectivity
|
||||
ft_net1_name = 'ft-net1'
|
||||
ft_net1_subs = {
|
||||
'ft-ipv4-subnet1': {
|
||||
'range': '22.22.22.0/24',
|
||||
'ip_version': 4
|
||||
},
|
||||
'ft-ipv6-subnet1': {
|
||||
'range': '1111:2222:4444::/64',
|
||||
'ip_version': 6
|
||||
}
|
||||
}
|
||||
ft_net1_id = cls.create_network(cls, ft_net1_name)
|
||||
cls.addClassCleanup(cls.delete_network, cls, ft_net1_id)
|
||||
for sub_name, val in ft_net1_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
cls.create_subnet(
|
||||
cls, ft_net1_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
cls.net_ids = cls.get_network_ids(
|
||||
cls, ['net0', 'net1', 'net_mgmt', 'ft-net0', 'ft-net1'])
|
||||
cls.subnet_ids = cls.get_subnet_ids(
|
||||
cls, ['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0',
|
||||
'ft-ipv4-subnet1', 'ft-ipv6-subnet1'])
|
||||
|
||||
def _get_vdu_indexes(self, inst, vdu):
|
||||
return {
|
||||
vnfc['metadata'].get('vdu_idx')
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']
|
||||
if vnfc['vduId'] == vdu
|
||||
}
|
||||
|
||||
def _get_vnfc_metadata_keys(self, inst, vdu):
|
||||
vnfc_metadata_keys = set()
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if vnfc['vduId'] == vdu:
|
||||
vnfc_metadata_keys.update(set(vnfc['metadata'].keys()))
|
||||
return vnfc_metadata_keys
|
||||
|
||||
def _add_additional_params(self, req):
|
||||
if not req.get('additionalParams'):
|
||||
req['additionalParams'] = {}
|
||||
req['additionalParams']['lcm-operation-user-data'] = (
|
||||
'./UserData/userdata_standard.py')
|
||||
req['additionalParams']['lcm-operation-user-data-class'] = (
|
||||
'StandardUserData')
|
||||
|
||||
def _get_vnfc_by_vdu_index(self, inst, vdu, index):
|
||||
for vnfc in inst['instantiatedVnfInfo']['vnfcResourceInfo']:
|
||||
if (vnfc['vduId'] == vdu and
|
||||
vnfc['metadata'].get('vdu_idx') == index):
|
||||
return vnfc
|
||||
|
||||
def _get_vnfc_id(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return vnfc['id']
|
||||
|
||||
def _get_vnfc_image(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for key, value in vnfc['metadata'].items():
|
||||
if key.startswith('image-'):
|
||||
# must be found
|
||||
return value
|
||||
|
||||
def _get_vnfc_storage_ids(self, inst, vdu, index):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
return vnfc['storageResourceIds']
|
||||
|
||||
def _get_vnf_ext_cp_id(self, inst, vdu, index, cp):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
ext_cp_id = cp_info['vnfExtCpId']
|
||||
break
|
||||
return ext_cp_id
|
||||
|
||||
def _get_vnf_link_port_id(self, inst, vdu, index, cp):
|
||||
vnfc = self._get_vnfc_by_vdu_index(inst, vdu, index)
|
||||
for cp_info in vnfc['vnfcCpInfo']:
|
||||
if cp_info['cpdId'] == cp:
|
||||
# must be found
|
||||
link_port_id = cp_info['vnfLinkPortId']
|
||||
break
|
||||
return link_port_id
|
||||
|
||||
def _check_for_show_operation(
|
||||
self, operation, expected_inst_attrs, inst_id,
|
||||
vdu_result=None, image_result=None):
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
|
||||
# check vnfState of VNF
|
||||
self.assertEqual(fields.VnfOperationalStateType.STARTED,
|
||||
body['instantiatedVnfInfo']['vnfState'])
|
||||
|
||||
if operation == 'INSTANTIATE':
|
||||
# check instantiationState of VNF
|
||||
self.assertEqual(fields.VnfInstanceState.INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
if operation == 'SCALE':
|
||||
# check scaleStatus
|
||||
scale_status = body['instantiatedVnfInfo']['scaleStatus']
|
||||
self.assertGreater(len(scale_status), 0)
|
||||
for status in scale_status:
|
||||
self.assertIn('aspectId', status)
|
||||
self.assertIn('scaleLevel', status)
|
||||
|
||||
# check instantiatedVnfInfo's information
|
||||
# check number of VDU, and index
|
||||
if vdu_result:
|
||||
self.assertEqual(vdu_result['VDU1'],
|
||||
self._get_vdu_indexes(body, 'VDU1'))
|
||||
self.assertEqual(vdu_result['VDU2'],
|
||||
self._get_vdu_indexes(body, 'VDU2'))
|
||||
# check exist of VDU-image
|
||||
if image_result:
|
||||
for result_1 in image_result['VDU1']:
|
||||
self.assertIn(
|
||||
result_1,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU1'))
|
||||
for result_2 in image_result['VDU2']:
|
||||
self.assertIn(
|
||||
result_2,
|
||||
self._get_vnfc_metadata_keys(body, 'VDU2'))
|
||||
|
||||
return body
|
||||
|
||||
def test_various_lcm_operations_before_and_after(self):
|
||||
"""Test various vnflcm operations before and after
|
||||
|
||||
* About attributes:
|
||||
All of the following cardinality attributes are set.
|
||||
In addition, 0..N or 1..N attributes are set to 2 or more.
|
||||
0..1 is set to 1.
|
||||
- 0..1 (1)
|
||||
- 0..N (2 or more)
|
||||
- 1..N (2 or more)
|
||||
|
||||
* About LCM operations:
|
||||
This test includes the following operations.
|
||||
- 0. Create VNF
|
||||
- 1. Instantiate VNF
|
||||
- 2. Show VNF instance
|
||||
- 3. Scale out operation
|
||||
- 4. Show VNF instance(check for scale)
|
||||
- 5. Heal VNF(vnfc)
|
||||
- 6. Show VNF instance(check for heal)
|
||||
- 7. Scale out operation
|
||||
- 8. Show VNF instance(check for scale)
|
||||
- 9. Scale in operation
|
||||
- 10. Show VNF instance(check for scale)
|
||||
- 11. Heal VNF(all with all=True parameter)
|
||||
- 12. Show VNF instance(check for heal)
|
||||
- 13. Scale in operation
|
||||
- 14. Show VNF instance(check for scale)
|
||||
- 15. Heal VNF(vnfc)
|
||||
- 16. Show VNF instance(check for heal)
|
||||
- 17. Scale out operation
|
||||
- 18. Show VNF instance(check for scale)
|
||||
- 19. Heal VNF(all with all=True parameter)
|
||||
- 20. Show VNF instance(check for heal)
|
||||
- 21. Change external connectivity
|
||||
- 22. Show VNF instance(check for change-ext-conn)
|
||||
- 23. Scale in operation
|
||||
- 24. Show VNF instance(check for scale)
|
||||
- 25. Update VNF
|
||||
- 26. Show VNF instance(check for update)
|
||||
- 27. Scale out operation
|
||||
- 28. Heal VNF(all with omit all parameter)
|
||||
- 29. Heal VNF(all with all=False parameter)
|
||||
- 30. Heal VNF(all with all=True parameter)
|
||||
- 31. Terminate VNF
|
||||
- 32. Delete VNF
|
||||
"""
|
||||
# 0. Create VNF
|
||||
create_req = paramgen.create_vnf_max(
|
||||
self.max_vnfd_id, description="test for various lcm operations")
|
||||
_, body = self.create_vnf_instance(create_req)
|
||||
inst_id = body['id']
|
||||
|
||||
# 1. Instantiate VNF
|
||||
instantiate_req = paramgen.instantiate_vnf_max(
|
||||
self.net_ids, self.subnet_ids, None, self.auth_url,
|
||||
user_data=True)
|
||||
resp, body = self.instantiate_vnf_instance(
|
||||
inst_id, instantiate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 2. Show VNF instance
|
||||
expected_inst_attrs = [
|
||||
'id',
|
||||
'vnfInstanceName',
|
||||
'vnfInstanceDescription',
|
||||
'vnfdId',
|
||||
'vnfProvider',
|
||||
'vnfProductName',
|
||||
'vnfSoftwareVersion',
|
||||
'vnfdVersion',
|
||||
# 'vnfConfigurableProperties', # omitted
|
||||
'vimConnectionInfo',
|
||||
'instantiationState',
|
||||
'instantiatedVnfInfo',
|
||||
'metadata',
|
||||
# 'extensions', # omitted
|
||||
'_links'
|
||||
]
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
_ = self._check_for_show_operation(
|
||||
'INSTANTIATE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 3. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
self._add_additional_params(scaleout_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 4. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0',
|
||||
'image-VDU1-VirtualStorage-1'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
inst_4 = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 5. Heal VNF(vnfc)
|
||||
vnfc_info = inst_4['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_id = [vnfc['id'] for vnfc in vnfc_info
|
||||
if (vnfc['vnfcResourceInfoId'] ==
|
||||
self._get_vnfc_id(inst_4, 'VDU1', 1))][0]
|
||||
heal_req = paramgen.heal_vnf_vnfc_max(vnfc_id)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 6. Show VNF instance(check for heal)
|
||||
inst_6 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id)
|
||||
|
||||
# check id of VDU1 with index 1 is changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_4, 'VDU1', 1),
|
||||
self._get_vnfc_id(inst_6, 'VDU1', 1))
|
||||
# check image of VDU1 with index 1 is not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_4, 'VDU1', 1),
|
||||
self._get_vnfc_image(inst_6, 'VDU1', 1))
|
||||
|
||||
# 7. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
self._add_additional_params(scaleout_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 8. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0, 1, 2}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0',
|
||||
'image-VDU1-VirtualStorage-1',
|
||||
'image-VDU1-VirtualStorage-2'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
_ = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 9. Scale in operation
|
||||
scalein_req = paramgen.scalein_vnf_max()
|
||||
self._add_additional_params(scalein_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scalein_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 10. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0',
|
||||
'image-VDU1-VirtualStorage-1'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
inst_10 = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 11. Heal VNF(all with all=True parameter)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(True)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 12. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
inst_12 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_10, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_12, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_10, 'VDU1', 1),
|
||||
self._get_vnfc_id(inst_12, 'VDU1', 1))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_10, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_12, 'VDU2', 0))
|
||||
# check storage ids are changed
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_10, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_12, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_10, 'VDU1', 1),
|
||||
self._get_vnfc_storage_ids(inst_12, 'VDU1', 1))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_10, 'VDU2', 0),
|
||||
self._get_vnfc_storage_ids(inst_12, 'VDU2', 0))
|
||||
# check cps are changed
|
||||
for cp_1 in ['VDU1_CP1', 'VDU1_CP2', 'VDU2_CP2']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(inst_10, cp_1.split('_')[0], 0, cp_1),
|
||||
self._get_vnf_ext_cp_id(inst_12, cp_1.split('_')[0], 0, cp_1))
|
||||
for cp_2 in ['VDU1_CP3', 'VDU1_CP4', 'VDU1_CP5',
|
||||
'VDU2_CP3', 'VDU2_CP4', 'VDU2_CP5']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_link_port_id(inst_10,
|
||||
cp_2.split('_')[0], 0, cp_2),
|
||||
self._get_vnf_link_port_id(inst_12,
|
||||
cp_2.split('_')[0], 0, cp_2))
|
||||
for ext_cp in ['VDU1_CP1', 'VDU1_CP2']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_10, ext_cp.split('_')[0], 1, ext_cp),
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_12, ext_cp.split('_')[0], 1, ext_cp))
|
||||
for link_port_cp in ['VDU1_CP3', 'VDU1_CP4', 'VDU1_CP5']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_link_port_id(
|
||||
inst_10, link_port_cp.split('_')[0], 1, link_port_cp),
|
||||
self._get_vnf_link_port_id(
|
||||
inst_12, link_port_cp.split('_')[0], 1, link_port_cp))
|
||||
|
||||
# 13. Scale in operation
|
||||
scalein_req = paramgen.scalein_vnf_max()
|
||||
self._add_additional_params(scalein_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scalein_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 14. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
inst_14 = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 15. Heal VNF(vnfc)
|
||||
vnfc_info = inst_14['instantiatedVnfInfo']['vnfcInfo']
|
||||
vnfc_id = [vnfc['id'] for vnfc in vnfc_info
|
||||
if (vnfc['vnfcResourceInfoId'] ==
|
||||
self._get_vnfc_id(inst_14, 'VDU1', 0))][0]
|
||||
heal_req = paramgen.heal_vnf_vnfc_max(vnfc_id)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 16. Show VNF instance(check for heal)
|
||||
inst_16 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id)
|
||||
|
||||
# check id of VDU1 with index 0 is changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_14, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_16, 'VDU1', 0))
|
||||
# check image of VDU1 with index 0 is not changed
|
||||
self.assertEqual(self._get_vnfc_image(inst_14, 'VDU1', 0),
|
||||
self._get_vnfc_image(inst_16, 'VDU1', 0))
|
||||
|
||||
# 17. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
self._add_additional_params(scaleout_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 18. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0',
|
||||
'image-VDU1-VirtualStorage-1'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
inst_18 = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 19. Heal VNF(all with all=True parameter)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(True)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 20. Show VNF instance(check for heal)
|
||||
vdu_result = {'VDU1': {0, 1}, 'VDU2': {0}}
|
||||
inst_20 = self._check_for_show_operation(
|
||||
'HEAL', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check all ids of VDU are changed
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_18, 'VDU1', 0),
|
||||
self._get_vnfc_id(inst_20, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_18, 'VDU1', 1),
|
||||
self._get_vnfc_id(inst_20, 'VDU1', 1))
|
||||
self.assertNotEqual(self._get_vnfc_id(inst_18, 'VDU2', 0),
|
||||
self._get_vnfc_id(inst_20, 'VDU2', 0))
|
||||
# check storage ids are changed
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_18, 'VDU1', 0),
|
||||
self._get_vnfc_storage_ids(inst_20, 'VDU1', 0))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_18, 'VDU1', 1),
|
||||
self._get_vnfc_storage_ids(inst_20, 'VDU1', 1))
|
||||
self.assertNotEqual(self._get_vnfc_storage_ids(inst_18, 'VDU2', 0),
|
||||
self._get_vnfc_storage_ids(inst_20, 'VDU2', 0))
|
||||
# check cps are changed
|
||||
for cp_1 in ['VDU1_CP1', 'VDU1_CP2', 'VDU2_CP2']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(inst_18, cp_1.split('_')[0], 0, cp_1),
|
||||
self._get_vnf_ext_cp_id(inst_20, cp_1.split('_')[0], 0, cp_1))
|
||||
for cp_2 in ['VDU1_CP3', 'VDU1_CP4', 'VDU1_CP5',
|
||||
'VDU2_CP3', 'VDU2_CP4', 'VDU2_CP5']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_link_port_id(inst_18,
|
||||
cp_2.split('_')[0], 0, cp_2),
|
||||
self._get_vnf_link_port_id(inst_20,
|
||||
cp_2.split('_')[0], 0, cp_2))
|
||||
for ext_cp in ['VDU1_CP1', 'VDU1_CP2']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_10, ext_cp.split('_')[0], 1, ext_cp),
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_12, ext_cp.split('_')[0], 1, ext_cp))
|
||||
for link_port_cp in ['VDU1_CP3', 'VDU1_CP4', 'VDU1_CP5']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_link_port_id(
|
||||
inst_10, link_port_cp.split('_')[0], 1, link_port_cp),
|
||||
self._get_vnf_link_port_id(
|
||||
inst_12, link_port_cp.split('_')[0], 1, link_port_cp))
|
||||
|
||||
# 21. Change external connectivity
|
||||
change_ext_conn_req = paramgen.change_ext_conn_max(
|
||||
self.net_ids, self.subnet_ids, self.auth_url)
|
||||
self._add_additional_params(change_ext_conn_req)
|
||||
resp, body = self.change_ext_conn(inst_id, change_ext_conn_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 22. Show VNF instance(check for change-ext-conn)
|
||||
inst_22 = self._check_for_show_operation(
|
||||
'CHANGE_EXT_CONN', expected_inst_attrs, inst_id)
|
||||
# check vnfExtCPIds of VDU are changed
|
||||
for ext_cp in ['VDU1_CP1', 'VDU2_CP2']:
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_20, ext_cp.split('_')[0], 0, ext_cp),
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_22, ext_cp.split('_')[0], 0, ext_cp))
|
||||
if ext_cp.split('_')[0] == 'VDU1':
|
||||
self.assertNotEqual(
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_20, ext_cp.split('_')[0], 1, ext_cp),
|
||||
self._get_vnf_ext_cp_id(
|
||||
inst_22, ext_cp.split('_')[0], 1, ext_cp))
|
||||
|
||||
# 23. Scale in operation
|
||||
scalein_req = paramgen.scalein_vnf_max()
|
||||
self._add_additional_params(scalein_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scalein_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 24. Show VNF instance(check for scale)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
image_result = {'VDU1': {'image-VDU1-VirtualStorage-0'},
|
||||
'VDU2': {'image-VDU2-VirtualStorage-0'}}
|
||||
inst_24 = self._check_for_show_operation(
|
||||
'SCALE', expected_inst_attrs, inst_id,
|
||||
vdu_result, image_result)
|
||||
|
||||
# 25. Update VNF
|
||||
# check attribute value before update VNF
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg, 'IN_USE')
|
||||
# check usageState of update max pattern VNF Package
|
||||
self.check_package_usage(self.upd_max_pkg)
|
||||
# check vnfd id
|
||||
self.assertEqual(self.max_vnfd_id, inst_24['vnfdId'])
|
||||
# check vnfc info
|
||||
vnfc_info = inst_24['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertGreater(len(vnfc_info), 1)
|
||||
vnfc_ids = [vnfc['id'] for vnfc in vnfc_info]
|
||||
for vnfc in vnfc_info:
|
||||
self.assertIn('id', vnfc)
|
||||
self.assertIn('vduId', vnfc)
|
||||
self.assertIsNotNone(vnfc.get('vnfcState'))
|
||||
self.assertIsNone(vnfc.get('vnfcConfigurableProperties'))
|
||||
|
||||
update_req = paramgen.update_vnf_max(self.upd_max_vnfd_id, vnfc_ids)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 26. Show VNF instance(check for update)
|
||||
vdu_result = {'VDU1': {0}, 'VDU2': {0}}
|
||||
inst_26 = self._check_for_show_operation(
|
||||
'MODIFY_INFO', expected_inst_attrs, inst_id, vdu_result)
|
||||
# check usageState of max pattern VNF Package
|
||||
self.check_package_usage(self.max_pkg)
|
||||
# check usageState of update max pattern VNF Package
|
||||
self.check_package_usage(self.upd_max_pkg, 'IN_USE')
|
||||
self.assertEqual(self.upd_max_vnfd_id, inst_26['vnfdId'])
|
||||
self.assertEqual('new name', inst_26['vnfInstanceName'])
|
||||
self.assertEqual('new description', inst_26['vnfInstanceDescription'])
|
||||
dummy_key_value = {'dummy-key': 'dummy-value'}
|
||||
self.assertEqual(dummy_key_value, inst_26['metadata'])
|
||||
self.assertEqual(dummy_key_value, inst_26['extensions'])
|
||||
self.assertEqual(dummy_key_value, inst_26['vnfConfigurableProperties'])
|
||||
vim_connection_info = {
|
||||
"vim2": {
|
||||
"vimId": "ac2d2ece-5e49-4b15-b92d-b681e9c096d8",
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {
|
||||
"endpoint": "http://127.0.0.1/identity/v3"
|
||||
},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {
|
||||
"dummy-key": "dummy-val"
|
||||
}
|
||||
}
|
||||
}
|
||||
self.assertEqual(vim_connection_info['vim2'],
|
||||
inst_26['vimConnectionInfo']['vim2'])
|
||||
|
||||
# check vnfc info
|
||||
vnfc_info = inst_26['instantiatedVnfInfo']['vnfcInfo']
|
||||
self.assertEqual(vnfc_ids[0], vnfc_info[0]['id'])
|
||||
self.assertEqual(vnfc_ids[1], vnfc_info[1]['id'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[0]['vnfcConfigurableProperties'])
|
||||
self.assertEqual(dummy_key_value,
|
||||
vnfc_info[1]['vnfcConfigurableProperties'])
|
||||
|
||||
# 27. Scale out operation
|
||||
scaleout_req = paramgen.scaleout_vnf_max()
|
||||
self._add_additional_params(scaleout_req)
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# 28. Heal VNF(all with omit all parameter)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter()
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_name = f'vnf-{inst_id}'
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("UPDATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_0_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu1_1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][1]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_0_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
|
||||
# 29. Heal VNF(all with all=False parameter)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(False)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("UPDATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [stack for stack in nested_stacks if
|
||||
(stack['resource_name'] in ['VDU1', 'VDU2'])]
|
||||
vdu1_0_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu1_1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][1]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_0_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
|
||||
# 30. Heal VNF(all with all=True parameter)
|
||||
heal_req = paramgen.heal_vnf_all_max_with_parameter(True)
|
||||
self._add_additional_params(heal_req)
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check stack info
|
||||
stack_status, _ = self.heat_client.get_status(stack_name)
|
||||
self.assertEqual("CREATE_COMPLETE", stack_status)
|
||||
nested_stacks = self.heat_client.get_resources(stack_name)
|
||||
temp_stacks = [
|
||||
stack for stack in nested_stacks
|
||||
if (stack['resource_name'] in
|
||||
['VDU1', 'VDU2', 'VDU1-VirtualStorage',
|
||||
'VDU2-VirtualStorage', 'internalVL3'])]
|
||||
vdu1_0_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][0]
|
||||
vdu1_1_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1')][1]
|
||||
vdu2_stack_after_heal = [stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2')][0]
|
||||
storage1_0_stack_after_heal = [
|
||||
stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1-VirtualStorage')][0]
|
||||
storage1_1_stack_after_heal = [
|
||||
stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU1-VirtualStorage')][1]
|
||||
storage2_stack_after_heal = [
|
||||
stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'VDU2-VirtualStorage')][0]
|
||||
network_stack_after_heal = [
|
||||
stack for stack in temp_stacks if
|
||||
(stack['resource_name'] == 'internalVL3')][0]
|
||||
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_0_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu1_1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
vdu2_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
storage1_0_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
storage1_1_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
storage2_stack_after_heal['resource_status'])
|
||||
self.assertEqual("CREATE_COMPLETE",
|
||||
network_stack_after_heal['resource_status'])
|
||||
|
||||
# 31. Terminate VNF
|
||||
terminate_req = paramgen.terminate_vnf_max()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# check instantiationState of VNF
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
body['instantiationState'])
|
||||
|
||||
# 32. Delete VNF
|
||||
self.exec_lcm_operation(self.delete_vnf_instance, inst_id)
|
File diff suppressed because it is too large
Load Diff
118
tox.ini
118
tox.ini
@ -22,149 +22,187 @@ deps =
|
||||
commands =
|
||||
stestr run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:functional]
|
||||
setenv = {[testenv]setenv}
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional run --slowest {posargs}
|
||||
|
||||
[testenv:dsvm-functional]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional run --slowest --concurrency 2 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-legacy-nfvo]
|
||||
[testenv:ft-legacy-vim]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol/legacy_nfvo run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-vnflcm]
|
||||
[testenv:ft-v1-tosca-vnflcm]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol/vnflcm run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-vnflcm-userdata]
|
||||
[testenv:ft-v1-userdata-vnflcm]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol/vnflcm_userdata run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-vnfpkgm]
|
||||
[testenv:ft-v1-vnfpkgm]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol/vnfpkgm run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-separated-nfvo]
|
||||
[testenv:ft-v1-userdata-separated-nfvo]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_separated_nfvo run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-separated-nfvo-v2]
|
||||
[testenv:ft-v2-df-userdata-separated-nfvo]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_separated_nfvo_v2 run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-kubernetes]
|
||||
[testenv:ft-v1-k8s]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_kubernetes run --slowest --concurrency 2 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-v2-basic]
|
||||
[testenv:ft-v2-df-userdata-ccvp]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/basic run --slowest --concurrency 1 {posargs}
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/df_userdata/change_vnfpkg run --slowest {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-v2-vnflcm]
|
||||
[testenv:ft-v2-st-userdata-basic]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm run --slowest --concurrency 1 {posargs}
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/st_userdata/basic run --slowest {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-v2-notification]
|
||||
[testenv:ft-v2-st-userdata-ccvp]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/st_userdata/change_vnfpkg run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-df-userdata-basic-max]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/df_userdata/basic_max run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-df-userdata-basic-min]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/df_userdata/basic_min run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-df-userdata-update]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/df_userdata/update run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-df-userdata-scale]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/df_userdata/scale run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-df-userdata-err-handling]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/df_userdata/err_handling run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-df-userdata-notification]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/notification run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-v2-prometheus]
|
||||
[testenv:ft-v2-prometheus]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/prometheus run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-v2-ubuntu-focal]
|
||||
[testenv:ft-v2-st-userdata-basic-max]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2 run --slowest --concurrency 1 {posargs}
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/st_userdata/basic_max run --slowest {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-v2-individual-vnfc-mgmt]
|
||||
[testenv:ft-v2-st-userdata-basic-min]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2_individual_vnfc_mgmt run --slowest --concurrency 1 {posargs}
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/st_userdata/basic_min run --slowest {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-kubernetes-v2]
|
||||
[testenv:ft-v2-st-userdata-various-lcm]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/st_userdata/various_lcm run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-st-userdata-err-handling]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2/vnflcm/st_userdata/err_handling run --slowest {posargs}
|
||||
|
||||
[testenv:ft-v2-k8s]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_kubernetes_v2 run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol_kubernetes_oidc_auth]
|
||||
[testenv:ft-k8s-oidc-auth]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_kubernetes_oidc_auth run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-multi-tenant]
|
||||
[testenv:ft-v1-userdata-multi-tenant]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_multi_tenant run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-kubernetes-multi-tenant]
|
||||
[testenv:ft-v1-k8s-multi-tenant]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_kubernetes_multi_tenant run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-v2-az-retry]
|
||||
[testenv:ft-v2-st-userdata-az-retry]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_v2_az_retry run --slowest --concurrency 1 {posargs}
|
||||
[testenv:dsvm-functional-enhanced-policy-sol]
|
||||
|
||||
[testenv:ft-enhanced-policy-sol]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_enhanced_policy/sol run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-enhanced-policy-sol-kubernetes]
|
||||
[testenv:ft-k8s-enhanced-policy-sol]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_enhanced_policy/sol_kubernetes run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-https-v2]
|
||||
[testenv:ft-v2-df-userdata-https]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_https_v2 run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-encrypt-cred-barbican]
|
||||
[testenv:ft-v2-df-userdata-encrypt-cred-barbican]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_encrypt_cred_v2 run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-functional-sol-encrypt-cred-local]
|
||||
[testenv:ft-v2-df-userdata-encrypt-cred-local]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
# Temporarily change directory permissions to read the contents of the fernet
|
||||
@ -178,13 +216,13 @@ commands_post =
|
||||
allowlist_externals =
|
||||
sudo
|
||||
|
||||
[testenv:dsvm-functional-sol-terraform-v2]
|
||||
[testenv:ft-v2-terraform]
|
||||
setenv = {[testenv]setenv}
|
||||
|
||||
commands =
|
||||
stestr --test-path=./tacker/tests/functional/sol_terraform_v2 run --slowest --concurrency 1 {posargs}
|
||||
|
||||
[testenv:dsvm-compliance-sol-api]
|
||||
[testenv:ft-v1-compliance-sol]
|
||||
passenv =
|
||||
{[testenv]passenv}
|
||||
*_PROXY
|
||||
|
338
zuul.d/jobs/base.yaml
Normal file
338
zuul.d/jobs/base.yaml
Normal file
@ -0,0 +1,338 @@
|
||||
- job:
|
||||
name: tacker-ft-openstack-base
|
||||
parent: devstack
|
||||
description: |
|
||||
Abstraction multinodes job for SOL devstack-based functional tests
|
||||
nodeset: openstack-4-nodes-jammy
|
||||
pre-run: playbooks/devstack/pre.yaml
|
||||
run: playbooks/devstack/run.yaml
|
||||
post-run: playbooks/devstack/post.yaml
|
||||
roles:
|
||||
- zuul: openstack-infra/devstack
|
||||
timeout: 10800
|
||||
required-projects:
|
||||
- openstack/cinder
|
||||
- openstack/glance
|
||||
- openstack/keystone
|
||||
- openstack/neutron
|
||||
- openstack/nova
|
||||
- openstack/placement
|
||||
- openstack/aodh
|
||||
- openstack/horizon
|
||||
- openstack/barbican
|
||||
- openstack/heat
|
||||
- openstack/networking-sfc
|
||||
- openstack/python-barbicanclient
|
||||
- openstack/python-tackerclient
|
||||
- openstack/tacker
|
||||
- openstack/tacker-horizon
|
||||
vars:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
DATABASE_TYPE: mysql
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
GNOCCHI_SERVICE_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
Q_SERVICE_PLUGIN_CLASSES: ovn-router,networking_sfc.services.flowclassifier.plugin.FlowClassifierPlugin,neutron.services.qos.qos_plugin.QoSPlugin,qos
|
||||
L2_AGENT_EXTENSIONS: qos
|
||||
DEVSTACK_PARALLEL: True
|
||||
OVN_L3_CREATE_PUBLIC_NETWORK: true
|
||||
OVN_DBS_LOG_LEVEL: dbg
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
test_matrix_configs: [neutron]
|
||||
zuul_work_dir: src/opendev.org/openstack/tacker
|
||||
host-vars:
|
||||
controller:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
# NOTE: workaround for Heat timeout due to communication
|
||||
# problem between nova and neutron.
|
||||
$NEUTRON_CONF:
|
||||
DEFAULT:
|
||||
client_socket_timeout: 60
|
||||
$NEUTRON_DHCP_CONF:
|
||||
DEFAULT:
|
||||
enable_isolated_metadata: True
|
||||
# NOTE: workaround for Cinder image volume cache problem.
|
||||
# https://bugs.launchpad.net/cinder/+bug/1953704
|
||||
$CINDER_CONF:
|
||||
lvmdriver-1:
|
||||
image_volume_cache_enabled: False
|
||||
devstack_plugins:
|
||||
heat: https://opendev.org/openstack/heat
|
||||
networking-sfc: https://opendev.org/openstack/networking-sfc
|
||||
aodh: https://opendev.org/openstack/aodh
|
||||
barbican: https://opendev.org/openstack/barbican
|
||||
devstack_services:
|
||||
# Core services enabled for this branch.
|
||||
# This list replaces the test-matrix.
|
||||
# Shared services
|
||||
mysql: true
|
||||
rabbit: true
|
||||
tls-proxy: false
|
||||
# Keystone services
|
||||
key: true
|
||||
# Glance services
|
||||
g-api: true
|
||||
# Nova services
|
||||
n-api: true
|
||||
n-api-meta: true
|
||||
n-cond: true
|
||||
n-cpu: false
|
||||
n-novnc: true
|
||||
n-sch: true
|
||||
placement-api: true
|
||||
# OVN services
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
# Neutron services
|
||||
q-svc: true
|
||||
q-qos: true
|
||||
q-ovn-metadata-agent: true
|
||||
# Cinder services
|
||||
c-api: true
|
||||
c-sch: true
|
||||
c-vol: true
|
||||
cinder: true
|
||||
# Services we don't need.
|
||||
# This section is not really needed, it's for readability.
|
||||
horizon: false
|
||||
tempest: false
|
||||
swift: false
|
||||
s-account: false
|
||||
s-container: false
|
||||
s-object: false
|
||||
s-proxy: false
|
||||
c-bak: false
|
||||
tox_install_siblings: false
|
||||
controller-tacker:
|
||||
devstack_plugins:
|
||||
tacker: https://opendev.org/openstack/tacker
|
||||
devstack_services:
|
||||
# OVN services
|
||||
ovn-controller: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
# Neutron services
|
||||
q-ovn-metadata-agent: true
|
||||
# Tacker services
|
||||
tacker: true
|
||||
tacker-conductor: true
|
||||
group-vars:
|
||||
compute:
|
||||
# Since a VirtualInterfaceCreateException occurs during a test,
|
||||
# the setting of network-vif-plugged is changed by the reference of
|
||||
# the following URL.
|
||||
# https://bugs.launchpad.net/heat/+bug/1694371
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$NOVA_CONF:
|
||||
DEFAULT:
|
||||
vif_plugging_is_fatal: False
|
||||
subnode:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
DATABASE_TYPE: mysql
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
GNOCCHI_SERVICE_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_MODE: standalone
|
||||
IS_ZUUL_FT: True
|
||||
Q_SERVICE_PLUGIN_CLASSES: "qos,\
|
||||
networking_sfc.services.flowclassifier.plugin.FlowClassifierPlugin,\
|
||||
neutron.services.qos.qos_plugin.QoSPlugin,\
|
||||
ovn-router"
|
||||
L2_AGENT_EXTENSIONS: qos
|
||||
ENABLE_CHASSIS_AS_GW: false
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
devstack_services:
|
||||
# To override the parent job's definitions.
|
||||
tls-proxy: false
|
||||
# OVN services
|
||||
ovn-controller: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
# Neutron services
|
||||
q-ovn-metadata-agent: true
|
||||
|
||||
- job:
|
||||
name: tacker-ft-k8s-base
|
||||
parent: devstack
|
||||
description: |
|
||||
Abstraction multinodes job for SOL devstack-based kubernetes functional
|
||||
tests
|
||||
nodeset: openstack-k8s-3-nodes-jammy
|
||||
pre-run: playbooks/devstack/pre.yaml
|
||||
run: playbooks/devstack/run.yaml
|
||||
post-run: playbooks/devstack/post.yaml
|
||||
roles:
|
||||
- zuul: openstack-infra/devstack
|
||||
timeout: 10800
|
||||
required-projects:
|
||||
- openstack/barbican
|
||||
- openstack/cinder
|
||||
- openstack/devstack-plugin-container
|
||||
- openstack/glance
|
||||
- openstack/heat
|
||||
- openstack/horizon
|
||||
- openstack/keystone
|
||||
- openstack/neutron
|
||||
- openstack/nova
|
||||
- openstack/placement
|
||||
- openstack/python-barbicanclient
|
||||
- openstack/python-tackerclient
|
||||
- openstack/tacker
|
||||
- openstack/tacker-horizon
|
||||
host-vars:
|
||||
controller:
|
||||
devstack_plugins:
|
||||
barbican: https://opendev.org/openstack/barbican
|
||||
heat: https://opendev.org/openstack/heat
|
||||
neutron: https://opendev.org/openstack/neutron
|
||||
devstack_services:
|
||||
base: false
|
||||
c-api: true
|
||||
c-bak: false
|
||||
c-sch: true
|
||||
c-vol: true
|
||||
cinder: true
|
||||
coredns: false
|
||||
etcd3: true
|
||||
g-api: true
|
||||
g-reg: true
|
||||
horizon: false
|
||||
key: true
|
||||
mysql: true
|
||||
n-api-meta: true
|
||||
n-api: true
|
||||
n-cond: true
|
||||
n-cpu: false
|
||||
n-novnc: true
|
||||
n-sch: true
|
||||
neutron: true
|
||||
placement-api: true
|
||||
placement-client: true
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-qos: true
|
||||
q-svc: true
|
||||
q-ovn-metadata-agent: true
|
||||
rabbit: true
|
||||
s-account: false
|
||||
s-container: false
|
||||
s-object: false
|
||||
s-proxy: false
|
||||
swift: false
|
||||
tempest: false
|
||||
tls-proxy: false
|
||||
tox_install_siblings: false
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
kubernetes_vim:
|
||||
stack_retries: 120
|
||||
devstack_services:
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-ovn-metadata-agent: true
|
||||
tacker: true
|
||||
tacker-conductor: true
|
||||
devstack_plugins:
|
||||
tacker: https://opendev.org/openstack/tacker
|
||||
controller-k8s:
|
||||
devstack_local_conf: {}
|
||||
devstack_plugins:
|
||||
devstack-plugin-container: https://opendev.org/openstack/devstack-plugin-container
|
||||
devstack_services:
|
||||
etcd3: false
|
||||
ovn-controller: true
|
||||
ovn-northd: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-ovn-metadata-agent: true
|
||||
container: true
|
||||
k8s-master: true
|
||||
tox_install_siblings: false
|
||||
group-vars:
|
||||
subnode:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
DATABASE_TYPE: mysql
|
||||
IS_ZUUL_FT: True
|
||||
K8S_API_SERVER_IP: "{{ hostvars['controller-k8s']['nodepool']['private_ipv4'] }}"
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
CONTAINER_ENGINE: crio
|
||||
K8S_VERSION: "1.30.5"
|
||||
CRIO_VERSION: "1.30.5"
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
TACKER_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_MODE: standalone
|
||||
USE_PYTHON3: true
|
||||
ENABLE_CHASSIS_AS_GW: false
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
# TODO(ueha): Remove this workarround if the Zuul jobs succeed with GLOBAL_VENV=true
|
||||
GLOBAL_VENV: false
|
||||
K8S_TOKEN: "9agf12.zsu5uh2m4pzt3qba"
|
||||
devstack_services:
|
||||
dstat: false
|
||||
horizon: false
|
||||
n-api-meta: false
|
||||
n-api: false
|
||||
n-cauth: false
|
||||
n-cond: false
|
||||
n-cpu: true
|
||||
n-novnc: false
|
||||
n-obj: false
|
||||
n-sch: false
|
||||
ovn-controller: true
|
||||
ovs-vswitchd: true
|
||||
ovsdb-server: true
|
||||
q-ovn-metadata-agent: true
|
||||
tls-proxy: false
|
||||
vars:
|
||||
devstack_localrc:
|
||||
CELLSV2_SETUP: singleconductor
|
||||
DATABASE_TYPE: mysql
|
||||
ETCD_USE_RAMDISK: true
|
||||
IS_ZUUL_FT: True
|
||||
KEYSTONE_SERVICE_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
L2_AGENT_EXTENSIONS: qos
|
||||
MYSQL_HOST: "{{ hostvars['controller']['nodepool']['private_ipv4'] }}"
|
||||
OVS_BRIDGE_MAPPINGS: public:br-ex,mgmtphysnet0:br-infra
|
||||
PHYSICAL_NETWORK: mgmtphysnet0
|
||||
Q_SERVICE_PLUGIN_CLASSES: ovn-router,neutron.services.qos.qos_plugin.QoSPlugin,qos
|
||||
TACKER_HOST: "{{ hostvars['controller-tacker']['nodepool']['private_ipv4'] }}"
|
||||
TACKER_MODE: standalone
|
||||
USE_PYTHON3: true
|
||||
DEVSTACK_PARALLEL: True
|
||||
OVN_L3_CREATE_PUBLIC_NETWORK: true
|
||||
OVN_DBS_LOG_LEVEL: dbg
|
||||
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
|
||||
# TODO(ueha): Remove this workarround if the Zuul jobs succeed with GLOBAL_VENV=true
|
||||
GLOBAL_VENV: false
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$NEUTRON_DHCP_CONF:
|
||||
DEFAULT:
|
||||
enable_isolated_metadata: True
|
||||
k8s_api_url: "https://{{ hostvars['controller-k8s']['nodepool']['private_ipv4'] }}:6443"
|
||||
k8s_ssl_verify: true
|
||||
helm_version: "3.15.4"
|
||||
test_matrix_configs: [neutron]
|
||||
zuul_work_dir: src/opendev.org/openstack/tacker
|
||||
zuul_copy_output:
|
||||
'{{ devstack_log_dir }}/kubernetes': 'logs'
|
77
zuul.d/jobs/kubernetes.yaml
Normal file
77
zuul.d/jobs/kubernetes.yaml
Normal file
@ -0,0 +1,77 @@
|
||||
- job:
|
||||
name: tacker-ft-v2-k8s
|
||||
parent: tacker-ft-k8s-base
|
||||
description: |
|
||||
V2 Kubernetes functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_vnfm:
|
||||
kubernetes_vim_rsc_wait_timeout: 800
|
||||
prometheus_plugin:
|
||||
fault_management: true
|
||||
performance_management: true
|
||||
auto_scaling: true
|
||||
auto_healing: true
|
||||
test_rule_with_promtool: true
|
||||
tox_envlist: ft-v2-k8s
|
||||
vars:
|
||||
prometheus_setup: true
|
||||
|
||||
- job:
|
||||
name: tacker-ft-k8s-oidc-auth
|
||||
parent: tacker-ft-v2-k8s
|
||||
description: |
|
||||
V1 Kubernetes functional tests for OIDC Auth
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-k8s-oidc-auth
|
||||
vars:
|
||||
keycloak_host: "{{ hostvars['controller-k8s']['nodepool']['private_ipv4'] }}"
|
||||
keycloak_http_port: 8080
|
||||
keycloak_https_port: 8443
|
||||
voting: false
|
||||
|
||||
- job:
|
||||
name: tacker-ft-k8s-enhanced-policy-sol
|
||||
parent: tacker-ft-v2-k8s
|
||||
description: |
|
||||
Enhanced policy Kubernetes functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-k8s-enhanced-policy-sol
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
oslo_policy:
|
||||
enhanced_tacker_policy: True
|
||||
vars:
|
||||
config_enhanced_policy: true
|
||||
voting: false
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v1-k8s
|
||||
parent: tacker-ft-k8s-base
|
||||
description: |
|
||||
V1 Kubernetes functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
database:
|
||||
max_pool_size: 0
|
||||
tox_envlist: ft-v1-k8s
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v1-k8s-multi-tenant
|
||||
parent: tacker-ft-k8s-base
|
||||
description: |
|
||||
V1 Kubernetes functional tests for multi tenant
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v1-k8s-multi-tenant
|
||||
vars:
|
||||
setup_multi_tenant: true
|
396
zuul.d/jobs/openstack.yaml
Normal file
396
zuul.d/jobs/openstack.yaml
Normal file
@ -0,0 +1,396 @@
|
||||
- job:
|
||||
name: tacker-ft-v2-df-userdata-basic-max
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 DefaultUserData functional tests for max pattern
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-df-userdata-basic-max
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-df-userdata-basic-min
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 DefaultUserData functional tests for min pattern
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-df-userdata-basic-min
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-df-userdata-update
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 DefaultUserData functional tests for Modify
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-df-userdata-update
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-df-userdata-scale
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 DefaultUserData functional tests for Scale
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-df-userdata-scale
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-df-userdata-ccvp
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 DefaultUserData functional tests for Change Current VNF Package
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-df-userdata-ccvp
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-df-userdata-err-handling
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 DefaultUserData functional tests for Error Handling
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-df-userdata-err-handling
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-st-userdata-basic
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 StandardUserData functional tests
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-st-userdata-basic
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-st-userdata-basic-max
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 StandardUserData functional tests for max pattern
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
devstack_local_conf:
|
||||
post-config:
|
||||
$TACKER_CONF:
|
||||
v2_vnfm:
|
||||
# Notes: The List API will return 'Link' Header in response
|
||||
# body only if page_size is not 0. This job will check 'Link'
|
||||
# Header, so these page_size parameters are set to 1.
|
||||
vnf_instance_page_size: 1
|
||||
lcm_op_occ_page_size: 1
|
||||
tox_envlist: ft-v2-st-userdata-basic-max
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-st-userdata-basic-min
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 StandardUserData functional tests for min pattern
|
||||
host-vars:
|
||||
controller-tacker:
|
||||
tox_envlist: ft-v2-st-userdata-basic-min
|
||||
|
||||
- job:
|
||||
name: tacker-ft-v2-st-userdata-ccvp
|
||||
parent: tacker-ft-openstack-base
|
||||
description: |
|
||||
V2 StandardUserData functional tests for Change Current VNF Package
|
||||