Fix API pagination problem in multi servers
This patch fixes the problem regarding pagination of target APIs in case of running by multiple Tacker servers. It changes the method of getting paginated records so that they are able to be done by specifying the last record's id in the last page. Closes-Bug: #1978901 Change-Id: Ie0a51f1b837b7426595c40efcbbc022f0ea66f65
This commit is contained in:
parent
a71771ac85
commit
fd41f08914
@ -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(
|
||||
|
@ -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,38 +589,42 @@ 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)
|
||||
|
||||
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,31 +1108,30 @@ 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
|
||||
|
||||
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
|
||||
|
||||
# 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)
|
||||
|
||||
LOG.debug("vnf_lcm_subscriptions %s" % vnf_lcm_subscriptions)
|
||||
subscription_data = self._view_builder_subscription. \
|
||||
subscription_list(vnf_lcm_subscriptions)
|
||||
subscription_list(result)
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return self._make_problem_detail(
|
||||
@ -1148,21 +1141,15 @@ class VnfLcmController(wsgi.Controller):
|
||||
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,14 +1735,10 @@ 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)
|
||||
|
||||
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,
|
||||
@ -1763,36 +1746,41 @@ class VnfLcmController(wsgi.Controller):
|
||||
|
||||
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
|
||||
|
||||
# get next page marker object from nextpage id
|
||||
if nextpage:
|
||||
marker_obj = vnf_lcm_op_occs_obj.VnfLcmOpOcc.get_by_id(
|
||||
request.context, nextpage)
|
||||
|
||||
try:
|
||||
vnf_lcm_op_occs = (
|
||||
vnf_lcm_op_occs_obj.VnfLcmOpOccList.get_by_filters(
|
||||
request.context, read_deleted='no', filters=filters))
|
||||
# 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, vnf_lcm_op_occs,
|
||||
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)
|
||||
|
||||
return res
|
||||
|
@ -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,18 +157,28 @@ 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,
|
||||
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,
|
||||
@ -182,21 +187,16 @@ class VnfPkgmController(wsgi.Controller):
|
||||
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)
|
||||
|
||||
return res
|
||||
|
@ -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',
|
||||
|
@ -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"))
|
||||
|
||||
]
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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,
|
||||
|
@ -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):
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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)"},
|
||||
@ -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}))
|
||||
|
||||
res_dict = self.controller.index(req)
|
||||
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]])
|
||||
|
||||
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})
|
||||
|
||||
mock_op_occ_list.return_value = vnf_lcm_op_occ
|
||||
resp = self.controller.list_lcm_op_occs(req)
|
||||
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]])
|
||||
|
||||
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)'},
|
||||
@ -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'},
|
||||
@ -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'},
|
||||
@ -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
|
||||
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)
|
||||
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)
|
||||
|
||||
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},
|
||||
|
@ -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 = [
|
||||
|
||||
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(
|
||||
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'})
|
||||
]
|
||||
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")
|
||||
|
Loading…
Reference in New Issue
Block a user