Merge "Fix API pagination problem in multi servers"

This commit is contained in:
Zuul 2023-03-09 15:56:24 +00:00 committed by Gerrit Code Review
commit c65931ceab
12 changed files with 604 additions and 310 deletions

View File

@ -44,7 +44,8 @@ class ViewBuilder(base.BaseViewBuilder):
def _basic_subscription_info(self, vnf_lcm_subscription, filter=None):
if filter is None:
if 'filter' in vnf_lcm_subscription:
filter_dict = {}
filter_dict = json.loads(
vnf_lcm_subscription.filter)
if 'filter' in vnf_lcm_subscription.filter:
filter_dict = json.loads(

View File

@ -56,8 +56,11 @@ from tacker import manager
from tacker import objects
from tacker.objects import fields
from tacker.objects.fields import ErrorPoint as EP
from tacker.objects.vnf_instance import VnfInstanceList as vnf_instance_list
from tacker.objects import vnf_lcm_op_occs as vnf_lcm_op_occs_obj
from tacker.objects.vnf_lcm_op_occs import VnfLcmOpOccList as vnf_lcm_op_list
from tacker.objects import vnf_lcm_subscriptions as subscription_obj
from tacker.objects.vnf_lcm_subscriptions import LccnSubscriptionList as s_list
from tacker.plugins.common import constants
from tacker.policies import vnf_lcm as vnf_lcm_policies
from tacker.tosca import utils as toscautils
@ -192,9 +195,6 @@ class VnfLcmController(wsgi.Controller):
self._vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM']
self._view_builder_op_occ = vnf_op_occs_view.ViewBuilder()
self._view_builder_subscription = vnf_subscription_view.ViewBuilder()
self._nextpages_vnf_instances = {}
self._nextpages_lcm_op_occs = {}
self._nextpages_subscriptions = {}
def _get_vnf_instance_href(self, vnf_instance):
return '{}vnflcm/v1/vnf_instances/{}'.format(
@ -560,13 +560,6 @@ class VnfLcmController(wsgi.Controller):
return vnf_package_info[0]
def _delete_expired_nextpages(self, nextpages):
for k, v in list(nextpages.items()):
if timeutils.is_older_than(v['created_time'],
CONF.vnf_lcm.nextpage_expiration_time):
LOG.debug('Old nextpages are deleted. id: %s' % k)
nextpages.pop(k)
@wsgi.response(http_client.OK)
@wsgi.expected_errors((http_client.FORBIDDEN, http_client.NOT_FOUND))
def show(self, request, id):
@ -596,39 +589,43 @@ class VnfLcmController(wsgi.Controller):
nextpage = request.GET.get('nextpage_opaque_marker')
allrecords = request.GET.get('all_records')
limit = None
marker_obj = None
result = []
if allrecords != 'yes' and nextpage:
self._delete_expired_nextpages(self._nextpages_vnf_instances)
# get maximum record size per page
if allrecords != 'yes':
limit = CONF.vnf_lcm.vnf_instance_num
if nextpage in self._nextpages_vnf_instances:
result = self._nextpages_vnf_instances.pop(
nextpage)['nextpage']
else:
vnf_instances = objects.VnfInstanceList.get_by_filters(
request.context, filters=filters)
# get next page marker object from nextpage id
if nextpage:
marker_obj = objects.VnfInstance.get_by_id(request.context,
nextpage)
try:
# get records from DB within maximum record size per page
# except for getting all records case
result = vnf_instance_list.get_by_marker_filter(request.context,
limit, marker_obj, filters=filters)
except Exception as e:
LOG.exception(traceback.format_exc())
return self._make_problem_detail(
str(e), 500, title='Internal Server Error')
result = self._view_builder.index(vnf_instances)
result = self._view_builder.index(result)
res = webob.Response(content_type='application/json')
res.status_int = 200
if (allrecords != 'yes' and
len(result) > CONF.vnf_lcm.vnf_instance_num):
nextpageid = uuidutils.generate_uuid()
# if the number of records obtained from DB is equal to maximum record
# size per page, the id of the last record is used as next page marker
# and set it to Link header of the response
if (allrecords != 'yes' and len(result) >= limit):
nextpageid = result[(limit - 1)]['id']
links = ('Link', '<%s?nextpage_opaque_marker=%s>; rel="next"' % (
request.path_url, nextpageid))
res.headerlist.append(links)
res.body = jsonutils.dump_as_bytes(
result[: CONF.vnf_lcm.vnf_instance_num])
self._delete_expired_nextpages(self._nextpages_vnf_instances)
remain = result[CONF.vnf_lcm.vnf_instance_num:]
self._nextpages_vnf_instances.update({nextpageid:
{'created_time': timeutils.utcnow(), 'nextpage': remain}})
else:
res.body = jsonutils.dump_as_bytes(result)
res.body = jsonutils.dump_as_bytes(result)
return res
@ -1061,9 +1058,9 @@ class VnfLcmController(wsgi.Controller):
@wsgi.response(http_client.OK)
def subscription_list(self, request):
nextpage_opaque_marker = None
paging = 1
filter_string = ""
ignore_nextpages = False
limit = None
marker_obj = None
subscription_data = []
query_params = request.query_string
@ -1083,9 +1080,6 @@ class VnfLcmController(wsgi.Controller):
filter_string = query_param_key_value[1]
if query_param_key_value[0] == 'nextpage_opaque_marker':
nextpage_opaque_marker = query_param_key_value[1]
if query_param_key_value[0] == 'page':
paging = int(query_param_key_value[1])
ignore_nextpages = True
if filter_string:
# check enumerations columns
@ -1114,55 +1108,48 @@ class VnfLcmController(wsgi.Controller):
title='Bad Request')
nextpage = nextpage_opaque_marker
if allrecords != 'yes' and not ignore_nextpages and nextpage:
self._delete_expired_nextpages(self._nextpages_subscriptions)
if nextpage in self._nextpages_subscriptions:
subscription_data = self._nextpages_subscriptions.pop(
nextpage)['nextpage']
else:
try:
filter_string_parsed = self._view_builder_subscription. \
validate_filter(filter_string)
if nextpage_opaque_marker:
start_index = paging - 1
else:
start_index = None
try:
filter_string_parsed = self._view_builder_subscription. \
validate_filter(filter_string)
vnf_lcm_subscriptions = (
subscription_obj.LccnSubscriptionList.
get_by_filters(request.context,
read_deleted='no',
filters=filter_string_parsed,
nextpage_opaque_marker=start_index))
# get maximum record size per page
if allrecords != 'yes':
limit = CONF.vnf_lcm.subscription_num
LOG.debug("vnf_lcm_subscriptions %s" % vnf_lcm_subscriptions)
subscription_data = self._view_builder_subscription. \
subscription_list(vnf_lcm_subscriptions)
except Exception as e:
LOG.error(traceback.format_exc())
return self._make_problem_detail(
str(e), 500, title='Internal Server Error')
# get next page marker object from nextpage id
if nextpage:
marker_obj = objects.LccnSubscription.get_by_id(
request.context, nextpage)
# get records from DB within maximum record size per page
# except for getting all records case
result = s_list.get_by_marker_filter(
request.context, limit,
marker_obj, filters=filter_string_parsed,
read_deleted='no')
LOG.debug("vnf_lcm_subscriptions %s" % result)
subscription_data = self._view_builder_subscription. \
subscription_list(result)
except Exception as e:
LOG.error(traceback.format_exc())
return self._make_problem_detail(
str(e), 500, title='Internal Server Error')
# make response
res = webob.Response(content_type='application/json')
res.status_int = 200
if (allrecords != 'yes' and not ignore_nextpages and
len(subscription_data) > CONF.vnf_lcm.subscription_num):
nextpageid = uuidutils.generate_uuid()
# if the number of records obtained from DB is equal to maximum record
# size per page, the id of the last record is used as next page marker
# and set it to Link header of the response
if (allrecords != 'yes' and len(subscription_data) >= limit):
nextpageid = subscription_data[(limit - 1)]['id']
links = ('Link', '<%s?nextpage_opaque_marker=%s>; rel="next"' % (
request.path_url, nextpageid))
res.headerlist.append(links)
remain = subscription_data[CONF.vnf_lcm.subscription_num:]
subscription_data = (
subscription_data[: CONF.vnf_lcm.subscription_num])
self._delete_expired_nextpages(self._nextpages_subscriptions)
self._nextpages_subscriptions.update({nextpageid:
{'created_time': timeutils.utcnow(), 'nextpage': remain}})
res.body = jsonutils.dump_as_bytes(subscription_data)
LOG.debug("subscription_list res %s" % res)
@ -1748,52 +1735,53 @@ class VnfLcmController(wsgi.Controller):
nextpage = request.GET.get('nextpage_opaque_marker')
allrecords = request.GET.get('all_records')
limit = None
marker_obj = None
result = []
if allrecords != 'yes' and nextpage:
self._delete_expired_nextpages(self._nextpages_lcm_op_occs)
self._view_builder_op_occ.validate_attribute_fields(
all_fields=all_fields, fields=fields,
exclude_fields=exclude_fields,
exclude_default=exclude_default)
if nextpage in self._nextpages_lcm_op_occs:
result = self._nextpages_lcm_op_occs.pop(nextpage)['nextpage']
else:
self._view_builder_op_occ.validate_attribute_fields(
all_fields=all_fields, fields=fields,
exclude_fields=exclude_fields,
exclude_default=exclude_default)
filters = self._view_builder_op_occ.validate_filter(filters)
filters = self._view_builder_op_occ.validate_filter(filters)
# get maximum record size per page
if allrecords != 'yes':
limit = CONF.vnf_lcm.lcm_op_occ_num
try:
vnf_lcm_op_occs = (
vnf_lcm_op_occs_obj.VnfLcmOpOccList.get_by_filters(
request.context, read_deleted='no', filters=filters))
except Exception as e:
LOG.exception(traceback.format_exc())
return self._make_problem_detail(
str(e), 500, title='Internal Server Error')
# get next page marker object from nextpage id
if nextpage:
marker_obj = vnf_lcm_op_occs_obj.VnfLcmOpOcc.get_by_id(
request.context, nextpage)
result = self._view_builder_op_occ.index(request, vnf_lcm_op_occs,
all_fields=all_fields, exclude_fields=exclude_fields,
fields=fields, exclude_default=exclude_default)
try:
# get records from DB within maximum record size per page
# except for getting all records case
result = vnf_lcm_op_list.get_by_marker_filter(request.context,
limit, marker_obj, filters=filters, read_deleted='no')
except Exception as e:
LOG.exception(traceback.format_exc())
return self._make_problem_detail(
str(e), 500, title='Internal Server Error')
result = self._view_builder_op_occ.index(request, result,
all_fields=all_fields, exclude_fields=exclude_fields,
fields=fields, exclude_default=exclude_default)
res = webob.Response(content_type='application/json')
res.status_int = 200
if allrecords != 'yes' and len(result) > CONF.vnf_lcm.lcm_op_occ_num:
nextpageid = uuidutils.generate_uuid()
# if the number of records obtained from DB is equal to maximum record
# size per page, the id of the last record is used as next page marker
# and set it to Link header of the response
if (allrecords != 'yes' and len(result) >= limit):
nextpageid = result[(limit - 1)]['id']
links = ('Link', '<%s?nextpage_opaque_marker=%s>; rel="next"' % (
request.path_url, nextpageid))
res.headerlist.append(links)
res.body = jsonutils.dump_as_bytes(
result[: CONF.vnf_lcm.lcm_op_occ_num])
self._delete_expired_nextpages(self._nextpages_lcm_op_occs)
remain = result[CONF.vnf_lcm.lcm_op_occ_num:]
self._nextpages_lcm_op_occs.update({nextpageid:
{'created_time': timeutils.utcnow(), 'nextpage': remain}})
else:
res.body = jsonutils.dump_as_bytes(result)
res.body = jsonutils.dump_as_bytes(result)
return res

View File

@ -18,6 +18,7 @@ from io import BytesIO
import json
import mimetypes
import os
import traceback
import webob
import zipfile
from zipfile import ZipFile
@ -28,7 +29,6 @@ from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import encodeutils
from oslo_utils import excutils
from oslo_utils import timeutils
from oslo_utils import uuidutils
from tacker._i18n import _
@ -40,8 +40,10 @@ from tacker.common import exceptions
from tacker.common import utils
from tacker.conductor.conductorrpc import vnf_pkgm_rpc
from tacker.glance_store import store as glance_store
from tacker import objects
from tacker.objects import fields
from tacker.objects import vnf_package as vnf_package_obj
from tacker.objects.vnf_package import VnfPackagesList as vnf_package_list
from tacker.policies import vnf_package as vnf_package_policies
from tacker import wsgi
@ -75,13 +77,6 @@ class VnfPkgmController(wsgi.Controller):
raise webob.exc.HTTPNotFound(explanation=msg)
return vnf_package
def _delete_expired_nextpages(self, nextpages):
for k, v in nextpages.items():
if timeutils.is_older_than(v['created_time'],
CONF.vnf_package.nextpage_expiration_time):
LOG.debug('Old nextpages are deleted. id: %s' % k)
nextpages.pop(k)
@wsgi.response(http_client.CREATED)
@wsgi.expected_errors((http_client.BAD_REQUEST, http_client.FORBIDDEN))
@validation.schema(vnf_packages.create)
@ -162,42 +157,47 @@ class VnfPkgmController(wsgi.Controller):
filters = self._view_builder.validate_filter(filters)
results = []
limit = None
marker_obj = None
if allrecords != 'yes' and nextpage:
self._delete_expired_nextpages(self._nextpages)
if allrecords != 'yes':
limit = CONF.vnf_package.vnf_package_num
if nextpage in self._nextpages:
results = self._nextpages.pop(
nextpage)['nextpage']
else:
vnf_packages = vnf_package_obj.VnfPackagesList.get_by_filters(
request.context, read_deleted='no', filters=filters)
# get next page marker object from nextpage id
if nextpage:
marker_obj = objects.VnfPackage.get_by_id(request.context,
nextpage)
results = self._view_builder.index(vnf_packages,
all_fields=all_fields,
exclude_fields=exclude_fields,
fields=fields,
exclude_default=exclude_default)
try:
# get records from DB within maximum record size per page
# except for getting all records case
result = vnf_package_list.get_by_marker_filter(request.context,
limit, marker_obj, filters=filters, read_deleted='no')
except Exception as e:
LOG.exception(traceback.format_exc())
return self._make_problem_detail(
str(e), 500, title='Internal Server Error')
results = self._view_builder.index(result,
all_fields=all_fields,
exclude_fields=exclude_fields,
fields=fields,
exclude_default=exclude_default)
res = webob.Response(content_type='application/json')
res.status_int = 200
# if the number of records obtained from DB is equal to maximum record
# size per page, the id of the last record is used as next page marker
# and set it to Link header of the response
if (allrecords != 'yes' and
len(results) > CONF.vnf_package.vnf_package_num):
nextpageid = uuidutils.generate_uuid()
len(results) >= limit):
nextpageid = result[(limit - 1)]['id']
links = ('Link', '<%s?nextpage_opaque_marker=%s>; rel="next"' % (
request.path_url, nextpageid))
res.headerlist.append(links)
res.body = jsonutils.dump_as_bytes(
results[: CONF.vnf_package.vnf_package_num], default=str)
self._delete_expired_nextpages(self._nextpages)
remain = results[CONF.vnf_package.vnf_package_num:]
self._nextpages.update({nextpageid:
{'created_time': timeutils.utcnow(), 'nextpage': remain}})
else:
res.body = jsonutils.dump_as_bytes(results, default=str)
res.body = jsonutils.dump_as_bytes(results, default=str)
return res

View File

@ -55,11 +55,7 @@ OPTS = [
cfg.IntOpt(
'vnf_instance_num',
default=100,
help="Number of vnf_instances contained in 1 page"),
cfg.IntOpt(
'nextpage_expiration_time',
default=3600,
help="Expiration time (sec) for paging")]
help="Number of vnf_instances contained in 1 page")]
vnf_lcm_group = cfg.OptGroup('vnf_lcm',
title='vnf_lcm options',

View File

@ -78,10 +78,7 @@ Related options:
help=_("List of del inputs from lower-vnfd")),
cfg.IntOpt('vnf_package_num',
default=100,
help=_("Number of vnf_packages contained in 1 page")),
cfg.IntOpt('nextpage_expiration_time',
default=3600,
help=_("Expiration time (sec) for paging")),
help=_("Number of vnf_packages contained in 1 page"))
]

View File

@ -27,6 +27,7 @@ from tacker.common import utils
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.db import sqlalchemyutils
from tacker.db.vnfm import vnfm_db
from tacker import objects
from tacker.objects import base
@ -127,6 +128,23 @@ def _vnf_instance_list_by_filter(context, columns_to_join=None,
return query.all()
@db_api.context_manager.reader
def _vnf_instance_list_by_filter_query(context, columns_to_join=None,
filters=None):
query = api.model_query(context, models.VnfInstance,
read_deleted="no",
project_only=True)
if columns_to_join:
for column in columns_to_join:
query = query.options(joinedload(column))
if filters:
query = common.apply_filters(query, filters)
return query
def _make_vnf_instance_list(context, vnf_instance_list, db_vnf_instance_list,
expected_attrs):
vnf_instance_cls = VnfInstance
@ -545,6 +563,22 @@ class VnfInstanceList(ovoo_base.ObjectListBase, base.TackerObject):
return _make_vnf_instance_list(context, cls(), db_vnf_instances,
expected_attrs)
@base.remotable_classmethod
def get_by_marker_filter(cls, context, limit, marker_obj,
filters=None, expected_attrs=None):
expected_attrs = ["instantiated_vnf_info"]
query = _vnf_instance_list_by_filter_query(context,
columns_to_join=expected_attrs,
filters=filters)
query = sqlalchemyutils.paginate_query(query, model=models.VnfInstance,
limit=limit,
sorts=[['id', 'asc']],
marker_obj=marker_obj)
db_vnf_instances = query.all()
return _make_vnf_instance_list(context, cls(), db_vnf_instances,
expected_attrs)
@base.remotable_classmethod
def get_by_filters(cls, context, filters=None,
expected_attrs=None):

View File

@ -24,6 +24,7 @@ from tacker.common import utils
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.db import sqlalchemyutils
from tacker import objects
from tacker.objects import base
from tacker.objects import common
@ -151,6 +152,19 @@ def _vnf_lcm_op_occs_get_by_filters(context, read_deleted=None,
return query.all()
@db_api.context_manager.reader
def _vnf_lcm_op_occs_get_by_filters_query(context, read_deleted=None,
filters=None):
query = api.model_query(context, models.VnfLcmOpOccs,
read_deleted=read_deleted, project_only=True)
if filters:
query = common.apply_filters(query, filters)
return query
@db_api.context_manager.reader
def _vnf_notify_get_by_id(context, vnf_instance_id, columns_to_join=None):
@ -484,6 +498,19 @@ class VnfLcmOpOccList(ovoo_base.ObjectListBase, base.TackerObject):
context, read_deleted=read_deleted, filters=filters)
return _make_vnf_lcm_op_occs_list(context, cls(), db_vnf_lcm_op_occs)
@base.remotable_classmethod
def get_by_marker_filter(cls, context, limit,
marker_obj, filters=None, read_deleted=None):
query = _vnf_lcm_op_occs_get_by_filters_query(
context, read_deleted=read_deleted, filters=filters)
query = sqlalchemyutils.paginate_query(query,
model=models.VnfLcmOpOccs,
limit=limit,
sorts=[['id', 'asc']],
marker_obj=marker_obj)
db_vnf_lcm_op_occs = query.all()
return _make_vnf_lcm_op_occs_list(context, cls(), db_vnf_lcm_op_occs)
@base.TackerObjectRegistry.register
class ResourceChanges(base.TackerObject,

View File

@ -24,6 +24,7 @@ import tacker.conf
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.db import sqlalchemyutils
from tacker import objects
from tacker.objects import base
from tacker.objects import common
@ -381,6 +382,37 @@ def _vnf_lcm_subscription_list_by_filters(context,
return query.order_by(models.VnfLcmSubscriptions.created_at).all()
@db_api.context_manager.reader
def _vnf_lcm_subscription_get_query(context, read_deleted=None, filters=None):
query = api.model_query(context, models.VnfLcmSubscriptions,
read_deleted=read_deleted,
project_only=True)
binary_columns = ['notification_types', 'operation_types']
if filters:
filter_data = json.dumps(filters)
if 'ChangeNotificationsFilter' in filter_data:
query = query.join(models.VnfLcmFilters)
if 'and' in filters:
filters_and = []
for filter in filters['and']:
if filter['field'] in binary_columns:
converted_value = utils.str_to_bytes(filter['value'])
filter['value'] = converted_value
filters_and.append(filter)
filters = {'and': filters_and}
else:
if filters['field'] in binary_columns:
converted_value = utils.str_to_bytes(filters['value'])
filters.update({'value': converted_value})
query = common.apply_filters(query, filters)
return query.order_by(models.VnfLcmSubscriptions.created_at)
@db_api.context_manager.writer
def _vnf_lcm_subscriptions_create(context, values, filter):
with db_api.context_manager.writer.using(context):
@ -721,6 +753,22 @@ class LccnSubscriptionList(ovoo_base.ObjectListBase, base.TackerObject):
'objects': fields.ListOfObjectsField('LccnSubscription')
}
@base.remotable_classmethod
def get_by_marker_filter(cls, context,
limit, marker_obj,
filters=None, read_deleted=None):
query = _vnf_lcm_subscription_get_query(context,
read_deleted=read_deleted,
filters=filters)
query = sqlalchemyutils.paginate_query(query,
model=models.VnfLcmSubscriptions,
limit=limit,
sorts=[['id', 'asc']],
marker_obj=marker_obj)
db_subscriptions = query.all()
return _make_subscription_list(context, cls(), db_subscriptions)
@base.remotable_classmethod
def get_by_filters(cls, context, read_deleted=None,
filters=None, nextpage_opaque_marker=None):

View File

@ -29,6 +29,7 @@ from tacker.common import utils
from tacker.db import api as db_api
from tacker.db.db_sqlalchemy import api
from tacker.db.db_sqlalchemy import models
from tacker.db import sqlalchemyutils
from tacker import objects
from tacker.objects import base
from tacker.objects import common
@ -115,6 +116,39 @@ def _update_user_defined_data(context, package_uuid, user_data):
return result
@db_api.context_manager.reader
def _vnf_packages_get_by_filters_query(context, read_deleted=None,
filters=None):
query = api.model_query(context, models.VnfPackage,
read_deleted=read_deleted,
project_only=True).options(joinedload('_metadata'))
if filters:
# Need to join VnfDeploymentFlavour, VnfSoftwareImage and
# VnfSoftwareImageMetadata db table explicitly
# only when filters contains one of the column matching
# from VnfSoftwareImage or VnfSoftwareImageMetadata db table.
filter_data = json.dumps(filters)
if 'VnfSoftwareImageMetadata' in filter_data:
query = query.join(models.VnfDeploymentFlavour).join(
models.VnfSoftwareImage).join(
models.VnfSoftwareImageMetadata)
elif 'VnfSoftwareImage' in filter_data:
query = query.join(models.VnfDeploymentFlavour).join(
models.VnfSoftwareImage)
if 'VnfPackageArtifactInfo' in filter_data:
query = query.join(models.VnfPackageArtifactInfo)
if 'VnfPackageVnfd' in filter_data:
query = query.join(models.VnfPackageVnfd)
query = common.apply_filters(query, filters)
return query
@db_api.context_manager.reader
def _vnf_package_get_by_id(context, package_uuid, columns_to_join=None):
@ -678,6 +712,22 @@ class VnfPackagesList(ovoo_base.ObjectListBase, base.TackerObject):
return _make_vnf_packages_list(context, cls(), db_vnf_packages,
expected_attrs)
@base.remotable_classmethod
def get_by_marker_filter(cls, context,
limit, marker_obj,
filters=None, read_deleted=None):
query = _vnf_packages_get_by_filters_query(context,
read_deleted=read_deleted,
filters=filters)
query = sqlalchemyutils.paginate_query(query,
model=models.VnfPackage,
limit=limit,
sorts=[['id', 'asc']],
marker_obj=marker_obj)
db_vnf_packages = query.all()
return _make_vnf_packages_list(context, cls(), db_vnf_packages)
@base.remotable_classmethod
def get_by_filters(cls, context, read_deleted=None, filters=None):
db_vnf_packages = _vnf_package_list_by_filters(context,

View File

@ -1882,7 +1882,15 @@ def _subscription_links(subscription_dict):
return subscription_dict
def return_subscription_obj(**updates):
def return_lccn_subscription(**updates):
subscription = _fake_subscription_obj(**updates)
subscription['filter'] = json.dumps(subscription['filter'])
obj = objects.LccnSubscription(**subscription)
return obj
def return_lccn_subscription_obj(**updates):
subscription = _fake_subscription_obj(**updates)
subscription['filter'] = json.dumps(subscription['filter'])
obj = objects.LccnSubscriptionRequest(**subscription)

View File

@ -1687,7 +1687,7 @@ class TestController(base.TestCase):
self.assertEqual(expected_message, exception.msg)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
def test_index(self, mock_vnf_list):
req = fake_request.HTTPRequest.blank('/vnf_instances')
vnf_instance_1 = fakes.return_vnf_instance()
@ -1701,7 +1701,8 @@ class TestController(base.TestCase):
fields.VnfInstanceState.INSTANTIATED)]
self.assertEqual(expected_result, resp.json)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter",
return_value=[])
def test_index_empty_response(self, mock_vnf_list):
req = fake_request.HTTPRequest.blank('/vnf_instances')
mock_vnf_list.return_value = []
@ -1831,7 +1832,7 @@ class TestController(base.TestCase):
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id,
resp.json['detail'])
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'filter': "(eq,vnfInstanceName,'dummy_name')"},
{'filter': "(in,vnfInstanceName,'dummy_name')"},
@ -1863,7 +1864,7 @@ class TestController(base.TestCase):
fields.VnfInstanceState.INSTANTIATED)]
self.assertEqual(expected_result, res_dict.json)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
def test_index_filter_combination(self, mock_vnf_list):
"""Test multiple filter parameters separated by semicolon."""
params = {
@ -1886,7 +1887,7 @@ class TestController(base.TestCase):
fields.VnfInstanceState.INSTANTIATED)]
self.assertEqual(expected_result, res_dict.json)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'filter': "(eq,vnfInstanceName,dummy_value)"},
{'filter': "(eq,vnfInstanceDescription,dummy value)"},
@ -1921,7 +1922,7 @@ class TestController(base.TestCase):
{'filter': "(eq,instantiatedInfo/additionalParams/error,'dummy')"},
)
def test_index_filter_attributes(self, filter_params,
mock_vnf_list):
mock_vnf_list):
"""Test various attributes supported for filter parameter."""
query = urllib.parse.urlencode(filter_params)
req = fake_request.HTTPRequest.blank(
@ -1939,7 +1940,7 @@ class TestController(base.TestCase):
fields.VnfInstanceState.INSTANTIATED)]
self.assertEqual(expected_result, res_dict.json)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'filter': "(eq,vnfInstanceName,value"},
{'filter': "eq,vnfInstanceName,value)"},
@ -1956,7 +1957,7 @@ class TestController(base.TestCase):
self.assertRaises(exceptions.ValidationError,
self.controller.index, req)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'filter': "(eq,vnfInstanceName,singl'quote)"},
{'filter': "(eq,vnfInstanceName,three''' quotes)"},
@ -1974,7 +1975,7 @@ class TestController(base.TestCase):
self.assertRaises(exceptions.ValidationError,
self.controller.index, req)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,vnfdId,value1,value2)'},
{'filter': '(fake,vnfdId,dummy_vnfd_id)'},
@ -1989,7 +1990,7 @@ class TestController(base.TestCase):
self.assertRaises(exceptions.ValidationError,
self.controller.index, req)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,fakeattr,fakevalue)'},
{'filter': '(eq,,fakevalue)'},
@ -2003,7 +2004,7 @@ class TestController(base.TestCase):
self.assertRaises(exceptions.ValidationError,
self.controller.index, req)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,data/size,fake_value)'},
{'filter': '(gt,data/createdAt,fake_value)'},
@ -2019,47 +2020,85 @@ class TestController(base.TestCase):
self.assertRaises(exceptions.ValidationError,
self.controller.index, req)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.vnf_instance.VnfInstanceList,
"get_by_marker_filter")
@mock.patch.object(objects.VnfInstance, "get_by_id")
@ddt.data(
{'params': {'all_records': 'yes'},
'result_names': ['sample1', 'sample2', 'sample3', 'sample4']},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker': 'abc'},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['sample1', 'sample2', 'sample3', 'sample4']},
{'params': {'nextpage_opaque_marker': 'abc'},
{'params': {'nextpage_opaque_marker':
'44444444-4444-4444-4444-444444444444'},
'result_names': []},
{'params': {'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['sample3', 'sample4']},
{'params': {},
'result_names': ['sample2']}
'result_names': ['sample1', 'sample2']}
)
def test_index_paging(self, values, mock_vnf_list):
cfg.CONF.set_override('vnf_instance_num', 1, group='vnf_lcm')
def test_index_paging(self, values,
mock_marker_obj,
mock_vnf_instance_list):
ids = ['11111111-1111-1111-1111-111111111111',
'22222222-2222-2222-2222-222222222222',
'33333333-3333-3333-3333-333333333333',
'44444444-4444-4444-4444-444444444444',
None]
cfg.CONF.set_override('vnf_instance_num', 2, group='vnf_lcm')
query = urllib.parse.urlencode(values['params'])
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_instances?' + query)
mock_vnf_list.return_value = [
fakes.return_vnf_instance(**{'vnf_instance_name': 'sample1'}),
fakes.return_vnf_instance(**{'vnf_instance_name': 'sample2'}),
fakes.return_vnf_instance(**{'vnf_instance_name': 'sample3'}),
fakes.return_vnf_instance(**{'vnf_instance_name': 'sample4'})
]
target_index = []
if 'all_records' in values['params'] \
and values['params']['all_records'] == 'yes':
mock_marker_obj.return_value = None
target_index = [0, 1, 2, 3]
elif 'nextpage_opaque_marker' in values['params']:
mock_marker_obj.return_value = fakes.return_vnf_instance(
**{'id': values['params']['nextpage_opaque_marker']})
marker_obj_index = ids.index(mock_marker_obj.return_value['id'])
for i in range(marker_obj_index + 1, len(ids) - 1):
target_index.append(i)
else:
mock_marker_obj.return_value = None
target_index = [0, 1]
mock_vnf_instance_list.return_value = []
for index in range(len(target_index)):
mock_vnf_instance_list.return_value.append(
fakes.return_vnf_instance(**{'id': ids[target_index[index]],
'vnf_instance_name':
values['result_names'][index]}))
expected_result = []
for name in values['result_names']:
for index in range(len(target_index)):
_links = fakes.fake_vnf_instance_response()['_links']
expected_links = (re.sub("vnf_instances/[a-zA-Z0-9-]*",
"vnf_instances/{}".format(ids[target_index[index]]),
str(_links)))
expected_links = json.loads(expected_links.replace("'", '"'))
expected_result.append(fakes.fake_vnf_instance_response(
**{'vnfInstanceName': name}))
**{'vnfInstanceName': values['result_names'][index],
'id': ids[target_index[index]],
'_links': expected_links}))
expected_result_link = None
if 'all_records' not in values['params'] and len(target_index) >= 2:
expected_result_link = (
'<http://localhost//vnflcm/v1/vnf_instances' +
'?nextpage_opaque_marker=%s>; rel="next"'
% ids[target_index[1]])
res_dict = self.controller.index(req)
if 'Link' in res_dict.headers:
next_url = re.findall('<(.*)>', res_dict.headers['Link'])[0]
query = urllib.parse.urlparse(next_url).query
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_instances?' + query)
res_dict = self.controller.index(req)
self.assertEqual(expected_result, res_dict.json)
if expected_result_link is not None:
self.assertEqual(expected_result_link, res_dict.headers['Link'])
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'attribute_not_exist': 'some_value'},
{'all_fields': {}},
@ -2078,7 +2117,7 @@ class TestController(base.TestCase):
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.index, req)
@mock.patch.object(objects.VnfInstanceList, "get_by_filters")
@mock.patch.object(objects.VnfInstanceList, "get_by_marker_filter")
@ddt.data(
{'attribute_not_exist': 'some_value'},
{'all_fields': {}},
@ -3795,7 +3834,7 @@ class TestController(base.TestCase):
resp = req.get_response(self.app)
self.assertEqual(http_client.INTERNAL_SERVER_ERROR, resp.status_code)
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_marker_filter")
def test_op_occ_list(self, mock_op_occ_list):
req = fake_request.HTTPRequest.blank('/vnflcm/v1/vnf_lcm_op_occs')
@ -3815,22 +3854,59 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result)),
resp.json)
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOccList,
"get_by_marker_filter")
@mock.patch.object(objects.vnf_lcm_op_occs.VnfLcmOpOcc, "get_by_id")
@ddt.data(
{'params': {'all_records': 'yes'},
'result_names': ['INSTANTIATE', 'SCALE', 'HEAL', 'TERMINATE']},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker': 'abc'},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['INSTANTIATE', 'SCALE', 'HEAL', 'TERMINATE']},
{'params': {'nextpage_opaque_marker': 'abc'},
{'params': {'nextpage_opaque_marker':
'44444444-4444-4444-4444-444444444444'},
'result_names': []},
{'params': {'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['HEAL', 'TERMINATE']},
{'params': {},
'result_names': ['SCALE']}
'result_names': ['INSTANTIATE', 'SCALE']}
)
def test_op_occ_list_paging(self, values, mock_op_occ_list):
cfg.CONF.set_override('lcm_op_occ_num', 1, group='vnf_lcm')
def test_op_occ_list_paging(self, values,
mock_marker_obj,
mock_op_occ_list):
ids = ['11111111-1111-1111-1111-111111111111',
'22222222-2222-2222-2222-222222222222',
'33333333-3333-3333-3333-333333333333',
'44444444-4444-4444-4444-444444444444',
None]
cfg.CONF.set_override('lcm_op_occ_num', 2, group='vnf_lcm')
query = urllib.parse.urlencode(values['params'])
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
target_index = []
if 'all_records' in values['params'] \
and values['params']['all_records'] == 'yes':
mock_marker_obj.return_value = None
target_index = [0, 1, 2, 3]
elif 'nextpage_opaque_marker' in values['params']:
mock_marker_obj.return_value = fakes.return_vnf_lcm_opoccs_obj(
**{'id': values['params']['nextpage_opaque_marker']})
if len(values['result_names']) > 0:
target_index.append(
ids.index(mock_marker_obj.return_value['id']) + 1)
target_index.append(
ids.index(mock_marker_obj.return_value['id']) + 2)
else:
mock_marker_obj.return_value = None
target_index = [0, 1]
mock_op_occ_list.return_value = []
for index in range(len(target_index)):
mock_op_occ_list.return_value.append(
fakes.return_vnf_lcm_opoccs_obj(
**{'id': ids[target_index[index]],
'operation': values['result_names'][index]}))
complex_attributes = [
'error',
@ -3838,34 +3914,36 @@ class TestController(base.TestCase):
'operationParams',
'changedInfo']
vnf_lcm_op_occ = [
fakes.return_vnf_lcm_opoccs_obj(**{'operation': 'INSTANTIATE'}),
fakes.return_vnf_lcm_opoccs_obj(**{'operation': 'SCALE'}),
fakes.return_vnf_lcm_opoccs_obj(**{'operation': 'HEAL'}),
fakes.return_vnf_lcm_opoccs_obj(**{'operation': 'TERMINATE'})
]
expected_result = []
for name in values['result_names']:
for index in range(len(target_index)):
_links = fakes.index_response()[0]['_links']
expected_links = re.sub("vnf_lcm_op_occs/[a-zA-Z0-9-]*",
"vnf_lcm_op_occs/{}".format(
ids[target_index[index]]), str(_links))
expected_links = json.loads(expected_links.replace("'", '"'))
expected_result += fakes.index_response(
remove_attrs=complex_attributes,
vnf_lcm_op_occs_updates={'operation': name})
vnf_lcm_op_occs_updates={'operation':
values['result_names'][index],
'id': ids[target_index[index]],
'_links': expected_links})
expected_result_link = None
if 'all_records' not in values['params'] and len(target_index) >= 2:
expected_result_link = (
'<http://localhost//vnflcm/v1/vnf_lcm_op_occs' +
'?nextpage_opaque_marker=%s>; rel="next"'
% ids[target_index[1]])
mock_op_occ_list.return_value = vnf_lcm_op_occ
resp = self.controller.list_lcm_op_occs(req)
if 'Link' in resp.headers:
next_url = re.findall('<(.*)>', resp.headers['Link'])[0]
query = urllib.parse.urlparse(next_url).query
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
resp = self.controller.list_lcm_op_occs(req)
self.assertEqual(
jsonutils.loads(jsonutils.dump_as_bytes(expected_result)),
resp.json)
if expected_result_link is not None:
self.assertEqual(expected_result_link, resp.headers['Link'])
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,id,f26f181d-7891-4720-b022-b074ec1733ef)'},
{'filter': '(neq,operationState,COMPLETED)'},
@ -3881,7 +3959,7 @@ class TestController(base.TestCase):
"""(neq,operationParams,'"{"terminationType": "FORCEFUL"}"')"""},
)
def test_op_occ_filter_attributes(self, filter_params,
mock_op_occ_list):
mock_op_occ_list):
query = urllib.parse.urlencode(filter_params)
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
@ -3902,8 +3980,9 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result)),
res_dict.json)
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
def test_op_occ_filter_attributes_invalid_filter(self, mock_op_occ_list):
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_marker_filter")
def test_op_occ_filter_attributes_invalid_filter(self,
mock_op_occ_list):
query = urllib.parse.urlencode({'filter': '(lt,non_existing,4)'})
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
@ -3913,8 +3992,9 @@ class TestController(base.TestCase):
self.assertRaises(
exceptions.ValidationError, self.controller.list_lcm_op_occs, req)
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
def test_op_occ_attribute_selector_all_fields(self, mock_op_occ_list):
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_marker_filter")
def test_op_occ_attribute_selector_all_fields(self,
mock_op_occ_list):
params = {'all_fields': 'True'}
query = urllib.parse.urlencode(params)
req = fake_request.HTTPRequest.blank('/vnflcm/v1/vnf_lcm_op_occs?' +
@ -3929,7 +4009,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result)),
res_dict.json)
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_marker_filter")
@ddt.data(
{'fields': 'error'},
{'fields': 'resourceChanges'},
@ -3937,7 +4017,7 @@ class TestController(base.TestCase):
{'fields': 'changedInfo'}
)
def test_op_occ_attribute_selector_fields(self, filter_params,
mock_op_occ_list):
mock_op_occ_list):
query = urllib.parse.urlencode(filter_params)
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
@ -3959,7 +4039,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result)),
res_dict.json)
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_marker_filter")
@ddt.data(
{'exclude_fields': 'error'},
{'exclude_fields': 'resourceChanges'},
@ -3967,7 +4047,7 @@ class TestController(base.TestCase):
{'exclude_fields': 'changedInfo'}
)
def test_op_occ_attribute_selector_exclude_fields(self, filter_params,
mock_op_occ_list):
mock_op_occ_list):
query = urllib.parse.urlencode(filter_params)
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
@ -3982,8 +4062,9 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result)),
res_dict.json)
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_filters")
def test_op_occ_attribute_selector_fields_error(self, mock_op_occ_list):
@mock.patch.object(objects.VnfLcmOpOccList, "get_by_marker_filter")
def test_op_occ_attribute_selector_fields_error(self,
mock_op_occ_list):
query = urllib.parse.urlencode({'fields': 'non_existent_column'})
req = fake_request.HTTPRequest.blank(
'/vnflcm/v1/vnf_lcm_op_occs?' + query)
@ -4409,7 +4490,7 @@ class TestController(base.TestCase):
@mock.patch.object(vnf_subscription_view.ViewBuilder,
"validate_filter")
@mock.patch.object(objects.LccnSubscriptionList,
"get_by_filters")
"get_by_marker_filter")
def test_subscription_list_all(self,
mock_subscription_list,
mock_subscription_filter,
@ -4436,7 +4517,7 @@ class TestController(base.TestCase):
@mock.patch.object(vnf_subscription_view.ViewBuilder,
"validate_filter")
@mock.patch.object(objects.LccnSubscriptionList,
"get_by_filters")
"get_by_marker_filter")
def test_subscription_list_empty(self,
mock_subscription_list,
mock_subscription_filter,
@ -4469,66 +4550,89 @@ class TestController(base.TestCase):
resp = req.get_response(self.app)
self.assertEqual(500, resp.status_code)
@mock.patch.object(TackerManager, 'get_service_plugins',
return_value={'VNFM':
test_nfvo_plugin.FakeVNFMPlugin()})
@mock.patch.object(vnf_subscription_view.ViewBuilder,
"subscription_list")
@mock.patch.object(vnf_subscription_view.ViewBuilder,
"validate_filter")
@mock.patch.object(objects.LccnSubscriptionList,
"get_by_filters")
@mock.patch.object(objects.vnf_lcm_subscriptions.LccnSubscriptionList,
"get_by_marker_filter")
@mock.patch.object(objects.LccnSubscription, "get_by_id")
@ddt.data(
{'params': {'all_records': 'yes'},
'result_names': ['subscription_id_1', 'subscription_id_2',
'subscription_id_3', 'subscription_id_4']},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker': 'abc'},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['subscription_id_1', 'subscription_id_2',
'subscription_id_3', 'subscription_id_4']},
{'params': {'nextpage_opaque_marker': 'abc'},
{'params': {'nextpage_opaque_marker':
'44444444-4444-4444-4444-444444444444'},
'result_names': []},
{'params': {'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['subscription_id_3', 'subscription_id_4']},
{'params': {},
'result_names': ['subscription_id_2']}
'result_names': ['subscription_id_1', 'subscription_id_2']}
)
def test_subscription_list_paging(self,
values,
mock_subscription_list,
mock_subscription_filter,
mock_subscription_view,
mock_get_service_plugins):
mock_subscription_filter.return_value = None
last = True
cfg.CONF.set_override('subscription_num', 1, group='vnf_lcm')
mock_marker_obj,
mock_subscription_list):
ids = ['11111111-1111-1111-1111-111111111111',
'22222222-2222-2222-2222-222222222222',
'33333333-3333-3333-3333-333333333333',
'44444444-4444-4444-4444-444444444444',
None]
mock_marker_obj.return_value = None
cfg.CONF.set_override('subscription_num', 2, group='vnf_lcm')
query = urllib.parse.urlencode(values['params'])
req = fake_request.HTTPRequest.blank('/subscriptions?' + query)
req.method = 'GET'
subscription_list = [
fakes.return_subscription_object(
**{'id': uuidsentinel.subscription_id_1}),
fakes.return_subscription_object(
**{'id': uuidsentinel.subscription_id_2}),
fakes.return_subscription_object(
**{'id': uuidsentinel.subscription_id_3}),
fakes.return_subscription_object(
**{'id': uuidsentinel.subscription_id_4})
]
mock_subscription_list.return_value = [subscription_list, last]
mock_subscription_view.return_value = subscription_list
target_index = []
if 'all_records' in values['params'] \
and values['params']['all_records'] == 'yes':
mock_marker_obj = None
target_index = [0, 1, 2, 3]
elif 'nextpage_opaque_marker' in values['params']:
mock_marker_obj.return_value = fakes.return_subscription_object(
**{'id': values['params']['nextpage_opaque_marker']})
marker_obj_index = ids.index(mock_marker_obj.return_value['id'])
for i in range(marker_obj_index + 1, len(ids) - 1):
target_index.append(i)
else:
mock_marker_obj.return_value = None
target_index = [0, 1]
mock_subscription_list.return_value = []
for index in range(len(target_index)):
mock_subscription_list.return_value.append(
fakes.return_lccn_subscription_obj(**{'id':
ids[target_index[index]]}))
resp = self.controller.subscription_list(req)
if 'Link' in resp.headers:
next_url = re.findall('<(.*)>', resp.headers['Link'])[0]
query = urllib.parse.urlparse(next_url).query
req = fake_request.HTTPRequest.blank('/subscriptions?' + query)
resp = self.controller.subscription_list(req)
expected_result = []
for name in values['result_names']:
expected_result.append(fakes.return_subscription_object(
**{'id': eval('uuidsentinel.' + name)}))
for index in range(len(target_index)):
href = ("http://localhost:9890//vnflcm/v1/subscriptions/{}"
.format(ids[target_index[index]]))
_link = {'self': {'href': href}}
subscription_object = fakes.return_subscription_object(
**{'id': ids[target_index[index]], '_links': _link})
subscription_object['callbackUri'] = \
subscription_object.pop('callback_uri')
expected_result.append(subscription_object)
expected_result_link = None
if 'all_records' not in values['params'] and len(target_index) >= 2:
expected_result_link = (
'<http://localhost//subscriptions' +
'?nextpage_opaque_marker=%s>; rel="next"'
% ids[target_index[1]])
self.assertEqual(200, resp.status_code)
self.assertEqual(expected_result, resp.json)
if expected_result_link is not None:
self.assertEqual(expected_result_link, resp.headers['Link'])
@mock.patch.object(TackerManager, 'get_service_plugins',
return_value={'VNFM':
@ -4538,7 +4642,7 @@ class TestController(base.TestCase):
def test_subscription_show(self, mock_get_subscription,
mock_get_service_plugins):
mock_get_subscription.return_value =\
fakes.return_subscription_obj()
fakes.return_lccn_subscription_obj()
req = fake_request.HTTPRequest.blank(
'/subscriptions/%s' % uuidsentinel.subscription_id)
@ -4559,7 +4663,7 @@ class TestController(base.TestCase):
@mock.patch.object(vnf_subscription_view.ViewBuilder,
"validate_filter")
@mock.patch.object(objects.LccnSubscriptionList,
"get_by_filters")
"get_by_marker_filter")
@ddt.data(
{'operator': "eq", 'key': 'id',
'value': uuidsentinel.subscription_id},

View File

@ -117,7 +117,7 @@ class TestController(base.TestCase):
self.assertRaises(exc.HTTPNotFound, self.controller.show,
req, constants.UUID)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data('/vnfpkgm/v1/vnf_packages')
def test_index(self, path, mock_vnf_list):
req = fake_request.HTTPRequest.blank(path)
@ -133,7 +133,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
def test_index_attribute_selector_all_fields(self, mock_vnf_list):
params = {'all_fields': ''}
query = urllib.parse.urlencode(params)
@ -146,7 +146,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
def test_index_attribute_selector_exclude_default(self, mock_vnf_list):
params = {'exclude_default': ''}
query = urllib.parse.urlencode(params)
@ -164,7 +164,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'exclude_fields': 'softwareImages'},
{'exclude_fields': 'checksum'},
@ -184,7 +184,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'fields': 'softwareImages'},
{'fields': 'checksum'},
@ -213,7 +213,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
def test_index_attribute_selector_user_defined_data_combination(self,
mock_vnf_list):
"""Query user defined data with fields parameter
@ -242,7 +242,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
def test_index_attribute_selector_user_defined_data(self, mock_vnf_list):
params = {'fields': 'userDefinedData/key1,userDefinedData/key2'}
query = urllib.parse.urlencode(params)
@ -256,7 +256,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
def test_index_attribute_selector_nested_complex_attribute(self,
mock_vnf_list):
params = {'fields': 'softwareImages/checksum/algorithm,'
@ -284,7 +284,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,vnfdId,%s)' % constants.UUID},
{'filter': '(in,vnfdId,%s)' % constants.UUID},
@ -325,7 +325,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
def test_index_filter_combination(self, mock_vnf_list):
"""Test multiple filter parameters separated by semicolon """
params = {'filter': '(eq,vnfdId,%s);(eq,id,%s)' %
@ -345,7 +345,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,id,%s)' % constants.UUID},
{'filter': '(eq,vnfdId,%s)' % constants.UUID},
@ -394,7 +394,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': "(eq,vnfProductName,dummy_value)"},
{'filter': "(eq,vnfProductName,dummy value)"},
@ -428,7 +428,7 @@ class TestController(base.TestCase):
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': "(eq,vnfProductName,value"},
{'filter': "eq,vnfProductName,value)"},
@ -446,7 +446,7 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': "(eq,vnfProductName,singl'quote)"},
{'filter': "(eq,vnfProductName,three''' quotes)"},
@ -466,7 +466,7 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,vnfdId,value1,value2)'},
{'filter': '(fake,vnfdId,dummy_vnfd_id)'},
@ -481,7 +481,7 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,fakeattr,fakevalue)'},
{'filter': '(eq,,fakevalue)'},
@ -495,7 +495,7 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'filter': '(eq,id,fake_value)'},
{'filter': '(eq,vnfd_id,fake_value)'},
@ -515,7 +515,7 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'fields': 'nonExistentField'},
{'exclude_fields': 'nonExistentField'}
@ -529,7 +529,7 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'fields': 'softwareImages', 'all_fields': ''},
{'exclude_fields': 'checksum', 'all_fields': ''},
@ -545,7 +545,7 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@ddt.data(
{'exclude_default': 'softwareImages'},
{'all_fields': 'checksum'},
@ -560,51 +560,92 @@ class TestController(base.TestCase):
self.assertRaises(tacker_exc.ValidationError, self.controller.index,
req)
@mock.patch.object(VnfPackagesList, "get_by_filters")
@mock.patch.object(VnfPackagesList, "get_by_marker_filter")
@mock.patch.object(objects.VnfPackage, "get_by_id")
@ddt.data(
{'params': {'all_records': 'yes'},
'result_names': ['sample1', 'sample2', 'sample3', 'sample4']},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker': 'abc'},
{'params': {'all_records': 'yes', 'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['sample1', 'sample2', 'sample3', 'sample4']},
{'params': {'nextpage_opaque_marker': 'abc'},
{'params': {'nextpage_opaque_marker':
'44444444-4444-4444-4444-444444444444'},
'result_names': []},
{'params': {'nextpage_opaque_marker':
'22222222-2222-2222-2222-222222222222'},
'result_names': ['sample3', 'sample4']},
{'params': {},
'result_names': ['sample2']}
'result_names': ['sample1', 'sample2']}
)
def test_index_paging(self, values, mock_vnf_list):
cfg.CONF.set_override('vnf_package_num', 1, group='vnf_package')
def test_index_paging(self, values,
mock_marker_obj, mock_vnf_package_list):
ids = ['11111111-1111-1111-1111-111111111111',
'22222222-2222-2222-2222-222222222222',
'33333333-3333-3333-3333-333333333333',
'44444444-4444-4444-4444-444444444444',
None]
cfg.CONF.set_override('vnf_package_num', 2, group='vnf_package')
query = urllib.parse.urlencode(values['params'])
req = fake_request.HTTPRequest.blank('/vnfpkgm/v1/vnf_packages?' +
query)
mock_vnf_list.return_value = [
fakes.return_vnfpkg_obj(
vnfd_updates={'vnf_product_name': 'sample1'}),
fakes.return_vnfpkg_obj(
vnfd_updates={'vnf_product_name': 'sample2'}),
fakes.return_vnfpkg_obj(
vnfd_updates={'vnf_product_name': 'sample3'}),
fakes.return_vnfpkg_obj(
vnfd_updates={'vnf_product_name': 'sample4'})
]
target_index = []
if 'all_records' in values['params'] \
and values['params']['all_records'] == 'yes':
mock_marker_obj.return_value = None
target_index = [0, 1, 2, 3]
elif 'nextpage_opaque_marker' in values['params']:
mock_marker_obj.return_value = fakes.return_vnfpkg_obj(
vnf_package_updates={'id':
values['params']['nextpage_opaque_marker']})
marker_obj_index = ids.index(mock_marker_obj.return_value['id'])
for i in range(marker_obj_index + 1, len(ids) - 1):
target_index.append(i)
else:
mock_marker_obj.return_value = None
target_index = [0, 1]
mock_vnf_package_list.return_value = []
for index in range(len(target_index)):
mock_vnf_package_list.return_value.append(
fakes.return_vnfpkg_obj(
vnf_package_updates={'id':
ids[target_index[index]]},
vnfd_updates={'vnf_product_name':
values['result_names'][index]}))
expected_result = []
for name in values['result_names']:
expected_result += fakes.index_response(
for index in range(len(target_index)):
_links = fakes.index_response()[0]['_links']
expected_links = (re.sub("vnf_packages/[a-zA-Z0-9-]*",
"vnf_packages/{}".format(ids[target_index[index]]),
str(_links)))
expected_links = json.loads(expected_links.replace("'", '"'))
print("expected_links", expected_links)
expected_result.append(fakes.index_response(
remove_attrs=[
'softwareImages',
'checksum',
'userDefinedData',
'additionalArtifacts'],
vnf_package_updates={'vnfProductName': name})
vnf_package_updates={'vnfProductName':
values['result_names'][index],
'id': ids[target_index[index]],
'_links': expected_links})[0])
res_dict = self.controller.index(req)
if 'Link' in res_dict.headers:
next_url = re.findall('<(.*)>', res_dict.headers['Link'])[0]
query = urllib.parse.urlparse(next_url).query
req = fake_request.HTTPRequest.blank('/vnfpkgm/v1/vnf_packages?' +
query)
res_dict = self.controller.index(req)
self.assertEqual(
jsonutils.loads(jsonutils.dump_as_bytes(expected_result,
default=str)), res_dict.json)
expected_result_link = None
if 'all_records' not in values['params'] and len(target_index) >= 2:
expected_result_link = (
'<http://localhost//vnfpkgm/v1/vnf_packages' +
'?nextpage_opaque_marker=%s>; rel="next"'
% ids[target_index[1]])
self.assertEqual(expected_result, res_dict.json)
if expected_result_link is not None:
self.assertEqual(expected_result_link, res_dict.headers['Link'])
@mock.patch.object(vnf_package.VnfPackage, "get_by_id")
@mock.patch.object(VNFPackageRPCAPI, "delete_vnf_package")