Enhancement of Tacker API resource access control
For fine-grained access control based on user and VNF information for API resources, this patch does the following things: 1.Add three comparison attributes of area, vendor, and tenant for the enhanced Tacker policy. 2.Convert special roles to API attributes in context. 3.Modify the API process to support Tacker policy authorize. 4.Add the Tacker policy filter to the list API processes. Implements: blueprint enhance-api-policy Change-Id: I5b4c39387860133a3bcf4544f18a6353c80773f6
This commit is contained in:
parent
3fe7831d63
commit
05fe9fa42c
34
.zuul.yaml
34
.zuul.yaml
@ -683,6 +683,38 @@
|
||||
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-legacy
|
||||
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-compliance-devstack-multinode-sol
|
||||
parent: tacker-functional-devstack-multinode-legacy
|
||||
@ -720,4 +752,6 @@
|
||||
- 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
|
||||
|
1436
doc/source/user/enhanced_tacker_policy_usage_guide.rst
Normal file
1436
doc/source/user/enhanced_tacker_policy_usage_guide.rst
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,3 +60,4 @@ Use Case Guide
|
||||
fault_notification_use_case_guide
|
||||
prometheus_plugin_use_case_guide
|
||||
db_migration_tool_usage_guide
|
||||
enhanced_tacker_policy_usage_guide
|
||||
|
251
etc/tacker/enhanced_tacker_policy.yaml.sample
Normal file
251
etc/tacker/enhanced_tacker_policy.yaml.sample
Normal file
@ -0,0 +1,251 @@
|
||||
# Decides what is required for the 'is_admin:True' check to succeed.
|
||||
"context_is_admin": "role:admin"
|
||||
|
||||
# Default rule for most non-Admin APIs.
|
||||
"admin_or_owner": "is_admin:True or project_id:%(project_id)s"
|
||||
|
||||
# Default rule for most Admin APIs.
|
||||
"admin_only": "is_admin:True"
|
||||
|
||||
# Default rule for sharing vims.
|
||||
"shared": "field:vims:shared=True"
|
||||
|
||||
# Default rule for most non-Admin APIs.
|
||||
"default": "rule:admin_or_owner"
|
||||
|
||||
# For manager
|
||||
"manager_and_owner": "role:manager and project_id:%(project_id)s"
|
||||
|
||||
# For user
|
||||
"owner": "project_id:%(project_id)s"
|
||||
|
||||
# VIM resource attributes compare rule.
|
||||
"vim_attrs_cmp": "area:%(area)s"
|
||||
|
||||
# Register a VIM.
|
||||
# Post /v1.0/vims
|
||||
"create_vim": "rule:manager_and_owner or role:admin"
|
||||
|
||||
# List VIMs or show a VIM.
|
||||
# GET /v1.0/vims
|
||||
# GET /v1.0/vims/{vim_id}
|
||||
"get_vim": "rule:vim_attrs_cmp or role:admin"
|
||||
|
||||
# Update a VIM.
|
||||
# PUT /v1.0/vims/{vim_id}
|
||||
"update_vim": "rule:vim_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Delete a VIM.
|
||||
# DELETE /v1.0/vims/{vim_id}
|
||||
"delete_vim": "rule:vim_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# vnf_packages resource attributes compare rule.
|
||||
"vnf_pkg_attrs_cmp": "vendor:%(vendor)s"
|
||||
|
||||
# Creates a VNF package.
|
||||
# POST /vnf_packages
|
||||
"os_nfv_orchestration_api:vnf_packages:create": "rule:admin_or_owner"
|
||||
|
||||
# Show a VNF package.
|
||||
# GET /vnf_packages/{vnf_package_id}
|
||||
"os_nfv_orchestration_api:vnf_packages:show": "rule:vnf_pkg_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# List all VNF packages.
|
||||
# GET /vnf_packages/
|
||||
"os_nfv_orchestration_api:vnf_packages:index": "rule:vnf_pkg_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# Delete a VNF package.
|
||||
# DELETE /vnf_packages/{vnf_package_id}
|
||||
"os_nfv_orchestration_api:vnf_packages:delete": "rule:vnf_pkg_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Fetch the contents of an on-boarded VNF Package.
|
||||
# GET /vnf_packages/{vnf_package_id}/package_content
|
||||
"os_nfv_orchestration_api:vnf_packages:fetch_package_content": "rule:vnf_pkg_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# Upload a VNF package content.
|
||||
# PUT /vnf_packages/{vnf_package_id}/package_content
|
||||
"os_nfv_orchestration_api:vnf_packages:upload_package_content": "rule:vnf_pkg_attrs_cmp or role:admin"
|
||||
|
||||
# Upload a VNF package content from URI.
|
||||
# POST /vnf_packages/{vnf_package_id}/package_content/upload_from_uri
|
||||
"os_nfv_orchestration_api:vnf_packages:upload_from_uri": "rule:admin_or_owner"
|
||||
|
||||
# Update information of VNF package.
|
||||
# PATCH /vnf_packages/{vnf_package_id}
|
||||
"os_nfv_orchestration_api:vnf_packages:patch": "rule:vnf_pkg_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Read the content of the VNFD within a VNF package.
|
||||
# GET /vnf_packages/{vnf_package_id}/vnfd
|
||||
"os_nfv_orchestration_api:vnf_packages:get_vnf_package_vnfd": "rule:vnf_pkg_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# Read the content of the artifact within a VNF package.
|
||||
# GET /vnf_packages/{vnfPkgId}/artifacts/{artifactPath}
|
||||
"os_nfv_orchestration_api:vnf_packages:fetch_artifact": "rule:vnf_pkg_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# vnflcm create attributes compare rule.
|
||||
"vnflcm_create_attrs_cmp": "vendor:%(vendor)s"
|
||||
|
||||
# vnflcm instantiate attributes compare rule.
|
||||
"vnflcm_inst_attrs_cmp": "vendor:%(vendor)s"
|
||||
|
||||
# vnflcm delete attributes compare rule.
|
||||
"vnflcm_delete_attrs_cmp": "vendor:%(vendor)s"
|
||||
|
||||
# vnflcm resource attributes compare rule.
|
||||
"vnflcm_attrs_cmp": "area:%(area)s and vendor:%(vendor)s and tenant:%(tenant)s"
|
||||
|
||||
# Get API Versions.
|
||||
# GET /vnflcm/v1/api_versions
|
||||
"os_nfv_orchestration_api:vnf_instances:api_versions": "@"
|
||||
|
||||
# Create VNF instance.
|
||||
# POST /vnflcm/v1/vnf_instances
|
||||
"os_nfv_orchestration_api:vnf_instances:create": "rule:vnflcm_create_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Instantiate VNF instance.
|
||||
# POST /vnflcm/v1/vnf_instances/{vnfInstanceId}/instantiate
|
||||
"os_nfv_orchestration_api:vnf_instances:instantiate": "rule:vnflcm_inst_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Query an Individual VNF instance.
|
||||
# GET /vnflcm/v1/vnf_instances/{vnfInstanceId}
|
||||
"os_nfv_orchestration_api:vnf_instances:show": "rule:vnflcm_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# Terminate a VNF instance.
|
||||
# POST /vnflcm/v1/vnf_instances/{vnfInstanceId}/terminate
|
||||
"os_nfv_orchestration_api:vnf_instances:terminate": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Heal a VNF instance.
|
||||
# POST /vnflcm/v1/vnf_instances/{vnfInstanceId}/heal
|
||||
"os_nfv_orchestration_api:vnf_instances:heal": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Scale a VNF instance.
|
||||
# POST /vnflcm/v1/vnf_instances/{vnfInstanceId}/scale
|
||||
"os_nfv_orchestration_api:vnf_instances:scale": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Query an Individual VNF LCM operation occurrence.
|
||||
# GET /vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}
|
||||
"os_nfv_orchestration_api:vnf_instances:show_lcm_op_occs": "rule:admin_or_owner"
|
||||
|
||||
# Query VNF LCM operation occurrence.
|
||||
# GET /vnflcm/v1/vnf_lcm_op_occs
|
||||
"os_nfv_orchestration_api:vnf_instances:list_lcm_op_occs": "rule:admin_or_owner"
|
||||
|
||||
# Query VNF instances.
|
||||
# GET /vnflcm/v1/vnf_instances
|
||||
"os_nfv_orchestration_api:vnf_instances:index": "rule:vnflcm_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# Delete an Individual VNF instance.
|
||||
# DELETE /vnflcm/v1/vnf_instances/{vnfInstanceId}
|
||||
"os_nfv_orchestration_api:vnf_instances:delete": "rule:vnflcm_delete_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Update an Individual VNF instance.
|
||||
# PATCH /vnflcm/v1/vnf_instances/{vnfInstanceId}
|
||||
"os_nfv_orchestration_api:vnf_instances:update_vnf": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Rollback a VNF instance.
|
||||
# POST /vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/rollback
|
||||
"os_nfv_orchestration_api:vnf_instances:rollback": "rule:admin_or_owner"
|
||||
|
||||
# Cancel a VNF instance.
|
||||
# POST /vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/cancel
|
||||
"os_nfv_orchestration_api:vnf_instances:cancel": "rule:admin_or_owner"
|
||||
|
||||
# Fail a VNF instance.
|
||||
# POST /vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/fail
|
||||
"os_nfv_orchestration_api:vnf_instances:fail": "rule:admin_or_owner"
|
||||
|
||||
# Retry a VNF instance.
|
||||
# POST /vnflcm/v1/vnf_lcm_op_occs/{vnfLcmOpOccId}/retry
|
||||
"os_nfv_orchestration_api:vnf_instances:retry": "rule:admin_or_owner"
|
||||
|
||||
# Change external VNF connectivity.
|
||||
# POST /vnflcm/v1/vnf_instances/{vnfInstanceId}/change_ext_conn
|
||||
"os_nfv_orchestration_api:vnf_instances:change_ext_conn": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Get API Versions.
|
||||
# GET /vnflcm/v2/api_versions
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:api_versions": "@"
|
||||
|
||||
# Creates VNF instance.
|
||||
# POST /vnflcm/v2/vnf_instances
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:create": "rule:vnflcm_create_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Query VNF instances.
|
||||
# GET /vnflcm/v2/vnf_instances
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:index": "rule:vnflcm_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# Query an Individual VNF instance.
|
||||
# GET /vnflcm/v2/vnf_instances/{vnfInstanceId}
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:show": "rule:vnflcm_attrs_cmp and rule:owner or role:admin"
|
||||
|
||||
# Delete an Individual VNF instance.
|
||||
# DELETE /vnflcm/v2/vnf_instances/{vnfInstanceId}
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:delete": "rule:vnflcm_delete_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Modify VNF instance information.
|
||||
# PATCH /vnflcm/v2/vnf_instances/{vnfInstanceId}
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:update": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Instantiate VNF instance.
|
||||
# POST /vnflcm/v2/vnf_instances/{vnfInstanceId}/instantiate
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:instantiate": "rule:vnflcm_inst_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Terminate VNF instance.
|
||||
# POST /vnflcm/v2/vnf_instances/{vnfInstanceId}/terminate
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:terminate": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Scale VNF instance.
|
||||
# POST /vnflcm/v2/vnf_instances/{vnfInstanceId}/scale
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:scale": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Heal VNF instance.
|
||||
# POST /vnflcm/v2/vnf_instances/{vnfInstanceId}/heal
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:heal": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Change external VNF connectivity.
|
||||
# POST /vnflcm/v2/vnf_instances/{vnfInstanceId}/change_ext_conn
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:change_ext_conn": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Change VNF package.
|
||||
# POST /vnflcm/v2/vnf_instances/{vnfInstanceId}/change_vnfpkg
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:change_vnfpkg": "rule:vnflcm_attrs_cmp and rule:manager_and_owner or role:admin"
|
||||
|
||||
# Create subscription.
|
||||
# POST /vnflcm/v2/subscriptions
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:subscription_create": "@"
|
||||
|
||||
# List subscription.
|
||||
# GET /vnflcm/v2/subscriptions
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:subscription_list": "@"
|
||||
|
||||
# Show subscription.
|
||||
# GET /vnflcm/v2/vnf_instances/{subscriptionId}
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:subscription_show": "@"
|
||||
|
||||
# Delete subscription.
|
||||
# DELETE /vnflcm/v2/vnf_instances/{subscriptionId}
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:subscription_delete": "@"
|
||||
|
||||
# List VnfLcmOpOcc.
|
||||
# GET /vnflcm/v2/vnf_lcm_op_occs
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:lcm_op_occ_list": "@"
|
||||
|
||||
# Show VnfLcmOpOcc.
|
||||
# GET /vnflcm/v2/vnf_lcm_op_occs/{vnfLcmOpOccId}
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:lcm_op_occ_show": "@"
|
||||
|
||||
# Retry VnfLcmOpOcc.
|
||||
# POST /vnflcm/v2/vnf_lcm_op_occs/{vnfLcmOpOccId}/retry
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:lcm_op_occ_retry": "@"
|
||||
|
||||
# Rollback VnfLcmOpOcc.
|
||||
# POST /vnflcm/v2/vnf_lcm_op_occs/{vnfLcmOpOccId}/rollback
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:lcm_op_occ_rollback": "@"
|
||||
|
||||
# Fail VnfLcmOpOcc.
|
||||
# POST /vnflcm/v2/vnf_lcm_op_occs/{vnfLcmOpOccId}/fail
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:lcm_op_occ_fail": "@"
|
||||
|
||||
# Delete VnfLcmOpOcc.
|
||||
# DELETE /vnflcm/v2/vnf_lcm_op_occs/{vnfLcmOpOccId}
|
||||
"os_nfv_orchestration_api_v2:vnf_instances:lcm_op_occ_delete": "@"
|
@ -15,6 +15,8 @@
|
||||
when: setup_multi_az is defined and setup_multi_az | bool
|
||||
- role: setup-fake-https-server
|
||||
when: https_setup is defined and https_setup | bool
|
||||
- role: config-enhanced-policy
|
||||
when: config_enhanced_policy is defined and config_enhanced_policy | bool
|
||||
- role: bindep
|
||||
bindep_profile: test
|
||||
bindep_dir: "{{ zuul_work_dir }}"
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Enhance the existing Tacker policy function so that users can obtain more
|
||||
fine-grained access control based on user roles and VNF information for
|
||||
API resources.
|
12
roles/config-enhanced-policy/tasks/main.yaml
Normal file
12
roles/config-enhanced-policy/tasks/main.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
- block:
|
||||
- name: Copy policy.yaml
|
||||
copy:
|
||||
src: "{{ devstack_base_dir }}/tacker/etc/tacker/enhanced_tacker_policy.yaml.sample"
|
||||
dest: "/etc/tacker/policy.yaml"
|
||||
remote_src: true
|
||||
mode: 0644
|
||||
owner: stack
|
||||
group: stack
|
||||
become: yes
|
||||
when:
|
||||
- inventory_hostname == 'controller-tacker'
|
@ -288,7 +288,7 @@ class VnfLcmController(wsgi.Controller):
|
||||
vim_client_obj = vim_client.VimClient()
|
||||
|
||||
try:
|
||||
vim_client_obj.get_vim(
|
||||
return vim_client_obj.get_vim(
|
||||
context, vim_id, region_name=region_name)
|
||||
except nfvo.VimDefaultNotDefined as exp:
|
||||
raise webob.exc.HTTPBadRequest(explanation=exp.message)
|
||||
@ -439,6 +439,7 @@ class VnfLcmController(wsgi.Controller):
|
||||
@validation.schema(vnf_lcm.create)
|
||||
def create(self, request, body):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'create')
|
||||
try:
|
||||
req_body = utils.convert_camelcase_to_snakecase(body)
|
||||
@ -466,6 +467,10 @@ class VnfLcmController(wsgi.Controller):
|
||||
vnfd_id)
|
||||
return self._make_problem_detail(
|
||||
msg, 500, 'Internal Server Error')
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'create',
|
||||
target={'vendor': vnfd.vnf_provider})
|
||||
|
||||
try:
|
||||
# get default vim information
|
||||
vim_client_obj = vim_client.VimClient()
|
||||
@ -489,6 +494,17 @@ class VnfLcmController(wsgi.Controller):
|
||||
try:
|
||||
vnf_instance.create()
|
||||
|
||||
vim_conn = objects.VimConnectionInfo(
|
||||
id=uuidutils.generate_uuid(),
|
||||
vim_id=default_vim.get('vim_id'),
|
||||
vim_type=default_vim.get('vim_type'),
|
||||
access_info={},
|
||||
interface_info={},
|
||||
extra=default_vim.get('extra', {})
|
||||
)
|
||||
vnf_instance.vim_connection_info = [vim_conn]
|
||||
vnf_instance.save()
|
||||
|
||||
# create entry to 'vnf' table and 'vnf_attribute' table
|
||||
attributes = {'placement_attr': default_vim.
|
||||
get('placement_attr', {})}
|
||||
@ -560,12 +576,52 @@ class VnfLcmController(wsgi.Controller):
|
||||
|
||||
return vnf_package_info[0]
|
||||
|
||||
def _get_policy_target(self, vnf_instance):
|
||||
vendor = vnf_instance.vnf_provider
|
||||
|
||||
area = None
|
||||
if vnf_instance.vim_connection_info:
|
||||
for connection_info in vnf_instance.vim_connection_info:
|
||||
area = connection_info.extra.get('area')
|
||||
if area:
|
||||
break
|
||||
|
||||
tenant = None
|
||||
if (vnf_instance.instantiation_state ==
|
||||
fields.VnfInstanceState.INSTANTIATED):
|
||||
if vnf_instance.vnf_metadata:
|
||||
tenant = vnf_instance.vnf_metadata.get('namespace')
|
||||
|
||||
# TODO(kexuesheng): Add steps to get tenant of VNFs deployed
|
||||
# in OpenStack VIM. This is a temporary workaround until that
|
||||
# information is available.
|
||||
if vnf_instance.vim_connection_info:
|
||||
vim_type = vnf_instance.vim_connection_info[0].vim_type
|
||||
if vim_type in ["openstack", "ETSINFV.OPENSTACK_KEYSTONE.v_2"]:
|
||||
tenant = '*'
|
||||
else:
|
||||
tenant = '*'
|
||||
|
||||
target = {
|
||||
'vendor': vendor,
|
||||
'area': area,
|
||||
'tenant': tenant
|
||||
}
|
||||
|
||||
target = {k: v for k, v in target.items() if v is not None}
|
||||
|
||||
return target
|
||||
|
||||
@wsgi.response(http_client.OK)
|
||||
@wsgi.expected_errors((http_client.FORBIDDEN, http_client.NOT_FOUND))
|
||||
def show(self, request, id):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'show')
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'show',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
|
||||
return self._view_builder.show(vnf_instance)
|
||||
|
||||
@ -579,8 +635,8 @@ class VnfLcmController(wsgi.Controller):
|
||||
@api_common.validate_supported_params({'filter', 'nextpage_opaque_marker',
|
||||
'all_records'})
|
||||
def index(self, request):
|
||||
if 'tacker.context' in request.environ:
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'index')
|
||||
|
||||
filters = request.GET.get('filter')
|
||||
@ -611,6 +667,13 @@ class VnfLcmController(wsgi.Controller):
|
||||
return self._make_problem_detail(
|
||||
str(e), 500, title='Internal Server Error')
|
||||
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
result = [vnf_instance for vnf_instance in result
|
||||
if context.can(
|
||||
vnf_lcm_policies.VNFLCM % 'index',
|
||||
target=self._get_policy_target(vnf_instance),
|
||||
fatal=False)]
|
||||
|
||||
result = self._view_builder.index(result)
|
||||
|
||||
res = webob.Response(content_type='application/json')
|
||||
@ -650,6 +713,10 @@ class VnfLcmController(wsgi.Controller):
|
||||
context = request.environ['tacker.context']
|
||||
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'delete',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
|
||||
vnf = self._get_vnf(context, id)
|
||||
self._delete(context, vnf_instance, vnf)
|
||||
|
||||
@ -683,7 +750,12 @@ class VnfLcmController(wsgi.Controller):
|
||||
req_body, context=context)
|
||||
|
||||
# validate the vim connection id passed through request is exist or not
|
||||
self._validate_vim_connection(context, instantiate_vnf_request)
|
||||
vim_res = self._validate_vim_connection(
|
||||
context, instantiate_vnf_request)
|
||||
|
||||
if instantiate_vnf_request.vim_connection_info:
|
||||
instantiate_vnf_request.vim_connection_info[0].extra = vim_res.get(
|
||||
'extra', {})
|
||||
|
||||
vnf_instance.task_state = fields.VnfInstanceTaskState.INSTANTIATING
|
||||
vnf_instance.save()
|
||||
@ -715,10 +787,14 @@ class VnfLcmController(wsgi.Controller):
|
||||
@validation.schema(vnf_lcm.instantiate)
|
||||
def instantiate(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'instantiate')
|
||||
|
||||
vnf = self._get_vnf(context, id)
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'instantiate',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
|
||||
return self._instantiate(context, vnf_instance, vnf, body)
|
||||
|
||||
@ -766,10 +842,14 @@ class VnfLcmController(wsgi.Controller):
|
||||
@validation.schema(vnf_lcm.terminate)
|
||||
def terminate(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'terminate')
|
||||
|
||||
vnf = self._get_vnf(context, id)
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'terminate',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
return self._terminate(context, vnf_instance, vnf, body)
|
||||
|
||||
@check_vnf_status_and_error_point(action="heal",
|
||||
@ -822,10 +902,14 @@ class VnfLcmController(wsgi.Controller):
|
||||
@validation.schema(vnf_lcm.heal)
|
||||
def heal(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'heal')
|
||||
|
||||
vnf = self._get_vnf(context, id)
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'heal',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
|
||||
if vnf_instance.instantiation_state not in \
|
||||
[fields.VnfInstanceState.INSTANTIATED]:
|
||||
@ -865,6 +949,11 @@ class VnfLcmController(wsgi.Controller):
|
||||
@wsgi.expected_errors((http_client.FORBIDDEN, http_client.NOT_FOUND))
|
||||
def update(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'update_vnf',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
else:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'update_vnf')
|
||||
|
||||
# get body
|
||||
@ -1343,6 +1432,7 @@ class VnfLcmController(wsgi.Controller):
|
||||
http_client.NOT_FOUND, http_client.CONFLICT))
|
||||
def scale(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'scale')
|
||||
|
||||
try:
|
||||
@ -1351,6 +1441,9 @@ class VnfLcmController(wsgi.Controller):
|
||||
return self._make_problem_detail(
|
||||
'VNF IS NOT ACTIVE', 409, title='VNF IS NOT ACTIVE')
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'scale',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
if not vnf_instance.instantiated_vnf_info.scale_status:
|
||||
return self._make_problem_detail(
|
||||
'NOT SCALE VNF', 409, title='NOT SCALE VNF')
|
||||
@ -1361,6 +1454,8 @@ class VnfLcmController(wsgi.Controller):
|
||||
except webob.exc.HTTPNotFound as inst_e:
|
||||
return self._make_problem_detail(
|
||||
str(inst_e), 404, title='VNF NOT FOUND')
|
||||
except exceptions.PolicyNotAuthorized:
|
||||
raise
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return self._make_problem_detail(
|
||||
@ -1819,10 +1914,14 @@ class VnfLcmController(wsgi.Controller):
|
||||
@validation.schema(vnf_lcm.change_ext_conn)
|
||||
def change_ext_conn(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'change_ext_conn')
|
||||
|
||||
vnf = self._get_vnf(context, id)
|
||||
vnf_instance = self._get_vnf_instance(context, id)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_lcm_policies.VNFLCM % 'change_ext_conn',
|
||||
target=self._get_policy_target(vnf_instance))
|
||||
if (vnf_instance.instantiation_state !=
|
||||
fields.VnfInstanceState.INSTANTIATED):
|
||||
return self._make_problem_detail(
|
||||
|
@ -104,6 +104,7 @@ class VnfPkgmController(wsgi.Controller):
|
||||
@wsgi.expected_errors((http_client.FORBIDDEN, http_client.NOT_FOUND))
|
||||
def show(self, request, id):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'show')
|
||||
|
||||
# check if id is of type uuid format
|
||||
@ -115,18 +116,33 @@ class VnfPkgmController(wsgi.Controller):
|
||||
vnf_package = vnf_package_obj.VnfPackage.get_by_id(
|
||||
request.context, id, expected_attrs=[
|
||||
"vnf_deployment_flavours", "vnfd", "vnf_artifacts"])
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'show',
|
||||
target=self._get_policy_target(vnf_package))
|
||||
except exceptions.VnfPackageNotFound:
|
||||
msg = _("Can not find requested vnf package: %s") % id
|
||||
raise webob.exc.HTTPNotFound(explanation=msg)
|
||||
|
||||
return self._view_builder.show(vnf_package)
|
||||
|
||||
def _get_policy_target(self, vnf_package):
|
||||
if vnf_package.onboarding_state == \
|
||||
fields.PackageOnboardingStateType.ONBOARDED:
|
||||
|
||||
vendor = (vnf_package.vnfd.get('vnf_provider')
|
||||
if vnf_package.vnfd is not None else None)
|
||||
|
||||
return {'vendor': vendor} if vendor else {}
|
||||
|
||||
else:
|
||||
return {'vendor': '*'}
|
||||
|
||||
@wsgi.response(http_client.OK)
|
||||
@wsgi.expected_errors((http_client.BAD_REQUEST, http_client.FORBIDDEN))
|
||||
@validation.query_schema(vnf_packages.query_params_v1)
|
||||
def index(self, request):
|
||||
if 'tacker.context' in request.environ:
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'index')
|
||||
|
||||
search_opts = {}
|
||||
@ -178,6 +194,13 @@ class VnfPkgmController(wsgi.Controller):
|
||||
return self._make_problem_detail(
|
||||
str(e), 500, title='Internal Server Error')
|
||||
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
result = [vnf_package for vnf_package in result
|
||||
if context.can(
|
||||
vnf_package_policies.VNFPKGM % 'index',
|
||||
target=self._get_policy_target(vnf_package),
|
||||
fatal=False)]
|
||||
|
||||
results = self._view_builder.index(result,
|
||||
all_fields=all_fields,
|
||||
exclude_fields=exclude_fields,
|
||||
@ -206,9 +229,13 @@ class VnfPkgmController(wsgi.Controller):
|
||||
http_client.CONFLICT))
|
||||
def delete(self, request, id):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'delete')
|
||||
|
||||
vnf_package = self._get_vnf_package(id, request)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'delete',
|
||||
target=self._get_policy_target(vnf_package))
|
||||
|
||||
if (vnf_package.operational_state ==
|
||||
fields.PackageOperationalStateType.ENABLED or
|
||||
@ -244,9 +271,13 @@ class VnfPkgmController(wsgi.Controller):
|
||||
http_client.REQUESTED_RANGE_NOT_SATISFIABLE))
|
||||
def fetch_vnf_package_content(self, request, id):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'fetch_package_content')
|
||||
|
||||
vnf_package = self._get_vnf_package(id, request)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'fetch_package_content',
|
||||
target=self._get_policy_target(vnf_package))
|
||||
|
||||
if vnf_package.onboarding_state != \
|
||||
fields.PackageOnboardingStateType.ONBOARDED:
|
||||
@ -367,7 +398,9 @@ class VnfPkgmController(wsgi.Controller):
|
||||
http_client.CONFLICT))
|
||||
def upload_vnf_package_content(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
context.can(vnf_package_policies.VNFPKGM % 'upload_package_content')
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(
|
||||
vnf_package_policies.VNFPKGM % 'upload_package_content')
|
||||
|
||||
# check if id is of type uuid format
|
||||
if not uuidutils.is_uuid_like(id):
|
||||
@ -404,6 +437,13 @@ class VnfPkgmController(wsgi.Controller):
|
||||
try:
|
||||
(location, size, checksum, multihash,
|
||||
loc_meta) = glance_store.store_csar(context, id, body)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
zip_path = glance_store.load_csar(vnf_package.id, location)
|
||||
vnf_data, flavours, vnf_artifacts = csar_utils.load_csar_data(
|
||||
context.elevated(), vnf_package.id, zip_path)
|
||||
context.can(
|
||||
vnf_package_policies.VNFPKGM % 'upload_package_content',
|
||||
target={'vendor': vnf_data.get('provider')})
|
||||
except exceptions.UploadFailedToGlanceStore:
|
||||
with excutils.save_and_reraise_exception():
|
||||
vnf_package.onboarding_state = (
|
||||
@ -413,6 +453,19 @@ class VnfPkgmController(wsgi.Controller):
|
||||
except Exception as e:
|
||||
return self._make_problem_detail(
|
||||
'Internal Server Error', str(e), 500)
|
||||
except exceptions.Forbidden:
|
||||
with excutils.save_and_reraise_exception():
|
||||
vnf_package.onboarding_state = (
|
||||
fields.PackageOnboardingStateType.CREATED)
|
||||
try:
|
||||
# Delete from glance store
|
||||
glance_store.delete_csar(context, vnf_package.id,
|
||||
location)
|
||||
csar_utils.delete_csar_data(vnf_package.id)
|
||||
vnf_package.save()
|
||||
except Exception as e:
|
||||
return self._make_problem_detail(
|
||||
'Internal Server Error', str(e), 500)
|
||||
|
||||
vnf_package.algorithm = CONF.vnf_package.hashing_algorithm
|
||||
vnf_package.hash = multihash
|
||||
@ -475,9 +528,13 @@ class VnfPkgmController(wsgi.Controller):
|
||||
@validation.schema(vnf_packages.patch)
|
||||
def patch(self, request, id, body):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'patch')
|
||||
|
||||
old_vnf_package = self._get_vnf_package(id, request)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'patch',
|
||||
target=self._get_policy_target(old_vnf_package))
|
||||
vnf_package = old_vnf_package.obj_clone()
|
||||
|
||||
user_data = body.get('userDefinedData')
|
||||
@ -529,6 +586,7 @@ class VnfPkgmController(wsgi.Controller):
|
||||
http_client.INTERNAL_SERVER_ERROR))
|
||||
def get_vnf_package_vnfd(self, request, id):
|
||||
context = request.environ['tacker.context']
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'get_vnf_package_vnfd')
|
||||
|
||||
valid_accept_headers = ['application/zip', 'text/plain']
|
||||
@ -543,6 +601,9 @@ class VnfPkgmController(wsgi.Controller):
|
||||
valid_accept_headers)})
|
||||
|
||||
vnf_package = self._get_vnf_package(id, request)
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'get_vnf_package_vnfd',
|
||||
target=self._get_policy_target(vnf_package))
|
||||
|
||||
if vnf_package.onboarding_state != \
|
||||
fields.PackageOnboardingStateType.ONBOARDED:
|
||||
@ -586,6 +647,7 @@ class VnfPkgmController(wsgi.Controller):
|
||||
def fetch_vnf_package_artifacts(self, request, id, artifact_path):
|
||||
context = request.environ['tacker.context']
|
||||
# get policy
|
||||
if not CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(vnf_package_policies.VNFPKGM % 'fetch_artifact')
|
||||
|
||||
# get vnf_package
|
||||
@ -597,6 +659,10 @@ class VnfPkgmController(wsgi.Controller):
|
||||
vnf_package = vnf_package_obj.VnfPackage.get_by_id(
|
||||
request.context, id,
|
||||
expected_attrs=["vnf_artifacts"])
|
||||
if CONF.oslo_policy.enhanced_tacker_policy:
|
||||
# get policy
|
||||
context.can(vnf_package_policies.VNFPKGM % 'fetch_artifact',
|
||||
target=self._get_policy_target(vnf_package))
|
||||
except exceptions.VnfPackageNotFound:
|
||||
msg = _("Can not find requested vnf package: %s") % id
|
||||
raise webob.exc.HTTPNotFound(explanation=msg)
|
||||
|
@ -174,6 +174,18 @@ def is_valid_ipv4(address):
|
||||
return False
|
||||
|
||||
|
||||
def is_valid_area(area):
|
||||
"""Verify that the area attribute is valid.
|
||||
|
||||
Area attribute is an area-region pair. The value of this attribute should
|
||||
be a string in the format of "area@region".
|
||||
"""
|
||||
try:
|
||||
return re.match(r'\w+@\w+', area) is not None
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def change_memory_unit(mem, to):
|
||||
"""Change the memory value(mem) based on the unit('to') specified.
|
||||
|
||||
|
@ -18,6 +18,7 @@ from oslo_config import cfg
|
||||
|
||||
from tacker.conf import conductor
|
||||
from tacker.conf import coordination
|
||||
from tacker.conf import policy
|
||||
from tacker.conf import vnf_lcm
|
||||
from tacker.conf import vnf_package
|
||||
|
||||
@ -29,3 +30,4 @@ vnf_lcm.register_opts(CONF)
|
||||
conductor.register_opts(CONF)
|
||||
coordination.register_opts(CONF)
|
||||
glance_store.register_opts(CONF)
|
||||
policy.register_opts(CONF)
|
||||
|
33
tacker/conf/policy.py
Normal file
33
tacker/conf/policy.py
Normal file
@ -0,0 +1,33 @@
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
policy_opts = [
|
||||
cfg.BoolOpt('enhanced_tacker_policy',
|
||||
default=False,
|
||||
help=_('Enable enhanced tacker policy')),
|
||||
]
|
||||
|
||||
|
||||
def register_opts(conf):
|
||||
conf.register_opts(policy_opts, group='oslo_policy')
|
||||
|
||||
|
||||
def list_opts():
|
||||
return {'oslo_policy': policy_opts}
|
@ -148,11 +148,14 @@ class ContextBase(oslo_context.RequestContext):
|
||||
:return: returns a non-False value (not necessarily "True") if
|
||||
authorized and False if not authorized and fatal is False.
|
||||
"""
|
||||
if target is None:
|
||||
target = {'project_id': self.tenant_id,
|
||||
'user_id': self.user_id}
|
||||
tgt = {
|
||||
'project_id': self.tenant_id,
|
||||
'user_id': self.user_id
|
||||
}
|
||||
if target is not None:
|
||||
tgt.update(target)
|
||||
try:
|
||||
return policy.authorize(self, action, target)
|
||||
return policy.authorize(self, action, tgt)
|
||||
except exceptions.Forbidden:
|
||||
if fatal:
|
||||
raise
|
||||
|
155
tacker/policy.py
155
tacker/policy.py
@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
from collections import abc
|
||||
import copy
|
||||
import re
|
||||
import sys
|
||||
|
||||
@ -28,6 +29,7 @@ from oslo_utils import importutils
|
||||
from tacker._i18n import _
|
||||
from tacker.api.v1 import attributes
|
||||
from tacker.common import exceptions
|
||||
from tacker.common.utils import is_valid_area
|
||||
from tacker import policies
|
||||
|
||||
|
||||
@ -60,10 +62,133 @@ def init(conf=cfg.CONF, policy_file=None):
|
||||
_ENFORCER.load_rules()
|
||||
|
||||
|
||||
def _pre_enhanced_policy_check(target, credentials):
|
||||
"""Preprocesses target and credentials for enhanced tacker policy.
|
||||
|
||||
This method does the following things:
|
||||
1) Convert special roles to enhanced policy attributes in credentials.
|
||||
Note: Special roles are roles that have prefixes 'AREA_', 'VENDOR_',
|
||||
or 'TENANT_'.
|
||||
Example::
|
||||
|
||||
Before conversion:
|
||||
credentials = {
|
||||
'roles': [
|
||||
'AREA_area_A@region_A',
|
||||
'VENDOR_company_A',
|
||||
'TENANT_default'
|
||||
]
|
||||
}
|
||||
After conversion:
|
||||
credentials = {
|
||||
'roles': [
|
||||
'AREA_area_A@region_A',
|
||||
'VENDOR_company_A',
|
||||
'TENANT_default'
|
||||
],
|
||||
'area': ['*', 'area_A@region_A'],
|
||||
'vendor': ['*', 'company_A'],
|
||||
'tenant: ['*', 'default']
|
||||
}
|
||||
2) Convert special value `all` to the corresponding attribute value in
|
||||
target.
|
||||
|
||||
:param target: a dictionary of the attributes of the object
|
||||
being accessed.
|
||||
:param credentials: The information about the user performing the action.
|
||||
:return tgt: The preprocessed target is returned.
|
||||
:return user_attrs: The preprocessed credentials is returned.
|
||||
"""
|
||||
if not cfg.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
return target, credentials
|
||||
|
||||
if target is None:
|
||||
tgt = {}
|
||||
else:
|
||||
tgt = copy.copy(target)
|
||||
|
||||
LOG.debug(f'target: {target}')
|
||||
|
||||
convert_map = {
|
||||
'area_': 'area',
|
||||
'vendor_': 'vendor',
|
||||
'tenant_': 'tenant'
|
||||
}
|
||||
user_attrs = {
|
||||
'area': ['*'],
|
||||
'vendor': ['*'],
|
||||
'tenant': ['*']
|
||||
}
|
||||
# Convert special roles to enhanced policy attributes in credentials.
|
||||
for role in credentials.get('roles'):
|
||||
role = role.lower()
|
||||
for prefix, key in convert_map.items():
|
||||
if role.startswith(prefix):
|
||||
attr = role[len(prefix):]
|
||||
if attr:
|
||||
user_attrs[key].append(attr)
|
||||
|
||||
common_keys = user_attrs.keys() & tgt.keys()
|
||||
|
||||
# Convert special value `all` to the corresponding attribute value in
|
||||
# target.
|
||||
for key in common_keys:
|
||||
tgt[key] = tgt[key].lower()
|
||||
attrs = user_attrs.get(key)
|
||||
if tgt.get(key) == '*':
|
||||
continue
|
||||
to_remove = []
|
||||
if 'area' == key:
|
||||
if not is_valid_area(tgt.get(key)):
|
||||
continue
|
||||
for attr in attrs:
|
||||
if not is_valid_area(attr):
|
||||
continue
|
||||
if 'all@all' == attr:
|
||||
# example:
|
||||
# target = {'area': 'area_A@region_A'}
|
||||
# then:
|
||||
# 'all@all' -> 'area_A@region_A'
|
||||
to_remove.append('all@all')
|
||||
attrs.append(tgt.get(key))
|
||||
elif attr.startswith('all@'):
|
||||
to_remove.append(attr)
|
||||
area, region = attr.split('@', 1)
|
||||
t_area, t_region = tgt.get(key).split('@', 1)
|
||||
if region == t_region:
|
||||
# example:
|
||||
# target = {'area': 'area_A@region_A'}
|
||||
# then:
|
||||
# 'all@region_A' -> 'area_A@region_A'
|
||||
attrs.append(f'{t_area}@{region}')
|
||||
# else:
|
||||
# example:
|
||||
# target = {'area': 'area_A@region_B'}
|
||||
# then:
|
||||
# 'all@region_A' -> to be removed.
|
||||
|
||||
else:
|
||||
for attr in attrs:
|
||||
if 'all' == attr:
|
||||
# example:
|
||||
# target = {'vendor': 'company_A'}
|
||||
# then:
|
||||
# 'all' -> 'company_A'
|
||||
to_remove.append('all')
|
||||
attrs.append(tgt.get(key))
|
||||
for item in to_remove:
|
||||
attrs.remove(item)
|
||||
|
||||
user_attrs.update(credentials)
|
||||
|
||||
return tgt, user_attrs
|
||||
|
||||
|
||||
def authorize(context, action, target, do_raise=True, exc=None):
|
||||
|
||||
init()
|
||||
credentials = context.to_policy_values()
|
||||
target, credentials = _pre_enhanced_policy_check(target, credentials)
|
||||
if not exc:
|
||||
exc = exceptions.PolicyNotAuthorized
|
||||
try:
|
||||
@ -387,6 +512,15 @@ def check(context, action, target, plugin=None, might_not_exist=False,
|
||||
action,
|
||||
target,
|
||||
pluralized)
|
||||
target = copy.copy(target)
|
||||
if 'area' not in target:
|
||||
area = target.get('extra', {}).get('area')
|
||||
if area:
|
||||
target.update({'area': area})
|
||||
if 'tenant_id' in target:
|
||||
target['project_id'] = target['tenant_id']
|
||||
target, credentials = _pre_enhanced_policy_check(target, credentials)
|
||||
|
||||
result = _ENFORCER.enforce(match_rule,
|
||||
target,
|
||||
credentials,
|
||||
@ -397,7 +531,8 @@ def check(context, action, target, plugin=None, might_not_exist=False,
|
||||
return result
|
||||
|
||||
|
||||
def enforce(context, action, target, plugin=None, pluralized=None):
|
||||
def enforce(context, action, target, plugin=None, pluralized=None,
|
||||
exc=exceptions.PolicyNotAuthorized):
|
||||
"""Verifies that the action is valid on the target in this context.
|
||||
|
||||
:param context: tacker context
|
||||
@ -410,8 +545,11 @@ def enforce(context, action, target, plugin=None, pluralized=None):
|
||||
Kept for backward compatibility.
|
||||
:param pluralized: pluralized case of resource
|
||||
e.g. firewall_policy -> pluralized = "firewall_policies"
|
||||
:param exc: Class of the exception to raise if the check fails.
|
||||
If not specified, :class:`PolicyNotAuthorized` will be used.
|
||||
|
||||
:raises oslo_policy.policy.PolicyNotAuthorized:
|
||||
:raises tacker.common.exceptions.PolicyNotAuthorized or exc specified by
|
||||
caller:
|
||||
if verification fails.
|
||||
"""
|
||||
# If we already know the context has admin rights do not perform an
|
||||
@ -422,10 +560,19 @@ def enforce(context, action, target, plugin=None, pluralized=None):
|
||||
action,
|
||||
target,
|
||||
pluralized)
|
||||
target = copy.copy(target)
|
||||
if 'area' not in target:
|
||||
area = target.get('extra', {}).get('area')
|
||||
if area:
|
||||
target.update({'area': area})
|
||||
if 'tenant_id' in target:
|
||||
target['project_id'] = target['tenant_id']
|
||||
target, credentials = _pre_enhanced_policy_check(target, credentials)
|
||||
|
||||
try:
|
||||
result = _ENFORCER.enforce(rule, target, credentials, action=action,
|
||||
do_raise=True)
|
||||
except policy.PolicyNotAuthorized:
|
||||
do_raise=True, exc=exc)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
log_rule_list(rule)
|
||||
LOG.error("Failed policy check for '%s'", action)
|
||||
|
@ -36,6 +36,20 @@ VNF_LCM_OP_OCCS_PATH = V2_PATH + '/vnf_lcm_op_occs'
|
||||
VNF_LCM_OP_OCCS_ID_PATH = VNF_LCM_OP_OCCS_PATH + '/{vnfLcmOpOccId}'
|
||||
SERVER_NOTIFICATION_PATH = CONF.server_notification.uri_path_prefix
|
||||
|
||||
ENHANCED_POLICY_ACTIONS = (
|
||||
POLICY_NAME.format('create'),
|
||||
POLICY_NAME.format('index'),
|
||||
POLICY_NAME.format('show'),
|
||||
POLICY_NAME.format('delete'),
|
||||
POLICY_NAME.format('update'),
|
||||
POLICY_NAME.format('instantiate'),
|
||||
POLICY_NAME.format('terminate'),
|
||||
POLICY_NAME.format('scale'),
|
||||
POLICY_NAME.format('heal'),
|
||||
POLICY_NAME.format('change_ext_conn'),
|
||||
POLICY_NAME.format('change_vnfpkg'),
|
||||
)
|
||||
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=POLICY_NAME.format('api_versions'),
|
||||
|
@ -24,6 +24,8 @@ from tacker.common import exceptions as common_ex
|
||||
from tacker import context
|
||||
|
||||
from tacker.sol_refactored.api import api_version
|
||||
from tacker.sol_refactored.api.policies.vnflcm_v2 import (
|
||||
ENHANCED_POLICY_ACTIONS)
|
||||
from tacker.sol_refactored.common import config
|
||||
from tacker.sol_refactored.common import exceptions as sol_ex
|
||||
|
||||
@ -159,6 +161,8 @@ class SolResource(object):
|
||||
return
|
||||
if action == 'reject':
|
||||
return
|
||||
if not (self.policy_name.format(action) in ENHANCED_POLICY_ACTIONS
|
||||
and config.CONF.oslo_policy.enhanced_tacker_policy):
|
||||
request.context.can(self.policy_name.format(action))
|
||||
|
||||
def _dispatch(self, request, action, action_args):
|
||||
|
@ -48,6 +48,7 @@ def vim_to_conn_info(vim):
|
||||
region = vim['placement_attr']['regions'][0]
|
||||
|
||||
vim_auth = vim['vim_auth']
|
||||
extra = vim.get('extra', {})
|
||||
|
||||
if vim['vim_type'] == "openstack":
|
||||
# see. https://nfvwiki.etsi.org/index.php
|
||||
@ -73,7 +74,8 @@ def vim_to_conn_info(vim):
|
||||
vimId=vim['vim_id'],
|
||||
vimType='ETSINFV.OPENSTACK_KEYSTONE.V_3',
|
||||
interfaceInfo=interface_info,
|
||||
accessInfo=access_info
|
||||
accessInfo=access_info,
|
||||
extra=extra
|
||||
)
|
||||
if vim['vim_type'] == "kubernetes":
|
||||
# When vimType is kubernetes, it will be converted to the vimType name
|
||||
@ -116,7 +118,8 @@ def vim_to_conn_info(vim):
|
||||
vimId=vim['vim_id'],
|
||||
vimType=vim_type,
|
||||
interfaceInfo=interface_info,
|
||||
accessInfo=access_info
|
||||
accessInfo=access_info,
|
||||
extra=extra
|
||||
)
|
||||
|
||||
raise sol_ex.SolException(sol_detail='not support vim type')
|
||||
|
@ -33,7 +33,8 @@ from tacker.sol_refactored.objects.v2 import fields as v2fields
|
||||
# and the creation of lcmocc and the call to start_lcm_op are
|
||||
# all executed by the controller, notification driver, etc.
|
||||
@coordinate.lock_vnf_instance('{vnf_instance_id}')
|
||||
def heal(context, vnf_instance_id, body):
|
||||
def heal(context, vnf_instance_id, body, inst=None):
|
||||
if not inst:
|
||||
inst = inst_utils.get_inst(context, vnf_instance_id)
|
||||
|
||||
if inst.instantiationState != 'INSTANTIATED':
|
||||
@ -73,7 +74,8 @@ def heal(context, vnf_instance_id, body):
|
||||
# and the creation of lcmocc and the call to start_lcm_op are
|
||||
# all executed by the controller, notification driver, etc.
|
||||
@coordinate.lock_vnf_instance('{vnf_instance_id}')
|
||||
def scale(context, vnf_instance_id, body):
|
||||
def scale(context, vnf_instance_id, body, inst=None):
|
||||
if not inst:
|
||||
inst = inst_utils.get_inst(context, vnf_instance_id)
|
||||
|
||||
if inst.instantiationState != 'INSTANTIATED':
|
||||
|
@ -18,6 +18,7 @@ from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.sol_refactored.api import api_version
|
||||
from tacker.sol_refactored.api.policies.vnflcm_v2 import POLICY_NAME
|
||||
from tacker.sol_refactored.api.schemas import vnflcm_v2 as schema
|
||||
from tacker.sol_refactored.api import validator
|
||||
from tacker.sol_refactored.api import wsgi as sol_wsgi
|
||||
@ -62,6 +63,10 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
|
||||
pkg_info = self.nfvo_client.get_vnf_package_info_vnfd(
|
||||
context, vnfd_id)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('create'),
|
||||
target={'vendor': pkg_info.vnfProvider})
|
||||
|
||||
if pkg_info.operationalState != "ENABLED":
|
||||
raise sol_ex.VnfdIdNotEnabled(vnfd_id=vnfd_id)
|
||||
|
||||
@ -122,6 +127,11 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
|
||||
insts = inst_utils.get_inst_all(request.context,
|
||||
marker=pager.marker)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
insts = [inst for inst in insts if request.context.can(
|
||||
POLICY_NAME.format('index'),
|
||||
target=self._get_policy_target(inst),
|
||||
fatal=False)]
|
||||
|
||||
resp_body = self._inst_view.detail_list(insts, filters,
|
||||
selector, pager)
|
||||
@ -130,7 +140,9 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
|
||||
def show(self, request, id):
|
||||
inst = inst_utils.get_inst(request.context, id)
|
||||
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
request.context.can(POLICY_NAME.format('show'),
|
||||
target=self._get_policy_target(inst))
|
||||
resp_body = self._inst_view.detail(inst)
|
||||
|
||||
return sol_wsgi.SolResponse(200, resp_body)
|
||||
@ -139,7 +151,9 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
def delete(self, request, id):
|
||||
context = request.context
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('delete'),
|
||||
target=self._get_policy_target(inst))
|
||||
if inst.instantiationState != 'NOT_INSTANTIATED':
|
||||
raise sol_ex.VnfInstanceIsInstantiated(inst_id=id)
|
||||
|
||||
@ -158,7 +172,9 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
def update(self, request, id, body):
|
||||
context = request.context
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('update'),
|
||||
target=self._get_policy_target(inst))
|
||||
lcmocc_utils.check_lcmocc_in_progress(context, id)
|
||||
if (inst.instantiationState == 'NOT_INSTANTIATED'
|
||||
and 'vimConnectionInfo' in body):
|
||||
@ -200,11 +216,54 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
|
||||
return sol_wsgi.SolResponse(202, None, location=location)
|
||||
|
||||
def _get_policy_target(self, vnf_instance):
|
||||
vendor = vnf_instance.vnfProvider
|
||||
|
||||
if vnf_instance.instantiationState == 'NOT_INSTANTIATED':
|
||||
area = '*'
|
||||
tenant = '*'
|
||||
else:
|
||||
vim_type = None
|
||||
area = None
|
||||
if vnf_instance.obj_attr_is_set('vimConnectionInfo'):
|
||||
for _, vim_conn_info in vnf_instance.vimConnectionInfo.items():
|
||||
area = vim_conn_info.get('extra', {}).get('area')
|
||||
vim_type = vim_conn_info.vimType
|
||||
if area and vim_type:
|
||||
break
|
||||
|
||||
tenant = None
|
||||
if (vnf_instance.obj_attr_is_set('instantiatedVnfInfo') and
|
||||
vnf_instance.instantiatedVnfInfo.obj_attr_is_set(
|
||||
'metadata')):
|
||||
|
||||
tenant = (vnf_instance.instantiatedVnfInfo
|
||||
.metadata.get('namespace'))
|
||||
|
||||
# TODO(kexuesheng): Add steps to get tenant of VNFs deployed
|
||||
# in OpenStack VIM. This is a temporary workaround until that
|
||||
# information is available.
|
||||
if vim_type == "ETSINFV.OPENSTACK_KEYSTONE.V_3":
|
||||
tenant = '*'
|
||||
|
||||
target = {
|
||||
'vendor': vendor,
|
||||
'area': area,
|
||||
'tenant': tenant
|
||||
}
|
||||
|
||||
target = {k: v for k, v in target.items() if v is not None}
|
||||
|
||||
return target
|
||||
|
||||
@validator.schema(schema.InstantiateVnfRequest_V200, '2.0.0')
|
||||
@coordinate.lock_vnf_instance('{id}')
|
||||
def instantiate(self, request, id, body):
|
||||
context = request.context
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('instantiate'),
|
||||
target=self._get_policy_target(inst))
|
||||
|
||||
if inst.instantiationState != 'NOT_INSTANTIATED':
|
||||
raise sol_ex.VnfInstanceIsInstantiated(inst_id=id)
|
||||
@ -239,6 +298,9 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
def terminate(self, request, id, body):
|
||||
context = request.context
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('terminate'),
|
||||
target=self._get_policy_target(inst))
|
||||
|
||||
if inst.instantiationState != 'INSTANTIATED':
|
||||
raise sol_ex.VnfInstanceIsNotInstantiated(inst_id=id)
|
||||
@ -258,7 +320,12 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
@validator.schema(schema.ScaleVnfRequest_V200, '2.0.0')
|
||||
def scale(self, request, id, body):
|
||||
context = request.context
|
||||
lcmocc = vnflcm_utils.scale(context, id, body)
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('scale'),
|
||||
target=self._get_policy_target(inst))
|
||||
|
||||
lcmocc = vnflcm_utils.scale(context, id, body, inst=inst)
|
||||
|
||||
location = lcmocc_utils.lcmocc_href(lcmocc.id, self.endpoint)
|
||||
|
||||
@ -267,7 +334,12 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
@validator.schema(schema.HealVnfRequest_V200, '2.0.0')
|
||||
def heal(self, request, id, body):
|
||||
context = request.context
|
||||
lcmocc = vnflcm_utils.heal(context, id, body)
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('heal'),
|
||||
target=self._get_policy_target(inst))
|
||||
|
||||
lcmocc = vnflcm_utils.heal(context, id, body, inst=inst)
|
||||
|
||||
location = lcmocc_utils.lcmocc_href(lcmocc.id, self.endpoint)
|
||||
|
||||
@ -278,6 +350,9 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
def change_ext_conn(self, request, id, body):
|
||||
context = request.context
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('change_ext_conn'),
|
||||
target=self._get_policy_target(inst))
|
||||
|
||||
if inst.instantiationState != 'INSTANTIATED':
|
||||
raise sol_ex.VnfInstanceIsNotInstantiated(inst_id=id)
|
||||
@ -336,6 +411,9 @@ class VnfLcmControllerV2(sol_wsgi.SolAPIController):
|
||||
def change_vnfpkg(self, request, id, body):
|
||||
context = request.context
|
||||
inst = inst_utils.get_inst(context, id)
|
||||
if config.CONF.oslo_policy.enhanced_tacker_policy:
|
||||
context.can(POLICY_NAME.format('change_vnfpkg'),
|
||||
target=self._get_policy_target(inst))
|
||||
vnfd_id = body['vnfdId']
|
||||
|
||||
if inst.instantiationState != 'INSTANTIATED':
|
||||
|
@ -0,0 +1,38 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: 'Simple Base HOT for Sample VNF'
|
||||
|
||||
parameters:
|
||||
nfv:
|
||||
type: json
|
||||
|
||||
resources:
|
||||
VDU1_scale:
|
||||
type: OS::Heat::AutoScalingGroup
|
||||
properties:
|
||||
min_size: 1
|
||||
max_size: 2
|
||||
desired_capacity: 1
|
||||
resource:
|
||||
type: vdu1.yaml
|
||||
properties:
|
||||
flavor: { get_param: [ nfv, VDU, VDU1, flavor ] }
|
||||
image: { get_param: [ nfv, VDU, VDU1, image ] }
|
||||
net1: { get_param: [ nfv, CP, CP1, network ] }
|
||||
|
||||
VDU1_scale_scale_out:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
scaling_adjustment: 1
|
||||
auto_scaling_group_id:
|
||||
get_resource: VDU1_scale
|
||||
adjustment_type: change_in_capacity
|
||||
|
||||
VDU1_scale_scale_in:
|
||||
type: OS::Heat::ScalingPolicy
|
||||
properties:
|
||||
scaling_adjustment: -1
|
||||
auto_scaling_group_id:
|
||||
get_resource: VDU1_scale
|
||||
adjustment_type: change_in_capacity
|
||||
|
||||
outputs: {}
|
@ -0,0 +1,28 @@
|
||||
heat_template_version: 2013-05-23
|
||||
description: "Template for test _generate_hot_from_tosca()."
|
||||
|
||||
parameters:
|
||||
flavor:
|
||||
type: string
|
||||
image:
|
||||
type: string
|
||||
net1:
|
||||
type: string
|
||||
|
||||
resources:
|
||||
VDU1:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
flavor: { get_param: flavor }
|
||||
name: VDU1
|
||||
image: { get_param: image }
|
||||
networks:
|
||||
- port:
|
||||
get_resource: CP1
|
||||
|
||||
CP1:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network: { get_param: net1 }
|
||||
|
||||
outputs: {}
|
@ -0,0 +1,195 @@
|
||||
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
|
||||
- sample_vnfd_types.yaml
|
||||
|
||||
topology_template:
|
||||
inputs:
|
||||
id:
|
||||
type: string
|
||||
vendor:
|
||||
type: string
|
||||
version:
|
||||
type: version
|
||||
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
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
# supporting only 'instantiate', 'terminate', 'modify',
|
||||
# and 'heal'
|
||||
# not supporting LCM script, supporting only default LCM
|
||||
instantiate: []
|
||||
# instantiate_start: []
|
||||
# instantiate_end: []
|
||||
terminate: []
|
||||
# terminate_start: []
|
||||
# terminate_end: []
|
||||
modify_information: []
|
||||
# modify_information_start: []
|
||||
# modify_information_end: []
|
||||
# change_flavour: []
|
||||
# change_flavour_start: []
|
||||
# change_flavour_end: []
|
||||
# change_external_connectivity: []
|
||||
# change_external_connectivity_start: []
|
||||
# change_external_connectivity_end: []
|
||||
# operate: []
|
||||
# operate_start: []
|
||||
# operate_end: []
|
||||
heal: []
|
||||
# heal_start: []
|
||||
# heal_end: []
|
||||
scale: []
|
||||
# scale_start: []
|
||||
# scale_end: []
|
||||
# scale_to_level: []
|
||||
# scale_to_level_start: []
|
||||
# scale_to_level_end: []
|
||||
|
||||
VDU1:
|
||||
type: tosca.nodes.nfv.Vdu.Compute
|
||||
properties:
|
||||
name: VDU1
|
||||
description: VDU1 compute node
|
||||
vdu_profile:
|
||||
min_number_of_instances: 1
|
||||
max_number_of_instances: 1
|
||||
sw_image_data:
|
||||
name: cirros-0.5.2-x86_64-disk
|
||||
version: "0.5.2"
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 1 GB
|
||||
size: 1 GB
|
||||
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
requested_additional_capabilities:
|
||||
properties:
|
||||
requested_additional_capability_name: m1.tiny
|
||||
support_mandatory: true
|
||||
target_performance_parameters:
|
||||
entry_schema: test
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 3 GB
|
||||
|
||||
CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ipv4]
|
||||
requirements:
|
||||
- virtual_binding: VDU1
|
||||
- virtual_link: internalVL1
|
||||
|
||||
internalVL1:
|
||||
type: tosca.nodes.nfv.VnfVirtualLink
|
||||
properties:
|
||||
connectivity_type:
|
||||
layer_protocols: [ipv4]
|
||||
description: Internal Virtual link in the VNF
|
||||
vl_profile:
|
||||
max_bitrate_requirements:
|
||||
root: 1048576
|
||||
leaf: 1048576
|
||||
min_bitrate_requirements:
|
||||
root: 1048576
|
||||
leaf: 1048576
|
||||
virtual_link_protocol_data:
|
||||
- associated_layer_protocol: ipv4
|
||||
l3_protocol_data:
|
||||
ip_version: ipv4
|
||||
cidr: 10.0.0.0/24
|
||||
policies:
|
||||
- scaling_aspects:
|
||||
type: tosca.policies.nfv.ScalingAspects
|
||||
properties:
|
||||
aspects:
|
||||
VDU1_scale:
|
||||
name: VDU1_scale
|
||||
description: VDU1 scaling aspect
|
||||
max_scale_level: 2
|
||||
step_deltas:
|
||||
- delta_1
|
||||
|
||||
- VDU1_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [VDU1]
|
||||
|
||||
- VDU1_scaling_aspect_deltas:
|
||||
type: tosca.policies.nfv.VduScalingAspectDeltas
|
||||
properties:
|
||||
aspect: VDU1_scale
|
||||
deltas:
|
||||
delta_1:
|
||||
number_of_instances: 1
|
||||
targets: [VDU1]
|
||||
|
||||
- instantiation_levels:
|
||||
type: tosca.policies.nfv.InstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
description: Smallest size
|
||||
scale_info:
|
||||
VDU1_scale:
|
||||
scale_level: 0
|
||||
instantiation_level_2:
|
||||
description: Largest size
|
||||
scale_info:
|
||||
VDU1_scale:
|
||||
scale_level: 2
|
||||
default_level: instantiation_level_1
|
||||
|
||||
- VDU1_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
number_of_instances: 1
|
||||
instantiation_level_2:
|
||||
number_of_instances: 3
|
||||
targets: [VDU1]
|
@ -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
|
||||
- sample_vnfd_types.yaml
|
||||
- sample_vnfd_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: c1bb0ce7-ebca-4fa7-95ed-4840d70a1175
|
||||
provider: Company
|
||||
product_name: Sample VNF
|
||||
software_version: "1.0"
|
||||
descriptor_version: "1.0"
|
||||
vnfm_info:
|
||||
- Tacker
|
||||
requirements:
|
||||
#- virtual_link_external # mapped in lower-level templates
|
||||
#- virtual_link_internal # mapped in lower-level templates
|
@ -0,0 +1,63 @@
|
||||
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:
|
||||
id:
|
||||
type: string
|
||||
description: ID of this VNF
|
||||
default: vnf_id
|
||||
vendor:
|
||||
type: string
|
||||
description: name of the vendor who generate this VNF
|
||||
default: vendor
|
||||
version:
|
||||
type: version
|
||||
description: version of the software for this VNF
|
||||
default: 1.0
|
||||
descriptor_id:
|
||||
type: string
|
||||
constraints: [valid_values: [c1bb0ce7-ebca-4fa7-95ed-4840d70a1175]]
|
||||
default: c1bb0ce7-ebca-4fa7-95ed-4840d70a1175
|
||||
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: This is the default flavour description
|
||||
requirements:
|
||||
- virtual_link_internal:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
type: tosca.interfaces.nfv.Vnflcm
|
@ -0,0 +1,4 @@
|
||||
TOSCA-Meta-File-Version: 1.0
|
||||
Created-by: Dummy User
|
||||
CSAR-Version: 1.1
|
||||
Entry-Definitions: Definitions/sample_vnfd_top.yaml
|
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from tacker.vnfm.lcm_user_data.abstract_user_data import AbstractUserData
|
||||
import tacker.vnfm.lcm_user_data.utils as UserDataUtil
|
||||
|
||||
|
||||
class SampleUserData(AbstractUserData):
|
||||
@staticmethod
|
||||
def instantiate(base_hot_dict=None,
|
||||
vnfd_dict=None,
|
||||
inst_req_info=None,
|
||||
grant_info=None):
|
||||
api_param = UserDataUtil.get_diff_base_hot_param_from_api(
|
||||
base_hot_dict, inst_req_info)
|
||||
initial_param_dict = \
|
||||
UserDataUtil.create_initial_param_server_port_dict(
|
||||
base_hot_dict)
|
||||
vdu_flavor_dict = \
|
||||
UserDataUtil.create_vdu_flavor_capability_name_dict(vnfd_dict)
|
||||
vdu_image_dict = UserDataUtil.create_sw_image_dict(vnfd_dict)
|
||||
cpd_vl_dict = UserDataUtil.create_network_dict(
|
||||
inst_req_info, initial_param_dict)
|
||||
final_param_dict = UserDataUtil.create_final_param_dict(
|
||||
initial_param_dict, vdu_flavor_dict, vdu_image_dict, cpd_vl_dict)
|
||||
return {**final_param_dict, **api_param}
|
@ -78,7 +78,8 @@ class SessionClient(adapter.Adapter):
|
||||
def do_request(self, url, method, **kwargs):
|
||||
kwargs.setdefault('authenticated', True)
|
||||
resp = self.request(url, method, **kwargs)
|
||||
if resp.headers['Content-Type'] == 'application/zip':
|
||||
if ('Content-Type' not in resp.headers or
|
||||
resp.headers['Content-Type'] == 'application/zip'):
|
||||
return resp, resp.content
|
||||
body = self._decode_json(resp)
|
||||
return resp, body
|
||||
|
1107
tacker/tests/functional/sol_enhanced_policy/base.py
Normal file
1107
tacker/tests/functional/sol_enhanced_policy/base.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tacker.tests.functional.sol_enhanced_policy.base import (
|
||||
VimAPIsTest)
|
||||
|
||||
|
||||
class VimAPIsOpenstackTest(VimAPIsTest):
|
||||
|
||||
def test_vim_apis_vim_with_area_openstack(self):
|
||||
self._test_vim_apis_enhanced_policy('openstack', 'local-vim.yaml')
|
||||
|
||||
def test_vim_apis_vim_without_area_openstack(self):
|
||||
self._test_vim_apis_vim_without_area_attribute(
|
||||
'openstack', 'local-vim.yaml')
|
@ -0,0 +1,244 @@
|
||||
#
|
||||
# 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.path
|
||||
import time
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tacker.tests.functional.base import BaseTackerTest
|
||||
from tacker.tests.functional.sol_enhanced_policy.base import (
|
||||
BaseEnhancedPolicyTest)
|
||||
|
||||
|
||||
class BaseVnfPackageAPIsTest(BaseTackerTest, BaseEnhancedPolicyTest):
|
||||
|
||||
VNF_PACKAGE_UPLOAD_TIMEOUT = 300
|
||||
base_url = '/vnfpkgm/v1/vnf_packages'
|
||||
user_role_map = {
|
||||
'user_a': ['VENDOR_company_A', 'manager'],
|
||||
'user_b': ['VENDOR_company_B', 'manager'],
|
||||
'user_all': ['VENDOR_all', 'manager'],
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
BaseTackerTest.setUpClass()
|
||||
BaseEnhancedPolicyTest.setUpClass(cls)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
BaseEnhancedPolicyTest.tearDownClass()
|
||||
BaseTackerTest.tearDownClass()
|
||||
|
||||
def _step_pkg_create(self, username):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
|
||||
resp, pkg = client.do_request(
|
||||
self.base_url, 'POST',
|
||||
body=jsonutils.dumps({"userDefinedData": {"foo": "bar"}}))
|
||||
|
||||
self.assertEqual(201, resp.status_code)
|
||||
return pkg
|
||||
|
||||
def _step_pkg_show(self, username, pkg, expected_status_code,
|
||||
expected_vendor=None):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
resp, pkg = client.do_request(
|
||||
os.path.join(self.base_url, pkg.get('id')),
|
||||
'GET')
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 200 and expected_vendor:
|
||||
self.assertEqual(expected_vendor, pkg.get('vnfProvider'))
|
||||
|
||||
def _step_pkg_list(self, username, expected_pkg_list):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
resp, pkgs = client.do_request(self.base_url, 'GET')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
pkg_ids = set([pkg.get('id') for pkg in pkgs])
|
||||
for pkg in expected_pkg_list:
|
||||
self.assertIn(pkg.get('id'), pkg_ids)
|
||||
|
||||
def _get_csar_dir_path(self, csar_name):
|
||||
csar_dir = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__),
|
||||
"../../../etc/samples/etsi/nfv", csar_name))
|
||||
|
||||
return csar_dir
|
||||
|
||||
def _wait_for_onboard(self, client, package_uuid):
|
||||
show_url = os.path.join(self.base_url, package_uuid)
|
||||
timeout = self.VNF_PACKAGE_UPLOAD_TIMEOUT
|
||||
start_time = int(time.time())
|
||||
while True:
|
||||
resp, body = client.do_request(show_url, "GET")
|
||||
if body['onboardingState'] == "ONBOARDED":
|
||||
break
|
||||
|
||||
if (int(time.time()) - start_time) > timeout:
|
||||
raise Exception("Failed to onboard vnf package")
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
def _step_pkg_upload_content(self, username, pkg, csar_name, provider,
|
||||
expected_status_code):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
csar_dir = self._get_csar_dir_path(csar_name)
|
||||
|
||||
file_path, vnfd_id = self.custom_csar(csar_dir, provider)
|
||||
self.addCleanup(os.remove, file_path)
|
||||
with open(file_path, 'rb') as file_object:
|
||||
resp, resp_body = client.do_request(
|
||||
'{base_path}/{id}/package_content'.format(
|
||||
id=pkg['id'],
|
||||
base_path=self.base_url),
|
||||
"PUT", body=file_object, content_type='application/zip')
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
self._wait_for_onboard(client, pkg['id'])
|
||||
|
||||
def _step_pkg_read_vnfd(self, username, pkg, expected_status_code):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
resp, resp_body = client.do_request(
|
||||
'{base_path}/{id}/vnfd'.format(id=pkg['id'],
|
||||
base_path=self.base_url),
|
||||
"GET", content_type='application/zip')
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 200:
|
||||
self.assertEqual('application/zip', resp.headers['Content-Type'])
|
||||
self.assertIsNotNone(resp.text)
|
||||
|
||||
def _step_pkg_fetch(self, username, pkg, expected_status_code):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
response = client.do_request(
|
||||
'{base_path}/{id}/package_content'.format(
|
||||
id=pkg['id'], base_path=self.base_url),
|
||||
"GET", body={}, headers={})
|
||||
self.assertEqual(expected_status_code, response[0].status_code)
|
||||
|
||||
def _step_pkg_update(self, username, pkg, expected_status_code):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
update_req_body = jsonutils.dumps({
|
||||
"operationalState": "DISABLED"})
|
||||
|
||||
resp, _ = client.do_request(
|
||||
'{base_path}/{id}'.format(id=pkg['id'],
|
||||
base_path=self.base_url),
|
||||
"PATCH", content_type='application/json', body=update_req_body)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
def _step_pkg_delete(self, username, pkg, expected_status_code):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
resp, _ = client.do_request(os.path.join(self.base_url, pkg.get('id')),
|
||||
'DELETE')
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
def _test_vnf_package_apis_enhanced_policy(self, csar_name):
|
||||
# step 1 PKG-Create, Resource Group A / User Group A
|
||||
pkg_a = self._step_pkg_create('user_a')
|
||||
|
||||
# step 2 PKG-Create, Resource Group B / User Group all
|
||||
pkg_b = self._step_pkg_create('user_all')
|
||||
|
||||
# step 3 PKG-Show, Resource Group A / User Group A
|
||||
self._step_pkg_show('user_a', pkg_a, 200)
|
||||
|
||||
# step 4 PKG-Show, Resource Group B / User Group A
|
||||
self._step_pkg_show('user_a', pkg_b, 200)
|
||||
|
||||
# step 5 PKG-Show, Resource Group A / User Group A
|
||||
self._step_pkg_show('user_all', pkg_b, 200)
|
||||
|
||||
# step 6 PKG-List, Resource Group - / User Group A
|
||||
self._step_pkg_list('user_a', [pkg_a, pkg_b])
|
||||
|
||||
# step 7 PKG-List, Resource Group - / User Group B
|
||||
self._step_pkg_list('user_b', [pkg_a, pkg_b])
|
||||
|
||||
# step 8 PKG-List, Resource Group - / User Group all
|
||||
self._step_pkg_list('user_all', [pkg_a, pkg_b])
|
||||
|
||||
# step 9 PKG-Upload-content, Resource Group B / User Group A
|
||||
self._step_pkg_upload_content(
|
||||
'user_a', pkg_a, csar_name, 'company_B', 403)
|
||||
|
||||
# step 10 PKG-Upload-content, Resource Group A / User Group A
|
||||
self._step_pkg_upload_content(
|
||||
'user_a', pkg_a, csar_name, 'company_A', 202)
|
||||
|
||||
# step 11 PKG-Upload-content, Resource Group B / User Group all
|
||||
self._step_pkg_upload_content(
|
||||
'user_all', pkg_b, csar_name, 'company_B', 202)
|
||||
|
||||
# step 12 PKG-Show, Resource Group A / User Group A
|
||||
self._step_pkg_show('user_a', pkg_a, 200)
|
||||
|
||||
# step 13 PKG-Show, Resource Group B / User Group A
|
||||
self._step_pkg_show('user_a', pkg_b, 403)
|
||||
|
||||
# step 14 PKG-Show, Resource Group A / User Group A
|
||||
self._step_pkg_show('user_all', pkg_b, 200)
|
||||
|
||||
# step 15 PKG-List, Resource Group - / User Group A
|
||||
self._step_pkg_list('user_a', [pkg_a])
|
||||
|
||||
# step 16 PKG-List, Resource Group - / User Group B
|
||||
self._step_pkg_list('user_b', [pkg_b])
|
||||
|
||||
# step 17 PKG-List, Resource Group - / User Group all
|
||||
self._step_pkg_list('user_all', [pkg_a, pkg_b])
|
||||
|
||||
# step 18 PKG-Read-vnfd, Resource Group A / User Group A
|
||||
self._step_pkg_read_vnfd('user_a', pkg_a, 200)
|
||||
|
||||
# step 19 PKG-Read-vnfd, Resource Group B / User Group A
|
||||
self._step_pkg_read_vnfd('user_a', pkg_b, 403)
|
||||
|
||||
# step 20 PKG-Read-vnfd, Resource Group B / User Group all
|
||||
self._step_pkg_read_vnfd('user_all', pkg_b, 200)
|
||||
|
||||
# step 21 PKG-Read-vnfd, Resource Group A / User Group A
|
||||
self._step_pkg_fetch('user_a', pkg_a, 200)
|
||||
|
||||
# step 22 PKG-Read-vnfd, Resource Group B / User Group A
|
||||
self._step_pkg_fetch('user_a', pkg_b, 403)
|
||||
|
||||
# step 23 PKG-Read-vnfd, Resource Group B / User Group all
|
||||
self._step_pkg_fetch('user_all', pkg_b, 200)
|
||||
|
||||
# step 24 PKG-Update, Resource Group B / User Group A
|
||||
self._step_pkg_update('user_a', pkg_b, 403)
|
||||
|
||||
# step 25 PKG-Update, Resource Group A / User Group A
|
||||
self._step_pkg_update('user_a', pkg_a, 200)
|
||||
|
||||
# step 26 PKG-Update, Resource Group B / User Group all
|
||||
self._step_pkg_update('user_all', pkg_b, 200)
|
||||
|
||||
# step 27 PKG-Delete, Resource Group A / User Group A
|
||||
self._step_pkg_delete('user_a', pkg_a, 204)
|
||||
|
||||
# step 29 PKG-Delete, Resource Group B / User Group all
|
||||
self._step_pkg_delete('user_all', pkg_b, 204)
|
||||
|
||||
|
||||
class VnfPackageAPIsTest(BaseVnfPackageAPIsTest):
|
||||
|
||||
def test_vnf_package_apis_enhanced_policy_vnf(self):
|
||||
self._test_vnf_package_apis_enhanced_policy('test_enhanced_policy')
|
||||
|
||||
|
||||
class CnfPackageAPIsTest(BaseVnfPackageAPIsTest):
|
||||
|
||||
def test_vnf_package_apis_enhanced_policy_cnf(self):
|
||||
self._test_vnf_package_apis_enhanced_policy('test_cnf_scale')
|
@ -0,0 +1,253 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import os
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.tests.functional.sol.vnflcm import fake_vnflcm
|
||||
from tacker.tests.functional.sol.vnflcm.test_vnf_instance import (
|
||||
get_external_virtual_links)
|
||||
from tacker.tests.functional.sol_enhanced_policy.base import (
|
||||
VnflcmAPIsV1Base)
|
||||
|
||||
|
||||
class VnflcmAPIsV1Test(VnflcmAPIsV1Base):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
vim_type = 'openstack'
|
||||
|
||||
local_vim = 'local-vim.yaml'
|
||||
|
||||
cls.vim_a = cls._step_vim_register(
|
||||
'user_a', vim_type, local_vim, 'vim_a', 'area_A@region_A')
|
||||
|
||||
cls.vim_a_1 = cls._step_vim_register(
|
||||
'user_a', vim_type, local_vim, 'vim_a_1', 'area_A@region_A')
|
||||
|
||||
cls.vim_b = cls._step_vim_register(
|
||||
'user_b', vim_type, local_vim, 'vim_b', 'area_B@region_B')
|
||||
|
||||
cls.vim_b_1 = cls._step_vim_register(
|
||||
'user_b', vim_type, local_vim, 'vim_b_1', 'area_B@region_B')
|
||||
|
||||
cls.vim_c = cls._step_vim_register(
|
||||
'user_b', vim_type, local_vim, 'vim_c', None)
|
||||
|
||||
cls.vim_c_1 = cls._step_vim_register(
|
||||
'user_b', vim_type, local_vim, 'vim_c_1', None)
|
||||
|
||||
cls.pkg_a = cls._step_pkg_create('user_a')
|
||||
|
||||
cls.vnfd_id_a = cls._step_pkg_upload_content(
|
||||
'user_a', cls.pkg_a, 'test_enhanced_policy', 'company_A')
|
||||
|
||||
cls.pkg_b = cls._step_pkg_create('user_b')
|
||||
|
||||
cls.vnfd_id_b = cls._step_pkg_upload_content(
|
||||
'user_b', cls.pkg_b, 'test_enhanced_policy', 'company_B')
|
||||
|
||||
cls.pkg_c = cls._step_pkg_create('user_c')
|
||||
|
||||
cls.vnfd_id_c = cls._step_pkg_upload_content(
|
||||
'user_c', cls.pkg_c, 'test_enhanced_policy', 'company_C')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
||||
cls._step_pkg_disable('user_a', cls.pkg_a,)
|
||||
cls._step_pkg_disable('user_b', cls.pkg_b,)
|
||||
cls._step_pkg_disable('user_c', cls.pkg_c,)
|
||||
cls._step_pkg_delete('user_a', cls.pkg_a)
|
||||
cls._step_pkg_delete('user_b', cls.pkg_b)
|
||||
cls._step_pkg_delete('user_c', cls.pkg_c)
|
||||
|
||||
cls._step_vim_delete('user_a', cls.vim_a)
|
||||
cls._step_vim_delete('user_a', cls.vim_a_1)
|
||||
cls._step_vim_delete('user_b', cls.vim_b)
|
||||
cls._step_vim_delete('user_b', cls.vim_b_1)
|
||||
cls._step_vim_delete('user_admin', cls.vim_c)
|
||||
cls._step_vim_delete('user_admin', cls.vim_c_1)
|
||||
|
||||
super().tearDownClass()
|
||||
|
||||
def _instantiate_vnf_request(self, flavour_id,
|
||||
instantiation_level_id=None, vim_id=None, ext_vl=None,
|
||||
ext_managed_vl=None):
|
||||
request_body = {
|
||||
"flavourId": flavour_id,
|
||||
"additionalParams": {
|
||||
"lcm-operation-user-data": "./UserData/lcm_user_data.py",
|
||||
"lcm-operation-user-data-class": "SampleUserData"
|
||||
}
|
||||
}
|
||||
|
||||
if instantiation_level_id:
|
||||
request_body["instantiationLevelId"] = instantiation_level_id
|
||||
|
||||
if ext_managed_vl:
|
||||
request_body["extManagedVirtualLinks"] = ext_managed_vl
|
||||
|
||||
if ext_vl:
|
||||
request_body["extVirtualLinks"] = ext_vl
|
||||
|
||||
if vim_id:
|
||||
request_body["vimConnectionInfo"] = [
|
||||
{"id": uuidutils.generate_uuid(),
|
||||
"vimId": vim_id,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.v_2"}]
|
||||
|
||||
return request_body
|
||||
|
||||
def _step_lcm_instantiate(
|
||||
self, username, inst_id, vim_id, expected_status_code):
|
||||
neutron_client = self.neutronclient()
|
||||
net = neutron_client.list_networks()
|
||||
networks = {}
|
||||
for network in net['networks']:
|
||||
networks[network['name']] = network['id']
|
||||
net0_id = networks.get('net0')
|
||||
if not net0_id:
|
||||
self.fail("net0 network is not available")
|
||||
net_mgmt_id = networks.get('net_mgmt')
|
||||
if not net_mgmt_id:
|
||||
self.fail("net_mgmt network is not available")
|
||||
network_uuid = self.create_network(neutron_client,
|
||||
"external_network")
|
||||
port_uuid = self.create_port(neutron_client, network_uuid)
|
||||
ext_vl = get_external_virtual_links(net0_id, net_mgmt_id,
|
||||
port_uuid)
|
||||
request_body = self._instantiate_vnf_request(
|
||||
"simple", vim_id=vim_id, ext_vl=ext_vl)
|
||||
|
||||
self._lcm_instantiate(
|
||||
username, inst_id, request_body, expected_status_code)
|
||||
|
||||
def _step_lcm_scale_out(self, username, inst_id, expected_status_code):
|
||||
request_body = fake_vnflcm.VnfInstances.make_scale_request_body(
|
||||
'SCALE_OUT')
|
||||
self._step_lcm_scale(
|
||||
username, inst_id, request_body, expected_status_code)
|
||||
|
||||
def _step_lcm_scale_in(self, username, inst_id, expected_status_code):
|
||||
request_body = fake_vnflcm.VnfInstances.make_scale_request_body(
|
||||
'SCALE_IN')
|
||||
self._step_lcm_scale(
|
||||
username, inst_id, request_body, expected_status_code)
|
||||
|
||||
def _change_ext_conn_vnf_request(self, vim_id=None, ext_vl=None,
|
||||
vim_type="ETSINFV.OPENSTACK_KEYSTONE.v_2"):
|
||||
request_body = {}
|
||||
if ext_vl:
|
||||
request_body["extVirtualLinks"] = ext_vl
|
||||
|
||||
if vim_id:
|
||||
request_body["vimConnectionInfo"] = [
|
||||
{"id": uuidutils.generate_uuid(),
|
||||
"vimId": vim_id,
|
||||
"vimType": vim_type}]
|
||||
|
||||
return request_body
|
||||
|
||||
def _step_lcm_change_connectivity(self, username, inst_id, new_vim_id,
|
||||
expected_status_code):
|
||||
client = self.get_tk_http_client_by_user(username)
|
||||
|
||||
neutron_client = self.neutronclient()
|
||||
net = neutron_client.list_networks()
|
||||
networks = {}
|
||||
for network in net['networks']:
|
||||
networks[network['name']] = network['id']
|
||||
net0_id = networks.get('net0')
|
||||
if not net0_id:
|
||||
self.fail("net0 network is not available")
|
||||
net_mgmt_id = networks.get('net_mgmt')
|
||||
if not net_mgmt_id:
|
||||
self.fail("net_mgmt network is not available")
|
||||
network_uuid = self.create_network(neutron_client,
|
||||
"external_network")
|
||||
port_uuid = self.create_port(neutron_client, network_uuid)
|
||||
ext_vl = get_external_virtual_links(net0_id, net_mgmt_id,
|
||||
port_uuid)
|
||||
change_ext_conn_req_body = self._change_ext_conn_vnf_request(
|
||||
vim_id=new_vim_id, ext_vl=ext_vl)
|
||||
url = os.path.join(
|
||||
self.base_vnf_instances_url,
|
||||
inst_id,
|
||||
"change_ext_conn")
|
||||
resp, body = client.do_request(url, "POST",
|
||||
body=jsonutils.dumps(change_ext_conn_req_body))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
self._wait_lcm_done(
|
||||
operation='CHANGE_EXT_CONN',
|
||||
expected_operation_status='COMPLETED',
|
||||
vnf_instance_id=inst_id)
|
||||
|
||||
def test_vnflcm_apis_vnf_instance_with_area_vnf(self):
|
||||
self.register_subscription()
|
||||
|
||||
inst_id_a, inst_id_b = self.steps_lcm_create_and_get_with_area()
|
||||
|
||||
# step 12 LCM-Instantiate, Resource Group A / User Group A
|
||||
self._step_lcm_instantiate('user_a', inst_id_a, self.vim_a['id'], 202)
|
||||
|
||||
# step 13 LCM-Instantiate, Resource Group B / User Group A
|
||||
self._step_lcm_instantiate('user_a', inst_id_b, self.vim_b['id'], 403)
|
||||
|
||||
# step 14 LCM-Instantiate, Resource Group B / User Group all
|
||||
self._step_lcm_instantiate(
|
||||
'user_all', inst_id_b, self.vim_b['id'], 202)
|
||||
|
||||
self.steps_lcm_get_scale_heal_modify_with_area(inst_id_a, inst_id_b)
|
||||
|
||||
# step 34 LCM-Change-Connectivity, Resource Group A / User Group A
|
||||
self._step_lcm_change_connectivity(
|
||||
'user_a', inst_id_a, self.vim_a_1['id'], 202)
|
||||
|
||||
# step 35 LCM-Change-Connectivity, Resource Group B / User Group A
|
||||
self._step_lcm_change_connectivity(
|
||||
'user_a', inst_id_b, self.vim_b_1['id'], 403)
|
||||
|
||||
# step 36 LCM-Change-Connectivity, Resource Group B / User Group all
|
||||
self._step_lcm_change_connectivity(
|
||||
'user_all', inst_id_b, self.vim_b_1['id'], 202)
|
||||
|
||||
self.steps_lcm_terminate_delete_with_area(inst_id_a, inst_id_b)
|
||||
|
||||
def test_vnflcm_apis_vnf_instance_without_area_vnf(self):
|
||||
self.register_subscription()
|
||||
|
||||
inst_id_c = self.steps_lcm_create_and_get_without_area()
|
||||
|
||||
# step 8 LCM-Instantiate, Resource Group C / User Group C
|
||||
self._step_lcm_instantiate('user_c', inst_id_c, self.vim_c['id'], 202)
|
||||
|
||||
self.steps_lcm_get_scale_heal_modify_without_area(inst_id_c)
|
||||
|
||||
# step 27 LCM-Change-Connectivity, Resource Group C / User Group C
|
||||
self._step_lcm_change_connectivity(
|
||||
'user_c', inst_id_c, self.vim_c_1['id'], 403)
|
||||
|
||||
# step 28 LCM-Change-Connectivity, Resource Group C / User Group all
|
||||
self._step_lcm_change_connectivity(
|
||||
'user_all', inst_id_c, self.vim_c_1['id'], 403)
|
||||
|
||||
# step 29 LCM-Change-Connectivity, Resource Group C / User Group admin
|
||||
self._step_lcm_change_connectivity(
|
||||
'user_admin', inst_id_c, self.vim_c_1['id'], 202)
|
||||
|
||||
self.steps_lcm_terminate_delete_without_area(inst_id_c)
|
@ -0,0 +1,974 @@
|
||||
#
|
||||
# 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
|
||||
import yaml
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.sol_refactored.common import http_client
|
||||
from tacker.sol_refactored import objects
|
||||
from tacker.tests.functional.sol_enhanced_policy.base import (
|
||||
BaseEnhancedPolicyTest)
|
||||
from tacker.tests.functional.sol_v2_common import base_v2
|
||||
from tacker.tests.functional.sol_v2_common import paramgen
|
||||
from tacker.tests.functional.sol_v2_common.test_vnflcm_basic_common import (
|
||||
CommonVnfLcmTest)
|
||||
from tacker.tests import utils as base_utils
|
||||
|
||||
|
||||
class VnflcmAPIsV2VNFBase(CommonVnfLcmTest, BaseEnhancedPolicyTest):
|
||||
|
||||
user_role_map = {
|
||||
'user_a': ['VENDOR_company_A', 'AREA_area_A@region_A',
|
||||
'TENANT_namespace_A', 'manager'],
|
||||
'user_a_1': ['VENDOR_company_A', 'manager'],
|
||||
'user_b': ['VENDOR_company_B', 'AREA_area_B@region_B',
|
||||
'TENANT_namespace_B', 'manager'],
|
||||
'user_c': ['VENDOR_company_C', 'AREA_area_C@region_C',
|
||||
'TENANT_namespace-c', 'manager'],
|
||||
'user_all': ['VENDOR_all', 'AREA_all@all', 'TENANT_all', 'manager'],
|
||||
'user_admin': ['admin']
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
CommonVnfLcmTest.setUpClass()
|
||||
BaseEnhancedPolicyTest.setUpClass(cls)
|
||||
|
||||
for user in cls.users:
|
||||
client = cls.get_local_tacker_http_client(user.name)
|
||||
setattr(cls,
|
||||
cls.TK_HTTP_CLIENT_NAME % {'username': user.name}, client)
|
||||
|
||||
cls.tacker_client = cls.get_local_tacker_http_client('user_all')
|
||||
|
||||
cur_dir = os.path.dirname(__file__)
|
||||
image_dir = os.path.join(
|
||||
cur_dir, "../../../etc/samples/etsi/nfv/common/Files/images")
|
||||
|
||||
image_file = "cirros-0.5.2-x86_64-disk.img"
|
||||
image_path = os.path.abspath(os.path.join(image_dir, image_file))
|
||||
|
||||
# for basic lcms tests min pattern
|
||||
basic_lcms_min_path = os.path.join(cur_dir,
|
||||
"../../sol_v2_common/samples/basic_lcms_min")
|
||||
|
||||
# for update vnf test
|
||||
update_vnf_path = os.path.join(cur_dir,
|
||||
"../../sol_v2_common/samples/update_vnf")
|
||||
# for change ext conn
|
||||
change_vnfpkg_from_image_to_image_path_2 = os.path.join(cur_dir,
|
||||
"../../sol_v2_common/samples/test_change_vnf_pkg_with_new_image")
|
||||
|
||||
# for user_a
|
||||
cls.vnf_pkg_a, cls.vnfd_id_a = cls.create_vnf_package(
|
||||
basic_lcms_min_path, image_path=image_path, provider='company_A')
|
||||
|
||||
cls.vnf_pkg_a_1, cls.vnfd_id_a_1 = cls.create_vnf_package(
|
||||
update_vnf_path, provider='company_A')
|
||||
|
||||
cls.vnf_pkg_a_2, cls.vnfd_id_a_2 = cls.create_vnf_package(
|
||||
change_vnfpkg_from_image_to_image_path_2, image_path=image_path,
|
||||
provider='company_A')
|
||||
|
||||
# for user_b
|
||||
cls.vnf_pkg_b, cls.vnfd_id_b = cls.create_vnf_package(
|
||||
basic_lcms_min_path, image_path=image_path, provider='company_B')
|
||||
|
||||
cls.vnf_pkg_b_1, cls.vnfd_id_b_1 = cls.create_vnf_package(
|
||||
update_vnf_path, provider='company_B')
|
||||
|
||||
cls.vnf_pkg_b_2, cls.vnfd_id_b_2 = cls.create_vnf_package(
|
||||
change_vnfpkg_from_image_to_image_path_2, image_path=image_path,
|
||||
provider='company_B')
|
||||
|
||||
# for user_c
|
||||
cls.vnf_pkg_c, cls.vnfd_id_c = cls.create_vnf_package(
|
||||
basic_lcms_min_path, image_path=image_path, provider='company_C')
|
||||
|
||||
cls.vnf_pkg_c_1, cls.vnfd_id_c_1 = cls.create_vnf_package(
|
||||
update_vnf_path, provider='company_C')
|
||||
|
||||
cls.vnf_pkg_c_2, cls.vnfd_id_c_2 = cls.create_vnf_package(
|
||||
change_vnfpkg_from_image_to_image_path_2, image_path=image_path,
|
||||
provider='company_C')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.delete_vnf_package(cls.vnf_pkg_a)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_a_1)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_a_2)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_b)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_b_1)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_b_2)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_c)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_c_1)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_c_2)
|
||||
BaseEnhancedPolicyTest.tearDownClass()
|
||||
super(VnflcmAPIsV2VNFBase, cls).tearDownClass()
|
||||
|
||||
@classmethod
|
||||
def get_vim_info(cls, vim_conf='local-vim.yaml'):
|
||||
vim_params = yaml.safe_load(base_utils.read_file(vim_conf))
|
||||
vim_params['auth_url'] += '/v3'
|
||||
|
||||
vim_info = objects.VimConnectionInfo(
|
||||
interfaceInfo={'endpoint': vim_params['auth_url']},
|
||||
accessInfo={
|
||||
'region': 'RegionOne',
|
||||
'project': vim_params['project_name'],
|
||||
'username': vim_params['username'],
|
||||
'password': vim_params['password'],
|
||||
'userDomain': vim_params['user_domain_name'],
|
||||
'projectDomain': vim_params['project_domain_name']
|
||||
}
|
||||
)
|
||||
|
||||
return vim_info
|
||||
|
||||
@classmethod
|
||||
def get_local_tacker_http_client(cls, username):
|
||||
vim_info = cls.get_vim_info(vim_conf=cls.local_vim_conf_file)
|
||||
|
||||
auth = http_client.KeystonePasswordAuthHandle(
|
||||
auth_url=vim_info.interfaceInfo['endpoint'],
|
||||
username=username,
|
||||
password='devstack',
|
||||
project_name=vim_info.accessInfo['project'],
|
||||
user_domain_name=vim_info.accessInfo['userDomain'],
|
||||
project_domain_name=vim_info.accessInfo['projectDomain']
|
||||
)
|
||||
return http_client.HttpClient(auth)
|
||||
|
||||
def change_ext_conn_max(self, net_ids, subnets, auth_url, area):
|
||||
vim_id_1 = uuidutils.generate_uuid()
|
||||
vim_id_2 = uuidutils.generate_uuid()
|
||||
|
||||
ext_vl_1 = {
|
||||
"id": uuidutils.generate_uuid(),
|
||||
"vimConnectionId": vim_id_1,
|
||||
"resourceProviderId": uuidutils.generate_uuid(),
|
||||
"resourceId": net_ids['ft-net1'],
|
||||
"extCps": [
|
||||
{
|
||||
"cpdId": "VDU1_CP1",
|
||||
"cpConfig": {
|
||||
"VDU1_CP1": {
|
||||
"cpProtocolData": [{
|
||||
"layerProtocol": "IP_OVER_ETHERNET",
|
||||
"ipOverEthernet": {
|
||||
# "macAddress": omitted,
|
||||
# "segmentationId": omitted,
|
||||
"ipAddresses": [{
|
||||
"type": "IPV4",
|
||||
# "fixedAddresses": omitted,
|
||||
"numDynamicAddresses": 1,
|
||||
# "addressRange": omitted,
|
||||
"subnetId": subnets[
|
||||
'ft-ipv4-subnet1']}]
|
||||
}
|
||||
}]}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cpdId": "VDU2_CP2",
|
||||
"cpConfig": {
|
||||
"VDU2_CP2": {
|
||||
"cpProtocolData": [{
|
||||
"layerProtocol": "IP_OVER_ETHERNET",
|
||||
"ipOverEthernet": {
|
||||
# "macAddress": omitted,
|
||||
# "segmentationId": omitted,
|
||||
"ipAddresses": [{
|
||||
"type": "IPV4",
|
||||
"fixedAddresses": [
|
||||
"22.22.22.101"
|
||||
],
|
||||
# "numDynamicAddresses": omitted
|
||||
# "addressRange": omitted,
|
||||
"subnetId": subnets['ft-ipv4-subnet1']
|
||||
}, {
|
||||
"type": "IPV6",
|
||||
# "fixedAddresses": omitted,
|
||||
# "numDynamicAddresses": omitted,
|
||||
"numDynamicAddresses": 1,
|
||||
# "addressRange": omitted,
|
||||
"subnetId": subnets['ft-ipv6-subnet1']
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}}
|
||||
}
|
||||
]
|
||||
}
|
||||
vim_1 = {
|
||||
"vimId": vim_id_1,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {"endpoint": auth_url},
|
||||
"accessInfo": {
|
||||
"username": "nfv_user",
|
||||
"region": "RegionOne",
|
||||
"password": "devstack",
|
||||
"project": "nfv",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {"area": area}
|
||||
}
|
||||
vim_2 = {
|
||||
"vimId": vim_id_2,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {"endpoint": auth_url},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"password": "dummy_password",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {"area": area}
|
||||
}
|
||||
if not area:
|
||||
vim_1.pop('extra')
|
||||
vim_2.pop('extra')
|
||||
return {
|
||||
"extVirtualLinks": [
|
||||
ext_vl_1
|
||||
],
|
||||
"vimConnectionInfo": {
|
||||
"vim1": vim_1,
|
||||
"vim2": vim_2
|
||||
},
|
||||
"additionalParams": {"dummy-key": "dummy-val"}
|
||||
}
|
||||
|
||||
def _step_lcm_create(self, username, vnfd_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
create_req = paramgen.create_vnf_min(vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 201:
|
||||
return body['id']
|
||||
else:
|
||||
return None
|
||||
|
||||
def instantiate_vnf(self, area=None, vim_id=None):
|
||||
# Omit except for required attributes
|
||||
# NOTE: Only the following cardinality attributes are set.
|
||||
# - 1
|
||||
# - 1..N (1)
|
||||
vim_id_1 = uuidutils.generate_uuid()
|
||||
vim_id_2 = uuidutils.generate_uuid()
|
||||
if area:
|
||||
vim_1 = {
|
||||
"vimId": vim_id_1,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {"endpoint": self.auth_url},
|
||||
"accessInfo": {
|
||||
"username": "nfv_user",
|
||||
"region": "RegionOne",
|
||||
"password": "devstack",
|
||||
"project": "nfv",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {"area": area}
|
||||
}
|
||||
vim_2 = {
|
||||
"vimId": vim_id_2,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {"endpoint": self.auth_url},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"password": "dummy_password",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {"area": area}
|
||||
}
|
||||
if vim_id:
|
||||
vim_1 = {
|
||||
"vimId": vim_id,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3"
|
||||
}
|
||||
vim_2 = {
|
||||
"vimId": vim_id,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3"
|
||||
}
|
||||
|
||||
return {
|
||||
"flavourId": "simple",
|
||||
"vimConnectionInfo": {
|
||||
"vim1": vim_1,
|
||||
"vim2": vim_2
|
||||
}
|
||||
}
|
||||
|
||||
def _step_lcm_instantiate(self, username, inst_id, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, expected_status_code,
|
||||
area=None, vim_id=None):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
self._set_grant_response(
|
||||
False, 'INSTANTIATE', glance_image=glance_image,
|
||||
flavour_vdu_dict=flavour_vdu_dict, zone_name_list=zone_name_list)
|
||||
instantiate_req = self.instantiate_vnf(area, vim_id)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# wait a bit because there is a bit time lag between lcmocc DB
|
||||
# update and instantiate completion.
|
||||
time.sleep(3)
|
||||
|
||||
def _step_lcm_show(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
def _step_lcm_list(self, username, expected_inst_list):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
resp, vnf_instances = self.list_vnf_instance()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
inst_ids = set([inst.get('id') for inst in vnf_instances])
|
||||
for inst_id in expected_inst_list:
|
||||
self.assertIn(inst_id, inst_ids)
|
||||
|
||||
def _step_lcm_heal(self, username, inst_id, glance_image, flavour_vdu_dict,
|
||||
zone_name_list, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
self._set_grant_response(
|
||||
False, 'HEAL', glance_image=glance_image,
|
||||
flavour_vdu_dict=flavour_vdu_dict, zone_name_list=zone_name_list)
|
||||
|
||||
heal_req = paramgen.heal_vnf_all_min()
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
time.sleep(3)
|
||||
|
||||
def _step_lcm_update(self, username, inst_id, update_vnfd_id,
|
||||
expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
update_req = paramgen.update_vnf_min_with_parameter(update_vnfd_id)
|
||||
resp, body = self.update_vnf_instance(inst_id, update_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def _step_lcm_scale_out(self, username, inst_id, glance_image,
|
||||
flavour_vdu_dict, zone_name_list,
|
||||
expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
self._set_grant_response(
|
||||
False, 'SCALE', glance_image=glance_image,
|
||||
flavour_vdu_dict=flavour_vdu_dict, zone_name_list=zone_name_list)
|
||||
scaleout_req = paramgen.scaleout_vnf_min()
|
||||
resp, body = self.scale_vnf_instance(inst_id, scaleout_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def _step_lcm_scale_in(self, username, inst_id, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
self._set_grant_response(
|
||||
False, 'SCALE', glance_image=glance_image,
|
||||
flavour_vdu_dict=flavour_vdu_dict, zone_name_list=zone_name_list)
|
||||
scalein_req = paramgen.scalein_vnf_min()
|
||||
resp, body = self.scale_vnf_instance(inst_id, scalein_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def _step_lcm_change_vnfpkg(self, username, inst_id, change_vnfd_id,
|
||||
glance_image, flavour_vdu_dict, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
change_vnfpkg_req = paramgen.change_vnfpkg_with_ext_vl(
|
||||
change_vnfd_id, self.get_network_ids(['net1']))
|
||||
|
||||
del change_vnfpkg_req[
|
||||
"additionalParams"]["lcm-operation-coordinate-old-vnf"]
|
||||
del change_vnfpkg_req[
|
||||
"additionalParams"]["lcm-operation-coordinate-new-vnf"]
|
||||
self._set_grant_response(False, 'CHANGE_VNFPKG',
|
||||
glance_image=glance_image,
|
||||
flavour_vdu_dict=flavour_vdu_dict)
|
||||
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnfpkg_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# wait a bit because there is a bit time lag between lcmocc DB
|
||||
# update and change_vnfpkg completion.
|
||||
time.sleep(3)
|
||||
|
||||
def _step_lcm_change_ext_conn(self, username, inst_id, area,
|
||||
zone_name_list, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
self._set_grant_response(
|
||||
False, 'CHANGE_EXT_CONN', zone_name_list=zone_name_list)
|
||||
|
||||
# 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'])
|
||||
|
||||
# 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 = self.create_network(ft_net1_name)
|
||||
self.addCleanup(self.delete_network, ft_net1_id)
|
||||
for sub_name, val in ft_net1_subs.items():
|
||||
# subnet is automatically deleted with network deletion
|
||||
self.create_subnet(
|
||||
ft_net1_id, sub_name, val['range'], val['ip_version'])
|
||||
|
||||
net_ids = self.get_network_ids(
|
||||
['net0', 'net1', 'net_mgmt', 'ft-net0', 'ft-net1'])
|
||||
subnet_ids = self.get_subnet_ids(
|
||||
['subnet0', 'subnet1', 'ft-ipv4-subnet0', 'ft-ipv6-subnet0',
|
||||
'ft-ipv4-subnet1', 'ft-ipv6-subnet1'])
|
||||
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)
|
||||
|
||||
change_ext_conn_req = self.change_ext_conn_max(
|
||||
net_ids, subnet_ids, self.auth_url, area)
|
||||
resp, body = self.change_ext_conn(inst_id, change_ext_conn_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
time.sleep(3)
|
||||
|
||||
def _step_lcm_terminate(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
self._set_grant_response(False, 'TERMINATE')
|
||||
terminate_req = paramgen.terminate_vnf_min()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# wait a bit because there is a bit time lag between lcmocc DB
|
||||
# update and terminate completion.
|
||||
time.sleep(3)
|
||||
|
||||
def _step_lcm_delete(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
resp, body = self.delete_vnf_instance(inst_id)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
def vnflcm_apis_v2_vnf_test_before_instantiate(self):
|
||||
# Create subscription
|
||||
self.tacker_client = self.get_tk_http_client_by_user('user_all')
|
||||
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_min(callback_uri)
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# Test notification
|
||||
self.assert_notification_get(callback_url)
|
||||
# check usageState of VNF Package
|
||||
self._check_package_usage(False, self.vnf_pkg_a)
|
||||
|
||||
# step 1 LCM-CreateV2, Resource Group A / User Group A
|
||||
inst_id_a = self._step_lcm_create('user_a', self.vnfd_id_a, 201)
|
||||
|
||||
# step 2 LCM-CreateV2, Resource Group B / User Group A
|
||||
self._step_lcm_create('user_a', self.vnfd_id_b, 403)
|
||||
|
||||
# step 3 LCM-CreateV2, Resource Group B / User Group all
|
||||
inst_id_b = self._step_lcm_create('user_all', self.vnfd_id_b, 201)
|
||||
|
||||
# step 4 LCM-ShowV2, Resource Group A / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_a, 200)
|
||||
|
||||
# step 5 LCM-ShowV2, Resource Group A / User Group A-1
|
||||
self._step_lcm_show('user_a_1', inst_id_a, 200)
|
||||
|
||||
# step 6 LCM-ShowV2, Resource Group B / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_b, 403)
|
||||
|
||||
# step 7 LCM-ShowV2, Resource Group B / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_b, 200)
|
||||
|
||||
# step 8 LCM-ListV2, Resource Group A / User Group A
|
||||
self._step_lcm_list('user_a', [inst_id_a])
|
||||
|
||||
# step 9 LCM-ListV2, Resource Group - / User Group A-1
|
||||
self._step_lcm_list('user_a_1', [inst_id_a])
|
||||
|
||||
# step 10 LCM-ListV2, Resource Group - / User Group B
|
||||
self._step_lcm_list('user_b', [inst_id_b])
|
||||
|
||||
# step 11 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [inst_id_a, inst_id_b])
|
||||
|
||||
return sub_id, inst_id_a, inst_id_b
|
||||
|
||||
def vnflcm_apis_v2_vnf_test_after_instantiate(
|
||||
self, sub_id, inst_id_a, inst_id_b, zone_name_list, glance_image,
|
||||
flavour_vdu_dict):
|
||||
|
||||
# step 15 LCM-ShowV2, Resource Group A / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_a, 200)
|
||||
|
||||
# step 16 LCM-ShowV2, Resource Group A / User Group A-1
|
||||
self._step_lcm_show('user_a_1', inst_id_a, 403)
|
||||
|
||||
# step 17 LCM-ShowV2, Resource Group B / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_b, 403)
|
||||
|
||||
# step 18 LCM-ShowV2, Resource Group B / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_b, 200)
|
||||
|
||||
# step 19 LCM-ListV2, Resource Group - / User Group A
|
||||
self._step_lcm_list('user_a', [inst_id_a])
|
||||
|
||||
# step 20 LCM-ListV2, Resource Group - / User Group A-1
|
||||
self._step_lcm_list('user_a_1', [])
|
||||
|
||||
# step 21 LCM-ListV2, Resource Group - / User Group B
|
||||
self._step_lcm_list('user_b', [inst_id_b])
|
||||
|
||||
# step 22 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [inst_id_a, inst_id_b])
|
||||
|
||||
# step 23 LCM-ScaleV2(out), Resource Group A / User Group A
|
||||
self._step_lcm_scale_out('user_a', inst_id_a, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 24 LCM-ScaleV2(out), Resource Group B / User Group A
|
||||
self._step_lcm_scale_out('user_a', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 25 LCM-ScaleV2(out), Resource Group B / User Group all
|
||||
self._step_lcm_scale_out('user_all', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 26 LCM-ScaleV2(in), Resource Group A / User Group A
|
||||
self._step_lcm_scale_in('user_a', inst_id_a, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 27 LCM-ScaleV2(in), Resource Group B / User Group A
|
||||
self._step_lcm_scale_in('user_a', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 28 LCM-ScaleV2(in), Resource Group B / User Group all
|
||||
self._step_lcm_scale_in('user_all', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 29 LCM-HealV2, Resource Group A / User Group A
|
||||
self._step_lcm_heal('user_a', inst_id_a, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 30 LCM-HealV2, Resource Group B / User Group A
|
||||
self._step_lcm_heal('user_a', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 31 LCM-HealV2, Resource Group B / User Group all
|
||||
self._step_lcm_heal('user_all', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 32 LCM-ModifyV2, Resource Group A / User Group A
|
||||
self._step_lcm_update('user_a', inst_id_a, self.vnfd_id_a_1, 202)
|
||||
|
||||
# step 33 LCM-ModifyV2, Resource Group b / User Group A
|
||||
self._step_lcm_update('user_a', inst_id_b, self.vnfd_id_b_1, 403)
|
||||
|
||||
# step 34 LCM-ModifyV2, Resource Group B / User Group all
|
||||
self._step_lcm_update('user_all', inst_id_b, self.vnfd_id_b_1, 202)
|
||||
|
||||
# step 35 LCM-Change-ConnectivityV2, Resource Group A / User Group A
|
||||
self._step_lcm_change_ext_conn(
|
||||
'user_a', inst_id_a, 'area_A@region_A', zone_name_list, 202)
|
||||
|
||||
# step 36 LCM-Change-ConnectivityV2, Resource Group B / User Group A
|
||||
self._step_lcm_change_ext_conn(
|
||||
'user_a', inst_id_b, 'area_B@region_B', zone_name_list, 403)
|
||||
|
||||
# step 37 LCM-Change-ConnectivityV2, Resource Group B / User Group all
|
||||
self._step_lcm_change_ext_conn(
|
||||
'user_all', inst_id_b, 'area_B@region_B', zone_name_list, 202)
|
||||
|
||||
# step 38 LCM-Change-VnfPkgV2, Resource Group A / User Group A
|
||||
self._step_lcm_update('user_a', inst_id_a, self.vnfd_id_a, 202)
|
||||
self._step_lcm_change_vnfpkg('user_a', inst_id_a, self.vnfd_id_a_2,
|
||||
glance_image, flavour_vdu_dict, 202)
|
||||
|
||||
# step 39 LCM-Change-VnfPkgV2, Resource Group B / User Group A
|
||||
self._step_lcm_change_vnfpkg('user_a', inst_id_b, self.vnfd_id_b_2,
|
||||
glance_image, flavour_vdu_dict, 403)
|
||||
|
||||
# step 40 LCM-Change-VnfPkgV2, Resource Group B / User Group all
|
||||
self._step_lcm_update('user_all', inst_id_b, self.vnfd_id_b, 202)
|
||||
self._step_lcm_change_vnfpkg('user_all', inst_id_b, self.vnfd_id_b_2,
|
||||
glance_image, flavour_vdu_dict, 202)
|
||||
|
||||
# step 41 LCM-TerminateV2, Resource Group A / User Group A
|
||||
self._step_lcm_terminate('user_a', inst_id_a, 202)
|
||||
|
||||
# step 42 LCM-TerminateV2, Resource Group B / User Group A
|
||||
self._step_lcm_terminate('user_a', inst_id_b, 403)
|
||||
|
||||
# step 43 LCM-TerminateV2, Resource Group B / User Group all
|
||||
self._step_lcm_terminate('user_all', inst_id_b, 202)
|
||||
|
||||
# step 44 LCM-DeleteV2, Resource Group A / User Group A
|
||||
self._step_lcm_delete('user_a', inst_id_a, 204)
|
||||
|
||||
# step 45 LCM-DeleteV2, Resource Group B / User Group A
|
||||
self._step_lcm_delete('user_a', inst_id_b, 403)
|
||||
|
||||
# step 46 LCM-DeleteV2, Resource Group B / User Group all
|
||||
self._step_lcm_delete('user_all', inst_id_b, 204)
|
||||
|
||||
# Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# Show subscription
|
||||
resp, body = self.show_subscription(sub_id)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
|
||||
class VnflcmAPIsV2VNFInstantiateWithArea(VnflcmAPIsV2VNFBase):
|
||||
|
||||
def test_vnflcm_apis_v2_vnf_with_area_in_vim_conn_info(self):
|
||||
glance_image = None
|
||||
flavour_vdu_dict = None
|
||||
zone_name_list = None
|
||||
|
||||
sub_id, inst_id_a, inst_id_b = (
|
||||
self.vnflcm_apis_v2_vnf_test_before_instantiate())
|
||||
|
||||
# step 12 LCM-InstantiateV2, Resource Group A / User Group A
|
||||
self._step_lcm_instantiate('user_a', inst_id_a, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202, area='area_A@region_A')
|
||||
|
||||
# step 13 LCM-InstantiateV2, Resource Group B / User Group A
|
||||
self._step_lcm_instantiate('user_a', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403,
|
||||
area='area_B@region_B')
|
||||
|
||||
# step 14 LCM-InstantiateV2, Resource Group B / User Group all
|
||||
self._step_lcm_instantiate('user_all', inst_id_b, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202,
|
||||
area='area_B@region_B')
|
||||
|
||||
self.vnflcm_apis_v2_vnf_test_after_instantiate(
|
||||
sub_id, inst_id_a, inst_id_b, zone_name_list, glance_image,
|
||||
flavour_vdu_dict)
|
||||
|
||||
|
||||
class VnflcmAPIsV2VNFInstantiateWithoutArea(VnflcmAPIsV2VNFBase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
vim_type = 'openstack'
|
||||
|
||||
local_vim = 'local-vim.yaml'
|
||||
|
||||
cls.vim_a = cls._step_vim_register(
|
||||
'user_a', vim_type, local_vim, 'vim_a', 'area_A@region_A')
|
||||
|
||||
cls.vim_a_1 = cls._step_vim_register(
|
||||
'user_a', vim_type, local_vim, 'vim_a_1', 'area_A@region_A')
|
||||
|
||||
cls.vim_b = cls._step_vim_register(
|
||||
'user_b', vim_type, local_vim, 'vim_b', 'area_B@region_B')
|
||||
|
||||
cls.vim_b_1 = cls._step_vim_register(
|
||||
'user_b', vim_type, local_vim, 'vim_b_1', 'area_B@region_B')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
||||
cls._step_vim_delete('user_a', cls.vim_a)
|
||||
cls._step_vim_delete('user_a', cls.vim_a_1)
|
||||
cls._step_vim_delete('user_b', cls.vim_b)
|
||||
cls._step_vim_delete('user_b', cls.vim_b_1)
|
||||
|
||||
super().tearDownClass()
|
||||
|
||||
def test_vnflcm_apis_v2_vnf_without_area_in_vim_conn_info(self):
|
||||
|
||||
glance_image = None
|
||||
flavour_vdu_dict = None
|
||||
zone_name_list = None
|
||||
|
||||
sub_id, inst_id_a, inst_id_b = (
|
||||
self.vnflcm_apis_v2_vnf_test_before_instantiate())
|
||||
|
||||
# step 12 LCM-InstantiateV2, Resource Group A / User Group A
|
||||
self._step_lcm_instantiate('user_a', inst_id_a,
|
||||
glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202,
|
||||
vim_id=self.vim_a['id'])
|
||||
|
||||
# step 13 LCM-InstantiateV2, Resource Group B / User Group A
|
||||
self._step_lcm_instantiate('user_a', inst_id_b,
|
||||
glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403,
|
||||
vim_id=self.vim_b['id'])
|
||||
|
||||
# step 14 LCM-InstantiateV2, Resource Group B / User Group all
|
||||
self._step_lcm_instantiate('user_all', inst_id_b,
|
||||
glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202,
|
||||
vim_id=self.vim_b['id'])
|
||||
|
||||
self.vnflcm_apis_v2_vnf_test_after_instantiate(
|
||||
sub_id, inst_id_a, inst_id_b, zone_name_list, glance_image,
|
||||
flavour_vdu_dict)
|
||||
|
||||
|
||||
class VnflcmAPIsV2VNFInstanceWithoutArea(VnflcmAPIsV2VNFBase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
vim_type = 'openstack'
|
||||
|
||||
local_vim = 'local-vim.yaml'
|
||||
|
||||
cls.vim_c = cls._step_vim_register(
|
||||
'user_c', vim_type, local_vim, 'vim_c', None)
|
||||
|
||||
cls.vim_c_1 = cls._step_vim_register(
|
||||
'user_c', vim_type, local_vim, 'vim_c_1', None)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
||||
cls._step_vim_delete('user_admin', cls.vim_c)
|
||||
cls._step_vim_delete('user_admin', cls.vim_c_1)
|
||||
|
||||
super().tearDownClass()
|
||||
|
||||
def test_vnflcm_apis_v2_vnf_instance_without_area(self):
|
||||
|
||||
glance_image = None
|
||||
flavour_vdu_dict = None
|
||||
zone_name_list = None
|
||||
|
||||
# Create subscription
|
||||
self.tacker_client = self.get_tk_http_client_by_user('user_all')
|
||||
|
||||
callback_url = os.path.join(base_v2.MOCK_NOTIFY_CALLBACK_URL,
|
||||
self._testMethodName)
|
||||
callback_uri = ('http://localhost:'
|
||||
f'{base_v2.FAKE_SERVER_MANAGER.SERVER_PORT}'
|
||||
f'{callback_url}')
|
||||
|
||||
sub_req = paramgen.sub_create_min(callback_uri)
|
||||
resp, body = self.create_subscription(sub_req)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.check_resp_headers_in_create(resp)
|
||||
sub_id = body['id']
|
||||
|
||||
# Test notification
|
||||
self.assert_notification_get(callback_url)
|
||||
# check usageState of VNF Package
|
||||
self._check_package_usage(False, self.vnf_pkg_c)
|
||||
|
||||
# step 1 LCM-CreateV2, Resource Group C / User Group C
|
||||
inst_id_c = self._step_lcm_create('user_c', self.vnfd_id_c, 201)
|
||||
|
||||
# step 2 LCM-ShowV2, Resource Group C / User Group C
|
||||
self._step_lcm_show('user_c', inst_id_c, 200)
|
||||
|
||||
# step 3 LCM-ShowV2, Resource Group C / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_c, 200)
|
||||
|
||||
# step 4 LCM-ShowV2, Resource Group C / User Group admin
|
||||
self._step_lcm_show('user_admin', inst_id_c, 200)
|
||||
|
||||
# step 5 LCM-ListV2, Resource Group - / User Group C
|
||||
self._step_lcm_list('user_c', [inst_id_c])
|
||||
|
||||
# step 6 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [inst_id_c])
|
||||
|
||||
# step 7 LCM-ListV2, Resource Group - / User Group admin
|
||||
self._step_lcm_list('user_admin', [inst_id_c])
|
||||
|
||||
# step 8 LCM-InstantiateV2, Resource Group C / User Group C
|
||||
self._step_lcm_instantiate('user_c', inst_id_c,
|
||||
glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202,
|
||||
vim_id=self.vim_c['id'])
|
||||
|
||||
# step 9 LCM-ShowV2, Resource Group C / User Group C
|
||||
self._step_lcm_show('user_c', inst_id_c, 403)
|
||||
|
||||
# step 10 LCM-ShowV2, Resource Group C / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_c, 403)
|
||||
|
||||
# step 11 LCM-ShowV2, Resource Group C / User Group admin
|
||||
self._step_lcm_show('user_admin', inst_id_c, 200)
|
||||
|
||||
# step 12 LCM-ListV2, Resource Group - / User Group C
|
||||
self._step_lcm_list('user_c', [])
|
||||
|
||||
# step 13 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [])
|
||||
|
||||
# step 14 LCM-ListV2, Resource Group - / User Group admin
|
||||
self._step_lcm_list('user_admin', [inst_id_c])
|
||||
|
||||
# step 15 LCM-ScaleV2(out), Resource Group C / User Group C
|
||||
self._step_lcm_scale_out('user_c', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 16 LCM-ScaleV2(out), Resource Group C / User Group all
|
||||
self._step_lcm_scale_out('user_all', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 17 LCM-ScaleV2(out), Resource Group C / User Group admin
|
||||
self._step_lcm_scale_out('user_admin', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 18 LCM-ScaleV2(in), Resource Group C / User Group C
|
||||
self._step_lcm_scale_in('user_c', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 19 LCM-ScaleV2(in), Resource Group C / User Group A
|
||||
self._step_lcm_scale_in('user_all', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 20 LCM-ScaleV2(in), Resource Group C / User Group all
|
||||
self._step_lcm_scale_in('user_admin', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 21 LCM-HealV2, Resource Group C / User Group C
|
||||
self._step_lcm_heal('user_c', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 22 LCM-HealV2, Resource Group C / User Group A
|
||||
self._step_lcm_heal('user_all', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 403)
|
||||
|
||||
# step 23 LCM-HealV2, Resource Group C / User Group all
|
||||
self._step_lcm_heal('user_admin', inst_id_c, glance_image,
|
||||
flavour_vdu_dict, zone_name_list, 202)
|
||||
|
||||
# step 24 LCM-ModifyV2, Resource Group C / User Group C
|
||||
self._step_lcm_update('user_c', inst_id_c, self.vnfd_id_c_1, 403)
|
||||
|
||||
# step 25 LCM-ModifyV2, Resource Group C / User Group A
|
||||
self._step_lcm_update('user_all', inst_id_c, self.vnfd_id_c_1, 403)
|
||||
|
||||
# step 26 LCM-ModifyV2, Resource Group C / User Group all
|
||||
self._step_lcm_update('user_admin', inst_id_c, self.vnfd_id_c_1, 202)
|
||||
|
||||
# step 27 LCM-Change-ConnectivityV2, Resource Group C / User Group C
|
||||
self._step_lcm_change_ext_conn(
|
||||
'user_c', inst_id_c, None, zone_name_list, 403)
|
||||
|
||||
# step 28 LCM-Change-ConnectivityV2, Resource Group C / User Group A
|
||||
self._step_lcm_change_ext_conn(
|
||||
'user_all', inst_id_c, None, zone_name_list, 403)
|
||||
|
||||
# step 29 LCM-Change-ConnectivityV2, Resource Group C / User Group all
|
||||
self._step_lcm_change_ext_conn(
|
||||
'user_admin', inst_id_c, None, zone_name_list, 202)
|
||||
|
||||
# step 30 LCM-Change-VnfPkgV2, Resource Group C / User Group C
|
||||
self._step_lcm_change_vnfpkg('user_c', inst_id_c, self.vnfd_id_c_2,
|
||||
glance_image, flavour_vdu_dict, 403)
|
||||
|
||||
# step 31 LCM-Change-VnfPkgV2, Resource Group C / User Group A
|
||||
self._step_lcm_change_vnfpkg('user_all', inst_id_c, self.vnfd_id_c_2,
|
||||
glance_image, flavour_vdu_dict, 403)
|
||||
|
||||
# step 32 LCM-Change-VnfPkgV2, Resource Group C / User Group all
|
||||
self._step_lcm_update('user_admin', inst_id_c, self.vnfd_id_c, 202)
|
||||
self._step_lcm_change_vnfpkg('user_admin', inst_id_c, self.vnfd_id_c_2,
|
||||
glance_image, flavour_vdu_dict, 202)
|
||||
|
||||
# step 33 LCM-TerminateV2, Resource Group C / User Group C
|
||||
self._step_lcm_terminate('user_c', inst_id_c, 403)
|
||||
|
||||
# step 34 LCM-TerminateV2, Resource Group C / User Group A
|
||||
self._step_lcm_terminate('user_all', inst_id_c, 403)
|
||||
|
||||
# step 35 LCM-TerminateV2, Resource Group C / User Group all
|
||||
self._step_lcm_terminate('user_admin', inst_id_c, 202)
|
||||
|
||||
# step 36 LCM-DeleteV2, Resource Group C / User Group C
|
||||
self._step_lcm_delete('user_c', inst_id_c, 204)
|
||||
|
||||
# Delete subscription
|
||||
resp, body = self.delete_subscription(sub_id)
|
||||
self.assertEqual(204, resp.status_code)
|
||||
self.check_resp_headers_in_delete(resp)
|
||||
|
||||
# Show subscription
|
||||
resp, body = self.show_subscription(sub_id)
|
||||
self.assertEqual(404, resp.status_code)
|
@ -0,0 +1,220 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker import context
|
||||
from tacker.tests.functional.sol_enhanced_policy.base import (
|
||||
VnflcmAPIsV1Base)
|
||||
|
||||
|
||||
class VnflcmAPIsV1CNFTest(VnflcmAPIsV1Base):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
cls.client = cls.tackerclient(cls.local_vim_conf_file)
|
||||
|
||||
# In the setUp of the parent class, it will be confirmed whether there
|
||||
# is a default vim named "VIM0". Here, it is confirmed in advance. If
|
||||
# it does not exist, it will be created to avoid the parent class
|
||||
# throwing an exception.
|
||||
cls.if_not_vim_create()
|
||||
|
||||
local_k8s_vim = 'local-k8s-vim.yaml'
|
||||
vim_type = 'kubernetes'
|
||||
|
||||
cls.vim_a = cls._step_vim_register(
|
||||
'user_a', vim_type, local_k8s_vim, 'vim_a', 'area_A@region_A')
|
||||
|
||||
cls.vim_a_1 = cls._step_vim_register(
|
||||
'user_a', vim_type, local_k8s_vim, 'vim_a_1', 'area_A@region_A')
|
||||
|
||||
cls.vim_b = cls._step_vim_register(
|
||||
'user_b', vim_type, local_k8s_vim, 'vim_b', 'area_B@region_B')
|
||||
|
||||
cls.vim_b_1 = cls._step_vim_register(
|
||||
'user_b', vim_type, local_k8s_vim, 'vim_b_1', 'area_B@region_B')
|
||||
|
||||
cls.vim_c = cls._step_vim_register(
|
||||
'user_c', vim_type, local_k8s_vim, 'vim_c', None)
|
||||
|
||||
cls.vim_c_1 = cls._step_vim_register(
|
||||
'user_c', vim_type, local_k8s_vim, 'vim_c_1', None)
|
||||
|
||||
cls.pkg_a = cls._step_pkg_create('user_a')
|
||||
|
||||
cls.vnfd_id_a = cls._step_pkg_upload_content(
|
||||
'user_a', cls.pkg_a, 'test_cnf', 'company_A',
|
||||
namespace='namespace-a')
|
||||
|
||||
cls.pkg_b = cls._step_pkg_create('user_b')
|
||||
|
||||
cls.vnfd_id_b = cls._step_pkg_upload_content(
|
||||
'user_b', cls.pkg_b, 'test_cnf', 'company_B',
|
||||
namespace='namespace-b')
|
||||
|
||||
cls.pkg_c = cls._step_pkg_create('user_c')
|
||||
|
||||
cls.vnfd_id_c = cls._step_pkg_upload_content(
|
||||
'user_c', cls.pkg_c, 'test_cnf', 'company_C',
|
||||
namespace='namespace-c')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls._step_pkg_disable('user_a', cls.pkg_a,)
|
||||
cls._step_pkg_disable('user_b', cls.pkg_b,)
|
||||
cls._step_pkg_disable('user_c', cls.pkg_c,)
|
||||
cls._step_pkg_delete('user_a', cls.pkg_a)
|
||||
cls._step_pkg_delete('user_b', cls.pkg_b)
|
||||
cls._step_pkg_delete('user_c', cls.pkg_c)
|
||||
|
||||
cls._step_vim_delete('user_a', cls.vim_a)
|
||||
cls._step_vim_delete('user_a', cls.vim_a_1)
|
||||
cls._step_vim_delete('user_b', cls.vim_b)
|
||||
cls._step_vim_delete('user_b', cls.vim_b_1)
|
||||
cls._step_vim_delete('user_admin', cls.vim_c)
|
||||
cls._step_vim_delete('user_admin', cls.vim_c_1)
|
||||
|
||||
super().tearDownClass()
|
||||
|
||||
@classmethod
|
||||
def get_vim(cls, vim_list, vim_name):
|
||||
if len(vim_list.values()) == 0:
|
||||
assert False, "vim_list is Empty: Default VIM is missing"
|
||||
|
||||
for vim_list in vim_list.values():
|
||||
for vim in vim_list:
|
||||
if vim['name'] == vim_name:
|
||||
return vim
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def if_not_vim_create(cls):
|
||||
cls.context = context.get_admin_context()
|
||||
vim_list = cls.client.list_vims()
|
||||
vim_name = 'VIM0'
|
||||
if not vim_list:
|
||||
cls.vim_k8s = cls._step_vim_register(
|
||||
'user_all', 'kubernetes', 'local-k8s-vim.yaml',
|
||||
vim_name, None)
|
||||
|
||||
vim = cls.get_vim(vim_list, vim_name)
|
||||
if not vim:
|
||||
|
||||
vim_k8s = cls._step_vim_register(
|
||||
'user_all', 'kubernetes', 'local-k8s-vim.yaml',
|
||||
vim_name, None)
|
||||
|
||||
cls.vim_k8s_id = vim_k8s.get('id')
|
||||
else:
|
||||
cls.vim_k8s_id = vim.get('id')
|
||||
|
||||
@classmethod
|
||||
def _instantiate_vnf_instance_request(
|
||||
cls, flavour_id, vim_id=None, additional_param=None,
|
||||
extra_param=None):
|
||||
request_body = {"flavourId": flavour_id}
|
||||
|
||||
if vim_id:
|
||||
request_body["vimConnectionInfo"] = [
|
||||
{"id": uuidutils.generate_uuid(),
|
||||
"vimId": vim_id,
|
||||
"vimType": "kubernetes"}]
|
||||
|
||||
if extra_param:
|
||||
request_body["vimConnectionInfo"][0]["extra"] = extra_param
|
||||
|
||||
if additional_param:
|
||||
request_body["additionalParams"] = additional_param
|
||||
|
||||
return request_body
|
||||
|
||||
def _step_lcm_instantiate(self, username, inst_id, vim_id, namespace,
|
||||
expected_status_code):
|
||||
additional_param = {
|
||||
"lcm-kubernetes-def-files": [
|
||||
"Files/kubernetes/deployment.yaml",
|
||||
"Files/kubernetes/namespace.yaml"
|
||||
],
|
||||
"namespace": namespace
|
||||
}
|
||||
request_body = self._instantiate_vnf_instance_request(
|
||||
"simple", vim_id, additional_param=additional_param)
|
||||
self._lcm_instantiate(
|
||||
username, inst_id, request_body, expected_status_code)
|
||||
|
||||
def _step_lcm_scale_out(self, username, inst_id, expected_status_code):
|
||||
scale_out_req = {
|
||||
"type": "SCALE_OUT",
|
||||
"aspectId": "vdu2_aspect",
|
||||
"numberOfSteps": 1
|
||||
}
|
||||
self._step_lcm_scale(
|
||||
username, inst_id, scale_out_req, expected_status_code)
|
||||
|
||||
def _step_lcm_scale_in(self, username, inst_id, expected_status_code):
|
||||
scale_in_req = {
|
||||
"type": "SCALE_IN",
|
||||
"aspectId": "vdu2_aspect",
|
||||
"numberOfSteps": 1
|
||||
}
|
||||
self._step_lcm_scale(
|
||||
username, inst_id, scale_in_req, expected_status_code)
|
||||
|
||||
def test_vnflcm_apis_vnf_instance_with_area_cnf(self):
|
||||
|
||||
self.register_subscription()
|
||||
|
||||
inst_id_a, inst_id_b = self.steps_lcm_create_and_get_with_area()
|
||||
|
||||
# step 12 LCM-Instantiate, Resource Group A / User Group A
|
||||
self._step_lcm_instantiate(
|
||||
'user_a', inst_id_a, self.vim_a['id'], 'namespace-a', 202)
|
||||
|
||||
# step 13 LCM-Instantiate, Resource Group B / User Group A
|
||||
self._step_lcm_instantiate(
|
||||
'user_a', inst_id_b, self.vim_b['id'], 'namespace-b', 403)
|
||||
|
||||
# step 14 LCM-Instantiate, Resource Group B / User Group all
|
||||
self._step_lcm_instantiate(
|
||||
'user_all', inst_id_b, self.vim_b['id'], 'namespace-b', 202)
|
||||
|
||||
self.steps_lcm_get_scale_heal_modify_with_area(inst_id_a, inst_id_b)
|
||||
|
||||
# NOTE: CNF has no LCM-Change-Connectivity
|
||||
# step 34 LCM-Change-Connectivity, Resource Group A / User Group A
|
||||
# step 35 LCM-Change-Connectivity, Resource Group b / User Group A
|
||||
# step 36 LCM-Change-Connectivity, Resource Group B / User Group all
|
||||
|
||||
self.steps_lcm_terminate_delete_with_area(inst_id_a, inst_id_b)
|
||||
|
||||
def test_vnflcm_apis_vnf_instance_without_area_cnf(self):
|
||||
|
||||
self.register_subscription()
|
||||
|
||||
inst_id_c = self.steps_lcm_create_and_get_without_area()
|
||||
|
||||
# step 8 LCM-Instantiate, Resource Group C / User Group C
|
||||
self._step_lcm_instantiate(
|
||||
'user_c', inst_id_c, self.vim_c['id'], 'namespace-c', 202)
|
||||
|
||||
self.steps_lcm_get_scale_heal_modify_without_area(inst_id_c)
|
||||
|
||||
# NOTE: CNF has no LCM-Change-Connectivity
|
||||
# step 27 LCM-Change-Connectivity, Resource Group C / User Group C
|
||||
# step 28 LCM-Change-Connectivity, Resource Group C / User Group all
|
||||
# step 29 LCM-Change-Connectivity, Resource Group C / User Group admin
|
||||
|
||||
self.steps_lcm_terminate_delete_without_area(inst_id_c)
|
@ -0,0 +1,797 @@
|
||||
#
|
||||
# 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
|
||||
import yaml
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.sol_refactored.common import http_client
|
||||
from tacker.sol_refactored import objects
|
||||
from tacker.tests.functional.sol_enhanced_policy.base import (
|
||||
BaseEnhancedPolicyTest)
|
||||
from tacker.tests.functional.sol_kubernetes_v2.base_v2 import (
|
||||
BaseVnfLcmKubernetesV2Test)
|
||||
from tacker.tests.functional.sol_kubernetes_v2 import paramgen
|
||||
from tacker.tests import utils as base_utils
|
||||
|
||||
|
||||
class VnflcmAPIsV2CNFBase(BaseVnfLcmKubernetesV2Test, BaseEnhancedPolicyTest):
|
||||
|
||||
user_role_map = {
|
||||
'user_a': ['VENDOR_company_A', 'AREA_area_A@region_A',
|
||||
'TENANT_namespace-a', 'manager'],
|
||||
'user_a_1': ['VENDOR_company_A', 'manager'],
|
||||
'user_b': ['VENDOR_company_B', 'AREA_area_B@region_B',
|
||||
'TENANT_namespace-b', 'manager'],
|
||||
'user_c': ['VENDOR_company_C', 'AREA_area_C@region_C',
|
||||
'TENANT_namespace-c', 'manager'],
|
||||
'user_all': ['VENDOR_all', 'AREA_all@all', 'TENANT_all', 'manager'],
|
||||
'user_admin': ['admin']
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
BaseVnfLcmKubernetesV2Test.setUpClass()
|
||||
BaseEnhancedPolicyTest.setUpClass(cls)
|
||||
|
||||
for user in cls.users:
|
||||
client = cls.get_local_tacker_http_client(user.name)
|
||||
setattr(
|
||||
cls, cls.TK_HTTP_CLIENT_NAME % {'username': user.name}, client)
|
||||
|
||||
cls.tacker_client = cls.get_local_tacker_http_client('user_all')
|
||||
|
||||
cur_dir = os.path.dirname(__file__)
|
||||
|
||||
test_instantiate_cnf_resources_path = os.path.join(
|
||||
cur_dir,
|
||||
"../../sol_kubernetes_v2/samples/test_instantiate_cnf_resources")
|
||||
test_change_vnf_pkg_with_deployment_path = os.path.join(
|
||||
cur_dir,
|
||||
"../../sol_kubernetes_v2/samples/"
|
||||
"test_change_vnf_pkg_with_deployment")
|
||||
|
||||
cls.vnf_pkg_a, cls.vnfd_id_a = cls.create_vnf_package(
|
||||
test_instantiate_cnf_resources_path, provider='company_A',
|
||||
namespace='namespace-a')
|
||||
|
||||
cls.vnf_pkg_a_1, cls.vnfd_id_a_1 = cls.create_vnf_package(
|
||||
test_change_vnf_pkg_with_deployment_path, provider='company_A',
|
||||
namespace='namespace-a')
|
||||
|
||||
cls.vnf_pkg_b, cls.vnfd_id_b = cls.create_vnf_package(
|
||||
test_instantiate_cnf_resources_path, provider='company_B',
|
||||
namespace='namespace-b')
|
||||
|
||||
cls.vnf_pkg_b_1, cls.vnfd_id_b_1 = cls.create_vnf_package(
|
||||
test_change_vnf_pkg_with_deployment_path, provider='company_B',
|
||||
namespace='namespace-b')
|
||||
|
||||
cls.vnf_pkg_c, cls.vnfd_id_c = cls.create_vnf_package(
|
||||
test_instantiate_cnf_resources_path, provider='company_C',
|
||||
namespace='namespace-c')
|
||||
|
||||
cls.vnf_pkg_c_1, cls.vnfd_id_c_1 = cls.create_vnf_package(
|
||||
test_change_vnf_pkg_with_deployment_path, provider='company_C',
|
||||
namespace='namespace-c')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
super(VnflcmAPIsV2CNFBase, cls).tearDownClass()
|
||||
|
||||
cls.delete_vnf_package(cls.vnf_pkg_a)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_a_1)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_b)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_b_1)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_c)
|
||||
cls.delete_vnf_package(cls.vnf_pkg_c_1)
|
||||
|
||||
@classmethod
|
||||
def get_vim_info(cls, vim_conf='local-vim.yaml'):
|
||||
vim_params = yaml.safe_load(base_utils.read_file(vim_conf))
|
||||
vim_params['auth_url'] += '/v3'
|
||||
|
||||
vim_info = objects.VimConnectionInfo(
|
||||
interfaceInfo={'endpoint': vim_params['auth_url']},
|
||||
accessInfo={
|
||||
'region': 'RegionOne',
|
||||
'project': vim_params['project_name'],
|
||||
'username': vim_params['username'],
|
||||
'password': vim_params['password'],
|
||||
'userDomain': vim_params['user_domain_name'],
|
||||
'projectDomain': vim_params['project_domain_name']
|
||||
}
|
||||
)
|
||||
|
||||
return vim_info
|
||||
|
||||
@classmethod
|
||||
def get_local_tacker_http_client(cls, username):
|
||||
vim_info = cls.get_vim_info(vim_conf=cls.local_vim_conf_file)
|
||||
|
||||
auth = http_client.KeystonePasswordAuthHandle(
|
||||
auth_url=vim_info.interfaceInfo['endpoint'],
|
||||
username=username,
|
||||
password='devstack',
|
||||
project_name=vim_info.accessInfo['project'],
|
||||
user_domain_name=vim_info.accessInfo['userDomain'],
|
||||
project_domain_name=vim_info.accessInfo['projectDomain']
|
||||
)
|
||||
|
||||
return http_client.HttpClient(auth)
|
||||
|
||||
def _step_lcm_create(self, username, vnfd_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
|
||||
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.test_instantiate_cnf_resources_create(
|
||||
vnfd_id)
|
||||
resp, body = self.create_vnf_instance(create_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 201:
|
||||
self.check_resp_headers_in_create(resp)
|
||||
self.check_resp_body(body, expected_inst_attrs)
|
||||
inst_id = body['id']
|
||||
return inst_id
|
||||
else:
|
||||
return None
|
||||
|
||||
def _sample_instantiate(self, auth_url, bearer_token, ssl_ca_cert=None,
|
||||
namespace='default', area=None, vim_id=None):
|
||||
vim_id_1 = uuidutils.generate_uuid()
|
||||
vim_id_2 = uuidutils.generate_uuid()
|
||||
vim_1 = {
|
||||
"vimId": vim_id_1,
|
||||
"vimType": "kubernetes",
|
||||
"interfaceInfo": {"endpoint": auth_url},
|
||||
"accessInfo": {
|
||||
"bearer_token": bearer_token,
|
||||
},
|
||||
"extra": {"dummy-key": "dummy-val"}
|
||||
}
|
||||
vim_2 = {
|
||||
"vimId": vim_id_2,
|
||||
"vimType": "kubernetes",
|
||||
"interfaceInfo": {"endpoint": auth_url},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"password": "dummy_password",
|
||||
},
|
||||
"extra": {"dummy-key": "dummy-val"}
|
||||
}
|
||||
|
||||
if ssl_ca_cert:
|
||||
vim_1["interfaceInfo"]["ssl_ca_cert"] = ssl_ca_cert
|
||||
vim_2["interfaceInfo"]["ssl_ca_cert"] = ssl_ca_cert
|
||||
|
||||
if area:
|
||||
vim_1.update({'extra': {'area': area}})
|
||||
vim_2.update({'extra': {'area': area}})
|
||||
|
||||
if vim_id:
|
||||
vim_1 = {
|
||||
"vimId": vim_id,
|
||||
"vimType": "kubernetes"
|
||||
}
|
||||
vim_2 = {
|
||||
"vimId": vim_id,
|
||||
"vimType": "kubernetes"
|
||||
}
|
||||
|
||||
return {
|
||||
"flavourId": "simple",
|
||||
"vimConnectionInfo": {
|
||||
"vim1": vim_1,
|
||||
"vim2": vim_2
|
||||
},
|
||||
"additionalParams": {
|
||||
"lcm-kubernetes-def-files": [
|
||||
"Files/kubernetes/namespace.yaml",
|
||||
"Files/kubernetes/deployment.yaml",
|
||||
],
|
||||
"namespace": namespace
|
||||
}
|
||||
}
|
||||
|
||||
def _step_lcm_instantiate(self, username, inst_id, namespace,
|
||||
expected_status_code, area=None, vim_id=None):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
# Instantiate a VNF instance
|
||||
instantiate_req = self._sample_instantiate(
|
||||
self.auth_url, self.bearer_token, ssl_ca_cert=self.ssl_ca_cert,
|
||||
namespace=namespace, area=area, vim_id=vim_id
|
||||
)
|
||||
resp, body = self.instantiate_vnf_instance(inst_id, instantiate_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def _step_lcm_show(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
def _step_lcm_list(self, username, expected_inst_list):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
path = "/vnflcm/v2/vnf_instances"
|
||||
resp, vnf_instances = self.tacker_client.do_request(
|
||||
path, "GET", version="2.0.0")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
inst_ids = set([inst.get('id') for inst in vnf_instances])
|
||||
for inst_id in expected_inst_list:
|
||||
self.assertIn(inst_id, inst_ids)
|
||||
|
||||
def _step_lcm_scale_out(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
scale_out_req = {
|
||||
"type": "SCALE_OUT",
|
||||
"aspectId": "vdu2_aspect",
|
||||
"numberOfSteps": 1
|
||||
}
|
||||
resp, body = self.scale_vnf_instance(inst_id, scale_out_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def change_ext_conn_max(self, net_ids, subnets, auth_url, area):
|
||||
vim_id_1 = uuidutils.generate_uuid()
|
||||
vim_id_2 = uuidutils.generate_uuid()
|
||||
|
||||
ext_vl_1 = {
|
||||
"id": uuidutils.generate_uuid(),
|
||||
"vimConnectionId": vim_id_1,
|
||||
"resourceProviderId": uuidutils.generate_uuid(),
|
||||
"resourceId": net_ids['ft-net1'],
|
||||
"extCps": [
|
||||
{
|
||||
"cpdId": "VDU1_CP1",
|
||||
"cpConfig": {
|
||||
"VDU1_CP1": {
|
||||
"cpProtocolData": [{
|
||||
"layerProtocol": "IP_OVER_ETHERNET",
|
||||
"ipOverEthernet": {
|
||||
# "macAddress": omitted,
|
||||
# "segmentationId": omitted,
|
||||
"ipAddresses": [{
|
||||
"type": "IPV4",
|
||||
# "fixedAddresses": omitted,
|
||||
"numDynamicAddresses": 1,
|
||||
# "addressRange": omitted,
|
||||
"subnetId": subnets[
|
||||
'ft-ipv4-subnet1']}]
|
||||
}
|
||||
}]}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cpdId": "VDU2_CP2",
|
||||
"cpConfig": {
|
||||
"VDU2_CP2": {
|
||||
"cpProtocolData": [{
|
||||
"layerProtocol": "IP_OVER_ETHERNET",
|
||||
"ipOverEthernet": {
|
||||
# "macAddress": omitted,
|
||||
# "segmentationId": omitted,
|
||||
"ipAddresses": [{
|
||||
"type": "IPV4",
|
||||
"fixedAddresses": [
|
||||
"22.22.22.101"
|
||||
],
|
||||
# "numDynamicAddresses": omitted
|
||||
# "addressRange": omitted,
|
||||
"subnetId": subnets['ft-ipv4-subnet1']
|
||||
}, {
|
||||
"type": "IPV6",
|
||||
# "fixedAddresses": omitted,
|
||||
# "numDynamicAddresses": omitted,
|
||||
"numDynamicAddresses": 1,
|
||||
# "addressRange": omitted,
|
||||
"subnetId": subnets['ft-ipv6-subnet1']
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}}
|
||||
}
|
||||
]
|
||||
}
|
||||
vim_1 = {
|
||||
"vimId": vim_id_1,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {"endpoint": auth_url},
|
||||
"accessInfo": {
|
||||
"username": "nfv_user",
|
||||
"region": "RegionOne",
|
||||
"password": "devstack",
|
||||
"project": "nfv",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {"area": area}
|
||||
}
|
||||
vim_2 = {
|
||||
"vimId": vim_id_2,
|
||||
"vimType": "ETSINFV.OPENSTACK_KEYSTONE.V_3",
|
||||
"interfaceInfo": {"endpoint": auth_url},
|
||||
"accessInfo": {
|
||||
"username": "dummy_user",
|
||||
"region": "RegionOne",
|
||||
"password": "dummy_password",
|
||||
"project": "dummy_project",
|
||||
"projectDomain": "Default",
|
||||
"userDomain": "Default"
|
||||
},
|
||||
"extra": {"area": area}
|
||||
}
|
||||
|
||||
return {
|
||||
"extVirtualLinks": [
|
||||
ext_vl_1
|
||||
],
|
||||
"vimConnectionInfo": {
|
||||
"vim1": vim_1,
|
||||
"vim2": vim_2
|
||||
},
|
||||
"additionalParams": {"dummy-key": "dummy-val"}
|
||||
}
|
||||
|
||||
def _step_lcm_change_vnfpkg(self, username, inst_id, new_vnfd_id,
|
||||
expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
change_vnfpkg_req = paramgen.change_vnfpkg(new_vnfd_id)
|
||||
resp, body = self.change_vnfpkg(inst_id, change_vnfpkg_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# wait a bit because there is a bit time lag between lcmocc DB
|
||||
# update and change_vnfpkg completion.
|
||||
time.sleep(3)
|
||||
|
||||
def _step_lcm_update(self, username, inst_id,
|
||||
expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
update_req = {
|
||||
"vnfInstanceName": "modify_{}".format(inst_id)
|
||||
}
|
||||
path = f"/vnflcm/v2/vnf_instances/{inst_id}"
|
||||
resp, body = self.tacker_client.do_request(
|
||||
path, "PATCH", body=update_req, version="2.0.0")
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def _step_lcm_scale_in(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
scale_in_req = {
|
||||
"type": "SCALE_IN",
|
||||
"aspectId": "vdu2_aspect",
|
||||
"numberOfSteps": 1
|
||||
}
|
||||
resp, body = self.scale_vnf_instance(inst_id, scale_in_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def _step_lcm_heal(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user('user_admin')
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.check_resp_headers_in_get(resp)
|
||||
|
||||
# check vnfc_resource_info
|
||||
vnfc_infos = body['instantiatedVnfInfo']['vnfcInfo']
|
||||
vdu2_ids = [vnfc_info['id'] for vnfc_info in vnfc_infos
|
||||
if vnfc_info['vduId'] == 'VDU2']
|
||||
target = [vdu2_ids[0]]
|
||||
|
||||
heal_req = paramgen.max_sample_heal(target)
|
||||
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
|
||||
resp, body = self.heal_vnf_instance(inst_id, heal_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
def _step_lcm_terminate(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
terminate_req = paramgen.max_sample_terminate()
|
||||
resp, body = self.terminate_vnf_instance(inst_id, terminate_req)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 202:
|
||||
self.check_resp_headers_in_operation_task(resp)
|
||||
|
||||
lcmocc_id = os.path.basename(resp.headers['Location'])
|
||||
self.wait_lcmocc_complete(lcmocc_id)
|
||||
|
||||
# wait a bit because there is a bit time lag between lcmocc DB
|
||||
# update and terminate completion.
|
||||
time.sleep(3)
|
||||
|
||||
def _step_lcm_delete(self, username, inst_id, expected_status_code):
|
||||
self.tacker_client = self.get_tk_http_client_by_user(username)
|
||||
# Delete a VNF instance
|
||||
resp, body = self.delete_vnf_instance(inst_id)
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == 204:
|
||||
# check deletion of VNF instance
|
||||
resp, body = self.show_vnf_instance(inst_id)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
def vnflcm_apis_v2_cnf_test_before_instantiate(self):
|
||||
|
||||
# step 1 LCM-CreateV2, Resource Group A / User Group A
|
||||
inst_id_a = self._step_lcm_create('user_a', self.vnfd_id_a, 201)
|
||||
|
||||
# step 2 LCM-CreateV2, Resource Group B / User Group A
|
||||
self._step_lcm_create('user_a', self.vnfd_id_b, 403)
|
||||
|
||||
# step 3 LCM-CreateV2, Resource Group B / User Group all
|
||||
inst_id_b = self._step_lcm_create('user_all', self.vnfd_id_b, 201)
|
||||
|
||||
# step 4 LCM-ShowV2, Resource Group A / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_a, 200)
|
||||
|
||||
# step 5 LCM-ShowV2, Resource Group A / User Group A-1
|
||||
self._step_lcm_show('user_a_1', inst_id_a, 200)
|
||||
|
||||
# step 6 LCM-ShowV2, Resource Group B / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_b, 403)
|
||||
|
||||
# step 7 LCM-ShowV2, Resource Group B / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_b, 200)
|
||||
|
||||
# step 8 LCM-ListV2, Resource Group A / User Group A
|
||||
self._step_lcm_list('user_a', [inst_id_a])
|
||||
|
||||
# step 9 LCM-ListV2, Resource Group - / User Group A-1
|
||||
self._step_lcm_list('user_a_1', [inst_id_a])
|
||||
|
||||
# step 10 LCM-ListV2, Resource Group - / User Group B
|
||||
self._step_lcm_list('user_b', [inst_id_b])
|
||||
|
||||
# step 11 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [inst_id_a, inst_id_b])
|
||||
|
||||
return inst_id_a, inst_id_b
|
||||
|
||||
def vnflcm_apis_v2_cnf_test_after_instantiate(self, inst_id_a, inst_id_b):
|
||||
|
||||
# step 15 LCM-ShowV2, Resource Group A / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_a, 200)
|
||||
|
||||
# step 16 LCM-Show, Resource Group A / User Group A-1
|
||||
self._step_lcm_show('user_a_1', inst_id_a, 403)
|
||||
|
||||
# step 17 LCM-ShowV2, Resource Group B / User Group A
|
||||
self._step_lcm_show('user_a', inst_id_b, 403)
|
||||
|
||||
# step 18 LCM-ShowV2, Resource Group B / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_b, 200)
|
||||
|
||||
# step 19 LCM-ListV2, Resource Group - / User Group A
|
||||
self._step_lcm_list('user_a', [inst_id_a])
|
||||
|
||||
# step 20 LCM-ListV2, Resource Group - / User Group A-1
|
||||
self._step_lcm_list('user_a_1', [])
|
||||
|
||||
# step 21 LCM-ListV2, Resource Group - / User Group B
|
||||
self._step_lcm_list('user_b', [inst_id_b])
|
||||
|
||||
# step 22 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [inst_id_a, inst_id_b])
|
||||
|
||||
# step 23 LCM-ScaleV2(out), Resource Group A / User Group A
|
||||
self._step_lcm_scale_out('user_a', inst_id_a, 202)
|
||||
|
||||
# step 24 LCM-ScaleV2(out), Resource Group B / User Group A
|
||||
self._step_lcm_scale_out('user_a', inst_id_b, 403)
|
||||
|
||||
# step 25 LCM-ScaleV2(out), Resource Group B / User Group all
|
||||
self._step_lcm_scale_out('user_all', inst_id_b, 202)
|
||||
|
||||
# step 26 LCM-ScaleV2(in), Resource Group A / User Group A
|
||||
self._step_lcm_scale_in('user_a', inst_id_a, 202)
|
||||
|
||||
# step 27 LCM-ScaleV2(in), Resource Group B / User Group A
|
||||
self._step_lcm_scale_in('user_a', inst_id_b, 403)
|
||||
|
||||
# step 28 LCM-ScaleV2(in), Resource Group B / User Group all
|
||||
self._step_lcm_scale_in('user_all', inst_id_b, 202)
|
||||
|
||||
# step 29 LCM-HealV2, Resource Group A / User Group A
|
||||
self._step_lcm_heal('user_a', inst_id_a, 202)
|
||||
|
||||
# step 30 LCM-HealV2, Resource Group B / User Group A
|
||||
self._step_lcm_heal('user_a', inst_id_b, 403)
|
||||
|
||||
# step 31 LCM-HealV2, Resource Group B / User Group all
|
||||
self._step_lcm_heal('user_all', inst_id_b, 202)
|
||||
|
||||
# step 32 LCM-ModifyV2, Resource Group A / User Group A
|
||||
self._step_lcm_update('user_a', inst_id_a, 202)
|
||||
|
||||
# step 33 LCM-ModifyV2, Resource Group b / User Group A
|
||||
self._step_lcm_update('user_a', inst_id_b, 403)
|
||||
|
||||
# step 34 LCM-ModifyV2, Resource Group B / User Group all
|
||||
self._step_lcm_update('user_all', inst_id_b, 202)
|
||||
|
||||
# NOTE: CNF has no LCM-Change-Connectivity
|
||||
# step 34 LCM-Change-ConnectivityV2, Resource Group A / User Group A
|
||||
# step 35 LCM-Change-ConnectivityV2, Resource Group b / User Group A
|
||||
# step 36 LCM-Change-ConnectivityV2, Resource Group B / User Group all
|
||||
|
||||
# step 38 LCM-Change-VnfPkgV2, Resource Group A / User Group A
|
||||
self._step_lcm_change_vnfpkg(
|
||||
'user_a', inst_id_a, self.vnfd_id_a_1, 202)
|
||||
|
||||
# step 39 LCM-Change-VnfPkgV2, Resource Group B / User Group A
|
||||
self._step_lcm_change_vnfpkg(
|
||||
'user_a', inst_id_b, self.vnfd_id_b_1, 403)
|
||||
|
||||
# step 40 LCM-Change-VnfPkgV2, Resource Group B / User Group all
|
||||
self._step_lcm_change_vnfpkg(
|
||||
'user_all', inst_id_b, self.vnfd_id_b_1, 202)
|
||||
|
||||
# step 41 LCM-TerminateV2, Resource Group A / User Group A
|
||||
self._step_lcm_terminate('user_a', inst_id_a, 202)
|
||||
|
||||
# step 42 LCM-TerminateV2, Resource Group B / User Group A
|
||||
self._step_lcm_terminate('user_a', inst_id_b, 403)
|
||||
|
||||
# step 43 LCM-TerminateV2, Resource Group B / User Group all
|
||||
self._step_lcm_terminate('user_all', inst_id_b, 202)
|
||||
|
||||
# step 44 LCM-DeleteV2, Resource Group A / User Group A
|
||||
self._step_lcm_delete('user_a', inst_id_a, 204)
|
||||
|
||||
# step 45 LCM-DeleteV2, Resource Group B / User Group A
|
||||
self._step_lcm_delete('user_a', inst_id_b, 403)
|
||||
|
||||
# step 46 LCM-DeleteV2, Resource Group B / User Group all
|
||||
self._step_lcm_delete('user_all', inst_id_b, 204)
|
||||
|
||||
|
||||
class VnflcmAPIsV2VNFInstantiateWithArea(VnflcmAPIsV2CNFBase):
|
||||
|
||||
def test_vnflcm_apis_v2_cnf_without_area_in_vim_conn_info(self):
|
||||
|
||||
inst_id_a, inst_id_b = (
|
||||
self.vnflcm_apis_v2_cnf_test_before_instantiate())
|
||||
|
||||
# step 12 LCM-InstantiateV2, Resource Group A / User Group A
|
||||
self._step_lcm_instantiate(
|
||||
'user_a', inst_id_a, 'namespace-a', 202, area='area_A@region_A')
|
||||
|
||||
# step 13 LCM-InstantiateV2, Resource Group B / User Group A
|
||||
self._step_lcm_instantiate(
|
||||
'user_a', inst_id_b, 'namespace-b', 403, area='area_B@region_B')
|
||||
|
||||
# step 14 LCM-InstantiateV2, Resource Group B / User Group all
|
||||
self._step_lcm_instantiate(
|
||||
'user_all', inst_id_b, 'namespace-b', 202, area='area_B@region_B')
|
||||
|
||||
self.vnflcm_apis_v2_cnf_test_after_instantiate(inst_id_a, inst_id_b)
|
||||
|
||||
|
||||
class VnflcmAPIsV2CNFInstantiateWithoutArea(VnflcmAPIsV2CNFBase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
vim_type = 'kubernetes'
|
||||
|
||||
local_k8s_vim = 'local-k8s-vim.yaml'
|
||||
|
||||
cls.vim_a = cls._step_vim_register(
|
||||
'user_a', vim_type, local_k8s_vim, 'vim_a', 'area_A@region_A')
|
||||
|
||||
cls.vim_a_1 = cls._step_vim_register(
|
||||
'user_a', vim_type, local_k8s_vim, 'vim_a_1', 'area_A@region_A')
|
||||
|
||||
cls.vim_b = cls._step_vim_register(
|
||||
'user_b', vim_type, local_k8s_vim, 'vim_b', 'area_B@region_B')
|
||||
|
||||
cls.vim_b_1 = cls._step_vim_register(
|
||||
'user_b', vim_type, local_k8s_vim, 'vim_b_1', 'area_B@region_B')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
||||
cls._step_vim_delete('user_a', cls.vim_a)
|
||||
cls._step_vim_delete('user_a', cls.vim_a_1)
|
||||
cls._step_vim_delete('user_b', cls.vim_b)
|
||||
cls._step_vim_delete('user_b', cls.vim_b_1)
|
||||
|
||||
super().tearDownClass()
|
||||
|
||||
def test_vnflcm_apis_v2_cnf_with_area_in_vim_conn_info(self):
|
||||
inst_id_a, inst_id_b = (
|
||||
self.vnflcm_apis_v2_cnf_test_before_instantiate())
|
||||
|
||||
# step 12 LCM-InstantiateV2, Resource Group A / User Group A
|
||||
self._step_lcm_instantiate(
|
||||
'user_a', inst_id_a, 'namespace-a', 202, vim_id=self.vim_a['id'])
|
||||
|
||||
# step 13 LCM-InstantiateV2, Resource Group B / User Group A
|
||||
self._step_lcm_instantiate(
|
||||
'user_a', inst_id_b, 'namespace-b', 403, vim_id=self.vim_b['id'])
|
||||
|
||||
# step 14 LCM-InstantiateV2, Resource Group B / User Group all
|
||||
self._step_lcm_instantiate(
|
||||
'user_all', inst_id_b, 'namespace-b', 202, vim_id=self.vim_b['id'])
|
||||
|
||||
self.vnflcm_apis_v2_cnf_test_after_instantiate(inst_id_a, inst_id_b)
|
||||
|
||||
|
||||
class VnflcmAPIsV2CNFInstanceWithoutArea(VnflcmAPIsV2CNFBase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
vim_type = 'kubernetes'
|
||||
|
||||
local_k8s_vim = 'local-k8s-vim.yaml'
|
||||
|
||||
cls.vim_c = cls._step_vim_register(
|
||||
'user_c', vim_type, local_k8s_vim, 'vim_c', None)
|
||||
|
||||
cls.vim_c_1 = cls._step_vim_register(
|
||||
'user_c', vim_type, local_k8s_vim, 'vim_c_1', None)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
|
||||
cls._step_vim_delete('user_admin', cls.vim_c)
|
||||
cls._step_vim_delete('user_admin', cls.vim_c_1)
|
||||
|
||||
super().tearDownClass()
|
||||
|
||||
def test_vnflcm_apis_v2_cnf_instance_without_area(self):
|
||||
|
||||
# step 1 LCM-CreateV2, Resource Group C / User Group C
|
||||
inst_id_c = self._step_lcm_create('user_c', self.vnfd_id_c, 201)
|
||||
|
||||
# step 2 LCM-ShowV2, Resource Group C / User Group C
|
||||
self._step_lcm_show('user_c', inst_id_c, 200)
|
||||
|
||||
# step 3 LCM-ShowV2, Resource Group C / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_c, 200)
|
||||
|
||||
# step 4 LCM-ShowV2, Resource Group C / User Group admin
|
||||
self._step_lcm_show('user_admin', inst_id_c, 200)
|
||||
|
||||
# step 5 LCM-ListV2, Resource Group - / User Group C
|
||||
self._step_lcm_list('user_c', [inst_id_c])
|
||||
|
||||
# step 6 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [inst_id_c])
|
||||
|
||||
# step 7 LCM-ListV2, Resource Group - / User Group admin
|
||||
self._step_lcm_list('user_admin', [inst_id_c])
|
||||
|
||||
# step 8 LCM-InstantiateV2, Resource Group C / User Group C
|
||||
self._step_lcm_instantiate('user_c', inst_id_c, 'namespace-c', 202,
|
||||
vim_id=self.vim_c['id'])
|
||||
|
||||
# step 9 LCM-ShowV2, Resource Group C / User Group C
|
||||
self._step_lcm_show('user_c', inst_id_c, 403)
|
||||
|
||||
# step 10 LCM-ShowV2, Resource Group C / User Group all
|
||||
self._step_lcm_show('user_all', inst_id_c, 403)
|
||||
|
||||
# step 11 LCM-ShowV2, Resource Group C / User Group admin
|
||||
self._step_lcm_show('user_admin', inst_id_c, 200)
|
||||
|
||||
# step 12 LCM-ListV2, Resource Group - / User Group C
|
||||
self._step_lcm_list('user_c', [])
|
||||
|
||||
# step 13 LCM-ListV2, Resource Group - / User Group all
|
||||
self._step_lcm_list('user_all', [])
|
||||
|
||||
# step 14 LCM-ListV2, Resource Group - / User Group admin
|
||||
self._step_lcm_list('user_admin', [inst_id_c])
|
||||
|
||||
# step 15 LCM-ScaleV2(out), Resource Group C / User Group C
|
||||
self._step_lcm_scale_out('user_c', inst_id_c, 403)
|
||||
|
||||
# step 16 LCM-ScaleV2(out), Resource Group C / User Group all
|
||||
self._step_lcm_scale_out('user_all', inst_id_c, 403)
|
||||
|
||||
# step 17 LCM-ScaleV2(out), Resource Group C / User Group admin
|
||||
self._step_lcm_scale_out('user_admin', inst_id_c, 202)
|
||||
|
||||
# step 18 LCM-ScaleV2(in), Resource Group C / User Group C
|
||||
self._step_lcm_scale_in('user_c', inst_id_c, 403)
|
||||
|
||||
# step 19 LCM-ScaleV2(in), Resource Group C / User Group A
|
||||
self._step_lcm_scale_in('user_all', inst_id_c, 403)
|
||||
|
||||
# step 20 LCM-ScaleV2(in), Resource Group C / User Group all
|
||||
self._step_lcm_scale_in('user_admin', inst_id_c, 202)
|
||||
|
||||
# step 21 LCM-HealV2, Resource Group C / User Group C
|
||||
self._step_lcm_heal('user_c', inst_id_c, 403)
|
||||
|
||||
# step 22 LCM-HealV2, Resource Group C / User Group A
|
||||
self._step_lcm_heal('user_all', inst_id_c, 403)
|
||||
|
||||
# step 23 LCM-HealV2, Resource Group C / User Group all
|
||||
self._step_lcm_heal('user_admin', inst_id_c, 202)
|
||||
|
||||
# step 24 LCM-ModifyV2, Resource Group C / User Group C
|
||||
self._step_lcm_update('user_c', inst_id_c, 403)
|
||||
|
||||
# step 25 LCM-ModifyV2, Resource Group C / User Group A
|
||||
self._step_lcm_update('user_all', inst_id_c, 403)
|
||||
|
||||
# step 26 LCM-ModifyV2, Resource Group C / User Group all
|
||||
self._step_lcm_update('user_admin', inst_id_c, 202)
|
||||
|
||||
# NOTE: CNF has no LCM-Change-Connectivity
|
||||
# step 27 LCM-Change-ConnectivityV2, Resource Group C / User Group C
|
||||
# step 28 LCM-Change-ConnectivityV2, Resource Group C / User Group all
|
||||
# step 29 LCM-Change-ConnectivityV2,
|
||||
# Resource Group C / User Group admin
|
||||
|
||||
# step 30 LCM-Change-VnfPkgV2, Resource Group C / User Group C
|
||||
self._step_lcm_change_vnfpkg(
|
||||
'user_c', inst_id_c, self.vnfd_id_c_1, 403)
|
||||
|
||||
# step 31 LCM-Change-VnfPkgV2, Resource Group C / User Group A
|
||||
self._step_lcm_change_vnfpkg(
|
||||
'user_all', inst_id_c, self.vnfd_id_c_1, 403)
|
||||
|
||||
# step 32 LCM-Change-VnfPkgV2, Resource Group C / User Group all
|
||||
self._step_lcm_change_vnfpkg(
|
||||
'user_admin', inst_id_c, self.vnfd_id_c_1, 202)
|
||||
|
||||
# step 33 LCM-TerminateV2, Resource Group C / User Group C
|
||||
self._step_lcm_terminate('user_c', inst_id_c, 403)
|
||||
|
||||
# step 34 LCM-TerminateV2, Resource Group C / User Group A
|
||||
self._step_lcm_terminate('user_all', inst_id_c, 403)
|
||||
|
||||
# step 35 LCM-TerminateV2, Resource Group C / User Group all
|
||||
self._step_lcm_terminate('user_admin', inst_id_c, 202)
|
||||
|
||||
# step 36 LCM-DeleteV2, Resource Group C / User Group C
|
||||
self._step_lcm_delete('user_c', inst_id_c, 204)
|
@ -0,0 +1,25 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from tacker.tests.functional.sol_enhanced_policy.base import (
|
||||
VimAPIsTest)
|
||||
|
||||
|
||||
class VimAPIsOpenstackTest(VimAPIsTest):
|
||||
|
||||
def test_vim_apis_vim_with_area_kubernetes(self):
|
||||
self._test_vim_apis_enhanced_policy('kubernetes', 'local-k8s-vim.yaml')
|
||||
|
||||
def test_vim_apis_vim_without_area_kubernetes(self):
|
||||
self._test_vim_apis_vim_without_area_attribute(
|
||||
'kubernetes', 'local-k8s-vim.yaml')
|
@ -136,11 +136,13 @@ class BaseVnfLcmKubernetesV2Test(base.BaseTestCase):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def create_vnf_package(cls, sample_path, user_data={}, image_path=None):
|
||||
def create_vnf_package(cls, sample_path, user_data={}, image_path=None,
|
||||
provider=None, namespace=None):
|
||||
vnfd_id = uuidutils.generate_uuid()
|
||||
tmp_dir = tempfile.mkdtemp()
|
||||
|
||||
utils.make_zip(sample_path, tmp_dir, vnfd_id, image_path)
|
||||
utils.make_zip(sample_path, tmp_dir, vnfd_id, image_path,
|
||||
provider=provider, namespace=namespace)
|
||||
|
||||
zip_file_name = os.path.basename(os.path.abspath(sample_path)) + ".zip"
|
||||
zip_file_path = os.path.join(tmp_dir, zip_file_name)
|
||||
|
@ -109,12 +109,13 @@ class BaseSolV2Test(base.BaseTestCase):
|
||||
|
||||
@classmethod
|
||||
def create_vnf_package(cls, sample_path, user_data={},
|
||||
image_path=None, nfvo=False, userdata_path=None):
|
||||
image_path=None, nfvo=False, userdata_path=None,
|
||||
provider=None):
|
||||
vnfd_id = uuidutils.generate_uuid()
|
||||
tmp_dir = tempfile.mkdtemp()
|
||||
|
||||
utils.make_zip(sample_path, tmp_dir, vnfd_id, image_path,
|
||||
userdata_path)
|
||||
userdata_path, provider)
|
||||
|
||||
zip_file_name = os.path.basename(os.path.abspath(sample_path)) + ".zip"
|
||||
zip_file_path = os.path.join(tmp_dir, zip_file_name)
|
||||
|
@ -13,10 +13,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import yaml
|
||||
|
||||
|
||||
# vnfdId of samples must be this.
|
||||
@ -24,7 +27,7 @@ SAMPLE_VNFD_ID = "b1bb0ce7-ebca-4fa7-95ed-4840d7000000"
|
||||
|
||||
|
||||
def make_zip(sample_dir, tmp_dir, vnfd_id, image_path=None,
|
||||
userdata_path=None):
|
||||
userdata_path=None, provider=None, namespace=None):
|
||||
# NOTE: '.zip' will be added by shutil.make_archive
|
||||
zip_file_name = os.path.basename(os.path.abspath(sample_dir))
|
||||
zip_file_path = os.path.join(tmp_dir, zip_file_name)
|
||||
@ -60,9 +63,83 @@ def make_zip(sample_dir, tmp_dir, vnfd_id, image_path=None,
|
||||
os.makedirs(file_path)
|
||||
shutil.copy(userdata_path, file_path)
|
||||
|
||||
if provider:
|
||||
# replace provider
|
||||
def_path = os.path.join(tmp_contents, "Definitions")
|
||||
for entry in os.listdir(def_path):
|
||||
entry_path = os.path.join(def_path, entry)
|
||||
with open(entry_path, 'r') as f:
|
||||
data = yaml.safe_load(f)
|
||||
_update_provider_in_yaml(data, provider)
|
||||
with open(entry_path, 'w') as f:
|
||||
yaml.dump(data, f, default_flow_style=False,
|
||||
allow_unicode=True)
|
||||
if namespace:
|
||||
file_path = os.path.join(
|
||||
tmp_contents, "Files", "kubernetes", "namespace.yaml")
|
||||
with open(file_path, 'r') as f:
|
||||
data = yaml.safe_load(f)
|
||||
data["metadata"]["name"] = namespace
|
||||
with open(file_path, 'w') as f:
|
||||
yaml.dump(data, f, default_flow_style=False,
|
||||
allow_unicode=True)
|
||||
with open(file_path, 'r') as f:
|
||||
content = f.read()
|
||||
hash_value = hashlib.sha256(content.encode()).hexdigest()
|
||||
tosca_file = os.path.join(tmp_contents, "TOSCA-Metadata", "TOSCA.meta")
|
||||
with open(tosca_file, 'rb') as f:
|
||||
artifacts_data = f.read()
|
||||
artifacts_data_split = re.split(b'\n\n+', artifacts_data)
|
||||
artifact_data_strs = []
|
||||
for data in artifacts_data_split:
|
||||
artifact_data_dict = yaml.safe_load(data)
|
||||
if re.findall(b'.?Algorithm:.?|.?Hash:.?', data):
|
||||
artifact_file = (artifact_data_dict['Source']
|
||||
if 'Source' in artifact_data_dict.keys()
|
||||
else artifact_data_dict['Name'])
|
||||
if artifact_file.endswith('namespace.yaml'):
|
||||
artifact_data_dict['Hash'] = hash_value
|
||||
if artifact_data_dict:
|
||||
artifact_data_strs.append(
|
||||
yaml.dump(
|
||||
artifact_data_dict,
|
||||
default_flow_style=False,
|
||||
allow_unicode=True))
|
||||
with open(tosca_file, 'w') as f:
|
||||
f.write('\n'.join(artifact_data_strs))
|
||||
|
||||
shutil.make_archive(zip_file_path, "zip", tmp_contents)
|
||||
|
||||
|
||||
def _update_provider_in_yaml(data, provider):
|
||||
try:
|
||||
prop = data['topology_template']['node_templates']['VNF'][
|
||||
'properties']
|
||||
if prop.get('provider', None):
|
||||
prop['provider'] = provider
|
||||
except KeyError:
|
||||
# Let's check for 'node_types'
|
||||
pass
|
||||
|
||||
if not data.get('node_types', None):
|
||||
return
|
||||
|
||||
for ntype in data['node_types'].values():
|
||||
if ntype['derived_from'] != 'tosca.nodes.nfv.VNF':
|
||||
continue
|
||||
try:
|
||||
desc_id = ntype['properties']['provider']
|
||||
if desc_id.get('constraints', None):
|
||||
for constraint in desc_id.get('constraints'):
|
||||
if constraint.get('valid_values', None):
|
||||
constraint['valid_values'] = [provider]
|
||||
if desc_id.get('default', None):
|
||||
desc_id['default'] = provider
|
||||
except KeyError:
|
||||
# Let's check next node_type
|
||||
pass
|
||||
|
||||
|
||||
def create_network(network):
|
||||
# assume OS_* environment variables are already set
|
||||
subprocess.run(
|
||||
|
@ -13,13 +13,18 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ddt
|
||||
from oslo_config import cfg
|
||||
from unittest import mock
|
||||
|
||||
from tacker import context
|
||||
from tacker.sol_refactored.api.policies.vnflcm_v2 import POLICY_NAME
|
||||
from tacker.sol_refactored.api import wsgi as sol_wsgi
|
||||
from tacker.sol_refactored.common import exceptions as sol_ex
|
||||
from tacker.tests.unit import base
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestWsgi(base.TestCase):
|
||||
|
||||
def test_response_too_big(self):
|
||||
@ -46,3 +51,88 @@ class TestWsgi(base.TestCase):
|
||||
request.headers = {}
|
||||
self.assertRaises(sol_ex.APIVersionMissing,
|
||||
resource._check_api_version, request, 'action')
|
||||
|
||||
@mock.patch.object(context.Context, 'can')
|
||||
def test_enhanced_policy_action(self, mock_can):
|
||||
cfg.CONF.set_override(
|
||||
"enhanced_tacker_policy", True, group='oslo_policy')
|
||||
resource = sol_wsgi.SolResource(sol_wsgi.SolAPIController(),
|
||||
policy_name=POLICY_NAME)
|
||||
request = mock.Mock()
|
||||
request.context = context.Context()
|
||||
request.headers = {}
|
||||
enhanced_policy_actions = [
|
||||
'create',
|
||||
'index',
|
||||
'show',
|
||||
'delete',
|
||||
'update',
|
||||
'instantiate',
|
||||
'terminate',
|
||||
'scale',
|
||||
'heal',
|
||||
'change_ext_conn',
|
||||
'change_vnfpkg'
|
||||
]
|
||||
for action in enhanced_policy_actions:
|
||||
resource._check_policy(request, action)
|
||||
mock_can.assert_not_called()
|
||||
|
||||
@ddt.data('api_versions',
|
||||
'subscription_create',
|
||||
'subscription_list',
|
||||
'subscription_show',
|
||||
'subscription_delete',
|
||||
'lcm_op_occ_list',
|
||||
'lcm_op_occ_show',
|
||||
'lcm_op_occ_retry',
|
||||
'lcm_op_occ_rollback',
|
||||
'lcm_op_occ_fail',
|
||||
'lcm_op_occ_delete')
|
||||
@mock.patch.object(context.Context, 'can')
|
||||
def test_not_enhanced_policy_action(self, action, mock_can):
|
||||
cfg.CONF.set_override(
|
||||
"enhanced_tacker_policy", True, group='oslo_policy')
|
||||
resource = sol_wsgi.SolResource(sol_wsgi.SolAPIController(),
|
||||
policy_name=POLICY_NAME)
|
||||
request = mock.Mock()
|
||||
request.context = context.Context()
|
||||
request.headers = {}
|
||||
|
||||
resource._check_policy(request, action)
|
||||
mock_can.assert_called_once()
|
||||
|
||||
@ddt.data('create',
|
||||
'index',
|
||||
'show',
|
||||
'delete',
|
||||
'update',
|
||||
'instantiate',
|
||||
'terminate',
|
||||
'scale',
|
||||
'heal',
|
||||
'change_ext_conn',
|
||||
'change_vnfpkg',
|
||||
'api_versions',
|
||||
'subscription_create',
|
||||
'subscription_list',
|
||||
'subscription_show',
|
||||
'subscription_delete',
|
||||
'lcm_op_occ_list',
|
||||
'lcm_op_occ_show',
|
||||
'lcm_op_occ_retry',
|
||||
'lcm_op_occ_rollback',
|
||||
'lcm_op_occ_fail',
|
||||
'lcm_op_occ_delete')
|
||||
@mock.patch.object(context.Context, 'can')
|
||||
def test_enhanced_policy_is_false(self, action, mock_can):
|
||||
cfg.CONF.set_override(
|
||||
"enhanced_tacker_policy", False, group='oslo_policy')
|
||||
resource = sol_wsgi.SolResource(sol_wsgi.SolAPIController(),
|
||||
policy_name=POLICY_NAME)
|
||||
request = mock.Mock()
|
||||
request.context = context.Context()
|
||||
request.headers = {}
|
||||
|
||||
resource._check_policy(request, action)
|
||||
mock_can.assert_called_once()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
||||
|
||||
from copy import deepcopy
|
||||
import datetime
|
||||
from http import client as http_client
|
||||
import iso8601
|
||||
import json
|
||||
import os
|
||||
@ -32,6 +33,7 @@ from tacker.objects.instantiate_vnf_req import ExtVirtualLinkData
|
||||
from tacker.objects.instantiate_vnf_req import InstantiateVnfRequest
|
||||
from tacker.objects import scale_vnf_request
|
||||
from tacker.objects.vim_connection import VimConnectionInfo
|
||||
from tacker.policies import vnf_lcm as vnf_lcm_policies
|
||||
from tacker.tests import constants
|
||||
from tacker.tests import uuidsentinel
|
||||
from tacker import wsgi
|
||||
@ -106,9 +108,9 @@ def fake_vnf_package_vnfd_model_dict(**updates):
|
||||
return vnfd
|
||||
|
||||
|
||||
def return_vnf_package_vnfd():
|
||||
def return_vnf_package_vnfd(**updates):
|
||||
model_obj = models.VnfPackageVnfd()
|
||||
model_obj.update(fake_vnf_package_vnfd_model_dict())
|
||||
model_obj.update(fake_vnf_package_vnfd_model_dict(**updates))
|
||||
return model_obj
|
||||
|
||||
|
||||
@ -1904,3 +1906,510 @@ def fake_subscription_response(**updates):
|
||||
data = _subscription_links(data)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_test_data_policy_create():
|
||||
rules = {vnf_lcm_policies.VNFLCM % 'create': "vendor:%(vendor)s"}
|
||||
test_data = [
|
||||
# 'expected_status_code': http_client.OK
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.CREATED
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_all'],
|
||||
'expected_status_code': http_client.CREATED
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_B'},
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_provider_B'],
|
||||
'expected_status_code': http_client.CREATED
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_B'},
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_all'],
|
||||
'expected_status_code': http_client.CREATED
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_B'},
|
||||
'rules': {vnf_lcm_policies.VNFLCM % 'create': "@"},
|
||||
'roles': [],
|
||||
'expected_status_code': http_client.CREATED
|
||||
},
|
||||
# 'expected_status_code': http_client.FORBIDDEN
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': ''},
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_B'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_B'},
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': rules,
|
||||
'roles': [],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
]
|
||||
return test_data
|
||||
|
||||
|
||||
def make_vnf_instance(vim_type, vendor, area=None, tenant=None,
|
||||
instantiated_state=fields.VnfInstanceState.NOT_INSTANTIATED):
|
||||
vnf_instance_updates = make_vnf_instance_updates(
|
||||
vim_type, vendor, area=area, tenant=tenant)
|
||||
return return_vnf_instance(instantiated_state, **vnf_instance_updates)
|
||||
|
||||
|
||||
def get_test_data_policy_index():
|
||||
rule_area_vendor_tenant = {
|
||||
vnf_lcm_policies.VNFLCM % 'index':
|
||||
"area:%(area)s and vendor:%(vendor)s and "
|
||||
"tenant:%(tenant)s"
|
||||
}
|
||||
test_data = []
|
||||
inst_1 = make_vnf_instance('openstack', 'provider_A',
|
||||
area='area_A@region_A')
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_1],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_area_A@region_A', 'VENDOR_provider_A'],
|
||||
'expected_vnf_inst_ids': [inst_1.id]
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_1],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@region_A', 'VENDOR_provider_A'],
|
||||
'expected_vnf_inst_ids': [inst_1.id]
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_1],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@all', 'VENDOR_all'],
|
||||
'expected_vnf_inst_ids': [inst_1.id]
|
||||
})
|
||||
inst_2 = make_vnf_instance(
|
||||
'openstack', 'provider_A', area='area_A@region_A',
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED)
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_2],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_area_A@region_A', 'VENDOR_provider_A'],
|
||||
'expected_vnf_inst_ids': [inst_2.id]
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_2],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@region_A', 'VENDOR_provider_A'],
|
||||
'expected_vnf_inst_ids': [inst_2.id]
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_2],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@all', 'VENDOR_all'],
|
||||
'expected_vnf_inst_ids': [inst_2.id]
|
||||
})
|
||||
inst_3 = make_vnf_instance(
|
||||
'openstack', 'provider_A',
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED)
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_3],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_area_A@region_A', 'VENDOR_provider_A'],
|
||||
'expected_vnf_inst_ids': []
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_3],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@region_A', 'VENDOR_provider_A'],
|
||||
'expected_vnf_inst_ids': []
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_3],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@all', 'VENDOR_all'],
|
||||
'expected_vnf_inst_ids': []
|
||||
})
|
||||
inst_4 = make_vnf_instance(
|
||||
'kubernetes', 'provider_A',
|
||||
tenant='namespace_A',
|
||||
area='area_A@region_A',
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED)
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_4],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_area_A@region_A',
|
||||
'VENDOR_provider_A',
|
||||
'TENANT_namespace_A'
|
||||
],
|
||||
'expected_vnf_inst_ids': [inst_4.id]
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_4],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@region_A',
|
||||
'VENDOR_provider_A',
|
||||
'TENANT_namespace_A'
|
||||
],
|
||||
'expected_vnf_inst_ids': [inst_4.id]
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_list': [inst_4],
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@all',
|
||||
'VENDOR_all',
|
||||
'TENANT_namespace_A'
|
||||
],
|
||||
'expected_vnf_inst_ids': [inst_4.id]
|
||||
})
|
||||
|
||||
return test_data
|
||||
|
||||
|
||||
def get_test_data_policy_instantiate():
|
||||
test_data = [
|
||||
# 'expected_status_code': http_client.ACCEPTED
|
||||
{
|
||||
'vnf_instance_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': {
|
||||
"os_nfv_orchestration_api:vnf_instances:instantiate":
|
||||
"vendor:%(vendor)s"
|
||||
},
|
||||
'roles': ['VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.ACCEPTED
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': {
|
||||
"os_nfv_orchestration_api:vnf_instances:instantiate":
|
||||
"vendor:%(vendor)s"
|
||||
},
|
||||
'roles': ['VENDOR_all'],
|
||||
'expected_status_code': http_client.ACCEPTED
|
||||
},
|
||||
# 'expected_status_code': http_client.FORBIDDEN
|
||||
{
|
||||
'vnf_instance_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': {
|
||||
"os_nfv_orchestration_api:vnf_instances:instantiate":
|
||||
"vendor:%(vendor)s"
|
||||
},
|
||||
'roles': [],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': {'vnf_provider': 'provider_A'},
|
||||
'rules': {
|
||||
"os_nfv_orchestration_api:vnf_instances:instantiate":
|
||||
"vendor:%(vendor)s"
|
||||
},
|
||||
'roles': ['VENDOR_provider_B'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
]
|
||||
return test_data
|
||||
|
||||
|
||||
def get_test_data_policy_vnf_not_instantiated(
|
||||
action, success_status_code=http_client.OK):
|
||||
# openstack
|
||||
vim_connection_info = {
|
||||
"id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_type": 'openstack',
|
||||
"access_info": {"key1": 'value1', "key2": 'value2'},
|
||||
'extra': {'area': 'area_A@region_A'}
|
||||
}
|
||||
vim_connection_info_wrong_area = {
|
||||
"id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_id": 'f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
"vim_type": 'openstack',
|
||||
"access_info": {"key1": 'value1', "key2": 'value2'},
|
||||
'extra': {'area': 'area_A'}
|
||||
}
|
||||
vnf_instance_updates = {
|
||||
'vnf_provider': 'provider_A',
|
||||
'vim_connection_info': [vim_connection_info]
|
||||
}
|
||||
vnf_instance_updates_with_wrong_area = {
|
||||
'vnf_provider': 'provider_A',
|
||||
'vim_connection_info': [vim_connection_info_wrong_area]
|
||||
}
|
||||
rule_area_vendor_tenant = {
|
||||
vnf_lcm_policies.VNFLCM % action:
|
||||
"area:%(area)s and vendor:%(vendor)s and "
|
||||
"tenant:%(tenant)s"
|
||||
}
|
||||
rule_vendor = {
|
||||
vnf_lcm_policies.VNFLCM % action: "vendor:%(vendor)s"
|
||||
}
|
||||
test_data = [
|
||||
# 'expected_status_code': http_client.OK
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_area_A@region_A', 'VENDOR_provider_A'],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@all', 'VENDOR_all', 'TENANT_all'],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@region_A', 'VENDOR_all', 'TENANT_all'],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@region_A', 'AREA_all@all', 'VENDOR_all',
|
||||
'TENANT_all'],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_vendor,
|
||||
'roles': ['AREA_area_A@region_A', 'VENDOR_provider_A'],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_vendor,
|
||||
'roles': ['AREA_all@all', 'VENDOR_all', 'TENANT_all'],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_vendor,
|
||||
'roles': ['AREA_all@region_A', 'VENDOR_all', 'TENANT_all'],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
# 'expected_status_code': http_client.FORBIDDEN
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_area_A@region_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_area_A@region_A', 'VENDOR_provider_B'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_area_B@region_A', 'VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@region_B', 'VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all', 'VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@', 'VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnf_instance_updates': vnf_instance_updates_with_wrong_area,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': ['AREA_all@', 'VENDOR_provider_A'],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
]
|
||||
return test_data
|
||||
|
||||
|
||||
def make_vnf_instance_updates(
|
||||
vim_type, vendor, area=None, tenant=None):
|
||||
vim_connection_info = VimConnectionInfo(
|
||||
id='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
vim_id='f8c35bd0-4d67-4436-9f11-14b8a84c92aa',
|
||||
vim_type=vim_type,
|
||||
access_info={"key1": 'value1', "key2": 'value2'},
|
||||
)
|
||||
if area:
|
||||
vim_connection_info.extra = {'area': area}
|
||||
vnf_instance_updates = {
|
||||
'vnf_provider': vendor,
|
||||
'vim_connection_info': [vim_connection_info]
|
||||
}
|
||||
if tenant:
|
||||
vnf_instance_updates.update({'vnf_metadata': {"namespace": tenant}})
|
||||
|
||||
return vnf_instance_updates
|
||||
|
||||
|
||||
def get_test_data_policy_vnf_instantiated(action, success_status_code):
|
||||
rule_area_vendor_tenant = {
|
||||
vnf_lcm_policies.VNFLCM % action:
|
||||
"area:%(area)s and vendor:%(vendor)s and "
|
||||
"tenant:%(tenant)s"
|
||||
}
|
||||
|
||||
test_data = []
|
||||
# openstack
|
||||
vnf_instance_updates_1 = make_vnf_instance_updates(
|
||||
'openstack', 'provider_A', area='area_A@region_A')
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_area_A@region_A',
|
||||
'VENDOR_provider_A'
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@region_A',
|
||||
'VENDOR_provider_A'
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@all',
|
||||
'VENDOR_provider_A'
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@all',
|
||||
'VENDOR_all'
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@all',
|
||||
'VENDOR_all'
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
})
|
||||
# wrong area role
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_area_B@region_A',
|
||||
'VENDOR_provider_A'
|
||||
],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
})
|
||||
# wrong region role
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_area_A@region_B',
|
||||
'VENDOR_provider_A'
|
||||
],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
})
|
||||
# wrong vendor role
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_1,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_area_A@region_A',
|
||||
'VENDOR_provider_B'
|
||||
],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
})
|
||||
|
||||
vnf_instance_updates_2 = make_vnf_instance_updates(
|
||||
'openstack', 'provider_A')
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_2,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_area_A@region_A',
|
||||
'VENDOR_provider_A'
|
||||
],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
})
|
||||
|
||||
# kubernetes
|
||||
vnf_instance_updates_3 = make_vnf_instance_updates(
|
||||
'kubernetes', 'provider_A', area='area_A@region_A',
|
||||
tenant='namespace_A')
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_3,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_area_A@region_A',
|
||||
'VENDOR_provider_A',
|
||||
'TENANT_namespace_A'
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
})
|
||||
test_data.append({
|
||||
'vnf_instance_updates': vnf_instance_updates_3,
|
||||
'rules': rule_area_vendor_tenant,
|
||||
'roles': [
|
||||
'AREA_all@all',
|
||||
'VENDOR_all',
|
||||
'TENANT_all'
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
})
|
||||
|
||||
return test_data
|
||||
|
@ -26,6 +26,7 @@ import webob
|
||||
from webob import exc
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy as oslo_policy
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tacker.api.views import vnf_subscriptions as vnf_subscription_view
|
||||
@ -42,6 +43,7 @@ from tacker.manager import TackerManager
|
||||
from tacker import objects
|
||||
from tacker.objects import fields
|
||||
from tacker.objects import vnf_lcm_subscriptions as subscription_obj
|
||||
from tacker import policy
|
||||
from tacker.tests import constants
|
||||
from tacker.tests.unit import base
|
||||
from tacker.tests.unit.db import utils
|
||||
@ -261,11 +263,13 @@ class TestController(base.TestCase):
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.vnf_instance, '_vnf_instance_update')
|
||||
@mock.patch.object(objects.vnf_instance, '_vnf_instance_create')
|
||||
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd, 'get_by_id')
|
||||
def test_create_without_name_and_description(
|
||||
self, mock_get_by_id,
|
||||
mock_vnf_instance_create,
|
||||
mock_vnf_instance_update,
|
||||
mock_get_service_plugins,
|
||||
mock_package_save,
|
||||
mock_private_create_vnf,
|
||||
@ -285,6 +289,8 @@ class TestController(base.TestCase):
|
||||
|
||||
mock_vnf_instance_create.return_value =\
|
||||
fakes.return_vnf_instance_model(**updates)
|
||||
mock_vnf_instance_update.return_value = \
|
||||
fakes.return_vnf_instance_model(**updates)
|
||||
|
||||
body = {'vnfdId': uuidsentinel.vnfd_id,
|
||||
"vnfInstanceName": "SampleVnf",
|
||||
@ -396,17 +402,20 @@ class TestController(base.TestCase):
|
||||
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(sync_resource.SyncVnfPackage, 'create_package')
|
||||
@mock.patch.object(nfvo_client.VnfPackageRequest, "index")
|
||||
@mock.patch.object(objects.vnf_instance, '_vnf_instance_update')
|
||||
@mock.patch.object(objects.vnf_instance, '_vnf_instance_create')
|
||||
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd, 'get_by_id')
|
||||
def test_create_vnf_package_not_found(
|
||||
self, mock_get_by_id_package_vnfd,
|
||||
mock_vnf_instance_create,
|
||||
mock_vnf_instance_update,
|
||||
mock_index, mock_create_pkg,
|
||||
mock_get_service_plugins,
|
||||
mock_private_create_vnf,
|
||||
mock_vnf_package_get_by_id,
|
||||
mock_update_package_usage_state,
|
||||
mock_get_vim):
|
||||
mock_get_vim.return_value = self.vim_info
|
||||
mock_get_by_id_package_vnfd.side_effect =\
|
||||
exceptions.VnfPackageVnfdNotFound
|
||||
|
||||
@ -421,6 +430,8 @@ class TestController(base.TestCase):
|
||||
updates = {'vnfd_id': uuidsentinel.vnfd_id}
|
||||
mock_vnf_instance_create.return_value =\
|
||||
fakes.return_vnf_instance_model(**updates)
|
||||
mock_vnf_instance_update.return_value =\
|
||||
fakes.return_vnf_instance_model(**updates)
|
||||
|
||||
body = {'vnfdId': uuidsentinel.vnfd_id}
|
||||
req = fake_request.HTTPRequest.blank('/vnf_instances')
|
||||
@ -584,6 +595,9 @@ class TestController(base.TestCase):
|
||||
mock_get_vnf, mock_insta_notfi_process,
|
||||
mock_get_service_plugins):
|
||||
|
||||
vim = fakes.return_default_vim()
|
||||
vim.update({'extra': {"area": "area_A@region_A"}})
|
||||
mock_get_vim.return_value = vim
|
||||
mock_vnf_instance_get_by_id.return_value =\
|
||||
fakes.return_vnf_instance_model()
|
||||
mock_vnf_package_vnfd_get_by_id.return_value = \
|
||||
@ -595,7 +609,12 @@ class TestController(base.TestCase):
|
||||
vnf_id=mock_vnf_instance_get_by_id.return_value.id,
|
||||
status='INACTIVE')
|
||||
|
||||
body = {"flavourId": "simple"}
|
||||
body = {"flavourId": "simple",
|
||||
"vimConnectionInfo": [
|
||||
{"id": uuidsentinel.vim_connection_id,
|
||||
"vimId": uuidsentinel.vim_id,
|
||||
"vimType": 'openstack'}
|
||||
]}
|
||||
body.update({"additionalParams": {"foo_number": 12}})
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
||||
@ -673,6 +692,9 @@ class TestController(base.TestCase):
|
||||
mock_get_vnf, mock_insta_notif_process,
|
||||
mock_get_service_plugins):
|
||||
|
||||
vim = fakes.return_default_vim()
|
||||
vim.update({'extra': {"area": "area_A@region_A"}})
|
||||
mock_get_vim.return_value = vim
|
||||
mock_vnf_instance_get_by_id.return_value =\
|
||||
fakes.return_vnf_instance_model()
|
||||
mock_vnf_package_vnfd_get_by_id.return_value = \
|
||||
@ -815,6 +837,9 @@ class TestController(base.TestCase):
|
||||
mock_get_vnf, mock_insta_notif_process,
|
||||
mock_get_service_plugins):
|
||||
|
||||
vim = fakes.return_default_vim()
|
||||
vim.update({'extra': {"area": "area_A@region_A"}})
|
||||
mock_get_vim.return_value = vim
|
||||
mock_vnf_instance_get_by_id.return_value =\
|
||||
fakes.return_vnf_instance_model()
|
||||
mock_vnf_package_vnfd_get_by_id.return_value = \
|
||||
@ -4814,3 +4839,790 @@ class TestController(base.TestCase):
|
||||
"<class 'webob.exc.HTTPInternalServerError'>"}}
|
||||
expected_msg = expected_vnf['tackerFault']['message']
|
||||
self.assertEqual(expected_msg, resp.json['detail'])
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestControllerEnhancedPolicy(TestController):
|
||||
|
||||
def setUp(self):
|
||||
super(TestControllerEnhancedPolicy, self).setUp()
|
||||
cfg.CONF.set_override(
|
||||
"enhanced_tacker_policy", True, group='oslo_policy')
|
||||
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_vnf_package_vnfd')
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "update")
|
||||
def test_update_vnf_with_pkg_id(
|
||||
self, mock_update,
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd,
|
||||
mock_vnf_instance_list, mock_vnf_index_list,
|
||||
mock_get_service_plugins, mock_vnf_by_id):
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||
mock_vnf_index_list.return_value = fakes._get_vnf()
|
||||
mock_vnf_instance_list.return_value = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd.return_value =\
|
||||
fakes.return_vnf_package_vnfd()
|
||||
|
||||
body = {"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
"vnfPkgId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {"test": "test_value"},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"]}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
|
||||
# Call Instantiate API
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||
mock_update.assert_called_once()
|
||||
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
def test_update_vnf_status_err(
|
||||
self,
|
||||
mock_vnf_index_list,
|
||||
mock_get_service_plugins,
|
||||
mock_vnf_by_id):
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||
updates = {'status': 'ERROR'}
|
||||
mock_vnf_index_list.return_value = fakes._get_vnf(**updates)
|
||||
|
||||
body = {"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
"vnfdId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {
|
||||
"test": "test_value"
|
||||
},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"],
|
||||
"metadata": {"testkey": "test_value"},
|
||||
"vimConnectionInfo": {"id": "testid"}}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
|
||||
msg = _("VNF %(id)s status is %(state)s") % {
|
||||
"id": constants.UUID, "state": "ERROR"}
|
||||
res = self._make_problem_detail(msg %
|
||||
{"state": "ERROR"}, 409, 'Conflict')
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(res.text, resp.text)
|
||||
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(sync_resource.SyncVnfPackage, 'create_package')
|
||||
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd,
|
||||
"get_vnf_package_vnfd")
|
||||
@mock.patch.object(nfvo_client.VnfPackageRequest, "index")
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_vnf_package_vnfd')
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "update")
|
||||
def test_update_vnf_none_vnfd(
|
||||
self,
|
||||
mock_update,
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd,
|
||||
mock_vnf_instance_list,
|
||||
mock_vnf_index_list,
|
||||
mock_index,
|
||||
mock_get_vnf_package_vnfd,
|
||||
mock_create_package,
|
||||
mock_get_service_plugins,
|
||||
mock_vnf_by_id):
|
||||
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||
mock_vnf_index_list.return_value = fakes._get_vnf()
|
||||
mock_vnf_instance_list.return_value = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd.return_value = ""
|
||||
mock_get_vnf_package_vnfd.side_effect =\
|
||||
exceptions.VnfPackageVnfdNotFound
|
||||
mock_create_package.return_value = fakes.return_vnf_package_vnfd()
|
||||
mock_response = mock.MagicMock()
|
||||
mock_response.ok = True
|
||||
mock_response.json = mock.MagicMock()
|
||||
mock_response.json.return_value = ['aaa', 'bbb', 'ccc']
|
||||
|
||||
mock_index.return_value = mock_response
|
||||
|
||||
body = {
|
||||
"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
"vnfPkgId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {"test": "test_value"},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"]
|
||||
}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||
mock_update.assert_called_once()
|
||||
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
def test_update_vnf_none_vnf_data(
|
||||
self,
|
||||
mock_vnf_index_list,
|
||||
mock_get_service_plugins,
|
||||
mock_vnf_by_id):
|
||||
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||
mock_vnf_index_list.return_value = None
|
||||
|
||||
body = {"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
"vnfdId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {
|
||||
"test": "test_value"
|
||||
},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"],
|
||||
"metadata": {"testkey": "test_value"},
|
||||
"vimConnectionInfo": {"id": "testid"}}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
|
||||
msg = _("Can not find requested vnf data: %s") % constants.UUID
|
||||
res = self._make_problem_detail(msg, 404, title='Not Found')
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(res.text, resp.text)
|
||||
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
||||
def test_update_vnf_none_instance_data(
|
||||
self,
|
||||
mock_vnf_instance_list,
|
||||
mock_vnf_index_list,
|
||||
mock_get_service_plugins,
|
||||
mock_vnf_by_id):
|
||||
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||
mock_vnf_index_list.return_value = fakes._get_vnf()
|
||||
mock_vnf_instance_list.return_value = ""
|
||||
|
||||
body = {"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
"vnfdId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {
|
||||
"test": "test_value"
|
||||
},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"],
|
||||
"metadata": {"testkey": "test_value"},
|
||||
"vimConnectionInfo": {"id": "testid"}}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
|
||||
vnf_data = fakes._get_vnf()
|
||||
msg = ("Can not find requested vnf instance data: %s") % vnf_data.get(
|
||||
'vnfd_id')
|
||||
res = self._make_problem_detail(msg, 404, title='Not Found')
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(res.text, resp.text)
|
||||
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_vnf_package_vnfd')
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "update")
|
||||
def test_update_vnf(
|
||||
self,
|
||||
mock_update,
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd,
|
||||
mock_vnf_instance_list,
|
||||
mock_vnf_index_list,
|
||||
mock_get_service_plugins,
|
||||
mock_vnf_by_id):
|
||||
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||
mock_vnf_index_list.return_value = fakes._get_vnf()
|
||||
mock_vnf_instance_list.return_value = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd.return_value =\
|
||||
fakes.return_vnf_package_vnfd()
|
||||
|
||||
body = {"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
"vnfdId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {
|
||||
"test": "test_value"
|
||||
},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"],
|
||||
"metadata": {"testkey": "test_value"},
|
||||
"vimConnectionInfo": {"id": "testid"}}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
|
||||
# Call Instantiate API
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||
mock_update.assert_called_once()
|
||||
|
||||
@ddt.data("vnfdId", "vnfPkgId")
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(sync_resource.SyncVnfPackage, 'create_package')
|
||||
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd,
|
||||
"get_vnf_package_vnfd")
|
||||
@mock.patch.object(nfvo_client.VnfPackageRequest, "index")
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_vnf_package_vnfd')
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "update")
|
||||
def test_update_none_vnf_package_info(
|
||||
self, input_id,
|
||||
mock_update,
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd,
|
||||
mock_vnf_instance_list,
|
||||
mock_vnf_index_list,
|
||||
mock_index,
|
||||
mock_get_vnf_package_vnfd,
|
||||
mock_create_package,
|
||||
mock_get_service_plugins,
|
||||
mock_vnf_by_id):
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance()
|
||||
mock_vnf_index_list.return_value = fakes._get_vnf()
|
||||
mock_vnf_instance_list.return_value = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED)
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd.return_value = ""
|
||||
mock_get_vnf_package_vnfd.side_effect = \
|
||||
exceptions.VnfPackageVnfdNotFound
|
||||
mock_create_package.return_value = fakes.return_vnf_package_vnfd()
|
||||
mock_response = mock.MagicMock()
|
||||
mock_response.ok = False
|
||||
mock_response.json = mock.MagicMock()
|
||||
mock_response.json.return_value = ['aaa', 'bbb', 'ccc']
|
||||
|
||||
mock_index.return_value = mock_response
|
||||
|
||||
body = {"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
input_id: "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {"test": "test_value"},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"]}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.BAD_REQUEST, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_not_instantiated(
|
||||
'show'))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||
def test_show_enhanced_policy_vnf_not_instantiated(
|
||||
self, mock_vnf_by_id, vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance_model(
|
||||
**vnf_instance_updates)
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % uuidsentinel.instance_id)
|
||||
req.method = 'GET'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_instantiated(
|
||||
'show', http_client.OK))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
def test_show_enhanced_policy_vnf_instantiated(
|
||||
self, mock_vnf_by_id, vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
mock_vnf_by_id.return_value = fakes.return_vnf_instance(
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED,
|
||||
**vnf_instance_updates)
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % uuidsentinel.instance_id)
|
||||
req.method = 'GET'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_create())
|
||||
@ddt.unpack
|
||||
@mock.patch.object(objects.VnfPackage, 'get_by_id')
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._create_vnf')
|
||||
@mock.patch.object(objects.vnf_instance, '_vnf_instance_update')
|
||||
@mock.patch.object(objects.vnf_instance, '_vnf_instance_create')
|
||||
@mock.patch.object(vim_client.VimClient, "get_vim")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id')
|
||||
def test_create_enhanced_policy(
|
||||
self,
|
||||
mock_vnf_package_vnfd_get_by_id,
|
||||
mock_get_vim,
|
||||
mock_vnf_instance_create,
|
||||
mock_vnf_instance_update,
|
||||
mock_private_create_vnf,
|
||||
mock_vnf_package_get_by_id,
|
||||
vnfd_updates,
|
||||
rules,
|
||||
roles,
|
||||
expected_status_code):
|
||||
|
||||
mock_vnf_package_vnfd_get_by_id.return_value = \
|
||||
fakes.return_vnf_package_vnfd(
|
||||
**vnfd_updates)
|
||||
updates = {'vnfd_id': uuidsentinel.vnfd_id}
|
||||
mock_vnf_instance_create.return_value = \
|
||||
fakes.return_vnf_instance_model(**updates)
|
||||
mock_vnf_instance_update.return_value = \
|
||||
fakes.return_vnf_instance_model(**updates)
|
||||
mock_get_vim.return_value = self.vim_info
|
||||
|
||||
body = {'vnfdId': uuidsentinel.vnfd_id,
|
||||
'metadata': {"key": "value"}}
|
||||
req = fake_request.HTTPRequest.blank('/vnf_instances')
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_instantiated(
|
||||
'terminate', http_client.ACCEPTED))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "terminate")
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._notification_process')
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._get_vnf')
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
def test_terminate_enhanced_policy(
|
||||
self, mock_vnf_by_id, mock_get_vnf, mock_save,
|
||||
mock_notification_process, mock_terminate,
|
||||
vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
vnf_instance_obj = fakes.return_vnf_instance(
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED,
|
||||
**vnf_instance_updates)
|
||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||
mock_get_vnf.return_value = \
|
||||
self._get_dummy_vnf(vnf_id=vnf_instance_obj.id, status='ACTIVE')
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s/terminate' % uuidsentinel.instance_id)
|
||||
body = {'terminationType': 'FORCEFUL'}
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_instantiated(
|
||||
'heal', http_client.ACCEPTED))
|
||||
@ddt.unpack
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._notification_process')
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._get_vnf')
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
def test_heal_enhanced_policy(
|
||||
self, mock_vnf_by_id, mock_get_vnf, mock_save,
|
||||
mock_notification_process,
|
||||
vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
vnf_instance_obj = fakes.return_vnf_instance(
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED,
|
||||
**vnf_instance_updates)
|
||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||
mock_get_vnf.return_value = \
|
||||
self._get_dummy_vnf(vnf_id=vnf_instance_obj.id, status='ACTIVE')
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s/heal' % uuidsentinel.instance_id)
|
||||
body = {}
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_instantiated(
|
||||
'delete', http_client.NO_CONTENT))
|
||||
@ddt.unpack
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._delete')
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._notification_process')
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._get_vnf')
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
def test_delete_enhanced_policy(
|
||||
self,
|
||||
mock_vnf_by_id,
|
||||
mock_get_vnf,
|
||||
mock_notification_process,
|
||||
mock_private_delete,
|
||||
vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
vnf_instance_obj = fakes.return_vnf_instance_delete(
|
||||
**vnf_instance_updates)
|
||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||
mock_get_vnf.return_value = \
|
||||
self._get_dummy_vnf(vnf_id=vnf_instance_obj.id, status='ACTIVE')
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'DELETE'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_instantiated(
|
||||
'scale', http_client.ACCEPTED))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(objects.VnfLcmOpOcc, "create")
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@mock.patch.object(tacker.db.vnfm.vnfm_db.VNFMPluginDb, "get_vnf")
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._notification_process')
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
# @mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "_scale")
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._scale')
|
||||
def test_scale_enhanced_policy(
|
||||
self, mock_scale, mock_vnf_by_id,
|
||||
mock_save,
|
||||
mock_notification_process,
|
||||
mock_get_vnf,
|
||||
mock_get_service_plugins,
|
||||
mock_opocc_create,
|
||||
vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
res = webob.Response()
|
||||
res.status_int = 202
|
||||
location = ('Location', 'http://mock.mock')
|
||||
res.headerlist.append(location)
|
||||
mock_scale.return_value = res
|
||||
vnf_instance_obj = fakes.return_vnf_instance(
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED,
|
||||
scale_status="scale_status",
|
||||
**vnf_instance_updates)
|
||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||
mock_get_vnf.return_value = fakes._get_vnf()
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s/scale' % uuidsentinel.instance_id)
|
||||
body = {"type": "SCALE_OUT",
|
||||
"aspectId": "SP1",
|
||||
"numberOfSteps": 1,
|
||||
"additionalParams": {
|
||||
"test": "test_value"}}
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_instantiated(
|
||||
'update_vnf', http_client.ACCEPTED))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch.object(objects.VNF, "vnf_index_list")
|
||||
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_vnf_package_vnfd')
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "update")
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
def test_update_vnf_enhanced_policy(
|
||||
self,
|
||||
mock_vnf_by_id,
|
||||
mock_update,
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd,
|
||||
mock_vnf_instance_list,
|
||||
mock_vnf_index_list,
|
||||
mock_get_service_plugins,
|
||||
vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
vnf_instance_obj = fakes.return_vnf_instance(
|
||||
instantiated_state=fields.VnfInstanceState.INSTANTIATED,
|
||||
scale_status="scale_status",
|
||||
**vnf_instance_updates)
|
||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||
mock_vnf_index_list.return_value = fakes._get_vnf()
|
||||
mock_vnf_instance_list.return_value = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED, **vnf_instance_updates)
|
||||
mock_vnf_package_vnf_get_vnf_package_vnfd.return_value =\
|
||||
fakes.return_vnf_package_vnfd()
|
||||
|
||||
body = {"vnfInstanceName": "new_instance_name",
|
||||
"vnfInstanceDescription": "new_instance_discription",
|
||||
"vnfdId": "2c69a161-0000-4b0f-bcf8-391f8fc76600",
|
||||
"vnfConfigurableProperties": {
|
||||
"test": "test_value"
|
||||
},
|
||||
"vnfcInfoModificationsDeleteIds": ["test1"],
|
||||
"metadata": {"testkey": "test_value"},
|
||||
"vimConnectionInfo": {"id": "testid"}}
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s' % constants.UUID)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
# Call Instantiate API
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code != http_client.FORBIDDEN:
|
||||
mock_update.assert_called_once()
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_vnf_instantiated(
|
||||
'change_ext_conn', http_client.ACCEPTED))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._notification_process')
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._get_vnf')
|
||||
@mock.patch.object(objects.VnfInstance, "get_by_id")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "change_ext_conn")
|
||||
def test_change_ext_conn_enhanced_policy(
|
||||
self, mock_rpc, mock_save,
|
||||
mock_vnf_by_id, mock_get_vnf,
|
||||
mock_notification_process,
|
||||
mock_get_service_plugins,
|
||||
vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
|
||||
vnf_instance_obj = fakes.return_vnf_instance(
|
||||
fields.VnfInstanceState.INSTANTIATED,
|
||||
**vnf_instance_updates
|
||||
)
|
||||
mock_vnf_by_id.return_value = vnf_instance_obj
|
||||
mock_get_vnf.return_value = \
|
||||
self._get_dummy_vnf(vnf_id=vnf_instance_obj.id, status='ACTIVE')
|
||||
|
||||
body = fakes.get_change_ext_conn_request_body()
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s/change_ext_conn' % uuidsentinel.vnf_instance_id)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code != http_client.FORBIDDEN:
|
||||
mock_rpc.assert_called_once()
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_instantiate())
|
||||
@ddt.unpack
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.VnfLcmController.'
|
||||
'_notification_process')
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._get_vnf')
|
||||
@mock.patch.object(vim_client.VimClient, "get_vim")
|
||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id')
|
||||
@mock.patch.object(objects.VnfPackage, "get_by_id")
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "instantiate")
|
||||
def test_instantiate_with_vim_connection_enhanced_policy(
|
||||
self, mock_instantiate, mock_vnf_package_get_by_id,
|
||||
mock_vnf_package_vnfd_get_by_id, mock_save,
|
||||
mock_vnf_instance_get_by_id, mock_get_vim,
|
||||
mock_get_vnf, mock_insta_notif_process,
|
||||
mock_get_service_plugins, vnf_instance_updates,
|
||||
rules, roles, expected_status_code):
|
||||
|
||||
vim = fakes.return_default_vim()
|
||||
vim.update({'extra': {"area": "area_A@region_A"}})
|
||||
mock_get_vim.return_value = vim
|
||||
mock_vnf_instance_get_by_id.return_value =\
|
||||
fakes.return_vnf_instance_model(**vnf_instance_updates)
|
||||
mock_vnf_package_vnfd_get_by_id.return_value = \
|
||||
fakes.return_vnf_package_vnfd()
|
||||
mock_vnf_package_get_by_id.return_value = \
|
||||
fakes.return_vnf_package_with_deployment_flavour()
|
||||
mock_get_vnf.return_value = \
|
||||
self._get_dummy_vnf(
|
||||
vnf_id=mock_vnf_instance_get_by_id.return_value.id,
|
||||
status='INACTIVE')
|
||||
|
||||
body = {"flavourId": "simple",
|
||||
"vimConnectionInfo": [
|
||||
{"id": uuidsentinel.vim_connection_id,
|
||||
"vimId": uuidsentinel.vim_id,
|
||||
"vimType": 'openstack'}
|
||||
]}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
# Call Instantiate API
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code != http_client.FORBIDDEN:
|
||||
self.assertTrue('Location' in resp.headers.keys())
|
||||
expected_location = (self.expected_location_prefix +
|
||||
str(mock_insta_notif_process.return_value))
|
||||
self.assertEqual(expected_location, resp.headers['location'])
|
||||
mock_instantiate.assert_called_once()
|
||||
mock_get_vnf.assert_called_once()
|
||||
mock_insta_notif_process.assert_called_once()
|
||||
|
||||
@ddt.data(*fakes.get_test_data_policy_index())
|
||||
@ddt.unpack
|
||||
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
|
||||
def test_index_enhanced_policy(self, mock_vnf_list, vnf_instance_list,
|
||||
rules, roles, expected_vnf_inst_ids):
|
||||
|
||||
mock_vnf_list.return_value = vnf_instance_list
|
||||
|
||||
req = fake_request.HTTPRequest.blank('/vnf_instances')
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'GET'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(http_client.OK, resp.status_code)
|
||||
self.assertEqual(
|
||||
expected_vnf_inst_ids, [inst.get('id') for inst in resp.json])
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM':
|
||||
test_nfvo_plugin.FakeVNFMPlugin()})
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.VnfLcmController.'
|
||||
'_notification_process')
|
||||
@mock.patch('tacker.api.vnflcm.v1.controller.'
|
||||
'VnfLcmController._get_vnf')
|
||||
@mock.patch.object(vim_client.VimClient, "get_vim")
|
||||
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id")
|
||||
@mock.patch.object(objects.VnfInstance, "save")
|
||||
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id')
|
||||
@mock.patch.object(objects.VnfPackage, "get_by_id")
|
||||
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "instantiate")
|
||||
def test_instantiate_add_area(
|
||||
self, mock_instantiate, mock_vnf_package_get_by_id,
|
||||
mock_vnf_package_vnfd_get_by_id, mock_save,
|
||||
mock_vnf_instance_get_by_id, mock_get_vim,
|
||||
mock_get_vnf, mock_insta_notif_process,
|
||||
mock_get_service_plugins):
|
||||
vim = fakes.return_default_vim()
|
||||
vim.update({'extra': {"area": "area_A@region_A"}})
|
||||
mock_get_vim.return_value = vim
|
||||
mock_vnf_instance_get_by_id.return_value =\
|
||||
fakes.return_vnf_instance_model()
|
||||
mock_vnf_package_vnfd_get_by_id.return_value = \
|
||||
fakes.return_vnf_package_vnfd()
|
||||
mock_vnf_package_get_by_id.return_value = \
|
||||
fakes.return_vnf_package_with_deployment_flavour()
|
||||
mock_get_vnf.return_value = \
|
||||
self._get_dummy_vnf(
|
||||
vnf_id=mock_vnf_instance_get_by_id.return_value.id,
|
||||
status='INACTIVE')
|
||||
|
||||
body = {"flavourId": "simple",
|
||||
"vimConnectionInfo": [
|
||||
{"id": uuidsentinel.vim_connection_id,
|
||||
"vimId": uuidsentinel.vim_id,
|
||||
"vimType": 'openstack'}
|
||||
]}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id)
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
# Call Instantiate API
|
||||
resp = req.get_response(self.app)
|
||||
self.assertTrue('Location' in resp.headers.keys())
|
||||
expected_location = (self.expected_location_prefix +
|
||||
str(mock_insta_notif_process.return_value))
|
||||
self.assertEqual(expected_location, resp.headers['location'])
|
||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||
mock_instantiate.assert_called_once()
|
||||
mock_get_vnf.assert_called_once()
|
||||
mock_insta_notif_process.assert_called_once()
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
from copy import deepcopy
|
||||
import datetime
|
||||
from http import client as http_client
|
||||
import iso8601
|
||||
import os
|
||||
from oslo_utils import uuidutils
|
||||
import shutil
|
||||
import uuid
|
||||
import webob
|
||||
@ -30,6 +32,7 @@ from tacker.objects import vnf_deployment_flavour as vnf_deployment_flavour_obj
|
||||
from tacker.objects import vnf_package as vnf_package_obj
|
||||
from tacker.objects import vnf_package_vnfd as vnf_package_vnfd_obj
|
||||
from tacker.objects import vnf_software_image as vnf_software_image_obj
|
||||
from tacker.policies import vnf_package as vnf_package_policies
|
||||
from tacker.tests import constants
|
||||
from tacker.tests import utils
|
||||
from tacker.tests import uuidsentinel
|
||||
@ -296,3 +299,128 @@ def return_vnfd_data(csar_without_tosca_meta=False):
|
||||
|
||||
shutil.rmtree(csar_temp_dir)
|
||||
return file_path_and_data
|
||||
|
||||
|
||||
def get_test_data_pkg_index():
|
||||
rules = {
|
||||
vnf_package_policies.VNFPKGM % 'index':
|
||||
"vendor:%(vendor)s"
|
||||
}
|
||||
id_a = uuidutils.generate_uuid()
|
||||
pkg_provider_a = return_vnfpkg_obj(
|
||||
vnf_package_updates={'id': uuidutils.generate_uuid()},
|
||||
vnfd_updates={
|
||||
'vnf_provider': 'provider_A',
|
||||
'id': id_a,
|
||||
})
|
||||
id_b = uuidutils.generate_uuid()
|
||||
pkg_provider_b = return_vnfpkg_obj(
|
||||
vnf_package_updates={'id': uuidutils.generate_uuid()},
|
||||
vnfd_updates={
|
||||
'vnf_provider': 'provider_B',
|
||||
'id': id_b,
|
||||
})
|
||||
# id_c = uuidutils.generate_uuid()
|
||||
updates = {'id': uuidutils.generate_uuid(),
|
||||
'onboarding_state': 'CREATED',
|
||||
'operational_state': 'DISABLED'}
|
||||
pkg_provider_c = return_vnfpkg_obj(
|
||||
vnf_package_updates=updates
|
||||
)
|
||||
test_data = [
|
||||
{
|
||||
'pkg_list': [pkg_provider_a],
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_provider_A'],
|
||||
'expected_pkg_ids': [pkg_provider_a.id]
|
||||
},
|
||||
{
|
||||
'pkg_list': [pkg_provider_b],
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_provider_B'],
|
||||
'expected_pkg_ids': [pkg_provider_b.id]
|
||||
},
|
||||
{
|
||||
'pkg_list': [pkg_provider_a, pkg_provider_b],
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_all'],
|
||||
'expected_pkg_ids': [pkg_provider_a.id, pkg_provider_b.id]
|
||||
},
|
||||
{
|
||||
'pkg_list': [pkg_provider_c],
|
||||
'rules': rules,
|
||||
'roles': [],
|
||||
'expected_pkg_ids': [pkg_provider_c.id]
|
||||
},
|
||||
{
|
||||
'pkg_list': [pkg_provider_c],
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_provider_A'],
|
||||
'expected_pkg_ids': [pkg_provider_c.id]
|
||||
},
|
||||
{
|
||||
'pkg_list': [pkg_provider_c],
|
||||
'rules': rules,
|
||||
'roles': ['VENDOR_all'],
|
||||
'expected_pkg_ids': [pkg_provider_c.id]
|
||||
},
|
||||
]
|
||||
return test_data
|
||||
|
||||
|
||||
def get_test_data_pkg_uploaded(action, success_status_code):
|
||||
rules = {
|
||||
vnf_package_policies.VNFPKGM % action:
|
||||
"vendor:%(vendor)s"
|
||||
}
|
||||
test_data = [
|
||||
# 'expected_status_code': success_status_code
|
||||
{
|
||||
'vnfd_updates': {
|
||||
'vnf_provider': 'provider_A',
|
||||
},
|
||||
'rules': rules,
|
||||
'roles': [
|
||||
'VENDOR_provider_A',
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {
|
||||
'vnf_provider': 'provider_A',
|
||||
},
|
||||
'rules': rules,
|
||||
'roles': [
|
||||
'VENDOR_all',
|
||||
],
|
||||
'expected_status_code': success_status_code
|
||||
},
|
||||
# 'expected_status_code': http_client.FORBIDDEN
|
||||
{
|
||||
'vnfd_updates': {
|
||||
'vnf_provider': 'provider_A',
|
||||
},
|
||||
'rules': rules,
|
||||
'roles': [
|
||||
'VENDOR_provider_B',
|
||||
],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
{
|
||||
'vnfd_updates': {
|
||||
'vnf_provider': 'provider_A',
|
||||
},
|
||||
'rules': rules,
|
||||
'roles': [],
|
||||
'expected_status_code': http_client.FORBIDDEN
|
||||
},
|
||||
]
|
||||
return test_data
|
||||
|
||||
|
||||
def get_test_data_pkg_to_upload(action, success_status_code):
|
||||
test_data = get_test_data_pkg_uploaded(action, success_status_code)
|
||||
for item in test_data:
|
||||
item['vnf_data'] = item.pop('vnfd_updates')
|
||||
item['vnf_data']['provider'] = item['vnf_data'].pop('vnf_provider')
|
||||
return test_data
|
||||
|
@ -24,17 +24,22 @@ import urllib
|
||||
from webob import exc
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_policy import policy as oslo_policy
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tacker.api.vnfpkgm.v1 import controller
|
||||
from tacker.common import csar_utils
|
||||
from tacker.common import exceptions as tacker_exc
|
||||
from tacker.conductor.conductorrpc.vnf_pkgm_rpc import VNFPackageRPCAPI
|
||||
from tacker import context
|
||||
from tacker.glance_store import store as glance_store
|
||||
from tacker import objects
|
||||
from tacker.objects import fields
|
||||
from tacker.objects import vnf_package
|
||||
from tacker.objects.vnf_package import VnfPackagesList
|
||||
from tacker.objects.vnf_software_image import VnfSoftwareImage
|
||||
from tacker.policies import vnf_package as vnf_package_policies
|
||||
from tacker import policy
|
||||
from tacker.tests import constants
|
||||
from tacker.tests.unit import base
|
||||
from tacker.tests.unit import fake_request
|
||||
@ -679,25 +684,25 @@ class TestController(base.TestCase):
|
||||
|
||||
@mock.patch.object(objects.VnfPackage, "get_by_id")
|
||||
def test_delete_with_operational_state_enabled(self, mock_vnf_by_id):
|
||||
vnfpkg_updates = {
|
||||
'operational_state': fields.PackageOperationalStateType.ENABLED}
|
||||
mock_vnf_by_id.return_value = fakes.return_vnfpkg_obj(
|
||||
vnf_package_updates=vnfpkg_updates)
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnfpkgm/v1/vnf_packages/%s' % constants.UUID)
|
||||
vnf_package_dict = fakes.fake_vnf_package()
|
||||
vnf_package_dict['operational_state'] = \
|
||||
fields.PackageOperationalStateType.ENABLED
|
||||
vnf_package = objects.VnfPackage(**vnf_package_dict)
|
||||
mock_vnf_by_id.return_value = vnf_package
|
||||
|
||||
self.assertRaises(exc.HTTPConflict, self.controller.delete,
|
||||
req, constants.UUID)
|
||||
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
def test_delete_with_usage_state_in_use(self, mock_vnf_by_id):
|
||||
vnfpkg_updates = {
|
||||
'usage_state': fields.PackageUsageStateType.IN_USE}
|
||||
mock_vnf_by_id.return_value = fakes.return_vnfpkg_obj(
|
||||
vnf_package_updates=vnfpkg_updates)
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnfpkgm/v1/vnf_packages/%s' % constants.UUID)
|
||||
vnf_package_dict = fakes.fake_vnf_package()
|
||||
vnf_package_dict['usage_state'] = \
|
||||
fields.PackageUsageStateType.IN_USE
|
||||
vnf_package = objects.VnfPackage(**vnf_package_dict)
|
||||
mock_vnf_by_id.return_value = vnf_package
|
||||
|
||||
self.assertRaises(exc.HTTPConflict, self.controller.delete,
|
||||
req, constants.UUID)
|
||||
|
||||
@ -1370,3 +1375,297 @@ class TestController(base.TestCase):
|
||||
self.controller.fetch_vnf_package_artifacts,
|
||||
req, constants.UUID,
|
||||
constants.ARTIFACT_PATH)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestControllerEnhancedPolicy(TestController):
|
||||
|
||||
def setUp(self):
|
||||
super(TestControllerEnhancedPolicy, self).setUp()
|
||||
cfg.CONF.set_override(
|
||||
"enhanced_tacker_policy", True, group='oslo_policy')
|
||||
|
||||
@mock.patch.object(csar_utils, 'load_csar_data')
|
||||
@mock.patch.object(glance_store, 'load_csar')
|
||||
@mock.patch.object(glance_store, 'store_csar')
|
||||
@mock.patch.object(VNFPackageRPCAPI, "upload_vnf_package_content")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "save")
|
||||
def test_upload_vnf_package_content(self, mock_vnf_pack_save,
|
||||
mock_vnf_by_id,
|
||||
mock_upload_vnf_package_content,
|
||||
mock_glance_store,
|
||||
mock_load_csar,
|
||||
mock_load_csar_data):
|
||||
updates = {'onboarding_state': 'CREATED',
|
||||
'operational_state': 'DISABLED'}
|
||||
vnf_package_dict = fakes.fake_vnf_package(updates)
|
||||
vnf_package_obj = objects.VnfPackage(**vnf_package_dict)
|
||||
mock_vnf_by_id.return_value = vnf_package_obj
|
||||
mock_vnf_pack_save.return_value = vnf_package_obj
|
||||
mock_glance_store.return_value = 'location', 0, 'checksum', \
|
||||
'multihash', 'loc_meta'
|
||||
mock_load_csar.return_value = '/var/lib/tacker/5f5d99c6-844a-4c3' \
|
||||
'1-9e6d-ab21b87dcfff.zip'
|
||||
mock_load_csar_data.return_value = (
|
||||
{'provider': 'company'}, mock.ANY, mock.ANY)
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s/package_content'
|
||||
% constants.UUID)
|
||||
req.headers['Content-Type'] = 'application/zip'
|
||||
req.method = 'PUT'
|
||||
req.body = jsonutils.dump_as_bytes(mock.mock_open())
|
||||
resp = req.get_response(self.app)
|
||||
mock_glance_store.assert_called()
|
||||
self.assertEqual(http_client.ACCEPTED, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_pkg_to_upload('upload_package_content',
|
||||
http_client.ACCEPTED))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(glance_store, 'delete_csar')
|
||||
@mock.patch.object(csar_utils, 'load_csar_data')
|
||||
@mock.patch.object(glance_store, 'load_csar')
|
||||
@mock.patch.object(glance_store, 'store_csar')
|
||||
@mock.patch.object(VNFPackageRPCAPI, "upload_vnf_package_content")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "save")
|
||||
def test_upload_vnf_package_content_enhanced_policy(
|
||||
self, mock_vnf_pack_save,
|
||||
mock_vnf_by_id,
|
||||
mock_upload_vnf_package_content,
|
||||
mock_glance_store,
|
||||
mock_load_csar,
|
||||
mock_load_csar_data,
|
||||
mock_delete_csar,
|
||||
vnf_data, rules, roles, expected_status_code):
|
||||
updates = {'onboarding_state': 'CREATED',
|
||||
'operational_state': 'DISABLED'}
|
||||
vnf_package_dict = fakes.fake_vnf_package(updates)
|
||||
vnf_package_obj = objects.VnfPackage(**vnf_package_dict)
|
||||
mock_vnf_by_id.return_value = vnf_package_obj
|
||||
mock_vnf_pack_save.return_value = vnf_package_obj
|
||||
mock_glance_store.return_value = 'location', 0, 'checksum', \
|
||||
'multihash', 'loc_meta'
|
||||
mock_load_csar.return_value = '/var/lib/tacker/5f5d99c6-844a-4c3' \
|
||||
'1-9e6d-ab21b87dcfff.zip'
|
||||
mock_load_csar_data.return_value = (
|
||||
vnf_data, mock.ANY, mock.ANY)
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s/package_content'
|
||||
% constants.UUID)
|
||||
req.headers['Content-Type'] = 'application/zip'
|
||||
req.method = 'PUT'
|
||||
req.body = jsonutils.dump_as_bytes(mock.mock_open())
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
mock_glance_store.assert_called()
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code == http_client.FORBIDDEN:
|
||||
mock_delete_csar.assert_called()
|
||||
|
||||
@ddt.data(*fakes.get_test_data_pkg_uploaded('show', http_client.OK))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(VnfSoftwareImage, 'get_by_id')
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
def test_show_enhanced_policy(
|
||||
self, mock_vnf_by_id, mock_sw_image_by_id,
|
||||
vnfd_updates, rules, roles, expected_status_code):
|
||||
|
||||
mock_vnf_by_id.return_value = fakes.return_vnfpkg_obj(
|
||||
vnfd_updates=vnfd_updates)
|
||||
mock_sw_image_by_id.return_value = fakes.return_software_image()
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s' % constants.UUID)
|
||||
req.method = 'GET'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@mock.patch.object(VnfSoftwareImage, 'get_by_id')
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
@ddt.data(['VENDOR_provider_A'], [])
|
||||
def test_show_enhanced_policy_created(
|
||||
self, roles, mock_vnf_by_id, mock_sw_image_by_id):
|
||||
updates = {'onboarding_state': 'CREATED',
|
||||
'operational_state': 'DISABLED'}
|
||||
mock_vnf_by_id.return_value = fakes.return_vnfpkg_obj(
|
||||
vnf_package_updates=updates)
|
||||
mock_sw_image_by_id.return_value = fakes.return_software_image()
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s' % constants.UUID)
|
||||
req.method = 'GET'
|
||||
rules = {
|
||||
vnf_package_policies.VNFPKGM % 'show':
|
||||
"vendor:%(vendor)s"
|
||||
}
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(http_client.OK, resp.status_code)
|
||||
|
||||
@ddt.data(
|
||||
*fakes.get_test_data_pkg_uploaded('delete', http_client.NO_CONTENT))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(vnf_package.VnfPackage, "destroy")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
@mock.patch.object(VNFPackageRPCAPI, "delete_vnf_package")
|
||||
def test_delete_enhanced_policy(
|
||||
self, mock_delete_rpc, mock_vnf_by_id, mock_vnf_pack_destroy,
|
||||
vnfd_updates, rules, roles, expected_status_code):
|
||||
vnfpkg_updates = {'operational_state': 'DISABLED'}
|
||||
mock_vnf_by_id.return_value = fakes.return_vnfpkg_obj(
|
||||
vnf_package_updates=vnfpkg_updates, vnfd_updates=vnfd_updates)
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s' % constants.UUID)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'DELETE'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_pkg_uploaded('patch', http_client.OK))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "save")
|
||||
def test_patch_enhanced_policy(self, mock_save, mock_vnf_by_id,
|
||||
vnfd_updates, rules, roles, expected_status_code):
|
||||
vnf_package_updates = {'operational_state': 'DISABLED'}
|
||||
mock_vnf_by_id.return_value = \
|
||||
fakes.return_vnfpkg_obj(
|
||||
vnf_package_updates=vnf_package_updates,
|
||||
vnfd_updates=vnfd_updates
|
||||
)
|
||||
|
||||
req_body = {"operationalState": "ENABLED",
|
||||
"userDefinedData": {"testKey1": "val01",
|
||||
"testKey2": "val02", "testkey3": "val03"}}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s'
|
||||
% constants.UUID)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'PATCH'
|
||||
req.body = jsonutils.dump_as_bytes(req_body)
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context(
|
||||
'fake', 'fake', roles=roles)
|
||||
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
if expected_status_code != http_client.FORBIDDEN:
|
||||
self.assertEqual(req_body, jsonutils.loads(resp.body))
|
||||
|
||||
@ddt.data(*fakes.get_test_data_pkg_uploaded(
|
||||
'get_vnf_package_vnfd', http_client.OK))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(VNFPackageRPCAPI, "get_vnf_package_vnfd")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
def test_get_vnf_package_vnfd_enhanced_policy(
|
||||
self, mock_vnf_by_id, mock_get_vnf_package_vnfd,
|
||||
vnfd_updates, rules, roles, expected_status_code):
|
||||
|
||||
mock_vnf_by_id.return_value = fakes.return_vnfpkg_obj(
|
||||
vnfd_updates=vnfd_updates)
|
||||
mock_get_vnf_package_vnfd.return_value = fakes.return_vnfd_data()
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s/vnfd'
|
||||
% constants.UUID)
|
||||
req.headers['Accept'] = 'application/zip'
|
||||
req.method = 'GET'
|
||||
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context('fake', 'fake', roles=roles)
|
||||
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_pkg_uploaded('fetch_package_content',
|
||||
http_client.ACCEPTED))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(controller.VnfPkgmController, "_download")
|
||||
@mock.patch.object(controller.VnfPkgmController, "_get_range_from_request")
|
||||
@mock.patch.object(glance_store, 'get_csar_size')
|
||||
@mock.patch.object(controller.VnfPkgmController, '_get_vnf_package')
|
||||
@mock.patch.object(vnf_package.VnfPackage, 'save')
|
||||
def test_fetch_vnf_package_content_enhanced_policy(
|
||||
self,
|
||||
mock_save,
|
||||
mock_get_vnf_package,
|
||||
mock_get_csar_size,
|
||||
mock_get_range,
|
||||
mock_download,
|
||||
vnfd_updates, rules, roles, expected_status_code):
|
||||
|
||||
mock_get_vnf_package.return_value = fakes.return_vnfpkg_obj(
|
||||
vnfd_updates=vnfd_updates)
|
||||
mock_get_csar_size.return_value = 1000
|
||||
mock_get_range.return_value = "10-20, 21-30"
|
||||
mock_download.return_value = "Response"
|
||||
|
||||
request = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s/package_content' % constants.UUID)
|
||||
request.method = 'GET'
|
||||
|
||||
request.headers["Range"] = 'bytes=10-20,21-30'
|
||||
request.response = ""
|
||||
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context('fake', 'fake', roles=roles)
|
||||
|
||||
resp = request.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_pkg_uploaded('fetch_artifact',
|
||||
http_client.OK))
|
||||
@ddt.unpack
|
||||
@mock.patch.object(controller.VnfPkgmController, "_get_csar_path")
|
||||
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
|
||||
def test_fetch_vnf_package_artifacts_enhanced_policy(
|
||||
self, mock_vnf_by_id, mock_get_csar_path,
|
||||
vnfd_updates, rules, roles, expected_status_code):
|
||||
mock_vnf_by_id.return_value = fakes.return_vnfpkg_obj(
|
||||
vnfd_updates=vnfd_updates)
|
||||
base_path = os.path.dirname(os.path.abspath(__file__))
|
||||
extract_path = os.path.join(base_path, '../../etc/samples/'
|
||||
'sample_vnf_package_csar_in_meta_and_manifest')
|
||||
mock_get_csar_path.return_value = extract_path
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/vnf_packages/%s/artifacts/%s'
|
||||
% (constants.UUID, constants.ARTIFACT_PATH))
|
||||
req.method = 'GET'
|
||||
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context('fake', 'fake', roles=roles)
|
||||
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
|
||||
self.assertEqual(expected_status_code, resp.status_code)
|
||||
|
||||
@ddt.data(*fakes.get_test_data_pkg_index())
|
||||
@ddt.unpack
|
||||
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
|
||||
def test_index_enhanced_policy(
|
||||
self, mock_vnf_list, pkg_list, rules, roles, expected_pkg_ids):
|
||||
mock_vnf_list.return_value = pkg_list
|
||||
req = fake_request.HTTPRequest.blank('/vnf_packages')
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'GET'
|
||||
policy.set_rules(oslo_policy.Rules.from_dict(rules), overwrite=True)
|
||||
ctx = context.Context('fake', 'fake', roles=roles)
|
||||
|
||||
resp = req.get_response(fakes.wsgi_app_v1(fake_auth_context=ctx))
|
||||
self.assertEqual(http_client.OK, resp.status_code)
|
||||
self.assertEqual(
|
||||
expected_pkg_ids, [pkg.get('id') for pkg in resp.json])
|
||||
|
11
tox.ini
11
tox.ini
@ -101,6 +101,17 @@ 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]
|
||||
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]
|
||||
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]
|
||||
setenv = {[testenv]setenv}
|
||||
|
Loading…
Reference in New Issue
Block a user