Support enhancement for Subscription Post
- Added support for the following attributes: *operationStates *vnfInstanceSubscriptionFilter - The filtering criteria is enhanced by adding the above attributes to effectively send_notifications - We also updated the following table in DB: vnf_lcm_filters Implements: blueprint support-fundamental-lcm Spec: https://specs.openstack.org/openstack/tacker-specs/specs/wallaby/support-fundamental-vnf-lcm-based-on-ETSI-NFV.html Change-Id: Iebe70c43ef1a5b653f8ec204b1b3a79ca882399f
This commit is contained in:
parent
ede9755ab5
commit
8242c132ad
|
@ -631,6 +631,18 @@ filter_notification_types:
|
|||
in: body
|
||||
required: false
|
||||
type: string
|
||||
filter_operation_states:
|
||||
description: |
|
||||
Match particular LCM operation state
|
||||
values as reported in notifications of type
|
||||
VnfLcmOperationOccurrenceNotification.
|
||||
May be present if the "notificationTypes"
|
||||
attribute contains the value
|
||||
"VnfLcmOperationOccurrenceNotification" and
|
||||
shall be absent otherwise.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
filter_operation_types:
|
||||
description: |
|
||||
Match particular VNF lifecycle operation types for
|
||||
|
@ -1237,6 +1249,13 @@ vnf_instance_name:
|
|||
in: body
|
||||
required: false
|
||||
type: string
|
||||
vnf_instance_subscription_filter:
|
||||
description: |
|
||||
Filter criteria to select VNF instances
|
||||
about which to notify.
|
||||
in: body
|
||||
required: false
|
||||
type: object
|
||||
vnf_instance_vim_connection_info:
|
||||
description: |
|
||||
Information about VIM connections to be used for managing the resources
|
||||
|
|
|
@ -2,7 +2,24 @@
|
|||
"filter": {
|
||||
"notificationTypes": [
|
||||
"VnfLcmOperationOccurrenceNotification"
|
||||
],
|
||||
"vnfInstanceSubscriptionFilter": {
|
||||
"vnfdIds": [],
|
||||
"vnfProductsFromProviders": {
|
||||
"vnfProvider": "Vnf Provider 1",
|
||||
"vnfProducts": [
|
||||
{
|
||||
"vnfProductName": "Vnf Product 1",
|
||||
"versions": [
|
||||
{
|
||||
"vnfSoftwareVersion": "v1",
|
||||
"vnfdVersions": ["vnfd.v1.1"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"callbackUri": "http://sample1.com/notification"
|
||||
}
|
|
@ -1,6 +1,23 @@
|
|||
{
|
||||
"id": "76057f8e65ab37fb82d9382dfc3f3c8b",
|
||||
"filter": {
|
||||
"vnfInstanceSubscriptionFilter": {
|
||||
"vnfdIds": [],
|
||||
"vnfProductsFromProviders": {
|
||||
"vnfProvider": "Vnf Provider 1",
|
||||
"vnfProducts": [
|
||||
{
|
||||
"vnfProductName": "Vnf Product 1",
|
||||
"versions": [
|
||||
{
|
||||
"vnfSoftwareVersion": "v1",
|
||||
"vnfdVersions": ["vnfd.v1.1"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"notificationTypes": [
|
||||
"VnfLcmOperationOccurrenceNotification"
|
||||
]
|
||||
|
|
|
@ -1155,8 +1155,10 @@ Request Parameters
|
|||
.. rest_parameters:: parameters_vnflcm.yaml
|
||||
|
||||
- filter: filter
|
||||
- vnfInstanceSubscriptionFilter: vnf_instance_subscription_filter
|
||||
- notificationTypes: filter_notification_types
|
||||
- operationTypes: filter_operation_types
|
||||
- operationStates: filter_operation_states
|
||||
- callbackUri : callback_uri
|
||||
- authentication: authentication
|
||||
- authType: authentication_auth_type
|
||||
|
|
|
@ -184,6 +184,109 @@ _vimConnectionInfo = {
|
|||
}
|
||||
}
|
||||
|
||||
_versions = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'objects',
|
||||
'properties': {
|
||||
'vnfSoftwareVersion': {'type': 'string'},
|
||||
'vnfdVersions': {
|
||||
'type': 'array',
|
||||
'items': {'type': 'string'}
|
||||
}
|
||||
},
|
||||
'required': ['vnfSoftwareVersion']
|
||||
}
|
||||
}
|
||||
|
||||
_vnf_products = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'vnfProductName': {'type': 'string'},
|
||||
'versions': _versions
|
||||
},
|
||||
'required': ['vnfProductName']
|
||||
}
|
||||
}
|
||||
|
||||
_vnf_products_from_providers = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'vnfProvider': {'type': 'string'},
|
||||
'vnfProducts': _vnf_products
|
||||
}
|
||||
},
|
||||
'required': ['vnfProvider']
|
||||
}
|
||||
|
||||
_lifecycle_change_notifications_filter = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'vnfInstanceSubscriptionFilter': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'vnfdIds': {
|
||||
'type': 'array',
|
||||
'items': parameter_types.identifier
|
||||
},
|
||||
'vnfProductsFromProviders': _vnf_products_from_providers,
|
||||
'vnfInstanceIds': {
|
||||
'type': 'array',
|
||||
'items': parameter_types.identifier
|
||||
},
|
||||
'vnfInstanceNames': {
|
||||
'type': 'array',
|
||||
'items': {'type': 'string'}
|
||||
}
|
||||
}
|
||||
},
|
||||
'notificationTypes': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'string',
|
||||
'enum': [
|
||||
'VnfLcmOperationOccurrenceNotification',
|
||||
'VnfIdentifierCreationNotification',
|
||||
'VnfIdentifierDeletionNotification']
|
||||
}
|
||||
},
|
||||
'operationTypes': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'string',
|
||||
'enum': [
|
||||
'INSTANTIATE',
|
||||
'SCALE',
|
||||
'SCALE_TO_LEVEL',
|
||||
'CHANGE_FLAVOUR',
|
||||
'TERMINATE',
|
||||
'HEAL',
|
||||
'OPERATE',
|
||||
'CHANGE_EXT_CONN',
|
||||
'MODIFY_INFO']
|
||||
}
|
||||
},
|
||||
'operationStates': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'string',
|
||||
'enum': [
|
||||
'STARTING',
|
||||
'PROCESSING',
|
||||
'COMPLETED',
|
||||
'FAILED_TEMP',
|
||||
'FAILED',
|
||||
'ROLLING_BACK',
|
||||
'ROLLED_BACK']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
|
@ -241,7 +344,7 @@ heal = {
|
|||
register_subscription = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'filter': parameter_types.keyvalue_pairs,
|
||||
'filter': _lifecycle_change_notifications_filter,
|
||||
'callbackUri': {'type': 'string', 'maxLength': 255},
|
||||
'authentication': parameter_types.keyvalue_pairs,
|
||||
},
|
||||
|
|
|
@ -162,26 +162,6 @@ def check_vnf_status_and_error_point(action, status=None):
|
|||
|
||||
class VnfLcmController(wsgi.Controller):
|
||||
|
||||
notification_type_list = ['VnfLcmOperationOccurrenceNotification',
|
||||
'VnfIdentifierCreationNotification',
|
||||
'VnfIdentifierDeletionNotification']
|
||||
operation_type_list = ['INSTANTIATE',
|
||||
'SCALE',
|
||||
'SCALE_TO_LEVEL',
|
||||
'CHANGE_FLAVOUR',
|
||||
'TERMINATE',
|
||||
'HEAL',
|
||||
'OPERATE',
|
||||
'CHANGE_EXT_CONN',
|
||||
'MODIFY_INFO']
|
||||
operation_state_list = ['STARTING',
|
||||
'PROCESSING',
|
||||
'COMPLETED',
|
||||
'FAILED_TEMP',
|
||||
'FAILED',
|
||||
'ROLLING_BACK',
|
||||
'ROLLED_BACK']
|
||||
|
||||
_view_builder_class = vnf_lcm_view.ViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
|
@ -904,28 +884,6 @@ class VnfLcmController(wsgi.Controller):
|
|||
@validation.schema(vnf_lcm.register_subscription)
|
||||
def register_subscription(self, request, body):
|
||||
subscription_request_data = body
|
||||
if subscription_request_data.get('filter'):
|
||||
# notificationTypes check
|
||||
notification_types = subscription_request_data.get(
|
||||
"filter").get("notificationTypes")
|
||||
for notification_type in notification_types:
|
||||
if notification_type not in self.notification_type_list:
|
||||
msg = (
|
||||
_("notificationTypes value mismatch: %s") %
|
||||
notification_type)
|
||||
return self._make_problem_detail(
|
||||
msg, 400, title='Bad Request')
|
||||
|
||||
# operationTypes check
|
||||
operation_types = subscription_request_data.get(
|
||||
"filter").get("operationTypes")
|
||||
for operation_type in operation_types:
|
||||
if operation_type not in self.operation_type_list:
|
||||
msg = (
|
||||
_("operationTypes value mismatch: %s") %
|
||||
operation_type)
|
||||
return self._make_problem_detail(
|
||||
msg, 400, title='Bad Request')
|
||||
|
||||
subscription_id = uuidutils.generate_uuid()
|
||||
|
||||
|
|
|
@ -337,6 +337,17 @@ def chunkiter(fp, chunk_size=65536):
|
|||
break
|
||||
|
||||
|
||||
# TODO(esto.aln): Consider to move this function to
|
||||
# convert_camelcase_to_snakecase(). We will consider the correct approach
|
||||
# to modify the common function so as not to introduce degrade.
|
||||
def convert_string_to_snakecase(name):
|
||||
"""Converts a string from camelCase to snake_case."""
|
||||
name_with_underscores = re.sub(
|
||||
'(.)([A-Z][a-z]+)', r'\1_\2', name)
|
||||
return re.sub('([a-z0-9])([A-Z])', r'\1_\2',
|
||||
name_with_underscores).lower()
|
||||
|
||||
|
||||
def convert_camelcase_to_snakecase(request_data):
|
||||
"""Converts dict keys or list of dict keys from camelCase to snake_case.
|
||||
|
||||
|
@ -347,17 +358,11 @@ def convert_camelcase_to_snakecase(request_data):
|
|||
|
||||
:param request_data: dict with keys or list with items, in camelCase.
|
||||
"""
|
||||
def convert(name):
|
||||
name_with_underscores = re.sub(
|
||||
'(.)([A-Z][a-z]+)', r'\1_\2', name)
|
||||
return re.sub('([a-z0-9])([A-Z])', r'\1_\2',
|
||||
name_with_underscores).lower()
|
||||
|
||||
if isinstance(request_data, dict):
|
||||
new_dict = {}
|
||||
for key, property_value in request_data.items():
|
||||
property_value = convert_camelcase_to_snakecase(property_value)
|
||||
underscore_joined = convert(key)
|
||||
underscore_joined = convert_string_to_snakecase(key)
|
||||
new_dict[underscore_joined] = property_value
|
||||
return new_dict
|
||||
|
||||
|
|
|
@ -287,6 +287,7 @@ class VnfLcmFilters(model_base.BASE):
|
|||
sa.ForeignKey('vnf_lcm_subscriptions.id'),
|
||||
nullable=False)
|
||||
filter = sa.Column(sa.JSON, nullable=False)
|
||||
vnf_products_from_providers = sa.Column(sa.JSON, nullable=True)
|
||||
notification_types = sa.Column(sa.VARBINARY(255), nullable=True)
|
||||
notification_types_len = sa.Column(sa.Integer, nullable=True)
|
||||
operation_types = sa.Column(
|
||||
|
|
|
@ -1 +1 @@
|
|||
3adac34764da
|
||||
c31f65e0d099
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
# Copyright 2021 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Add columns to vnf_lcm_filter
|
||||
|
||||
Revision ID: c31f65e0d099
|
||||
Revises: 3adac34764da
|
||||
Create Date: 2021-02-03 22:53:36.352774
|
||||
|
||||
"""
|
||||
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c31f65e0d099'
|
||||
down_revision = '3adac34764da'
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
sql_text_length = 65535
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_products_from_providers', sa.JSON()))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'operation_states', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"json_unquote(json_extract(`filter`,'$.operationStates'))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'operation_states_len', sa.Integer,
|
||||
sa.Computed(
|
||||
"ifnull(json_length(`operation_states`),0)")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnfd_ids', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"json_unquote(json_extract(`filter`,'$.vnfdIds'))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnfd_ids_len', sa.Integer,
|
||||
sa.Computed(
|
||||
"ifnull(json_length(`vnfd_ids`),0)")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_provider', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"(ifnull(json_unquote(json_extract("
|
||||
"`vnf_products_from_providers`,'$.vnfProvider')),''))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_product_name', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"(ifnull(json_unquote(json_extract("
|
||||
"`vnf_products_from_providers`,"
|
||||
"'$.vnfProducts[0].vnfProductName')),''))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_software_version', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"(ifnull(json_unquote(json_extract("
|
||||
"`vnf_products_from_providers`,'$.vnfProducts[0]"
|
||||
".versions[0].vnfSoftwareVersion')),''))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnfd_versions', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"json_unquote(json_extract(`vnf_products_from_providers`,"
|
||||
"'$.vnfProducts[0].versions[0].vnfdVersions'))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnfd_versions_len', sa.Integer,
|
||||
sa.Computed(
|
||||
"ifnull(json_length(`vnfd_versions`),0)")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_instance_ids', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"json_unquote(json_extract(`filter`,'$.vnfInstanceIds'))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_instance_ids_len', sa.Integer,
|
||||
sa.Computed(
|
||||
"ifnull(json_length(`vnf_instance_ids`),0)")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_instance_names', sa.TEXT(length=sql_text_length),
|
||||
sa.Computed(
|
||||
"json_unquote(json_extract(`filter`,'$.vnfInstanceNames'))")))
|
||||
|
||||
op.add_column(
|
||||
'vnf_lcm_filters',
|
||||
sa.Column(
|
||||
'vnf_instance_names_len', sa.Integer,
|
||||
sa.Computed(
|
||||
"ifnull(json_length(`vnf_instance_names`),0)")))
|
|
@ -15,6 +15,7 @@ from oslo_utils import timeutils
|
|||
from sqlalchemy.sql import text
|
||||
|
||||
from tacker.common import exceptions
|
||||
from tacker.common.utils import convert_string_to_snakecase
|
||||
import tacker.conf
|
||||
from tacker.db import api as db_api
|
||||
from tacker.db.db_sqlalchemy import api
|
||||
|
@ -28,6 +29,50 @@ LOG = logging.getLogger(__name__)
|
|||
CONF = tacker.conf.CONF
|
||||
|
||||
|
||||
VNF_INSTANCE_SUBSCRIPTION_FILTER = [
|
||||
"vnfdIds", "vnfProvider", "vnfProductName",
|
||||
"vnfSoftwareVersion", "vnfdVersions", "vnfInstanceIds",
|
||||
"vnfInstanceNames"
|
||||
]
|
||||
|
||||
|
||||
VNF_INSTANCE_SUBSCRIPTION_FILTER_LISTS = [
|
||||
"vnfdIds", "vnfdVersions", "vnfInstanceIds", "vnfInstanceNames"
|
||||
]
|
||||
|
||||
|
||||
def _get_vnf_subscription_filter_values(vnf_subscription_filter):
|
||||
vnfd_ids = vnf_subscription_filter.get('vnfdIds', [])
|
||||
vnf_instance_ids = vnf_subscription_filter.get('vnfInstanceIds', [])
|
||||
vnf_instance_names = vnf_subscription_filter.get('vnfInstanceNames', [])
|
||||
|
||||
vnfd_products_from_providers = vnf_subscription_filter.get(
|
||||
'vnfProductsFromProviders', {})
|
||||
vnf_provider = vnfd_products_from_providers.get('vnfProvider', "")
|
||||
vnf_products = vnfd_products_from_providers.get('vnfProducts', [])
|
||||
|
||||
vnf_product_name = ""
|
||||
vnf_software_version = ""
|
||||
vnfd_versions = []
|
||||
if vnf_products:
|
||||
vnf_product_name = vnf_products[0].get('vnfProductName', "")
|
||||
versions = vnf_products[0].get('versions', [])
|
||||
if versions:
|
||||
vnf_software_version = versions[0].get('vnfSoftwareVersion', "")
|
||||
vnfd_versions = versions[0].get('vnfdVersions', [])
|
||||
|
||||
vnf_subscription_array = [
|
||||
{'vnfdIds': vnfd_ids},
|
||||
{'vnfInstanceIds': vnf_instance_ids},
|
||||
{'vnfInstanceNames': vnf_instance_names},
|
||||
{'vnfProvider': vnf_provider},
|
||||
{'vnfProductName': vnf_product_name},
|
||||
{'vnfSoftwareVersion': vnf_software_version},
|
||||
{'vnfdVersions': vnfd_versions}]
|
||||
|
||||
return vnf_subscription_array
|
||||
|
||||
|
||||
def _make_list(value):
|
||||
if isinstance(value, list):
|
||||
res = ""
|
||||
|
@ -165,7 +210,9 @@ def _get_by_subscriptionid(context, subscriptionsId):
|
|||
def _vnf_lcm_subscriptions_id_get(context,
|
||||
callbackUri,
|
||||
notification_type=None,
|
||||
operation_type=None
|
||||
operation_type=None,
|
||||
operation_state=None,
|
||||
vnf_instance_subscription_filter=None
|
||||
):
|
||||
|
||||
sql = ("select "
|
||||
|
@ -175,6 +222,35 @@ def _vnf_lcm_subscriptions_id_get(context,
|
|||
"(select subscription_uuid from vnf_lcm_filters "
|
||||
"where ")
|
||||
|
||||
if vnf_instance_subscription_filter:
|
||||
included_in_filter = []
|
||||
column_list = _get_vnf_subscription_filter_values(
|
||||
vnf_instance_subscription_filter)
|
||||
|
||||
for column in column_list:
|
||||
for key in column:
|
||||
if key in VNF_INSTANCE_SUBSCRIPTION_FILTER:
|
||||
value = column[key]
|
||||
if key in VNF_INSTANCE_SUBSCRIPTION_FILTER_LISTS:
|
||||
value = _make_list(value)
|
||||
else:
|
||||
value = '"{}"'.format(value)
|
||||
sql = (sql + " JSON_CONTAINS({}, '{}') and ".format(
|
||||
convert_string_to_snakecase(key),
|
||||
value
|
||||
))
|
||||
included_in_filter.append(key)
|
||||
|
||||
not_included_in_filter = list(
|
||||
set(VNF_INSTANCE_SUBSCRIPTION_FILTER_LISTS) -
|
||||
set(included_in_filter))
|
||||
|
||||
# items not being searched for is excluded by adding
|
||||
# <name>_len=0 to the sql query
|
||||
for key in not_included_in_filter:
|
||||
sql = sql + " {}_len=0 and ".format(
|
||||
convert_string_to_snakecase(key))
|
||||
|
||||
if notification_type:
|
||||
sql = (sql + " JSON_CONTAINS(notification_types, '" +
|
||||
_make_list(notification_type) + "') ")
|
||||
|
@ -182,6 +258,13 @@ def _vnf_lcm_subscriptions_id_get(context,
|
|||
sql = sql + " notification_types_len=0 "
|
||||
sql = sql + "and "
|
||||
|
||||
if operation_state:
|
||||
sql = (sql + " JSON_CONTAINS(operation_states, '" +
|
||||
_make_list(operation_state) + "') ")
|
||||
else:
|
||||
sql = sql + " operation_states_len=0 "
|
||||
sql = sql + "and "
|
||||
|
||||
if operation_type:
|
||||
sql = sql + " JSON_CONTAINS(operation_types, '" + \
|
||||
_make_list(operation_type) + "') "
|
||||
|
@ -200,14 +283,25 @@ def _vnf_lcm_subscriptions_id_get(context,
|
|||
return line
|
||||
except exceptions.NotFound:
|
||||
return ''
|
||||
except Exception as exc:
|
||||
LOG.error("SQL Error: %s" % str(exc))
|
||||
return ''
|
||||
|
||||
|
||||
def _add_filter_data(context, subscription_id, filter):
|
||||
with db_api.context_manager.writer.using(context):
|
||||
vnf_instance_subscription_filter = \
|
||||
filter.get('vnfInstanceSubscriptionFilter')
|
||||
|
||||
vnf_products_from_providers = \
|
||||
vnf_instance_subscription_filter.get(
|
||||
'vnfProductsFromProviders')
|
||||
|
||||
new_entries = []
|
||||
new_entries.append({"subscription_uuid": subscription_id,
|
||||
"filter": filter})
|
||||
"filter": filter,
|
||||
"vnf_products_from_providers":
|
||||
vnf_products_from_providers})
|
||||
|
||||
context.session.execute(
|
||||
models.VnfLcmFilters.__table__.insert(None),
|
||||
|
@ -236,12 +330,16 @@ def _vnf_lcm_subscriptions_create(context, values, filter):
|
|||
if filter:
|
||||
notification_type = filter.get('notificationTypes')
|
||||
operation_type = filter.get('operationTypes')
|
||||
operation_state = filter.get('operationStates')
|
||||
subscription_filter = filter.get('vnfInstanceSubscriptionFilter')
|
||||
|
||||
vnf_lcm_subscriptions_id = _vnf_lcm_subscriptions_id_get(
|
||||
context,
|
||||
callbackUri,
|
||||
notification_type=notification_type,
|
||||
operation_type=operation_type)
|
||||
operation_type=operation_type,
|
||||
operation_state=operation_state,
|
||||
vnf_instance_subscription_filter=subscription_filter)
|
||||
|
||||
if vnf_lcm_subscriptions_id:
|
||||
raise Exception("303" + vnf_lcm_subscriptions_id)
|
||||
|
|
|
@ -30,6 +30,23 @@ class Subscription:
|
|||
"""
|
||||
return {
|
||||
"filter": {
|
||||
"vnfInstanceSubscriptionFilter": {
|
||||
"vnfdIds": ["b1bb0ce7-ebca-4fa7-95ed-4840d7000000"],
|
||||
"vnfProductsFromProviders": {
|
||||
"vnfProvider": "Company",
|
||||
"vnfProducts": [
|
||||
{
|
||||
"vnfProductName": "Sample VNF",
|
||||
"versions": [
|
||||
{
|
||||
"vnfSoftwareVersion": "1.0",
|
||||
"vnfdVersions": ["1.0"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"notificationTypes": [
|
||||
"VnfLcmOperationOccurrenceNotification",
|
||||
"VnfIdentifierCreationNotification",
|
||||
|
@ -42,7 +59,8 @@ class Subscription:
|
|||
"HEAL",
|
||||
"MODIFY_INFO",
|
||||
"CHANGE_EXT_CONN"
|
||||
]
|
||||
],
|
||||
"operationStates": ["STARTING"]
|
||||
},
|
||||
"callbackUri": callback_uri
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import urllib
|
|||
import webob
|
||||
from webob import exc
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from tacker.api.vnflcm.v1 import controller
|
||||
|
@ -37,6 +38,7 @@ from tacker.extensions import vnfm
|
|||
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.tests import constants
|
||||
from tacker.tests.unit import base
|
||||
from tacker.tests.unit.db import utils
|
||||
|
@ -3731,3 +3733,143 @@ class TestController(base.TestCase):
|
|||
self.assertEqual(
|
||||
"Can not find requested vnf: %s" % constants.INVALID_UUID,
|
||||
resp.json['itemNotFound']['message'])
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
@ddt.data('operationTypes', 'operationStates')
|
||||
def test_register_subscription_operation_mismatch(
|
||||
self, attribute, mock_get_service_plugins):
|
||||
body = {
|
||||
'callbackUri': 'http://sample_callback_uri',
|
||||
'filter': {
|
||||
'notificationType': [
|
||||
'VnfLcmOperationOccurrenceNotification'],
|
||||
attribute: ['sample_operation']
|
||||
}
|
||||
}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/subscriptions')
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
|
||||
self.assertEqual(http_client.BAD_REQUEST, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
def test_register_subscription_operation_notification_mismatch(
|
||||
self, mock_get_service_plugins):
|
||||
body = {
|
||||
'callbackUri': 'http://sample_callback_uri',
|
||||
'filter': {
|
||||
'notificationTypes': ['sample_notification'],
|
||||
}
|
||||
}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/subscriptions')
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
|
||||
self.assertEqual(http_client.BAD_REQUEST, resp.status_code)
|
||||
|
||||
@mock.patch.object(subscription_obj.LccnSubscriptionRequest, 'create')
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
def test_register_subscription_vnf_instance_subscription_filter(
|
||||
self, mock_get_service_plugins, mock_create):
|
||||
cfg.CONF.set_override('test_callback_uri', False,
|
||||
group='vnf_lcm')
|
||||
body = {
|
||||
'callbackUri': 'http://sample_callback_uri',
|
||||
'filter': {
|
||||
'notificationTypes': ['VnfLcmOperationOccurrenceNotification'],
|
||||
'vnfInstanceSubscriptionFilter': {
|
||||
"vnfdIds": [],
|
||||
"vnfProductsFromProviders": {
|
||||
"vnfProvider": "Vnf Provider 1",
|
||||
"vnfProducts": [
|
||||
{
|
||||
"vnfProductName": "Vnf Product 1",
|
||||
"versions": [
|
||||
{
|
||||
"vnfSoftwareVersion": "v1",
|
||||
"vnfdVersions": ["vnfd.v1.1"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/subscriptions')
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.CREATED, resp.status_code)
|
||||
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
def test_register_subscription_vnf_instance_subscription_filter_error(
|
||||
self, mock_get_service_plugins):
|
||||
body = {
|
||||
'callbackUri': 'http://sample_callback_uri',
|
||||
'filter': {
|
||||
'notificationTypes': ['VnfLcmOperationOccurrenceNotification'],
|
||||
'vnfInstanceSubscriptionFilter': {
|
||||
"vnfdIds": [],
|
||||
"vnfProductsFromProviders": {
|
||||
"vnfProducts": [
|
||||
{
|
||||
"vnfProductName": "Vnf Product 1",
|
||||
"versions": [
|
||||
{
|
||||
"vnfSoftwareVersion": "v1",
|
||||
"vnfdVersions": ["vnfd.v1.1"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/subscriptions')
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.BAD_REQUEST, resp.status_code)
|
||||
|
||||
@mock.patch.object(subscription_obj.LccnSubscriptionRequest, 'create')
|
||||
@mock.patch.object(TackerManager, 'get_service_plugins',
|
||||
return_value={'VNFM': FakeVNFMPlugin()})
|
||||
def test_register_subscription(
|
||||
self, mock_get_service_plugins, mock_save):
|
||||
cfg.CONF.set_override('test_callback_uri', False,
|
||||
group='vnf_lcm')
|
||||
body = {
|
||||
'callbackUri': 'http://sample_callback_uri'
|
||||
}
|
||||
|
||||
req = fake_request.HTTPRequest.blank(
|
||||
'/subscriptions')
|
||||
req.body = jsonutils.dump_as_bytes(body)
|
||||
req.headers['Content-Type'] = 'application/json'
|
||||
req.method = 'POST'
|
||||
|
||||
resp = req.get_response(self.app)
|
||||
self.assertEqual(http_client.CREATED, resp.status_code)
|
||||
|
|
Loading…
Reference in New Issue