Browse Source

Merge "Refactor FT of sol-kubernetes job"

changes/05/825705/1
Zuul 4 months ago committed by Gerrit Code Review
parent
commit
278bb0abf5
  1. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Definitions/helloworld3_df_simple.yaml
  2. 31
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Definitions/helloworld3_top.vnfd.yaml
  3. 53
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Definitions/helloworld3_types.yaml
  4. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/bindings.yaml
  5. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/clusterrole_clusterrolebinding_SA.yaml
  6. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/config-map.yaml
  7. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/controller-revision.yaml
  8. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/daemon-set.yaml
  9. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/deployment.yaml
  10. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/horizontal-pod-autoscaler.yaml
  11. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/job.yaml
  12. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/limit-range.yaml
  13. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/local-subject-access-review.yaml
  14. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/multiple_yaml_lease.yaml
  15. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/multiple_yaml_network-policy.yaml
  16. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/multiple_yaml_priority-class.yaml
  17. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/namespace.yaml
  18. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/persistent-volume-0.yaml
  19. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/persistent-volume-1.yaml
  20. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/pod-template.yaml
  21. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/pod.yaml
  22. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/replicaset_service_secret.yaml
  23. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/resource-quota.yaml
  24. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/role_rolebinding_SA.yaml
  25. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/self-subject-access-review_and_self-subject-rule-review.yaml
  26. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/statefulset.yaml
  27. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/statefulset_fail.yaml
  28. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/storage-class.yaml
  29. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/storage-class_pv_pvc.yaml
  30. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/subject-access-review.yaml
  31. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/token-review.yaml
  32. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf/TOSCA-Metadata/TOSCA.meta
  33. 42
      tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Definitions/helloworld3_df_simple.yaml
  34. 31
      tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Definitions/helloworld3_top.vnfd.yaml
  35. 53
      tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Definitions/helloworld3_types.yaml
  36. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Files/kubernetes/storage-class-url.yaml
  37. 0
      tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/TOSCA-Metadata/TOSCA.meta
  38. 417
      tacker/tests/functional/sol_kubernetes/vnflcm/base.py
  39. 1217
      tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes.py
  40. 310
      tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_heal.py
  41. 371
      tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_helm.py
  42. 500
      tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_scale.py
  43. 6
      tacker/tests/utils.py

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Definitions/helloworld3_df_simple.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Definitions/helloworld3_df_simple.yaml

31
tacker/tests/etc/samples/etsi/nfv/test_cnf/Definitions/helloworld3_top.vnfd.yaml

@ -0,0 +1,31 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- helloworld3_types.yaml
- helloworld3_df_simple.yaml
topology_template:
inputs:
selected_flavour:
type: string
description: VNF deployment flavour selected by the consumer. It is provided in the API
node_templates:
VNF:
type: company.provider.VNF
properties:
flavour_id: { get_input: selected_flavour }
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
provider: Company
product_name: Sample VNF
software_version: '1.0'
descriptor_version: '1.0'
vnfm_info:
- Tacker
requirements:
#- virtual_link_external # mapped in lower-level templates
#- virtual_link_internal # mapped in lower-level templates

53
tacker/tests/etc/samples/etsi/nfv/test_cnf/Definitions/helloworld3_types.yaml

@ -0,0 +1,53 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: VNF type definition
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
node_types:
company.provider.VNF:
derived_from: tosca.nodes.nfv.VNF
properties:
descriptor_id:
type: string
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 ] ]
default: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
descriptor_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
provider:
type: string
constraints: [ valid_values: [ 'Company' ] ]
default: 'Company'
product_name:
type: string
constraints: [ valid_values: [ 'Sample VNF' ] ]
default: 'Sample VNF'
software_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
vnfm_info:
type: list
entry_schema:
type: string
constraints: [ valid_values: [ Tacker ] ]
default: [ Tacker ]
flavour_id:
type: string
constraints: [ valid_values: [ simple ] ]
default: simple
flavour_description:
type: string
default: ""
requirements:
- virtual_link_external:
capability: tosca.capabilities.nfv.VirtualLinkable
- virtual_link_internal:
capability: tosca.capabilities.nfv.VirtualLinkable
interfaces:
Vnflcm:
type: tosca.interfaces.nfv.Vnflcm

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/bindings.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/bindings.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/clusterrole_clusterrolebinding_SA.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/clusterrole_clusterrolebinding_SA.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/config-map.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/config-map.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/controller-revision.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/controller-revision.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/daemon-set.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/daemon-set.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/deployment.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/deployment.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/horizontal-pod-autoscaler.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/horizontal-pod-autoscaler.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/job.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/job.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/limit-range.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/limit-range.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/local-subject-access-review.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/local-subject-access-review.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/multiple_yaml_lease.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/multiple_yaml_lease.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/multiple_yaml_network-policy.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/multiple_yaml_network-policy.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/multiple_yaml_priority-class.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/multiple_yaml_priority-class.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/namespace.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/namespace.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/persistent-volume-0.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/persistent-volume-0.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/persistent-volume-1.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/persistent-volume-1.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/pod-template.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/pod-template.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/pod.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/pod.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/replicaset_service_secret.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/replicaset_service_secret.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/resource-quota.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/resource-quota.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/role_rolebinding_SA.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/role_rolebinding_SA.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/self-subject-access-review_and_self-subject-rule-review.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/self-subject-access-review_and_self-subject-rule-review.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/statefulset.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/statefulset.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/statefulset_fail.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/statefulset_fail.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/storage-class.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/storage-class.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/storage-class_pv_pvc.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/storage-class_pv_pvc.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/subject-access-review.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/subject-access-review.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/Files/kubernetes/token-review.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf/Files/kubernetes/token-review.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_resources/TOSCA-Metadata/TOSCA.meta → tacker/tests/etc/samples/etsi/nfv/test_cnf/TOSCA-Metadata/TOSCA.meta

42
tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Definitions/helloworld3_df_simple.yaml

@ -0,0 +1,42 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: Simple deployment flavour for Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- helloworld3_types.yaml
topology_template:
inputs:
descriptor_id:
type: string
descriptor_version:
type: string
provider:
type: string
product_name:
type: string
software_version:
type: string
vnfm_info:
type: list
entry_schema:
type: string
flavour_id:
type: string
flavour_description:
type: string
substitution_mappings:
node_type: company.provider.VNF
properties:
flavour_id: simple
requirements:
virtual_link_external: []
node_templates:
VNF:
type: company.provider.VNF
properties:
flavour_description: A simple flavour

31
tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Definitions/helloworld3_top.vnfd.yaml

@ -0,0 +1,31 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- helloworld3_types.yaml
- helloworld3_df_simple.yaml
topology_template:
inputs:
selected_flavour:
type: string
description: VNF deployment flavour selected by the consumer. It is provided in the API
node_templates:
VNF:
type: company.provider.VNF
properties:
flavour_id: { get_input: selected_flavour }
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
provider: Company
product_name: Sample VNF
software_version: '1.0'
descriptor_version: '1.0'
vnfm_info:
- Tacker
requirements:
#- virtual_link_external # mapped in lower-level templates
#- virtual_link_internal # mapped in lower-level templates

53
tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Definitions/helloworld3_types.yaml

@ -0,0 +1,53 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: VNF type definition
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
node_types:
company.provider.VNF:
derived_from: tosca.nodes.nfv.VNF
properties:
descriptor_id:
type: string
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 ] ]
default: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
descriptor_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
provider:
type: string
constraints: [ valid_values: [ 'Company' ] ]
default: 'Company'
product_name:
type: string
constraints: [ valid_values: [ 'Sample VNF' ] ]
default: 'Sample VNF'
software_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
vnfm_info:
type: list
entry_schema:
type: string
constraints: [ valid_values: [ Tacker ] ]
default: [ Tacker ]
flavour_id:
type: string
constraints: [ valid_values: [ simple ] ]
default: simple
flavour_description:
type: string
default: ""
requirements:
- virtual_link_external:
capability: tosca.capabilities.nfv.VirtualLinkable
- virtual_link_internal:
capability: tosca.capabilities.nfv.VirtualLinkable
interfaces:
Vnflcm:
type: tosca.interfaces.nfv.Vnflcm

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_with_artifact_is_url/Files/kubernetes/storage-class-url.yaml → tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/Files/kubernetes/storage-class-url.yaml

0
tacker/tests/etc/samples/etsi/nfv/test_create_vnf_instance_and_instantiate_and_terminate_cnf_with_artifact_is_url/TOSCA-Metadata/TOSCA.meta → tacker/tests/etc/samples/etsi/nfv/test_cnf_ext_artifact/TOSCA-Metadata/TOSCA.meta

417
tacker/tests/functional/sol_kubernetes/vnflcm/base.py

@ -0,0 +1,417 @@
# 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 time
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
from sqlalchemy import desc
from sqlalchemy.orm import joinedload
from tacker.common import exceptions
from tacker import context
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.objects import fields
from tacker.objects import vnf_lcm_op_occs
from tacker.tests.functional import base
from tacker.tests import utils
VNF_PACKAGE_UPLOAD_TIMEOUT = 300
VNF_INSTANTIATE_TIMEOUT = 600
VNF_TERMINATE_TIMEOUT = 600
VNF_HEAL_SOL002_TIMEOUT = 600
VNF_HEAL_SOL003_TIMEOUT = 1200
VNF_SCALE_TIMEOUT = 600
RETRY_WAIT_TIME = 5
WAIT_TIMEOUT_ERR_MSG = ("Failed to %(action)s, process could not be completed"
" within %(timeout)s seconds")
class BaseVnfLcmKubernetesTest(base.BaseTackerTest):
@classmethod
def setUpClass(cls):
super(BaseVnfLcmKubernetesTest, cls).setUpClass()
cls.tacker_client = base.BaseTackerTest.tacker_http_client()
cls.base_vnf_package_url = "/vnfpkgm/v1/vnf_packages"
cls.base_vnf_instances_url = "/vnflcm/v1/vnf_instances"
cls.base_vnf_lcm_op_occs_url = "/vnflcm/v1/vnf_lcm_op_occs"
cls.vnf_package_ids = []
@classmethod
def tearDownClass(cls):
# Update vnf package operational state to DISABLED and delete
for package_id in cls.vnf_package_ids:
cls._disable_and_delete_vnf_package(package_id)
super(BaseVnfLcmKubernetesTest, cls).tearDownClass()
def setUp(self):
super(BaseVnfLcmKubernetesTest, self).setUp()
self.context = context.get_admin_context()
vim_list = self.client.list_vims()
if not vim_list:
self.skipTest("Vims are not configured")
vim_name = 'vim-kubernetes'
vim = self.get_vim(vim_list, vim_name)
if not vim:
self.skipTest(f"Kubernetes VIM '{vim_name}' is missing")
self.vim_id = vim['id']
def _create_and_upload_vnf_package(self, tacker_client, csar_package_name,
user_defined_data):
# create vnf package
body = jsonutils.dumps({"userDefinedData": user_defined_data})
_, vnf_package = tacker_client.do_request(
self.base_vnf_package_url, "POST", body=body)
vnf_pkg_id = vnf_package['id']
# upload vnf package
csar_package_path = ("../../../etc/samples/etsi/nfv/"
f"{csar_package_name}")
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
csar_package_path))
# Generating unique vnfd id. This is required when multiple workers
# are running concurrently. The call below creates a new temporary
# CSAR with unique vnfd id.
file_path, _ = utils.create_csar_with_unique_vnfd_id(file_path)
with open(file_path, 'rb') as file_object:
tacker_client.do_request(
f"{self.base_vnf_package_url}/{vnf_pkg_id}/package_content",
"PUT", body=file_object, content_type='application/zip')
# wait for onboard
start_time = int(time.time())
show_url = os.path.join(self.base_vnf_package_url, vnf_pkg_id)
vnfd_id = None
while True:
_, body = tacker_client.do_request(show_url, "GET")
if body['onboardingState'] == "ONBOARDED":
vnfd_id = body['vnfdId']
break
if (int(time.time()) - start_time) > VNF_PACKAGE_UPLOAD_TIMEOUT:
raise Exception(WAIT_TIMEOUT_ERR_MSG %
{"action": "onboard vnf package",
"timeout": VNF_PACKAGE_UPLOAD_TIMEOUT})
time.sleep(RETRY_WAIT_TIME)
# remove temporarily created CSAR file
os.remove(file_path)
return vnf_package['id'], vnfd_id
@classmethod
def _disable_and_delete_vnf_package(cls, package_id):
# Update vnf package operational state to DISABLED
update_req_body = jsonutils.dumps({
"operationalState": "DISABLED"})
cls.tacker_client.do_request(
f'{cls.base_vnf_package_url}/{package_id}',
"PATCH", content_type='application/json',
body=update_req_body)
# Delete vnf package
url = f'{cls.base_vnf_package_url}/{package_id}'
cls.tacker_client.do_request(url, "DELETE")
@classmethod
def _instantiate_vnf_instance_request(
cls, flavour_id, vim_id=None, additional_param=None):
request_body = {"flavourId": flavour_id}
if vim_id:
request_body["vimConnectionInfo"] = [
{"id": uuidutils.generate_uuid(),
"vimId": vim_id,
"vimType": "kubernetes"}]
if additional_param:
request_body["additionalParams"] = additional_param
return request_body
def _create_vnf_instance(self, vnfd_id, vnf_instance_name=None,
vnf_instance_description=None):
request_body = {'vnfdId': vnfd_id}
if vnf_instance_name:
request_body['vnfInstanceName'] = vnf_instance_name
if vnf_instance_description:
request_body['vnfInstanceDescription'] = vnf_instance_description
resp, response_body = self.http_client.do_request(
self.base_vnf_instances_url, "POST",
body=jsonutils.dumps(request_body))
return resp, response_body
def _delete_wait_vnf_instance(self, id):
url = os.path.join(self.base_vnf_instances_url, id)
start_time = int(time.time())
while True:
resp, _ = self.tacker_client.do_request(url, "DELETE")
if 204 == resp.status_code:
break
if (int(time.time()) - start_time) > VNF_TERMINATE_TIMEOUT:
raise Exception(WAIT_TIMEOUT_ERR_MSG %
{"action": "delete vnf instance",
"timeout": VNF_TERMINATE_TIMEOUT})
time.sleep(RETRY_WAIT_TIME)
def _show_vnf_instance(self, id):
show_url = os.path.join(self.base_vnf_instances_url, id)
_, vnf_instance = self.tacker_client.do_request(show_url, "GET")
return vnf_instance
def _vnf_instance_wait(
self, id,
instantiation_state=fields.VnfInstanceState.INSTANTIATED,
timeout=VNF_INSTANTIATE_TIMEOUT):
show_url = os.path.join(self.base_vnf_instances_url, id)
start_time = int(time.time())
while True:
_, body = self.tacker_client.do_request(show_url, "GET")
if body['instantiationState'] == instantiation_state:
break
if (int(time.time()) - start_time) > timeout:
raise Exception(WAIT_TIMEOUT_ERR_MSG %
{"action": "wait vnf instance", "timeout": timeout})
time.sleep(RETRY_WAIT_TIME)
def _instantiate_vnf_instance(self, id, request_body,
wait_state="COMPLETED"):
url = os.path.join(self.base_vnf_instances_url, id, "instantiate")
resp, _ = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
if wait_state == "COMPLETED":
self._vnf_instance_wait(id)
# wait vnflcm_op_occs.operation_state become wait_state
self._wait_vnflcm_op_occs(self.context, id, VNF_INSTANTIATE_TIMEOUT,
wait_state)
def _create_and_instantiate_vnf_instance(self, vnfd_id, flavour_id,
inst_name, inst_desc,
additional_params):
# create vnf instance
_, vnf_instance = self._create_vnf_instance(
vnfd_id, vnf_instance_name=inst_name,
vnf_instance_description=inst_desc)
# instantiate vnf instance
additional_param = additional_params
request_body = self._instantiate_vnf_instance_request(
flavour_id, vim_id=self.vim_id, additional_param=additional_param)
self._instantiate_vnf_instance(vnf_instance['id'], request_body)
vnf_instance = self._show_vnf_instance(vnf_instance['id'])
return vnf_instance
def _terminate_vnf_instance(self, id, request_body=None):
if request_body is None:
# Terminate vnf forcefully
request_body = {
"terminationType": fields.VnfInstanceTerminationType.FORCEFUL,
}
url = os.path.join(self.base_vnf_instances_url, id, "terminate")
resp, _ = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
timeout = request_body.get('gracefulTerminationTimeout', None)
start_time = int(time.time())
self._vnf_instance_wait(
id, instantiation_state=fields.VnfInstanceState.NOT_INSTANTIATED,
timeout=VNF_TERMINATE_TIMEOUT)
# If gracefulTerminationTimeout is set, check whether vnf
# instantiation_state is set to NOT_INSTANTIATED after
# gracefulTerminationTimeout seconds.
if timeout and int(time.time()) - start_time < timeout:
self.fail("Vnf is terminated before graceful termination "
"timeout period")
def _delete_vnf_instance(self, id):
self._delete_wait_vnf_instance(id)
# verify vnf instance is deleted
url = os.path.join(self.base_vnf_instances_url, id)
resp, _ = self.http_client.do_request(url, "GET")
self.assertEqual(404, resp.status_code)
def _scale_vnf_instance(self, id, type, aspect_id,
number_of_steps=1):
url = os.path.join(self.base_vnf_instances_url, id, "scale")
# generate body
request_body = {
"type": type,
"aspectId": aspect_id,
"numberOfSteps": number_of_steps}
resp, _ = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
def _heal_vnf_instance(self, id, vnfc_instance_id):
url = os.path.join(self.base_vnf_instances_url, id, "heal")
# generate body
request_body = {
"vnfcInstanceId": vnfc_instance_id}
resp, _ = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
@classmethod
@db_api.context_manager.reader
def _get_vnflcm_op_occs_by_id(cls, context, vnf_instance_id,
columns_to_join=None):
query = api.model_query(
context, models.VnfLcmOpOccs,
read_deleted="no", project_only=True).filter_by(
vnf_instance_id=vnf_instance_id).order_by(
desc("created_at"))
if columns_to_join:
for column in columns_to_join:
query = query.options(joinedload(column))
db_vnflcm_op_occ = query.first()
if not db_vnflcm_op_occ:
raise exceptions.VnfInstanceNotFound(id=vnf_instance_id)
vnflcm_op_occ = vnf_lcm_op_occs.VnfLcmOpOcc.obj_from_db_obj(
context, db_vnflcm_op_occ)
return vnflcm_op_occ
def _wait_vnflcm_op_occs(
self, context, vnf_instance_id, timeout,
operation_state='COMPLETED'):
start_time = int(time.time())
while True:
vnflcm_op_occ = self._get_vnflcm_op_occs_by_id(
context, vnf_instance_id)
if vnflcm_op_occ.operation_state == operation_state:
break
if (int(time.time()) - start_time) > timeout:
raise Exception("Timeout waiting for transition to"
f" {operation_state} state.")
time.sleep(RETRY_WAIT_TIME)
@classmethod
def _get_vnfc_resource_info(cls, vnf_instance):
inst_vnf_info = vnf_instance['instantiatedVnfInfo']
vnfc_resource_info = inst_vnf_info['vnfcResourceInfo']
return vnfc_resource_info
def _get_scale_level_by_aspect_id(self, vnf_instance, aspect_id):
scale_status = vnf_instance['instantiatedVnfInfo']['scaleStatus']
self.assertTrue(len(scale_status) > 0)
for status in scale_status:
self.assertIsNotNone(status.get('aspectId'))
self.assertIsNotNone(status.get('scaleLevel'))
if status.get('aspectId') == aspect_id:
scale_level = status.get('scaleLevel')
break
else:
raise Exception(f"aspectId {aspect_id} is not found.")
return scale_level
def _test_scale(self, id, type, aspect_id, previous_level,
number_of_steps=1, error=False):
# scale operation
self._scale_vnf_instance(id, type, aspect_id, number_of_steps)
wait_state = "COMPLETED"
if error:
expected_level = previous_level
wait_state = "FAILED_TEMP"
elif type == 'SCALE_OUT':
expected_level = previous_level + number_of_steps
else:
expected_level = previous_level - number_of_steps
# wait vnflcm_op_occs.operation_state become COMPLETE/FAILED_TEMP
self._wait_vnflcm_op_occs(
self.context, id, VNF_SCALE_TIMEOUT, wait_state)
# check scaleStatus after scale operation
vnf_instance = self._show_vnf_instance(id)
scale_level = self._get_scale_level_by_aspect_id(
vnf_instance, aspect_id)
self.assertEqual(scale_level, expected_level)
return scale_level
def _test_heal(self, vnf_instance, vnfc_instance_id):
before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance)
self._heal_vnf_instance(vnf_instance['id'], vnfc_instance_id)
# wait vnflcm_op_occs.operation_state become COMPLETE
if vnfc_instance_id:
timeout = VNF_HEAL_SOL002_TIMEOUT
else:
timeout = VNF_HEAL_SOL003_TIMEOUT
self._wait_vnflcm_op_occs(self.context, vnf_instance['id'], timeout)
# check vnfcResourceInfo after heal operation
vnf_instance = self._show_vnf_instance(vnf_instance['id'])
after_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance)
self.assertEqual(len(before_vnfc_rscs), len(after_vnfc_rscs))
return after_vnfc_rscs
def _rollback_vnf_instance(self, vnf_lcm_op_occ_id):
url = os.path.join(
self.base_vnf_lcm_op_occs_url, vnf_lcm_op_occ_id, "rollback")
# generate body
resp, _ = self.http_client.do_request(url, "POST")
self.assertEqual(202, resp.status_code)
def _test_rollback_cnf_instantiate(self, id):
# get vnflcm_op_occ id for rollback
vnflcm_op_occ = self._get_vnflcm_op_occs_by_id(
self.context, id)
vnf_lcm_op_occ_id = vnflcm_op_occ.id
# rollback operation
self._rollback_vnf_instance(vnf_lcm_op_occ_id)
# wait vnflcm_op_occs.operation_state become ROLLED_BACK
self._wait_vnflcm_op_occs(self.context, id,
VNF_TERMINATE_TIMEOUT, "ROLLED_BACK")
def _test_rollback_cnf_scale(self, id, aspect_id, previous_level):
# get vnflcm_op_occ id for rollback
vnflcm_op_occ = self._get_vnflcm_op_occs_by_id(self.context, id)
vnf_lcm_op_occ_id = vnflcm_op_occ.id
# rollback operation
self._rollback_vnf_instance(vnf_lcm_op_occ_id)
# wait vnflcm_op_occs.operation_state become ROLLED_BACK
self._wait_vnflcm_op_occs(self.context, id, VNF_SCALE_TIMEOUT,
"ROLLED_BACK")
# check scaleStatus after scale operation
vnf_instance = self._show_vnf_instance(id)
expected_level = previous_level
scale_level = self._get_scale_level_by_aspect_id(
vnf_instance, aspect_id)
self.assertEqual(scale_level, expected_level)

1217
tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes.py

File diff suppressed because it is too large Load Diff

310
tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_heal.py

@ -13,293 +13,24 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import time
from tacker.tests.functional.sol_kubernetes.vnflcm import base as vnflcm_base
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
from sqlalchemy import desc
from sqlalchemy.orm import joinedload
from tacker.common import exceptions
from tacker import context
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.objects import fields
from tacker.objects import vnf_lcm_op_occs
from tacker.tests.functional import base
from tacker.tests import utils
VNF_PACKAGE_UPLOAD_TIMEOUT = 300
VNF_INSTANTIATE_TIMEOUT = 600
VNF_TERMINATE_TIMEOUT = 600
VNF_HEAL_TIMEOUT = 600
RETRY_WAIT_TIME = 5
def _create_and_upload_vnf_package(tacker_client, csar_package_name,
user_defined_data):
# create vnf package
body = jsonutils.dumps({"userDefinedData": user_defined_data})
resp, vnf_package = tacker_client.do_request(
'/vnfpkgm/v1/vnf_packages', "POST", body=body)
# upload vnf package
csar_package_path = "../../../etc/samples/etsi/nfv/%s" % csar_package_name
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
csar_package_path))
# Generating unique vnfd id. This is required when multiple workers
# are running concurrently. The call below creates a new temporary
# CSAR with unique vnfd id.
file_path, uniqueid = utils.create_csar_with_unique_vnfd_id(file_path)
with open(file_path, 'rb') as file_object:
resp, resp_body = tacker_client.do_request(
'/vnfpkgm/v1/vnf_packages/{id}/package_content'.format(
id=vnf_package['id']),
"PUT", body=file_object, content_type='application/zip')
# wait for onboard
start_time = int(time.time())
show_url = os.path.join('/vnfpkgm/v1/vnf_packages', vnf_package['id'])
vnfd_id = None
while True:
resp, body = tacker_client.do_request(show_url, "GET")
if body['onboardingState'] == "ONBOARDED":
vnfd_id = body['vnfdId']
break
if ((int(time.time()) - start_time) > VNF_PACKAGE_UPLOAD_TIMEOUT):
raise Exception("Failed to onboard vnf package, process could not"
" be completed within %d seconds", VNF_PACKAGE_UPLOAD_TIMEOUT)
time.sleep(RETRY_WAIT_TIME)
# remove temporarily created CSAR file
os.remove(file_path)
return vnf_package['id'], vnfd_id
def _delete_wait_vnf_instance(tacker_client, id):
url = os.path.join("/vnflcm/v1/vnf_instances", id)
start_time = int(time.time())
while True:
resp, body = tacker_client.do_request(url, "DELETE")
if 204 == resp.status_code:
break
if ((int(time.time()) - start_time) > VNF_TERMINATE_TIMEOUT):
raise Exception("Failed to delete vnf instance, process could not"
" be completed within %d seconds", VNF_TERMINATE_TIMEOUT)
time.sleep(RETRY_WAIT_TIME)
def _show_vnf_instance(tacker_client, id):
show_url = os.path.join("/vnflcm/v1/vnf_instances", id)
resp, vnf_instance = tacker_client.do_request(show_url, "GET")
return vnf_instance
def _vnf_instance_wait(
tacker_client, id,
instantiation_state=fields.VnfInstanceState.INSTANTIATED,
timeout=VNF_INSTANTIATE_TIMEOUT):
show_url = os.path.join("/vnflcm/v1/vnf_instances", id)
start_time = int(time.time())
while True:
resp, body = tacker_client.do_request(show_url, "GET")
if body['instantiationState'] == instantiation_state:
break
if ((int(time.time()) - start_time) > timeout):
raise Exception("Failed to wait vnf instance, process could not"
" be completed within %d seconds", timeout)
time.sleep(RETRY_WAIT_TIME)
class VnfLcmKubernetesHealTest(base.BaseTackerTest):
class VnfLcmKubernetesHealTest(vnflcm_base.BaseVnfLcmKubernetesTest):
@classmethod
def setUpClass(cls):
cls.tacker_client = base.BaseTackerTest.tacker_http_client()
cls.vnf_package_resource, cls.vnfd_id_resource = \
_create_and_upload_vnf_package(
cls.tacker_client, "test_cnf_heal",
{"key": "sample_heal_functional"})
cls.vnf_instance_ids = []
super(VnfLcmKubernetesHealTest, cls).setUpClass()
vnf_package_id, cls.vnfd_id = \
cls._create_and_upload_vnf_package(
cls, cls.tacker_client, "test_cnf_heal",
{"key": "sample_heal_functional"})
cls.vnf_package_ids.append(vnf_package_id)
@classmethod
def tearDownClass(cls):
# Update vnf package operational state to DISABLED
update_req_body = jsonutils.dumps({
"operationalState": "DISABLED"})
base_path = "/vnfpkgm/v1/vnf_packages"
for package_id in [cls.vnf_package_resource]:
resp, resp_body = cls.tacker_client.do_request(
'{base_path}/{id}'.format(id=package_id,
base_path=base_path),
"PATCH", content_type='application/json',
body=update_req_body)
# Delete vnf package
url = '/vnfpkgm/v1/vnf_packages/%s' % package_id
cls.tacker_client.do_request(url, "DELETE")
super(VnfLcmKubernetesHealTest, cls).tearDownClass()
def setUp(self):
super(VnfLcmKubernetesHealTest, self).setUp()
self.base_vnf_instances_url = "/vnflcm/v1/vnf_instances"
self.base_vnf_lcm_op_occs_url = "/vnflcm/v1/vnf_lcm_op_occs"
self.context = context.get_admin_context()
vim_list = self.client.list_vims()
if not vim_list:
self.skipTest("Vims are not configured")
vim_id = 'vim-kubernetes'
vim = self.get_vim(vim_list, vim_id)
if not vim:
self.skipTest("Kubernetes VIM '%s' is missing" % vim_id)
self.vim_id = vim['id']
def _instantiate_vnf_instance_request(
self, flavour_id, vim_id=None, additional_param=None):
request_body = {"flavourId": flavour_id}
if vim_id:
request_body["vimConnectionInfo"] = [
{"id": uuidutils.generate_uuid(),
"vimId": vim_id,
"vimType": "kubernetes"}]
if additional_param:
request_body["additionalParams"] = additional_param
return request_body
def _create_vnf_instance(self, vnfd_id, vnf_instance_name=None,
vnf_instance_description=None):
request_body = {'vnfdId': vnfd_id}
if vnf_instance_name:
request_body['vnfInstanceName'] = vnf_instance_name
if vnf_instance_description:
request_body['vnfInstanceDescription'] = vnf_instance_description
resp, response_body = self.http_client.do_request(
self.base_vnf_instances_url, "POST",
body=jsonutils.dumps(request_body))
return resp, response_body
def _instantiate_vnf_instance(self, id, request_body):
url = os.path.join(self.base_vnf_instances_url, id, "instantiate")
resp, body = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
_vnf_instance_wait(self.tacker_client, id)
def _create_and_instantiate_vnf_instance(self, flavour_id,
additional_params):
# create vnf instance
vnf_instance_name = "test_vnf_instance_for_cnf_heal-%s" % \
uuidutils.generate_uuid()
vnf_instance_description = "vnf instance for cnf heal testing"
resp, vnf_instance = self._create_vnf_instance(
self.vnfd_id_resource, vnf_instance_name=vnf_instance_name,
vnf_instance_description=vnf_instance_description)
# instantiate vnf instance
additional_param = additional_params
request_body = self._instantiate_vnf_instance_request(
flavour_id, vim_id=self.vim_id, additional_param=additional_param)
self._instantiate_vnf_instance(vnf_instance['id'], request_body)
vnf_instance = _show_vnf_instance(
self.tacker_client, vnf_instance['id'])
self.vnf_instance_ids.append(vnf_instance['id'])
return vnf_instance
def _terminate_vnf_instance(self, id):
# Terminate vnf forcefully
request_body = {
"terminationType": fields.VnfInstanceTerminationType.FORCEFUL,
}
url = os.path.join(self.base_vnf_instances_url, id, "terminate")
resp, body = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
_vnf_instance_wait(
self.tacker_client, id,
instantiation_state=fields.VnfInstanceState.NOT_INSTANTIATED,
timeout=VNF_TERMINATE_TIMEOUT)
def _delete_vnf_instance(self, id):
_delete_wait_vnf_instance(self.tacker_client, id)
# verify vnf instance is deleted
url = os.path.join(self.base_vnf_instances_url, id)
resp, body = self.http_client.do_request(url, "GET")
self.assertEqual(404, resp.status_code)
def _heal_vnf_instance(self, id, vnfc_instance_id):
url = os.path.join(self.base_vnf_instances_url, id, "heal")
# generate body
request_body = {
"vnfcInstanceId": vnfc_instance_id}
resp, body = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
@db_api.context_manager.reader
def _vnf_notify_get_by_id(self, context, vnf_instance_id,
columns_to_join=None):
query = api.model_query(
context, models.VnfLcmOpOccs,
read_deleted="no", project_only=True).filter_by(
vnf_instance_id=vnf_instance_id).order_by(
desc("created_at"))
if columns_to_join:
for column in columns_to_join:
query = query.options(joinedload(column))
db_vnflcm_op_occ = query.first()
if not db_vnflcm_op_occ:
raise exceptions.VnfInstanceNotFound(id=vnf_instance_id)
vnflcm_op_occ = vnf_lcm_op_occs.VnfLcmOpOcc.obj_from_db_obj(
context, db_vnflcm_op_occ)
return vnflcm_op_occ
def _wait_vnflcm_op_occs(
self, context, vnf_instance_id,
operation_state='COMPLETED'):
start_time = int(time.time())
while True:
vnflcm_op_occ = self._vnf_notify_get_by_id(
context, vnf_instance_id)
if vnflcm_op_occ.operation_state == operation_state:
break
if ((int(time.time()) - start_time) > VNF_HEAL_TIMEOUT):
raise Exception("Failed to wait heal instance")
time.sleep(RETRY_WAIT_TIME)
def _get_vnfc_resource_info(self, vnf_instance):
inst_vnf_info = vnf_instance['instantiatedVnfInfo']
vnfc_resource_info = inst_vnf_info['vnfcResourceInfo']
return vnfc_resource_info
def test_heal_cnf_with_sol002(self):
"""Test heal as per SOL002 for CNF
@ -307,13 +38,16 @@ class VnfLcmKubernetesHealTest(base.BaseTackerTest):
i.e. with vnfcInstanceId, so that the specified vnfc instance is healed
which includes Kubernetes resources (Pod and Deployment).
"""
vnf_instance_name = "cnf_heal_with_sol002"
vnf_instance_description = "cnf heal with sol002"
# use def-files of singleton Pod and Deployment (replicas=2)
inst_additional_param = {
"lcm-kubernetes-def-files": [
"Files/kubernetes/deployment_heal_complex.yaml",
"Files/kubernetes/pod_heal.yaml"]}
vnf_instance = self._create_and_instantiate_vnf_instance(
"complex", inst_additional_param)
self.vnfd_id, "complex", vnf_instance_name,
vnf_instance_description, inst_additional_param)
before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance)
# get vnfc_instance_id of heal target
@ -334,14 +68,7 @@ class VnfLcmKubernetesHealTest(base.BaseTackerTest):
# test heal SOL-002 (partial heal)
vnfc_instance_id = \
[pod_target_vnfc['id'], deployment_target_vnfc['id']]
self._heal_vnf_instance(vnf_instance['id'], vnfc_instance_id)
# wait vnflcm_op_occs.operation_state become COMPLETE
self._wait_vnflcm_op_occs(self.context, vnf_instance['id'])
# check vnfcResourceInfo after heal operation
vnf_instance = _show_vnf_instance(
self.tacker_client, vnf_instance['id'])
after_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance)
self.assertEqual(len(before_vnfc_rscs), len(after_vnfc_rscs))
after_vnfc_rscs = self._test_heal(vnf_instance, vnfc_instance_id)
for vnfc_rsc in after_vnfc_rscs:
after_pod_name = vnfc_rsc['computeResource']['resourceId']
if vnfc_rsc['id'] == pod_target_vnfc['id']:
@ -372,23 +99,20 @@ class VnfLcmKubernetesHealTest(base.BaseTackerTest):
i.e. without passing vnfcInstanceId, so that the entire vnf is healed
which includes Kubernetes resource (Deployment).
"""
vnf_instance_name = "cnf_heal_with_sol003"
vnf_instance_description = "cnf heal with sol003"
# use def-files of Deployment (replicas=2)
inst_additional_param = {
"lcm-kubernetes-def-files": [
"Files/kubernetes/deployment_heal_simple.yaml"]}
vnf_instance = self._create_and_instantiate_vnf_instance(
"simple", inst_additional_param)
self.vnfd_id, "simple", vnf_instance_name,
vnf_instance_description, inst_additional_param)
before_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance)
# test heal SOL-003 (entire heal)
vnfc_instance_id = []
self._heal_vnf_instance(vnf_instance['id'], vnfc_instance_id)
# wait vnflcm_op_occs.operation_state become COMPLETE
self._wait_vnflcm_op_occs(self.context, vnf_instance['id'])
# check vnfcResourceInfo after heal operation
vnf_instance = _show_vnf_instance(
self.tacker_client, vnf_instance['id'])
after_vnfc_rscs = self._get_vnfc_resource_info(vnf_instance)
after_vnfc_rscs = self._test_heal(vnf_instance, vnfc_instance_id)
self.assertEqual(len(before_vnfc_rscs), len(after_vnfc_rscs))
# check id and pod name (as computeResource.resourceId) is changed
for before_vnfc_rsc in before_vnfc_rscs:

371
tacker/tests/functional/sol_kubernetes/vnflcm/test_kubernetes_helm.py

@ -12,347 +12,36 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import time
from tacker.tests.functional.sol_kubernetes.vnflcm import base as vnflcm_base
from oslo_serialization import jsonutils
from oslo_utils import uuidutils
from sqlalchemy import desc
from sqlalchemy.orm import joinedload
from tacker.common import exceptions
from tacker import context
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.objects import fields
from tacker.objects import vnf_lcm_op_occs
from tacker.tests.functional import base
from tacker.tests import utils
VNF_PACKAGE_UPLOAD_TIMEOUT = 300
VNF_INSTANTIATE_TIMEOUT = 600
VNF_TERMINATE_TIMEOUT = 600
VNF_HEAL_SOL002_TIMEOUT = 600
VNF_HEAL_SOL003_TIMEOUT = 1200
VNF_SCALE_TIMEOUT = 600
RETRY_WAIT_TIME = 5
def _create_and_upload_vnf_package(tacker_client, csar_package_name,
user_defined_data):
# create vnf package
body = jsonutils.dumps({"userDefinedData": user_defined_data})
resp, vnf_package = tacker_client.do_request(
'/vnfpkgm/v1/vnf_packages', "POST", body=body)
# upload vnf package
csar_package_path = "../../../etc/samples/etsi/nfv/{}".format(
csar_package_name)
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
csar_package_path))
# Generating unique vnfd id. This is required when multiple workers
# are running concurrently. The call below creates a new temporary
# CSAR with unique vnfd id.
file_path, uniqueid = utils.create_csar_with_unique_vnfd_id(file_path)
with open(file_path, 'rb') as file_object:
resp, resp_body = tacker_client.do_request(
'/vnfpkgm/v1/vnf_packages/{}/package_content'.format(
vnf_package['id']),
"PUT", body=file_object, content_type='application/zip')
# wait for onboard
start_time = int(time.time())
show_url = os.path.join('/vnfpkgm/v1/vnf_packages', vnf_package['id'])
vnfd_id = None
while True:
resp, body = tacker_client.do_request(show_url, "GET")
if body['onboardingState'] == "ONBOARDED":
vnfd_id = body['vnfdId']
break
if ((int(time.time()) - start_time) > VNF_PACKAGE_UPLOAD_TIMEOUT):
raise Exception("Failed to onboard vnf package, process could not"
" be completed within {} seconds".format(
VNF_PACKAGE_UPLOAD_TIMEOUT))
time.sleep(RETRY_WAIT_TIME)
# remove temporarily created CSAR file
os.remove(file_path)
return vnf_package['id'], vnfd_id
class VnfLcmKubernetesHelmTest(base.BaseTackerTest):
class VnfLcmKubernetesHelmTest(vnflcm_base.BaseVnfLcmKubernetesTest):
@classmethod
def setUpClass(cls):
cls.tacker_client = base.BaseTackerTest.tacker_http_client()
cls.vnf_package_resource, cls.vnfd_id_resource = \
_create_and_upload_vnf_package(
cls.tacker_client, "test_cnf_helmchart",
{"key": "sample_helmchart_functional"})
cls.vnf_instance_ids = []
super(VnfLcmKubernetesHelmTest, cls).setUpClass()
vnf_package_id, cls.vnfd_id = \
cls._create_and_upload_vnf_package(
cls, cls.tacker_client, "test_cnf_helmchart",
{"key": "sample_helmchart_functional"})
cls.vnf_package_ids.append(vnf_package_id)
@classmethod
def tearDownClass(cls):
# Update vnf package operational state to DISABLED
update_req_body = jsonutils.dumps({
"operationalState": "DISABLED"})
base_path = "/vnfpkgm/v1/vnf_packages"
for package_id in [cls.vnf_package_resource]:
resp, resp_body = cls.tacker_client.do_request(
'{base_path}/{id}'.format(id=package_id,
base_path=base_path),
"PATCH", content_type='application/json',
body=update_req_body)
# Delete vnf package
url = '/vnfpkgm/v1/vnf_packages/{}'.format(package_id)
cls.tacker_client.do_request(url, "DELETE")
super(VnfLcmKubernetesHelmTest, cls).tearDownClass()
def setUp(self):
super(VnfLcmKubernetesHelmTest, self).setUp()
self.base_vnf_instances_url = "/vnflcm/v1/vnf_instances"
self.base_vnf_lcm_op_occs_url = "/vnflcm/v1/vnf_lcm_op_occs"
self.context = context.get_admin_context()
vim_list = self.client.list_vims()
if not vim_list:
self.skipTest("Vims are not configured")
vim_id = 'vim-kubernetes'
vim = self.get_vim(vim_list, vim_id)
if not vim:
self.skipTest("Kubernetes VIM '{}' is missing".format(vim_id))
self.vim_id = vim['id']
def _instantiate_vnf_instance_request(
self, flavour_id, vim_id=None, additional_param=None):
request_body = {"flavourId": flavour_id}
if vim_id:
request_body["vimConnectionInfo"] = [
{"id": uuidutils.generate_uuid(),
"vimId": vim_id,
"vimType": "kubernetes"}]
if additional_param:
request_body["additionalParams"] = additional_param
return request_body
def _create_vnf_instance(self, vnfd_id, vnf_instance_name=None,
vnf_instance_description=None):
request_body = {'vnfdId': vnfd_id}
if vnf_instance_name:
request_body['vnfInstanceName'] = vnf_instance_name
if vnf_instance_description:
request_body['vnfInstanceDescription'] = vnf_instance_description
resp, response_body = self.http_client.do_request(
self.base_vnf_instances_url, "POST",
body=jsonutils.dumps(request_body))
return resp, response_body
def _delete_wait_vnf_instance(self, id):
url = os.path.join("/vnflcm/v1/vnf_instances", id)
start_time = int(time.time())
while True:
resp, body = self.tacker_client.do_request(url, "DELETE")
if 204 == resp.status_code:
break
if ((int(time.time()) - start_time) > VNF_TERMINATE_TIMEOUT):
raise Exception("Failed to delete vnf instance, process could"
" not be completed within {} seconds".format(
VNF_TERMINATE_TIMEOUT))
time.sleep(RETRY_WAIT_TIME)
def _show_vnf_instance(self, id):
show_url = os.path.join("/vnflcm/v1/vnf_instances", id)
resp, vnf_instance = self.tacker_client.do_request(show_url, "GET")
return vnf_instance
def _vnf_instance_wait(
self, id,
instantiation_state=fields.VnfInstanceState.INSTANTIATED,
timeout=VNF_INSTANTIATE_TIMEOUT):
show_url = os.path.join("/vnflcm/v1/vnf_instances", id)
start_time = int(time.time())
while True:
resp, body = self.tacker_client.do_request(show_url, "GET")
if body['instantiationState'] == instantiation_state:
break
if ((int(time.time()) - start_time) > timeout):
raise Exception("Failed to wait vnf instance, process could"
" not be completed within {} seconds".format(timeout))
time.sleep(RETRY_WAIT_TIME)
def _instantiate_vnf_instance(self, id, request_body):
url = os.path.join(self.base_vnf_instances_url, id, "instantiate")
resp, body = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
self._vnf_instance_wait(id)
def _create_and_instantiate_vnf_instance(self, flavour_id,
additional_params):
# create vnf instance
vnf_instance_name = "test_vnf_instance_for_cnf_heal-{}".format(
uuidutils.generate_uuid())
vnf_instance_description = "vnf instance for cnf heal testing"
resp, vnf_instance = self._create_vnf_instance(
self.vnfd_id_resource, vnf_instance_name=vnf_instance_name,
vnf_instance_description=vnf_instance_description)
# instantiate vnf instance
additional_param = additional_params
request_body = self._instantiate_vnf_instance_request(
flavour_id, vim_id=self.vim_id, additional_param=additional_param)
self._instantiate_vnf_instance(vnf_instance['id'], request_body)
vnf_instance = self._show_vnf_instance(vnf_instance['id'])
self.vnf_instance_ids.append(vnf_instance['id'])
return vnf_instance
def _terminate_vnf_instance(self, id):
# Terminate vnf forcefully
request_body = {
"terminationType": fields.VnfInstanceTerminationType.FORCEFUL,
}
url = os.path.join(self.base_vnf_instances_url, id, "terminate")
resp, body = self.http_client.do_request(
url, "POST", body=jsonutils.dumps(request_body))
self.assertEqual(202, resp.status_code)
self._vnf_instance_wait(
id,
instantiation_state=fields.VnfInstanceState.NOT_INSTANTIATED,
timeout=VNF_TERMINATE_TIMEOUT)