Add parameters field for protectable instances API

Scenario #1
User need a parameter for the region name to query resource
instances from different region endpoint.

Scenario #2
User uses the Protectable Instances API to query database
instances from the verdor's backup software. User must provide
some parameters about authentication to the restfull API of the
verdor's backup software.

A dict type parameter is needed for Protectable Instances API.
And it is optional.

blueprint instances-parameters

Change-Id: I6677e86467c516433a1ba15eac42f339b953d3d9
This commit is contained in:
chenying 2016-09-27 15:35:56 +08:00
parent 1a8adb3014
commit 8af4ffc5f7
11 changed files with 65 additions and 32 deletions

View File

@ -765,6 +765,7 @@ paths:
- $ref: '#/parameters/sortParam'
- $ref: '#/parameters/limitParam'
- $ref: '#/parameters/markerParam'
- $ref: '#/parameters/parametersParam'
tags:
- Protectable
- Resource
@ -811,6 +812,7 @@ paths:
- $ref: '#/parameters/projectParam'
- $ref: '#/parameters/protectable_typeParam'
- $ref: '#/parameters/resource_idParam'
- $ref: '#/parameters/parametersParam'
tags:
- Protectable
- Resource
@ -1893,6 +1895,12 @@ parameters:
response as the marker parameter value in a subsequent limited request.
type: string
parametersParam:
name: parameters
in: query
description: |
The parameters field for protectable instances query.
type: string
provider_idParam:
name: provider_id
in: path

View File

@ -11,7 +11,6 @@
# under the License.
"""The protectables api."""
from oslo_config import cfg
from oslo_log import log as logging
@ -126,6 +125,7 @@ class ProtectablesController(wsgi.Controller):
"""Return data about the given protectable_type."""
context = req.environ['karbor.context']
protectable_type = id
LOG.info(_LI("Show the information of a given"
" protectable type: %s"), protectable_type)
@ -181,6 +181,13 @@ class ProtectablesController(wsgi.Controller):
marker, limit, offset = common.get_pagination_params(params)
sort_keys, sort_dirs = common.get_sort_params(params)
filters = params
utils.check_filters(filters)
parameters = filters.get("parameters", None)
if parameters is not None:
if not isinstance(parameters, dict):
msg = _("The parameters must be a dict.")
raise exception.InvalidInput(reason=msg)
utils.remove_invalid_filter_options(
context,
@ -193,11 +200,10 @@ class ProtectablesController(wsgi.Controller):
msg = _("Invalid protectable type provided.")
raise exception.InvalidInput(reason=msg)
utils.check_filters(filters)
instances = self._instances_get_all(
context, protectable_type, marker, limit,
sort_keys=sort_keys, sort_dirs=sort_dirs,
filters=filters, offset=offset)
filters=filters, offset=offset, parameters=parameters)
for instance in instances:
protectable_id = instance.get("id")
@ -216,7 +222,7 @@ class ProtectablesController(wsgi.Controller):
def _instances_get_all(self, context, protectable_type, marker=None,
limit=None, sort_keys=None, sort_dirs=None,
filters=None, offset=None):
filters=None, offset=None, parameters=None):
check_policy(context, 'get_all')
if filters is None:
@ -240,7 +246,8 @@ class ProtectablesController(wsgi.Controller):
sort_keys=sort_keys,
sort_dirs=sort_dirs,
filters=filters,
offset=offset)
offset=offset,
parameters=parameters)
LOG.info(_LI("Get all instances completed successfully."))
return instances
@ -253,9 +260,18 @@ class ProtectablesController(wsgi.Controller):
"""Return a instance about the given protectable_type and id."""
context = req.environ['karbor.context']
params = req.params.copy()
utils.check_filters(params)
parameters = params.get("parameters", None)
LOG.info(_LI("Show the instance of a given protectable"
" type: %s"), protectable_type)
if parameters is not None:
if not isinstance(parameters, dict):
msg = _("The parameters must be a dict.")
raise exception.InvalidInput(reason=msg)
protectable_types = self._get_all(context)
if protectable_type not in protectable_types:
@ -264,7 +280,7 @@ class ProtectablesController(wsgi.Controller):
instance = self.protection_api.\
show_protectable_instance(context, protectable_type,
protectable_id)
protectable_id, parameters=parameters)
if instance is None:
raise exception.InvalidProtectableInstance(
protectable_id=instance.get('id'))

View File

@ -61,11 +61,11 @@ class API(base.Base):
def list_protectable_instances(self, context, protectable_type,
marker, limit, sort_keys,
sort_dirs, filters, offset):
sort_dirs, filters, offset, parameters):
return self.protection_rpcapi.\
list_protectable_instances(context, protectable_type,
marker, limit, sort_keys,
sort_dirs, filters)
sort_dirs, filters, parameters)
def list_protectable_dependents(self, context,
protectable_id,
@ -77,11 +77,13 @@ class API(base.Base):
def show_protectable_instance(self, context,
protectable_type,
protectable_id):
protectable_id,
parameters=None):
return self.protection_rpcapi.\
show_protectable_instance(context,
protectable_type,
protectable_id)
protectable_id,
parameters=parameters)
def show_provider(self, context, provider_id):
return self.protection_rpcapi.\

View File

@ -284,14 +284,15 @@ class ProtectionManager(manager.Manager):
limit=None,
sort_keys=None,
sort_dirs=None,
filters=None):
filters=None,
parameters=None):
LOG.info(_LI("Start to list protectable instances of type: %s"),
protectable_type)
try:
resource_instances = self.protectable_registry.list_resources(
context, protectable_type)
context, protectable_type, parameters)
except exception.ListProtectableResourceFailed as err:
LOG.error(_LE("List resources of type %(type)s failed: %(err)s"),
{'type': protectable_type,
@ -306,7 +307,7 @@ class ProtectionManager(manager.Manager):
@messaging.expected_exceptions(exception.ListProtectableResourceFailed)
def show_protectable_instance(self, context, protectable_type,
protectable_id):
protectable_id, parameters=None):
LOG.info(_LI("Start to show protectable instance of type: %s"),
protectable_type)
@ -314,7 +315,8 @@ class ProtectionManager(manager.Manager):
resource_instance = \
self.protectable_registry.show_resource(context,
protectable_type,
protectable_id)
protectable_id,
parameters=parameters)
except exception.ListProtectableResourceFailed as err:
LOG.error(_LE("Show resources of type %(type)s id %(id)s "
"failed: %(err)s"),

View File

@ -43,7 +43,7 @@ class ProtectablePlugin(object):
pass
@abc.abstractmethod
def list_resources(self, context):
def list_resources(self, context, parameters=None):
"""List resource instances of type this plugin supported.
:return: The list of resource instance.
@ -51,7 +51,7 @@ class ProtectablePlugin(object):
pass
@abc.abstractmethod
def show_resource(self, context, resource_id):
def show_resource(self, context, resource_id, parameters=None):
"""Show resource detail information.
"""

View File

@ -43,7 +43,7 @@ class ImageProtectablePlugin(protectable_plugin.ProtectablePlugin):
return (constants.SERVER_RESOURCE_TYPE,
constants.PROJECT_RESOURCE_TYPE,)
def list_resources(self, context):
def list_resources(self, context, parameters=None):
try:
images = self._glance_client(context).images.list()
except Exception as e:
@ -98,7 +98,7 @@ class ImageProtectablePlugin(protectable_plugin.ProtectablePlugin):
for image in images
if image.owner == parent_resource.id]
def show_resource(self, context, resource_id):
def show_resource(self, context, resource_id, parameters=None):
try:
image = self._glance_client(context).images.get(resource_id)
except Exception as e:

View File

@ -28,7 +28,7 @@ class ProjectProtectablePlugin(protectable_plugin.ProtectablePlugin):
def get_parent_resource_types(self):
return ()
def list_resources(self, context):
def list_resources(self, context, parameters=None):
# TODO(yuvalbr) handle admin context for multiple projects?
return [resource.Resource(type=self._SUPPORT_RESOURCE_TYPE,
id=context.project_id,
@ -37,7 +37,7 @@ class ProjectProtectablePlugin(protectable_plugin.ProtectablePlugin):
def get_dependent_resources(self, context, parent_resource):
pass
def show_resource(self, context, resource_id):
def show_resource(self, context, resource_id, parameters=None):
# TODO(yinwei) get project name through keystone client
return resource.Resource(type=self._SUPPORT_RESOURCE_TYPE,
id=resource_id,

View File

@ -43,7 +43,7 @@ class ServerProtectablePlugin(protectable_plugin.ProtectablePlugin):
def get_parent_resource_types(self):
return (constants.PROJECT_RESOURCE_TYPE, )
def list_resources(self, context):
def list_resources(self, context, parameters=None):
try:
servers = self._client(context).servers.list(detailed=False)
except Exception as e:
@ -57,7 +57,7 @@ class ServerProtectablePlugin(protectable_plugin.ProtectablePlugin):
name=server.name)
for server in servers]
def show_resource(self, context, resource_id):
def show_resource(self, context, resource_id, parameters=None):
try:
server = self._client(context).servers.get(resource_id)
except Exception as e:

View File

@ -44,7 +44,7 @@ class VolumeProtectablePlugin(protectable_plugin.ProtectablePlugin):
return (constants.SERVER_RESOURCE_TYPE,
constants.PROJECT_RESOURCE_TYPE)
def list_resources(self, context):
def list_resources(self, context, parameters=None):
try:
volumes = self._client(context).volumes.list(detailed=False)
except Exception as e:
@ -58,7 +58,7 @@ class VolumeProtectablePlugin(protectable_plugin.ProtectablePlugin):
id=vol.id, name=vol.name)
for vol in volumes]
def show_resource(self, context, resource_id):
def show_resource(self, context, resource_id, parameters=None):
try:
volume = self._client(context).volumes.get(resource_id)
except Exception as e:

View File

@ -70,16 +70,17 @@ class ProtectableRegistry(object):
"""Get the protectable plugin with the specified type."""
return self._plugin_map.get(resource_type)
def list_resources(self, context, resource_type):
def list_resources(self, context, resource_type, parameters=None):
"""List resource instances of given type.
:param resource_type: The resource type to list instance.
:return: The list of resource instance.
"""
protectable = self._get_protectable(context, resource_type)
return protectable.list_resources(context)
return protectable.list_resources(context, parameters=parameters)
def show_resource(self, context, resource_type, resource_id):
def show_resource(self, context, resource_type, resource_id,
parameters=None):
"""List resource instances of given type.
:param resource_type: The resource type of instance.
@ -87,7 +88,8 @@ class ProtectableRegistry(object):
:return: The show of resource instance.
"""
protectable = self._get_protectable(context, resource_type)
return protectable.show_resource(context, resource_id)
return protectable.show_resource(context, resource_id,
parameters=parameters)
def fetch_dependent_resources(self, context, resource):
"""List dependent resources under given parent resource.

View File

@ -105,7 +105,7 @@ class ProtectionAPI(object):
def list_protectable_instances(
self, ctxt, protectable_type=None,
marker=None, limit=None, sort_keys=None,
sort_dirs=None, filters=None):
sort_dirs=None, filters=None, parameters=None):
cctxt = self.client.prepare(version='1.0')
return cctxt.call(
ctxt,
@ -115,7 +115,8 @@ class ProtectionAPI(object):
limit=limit,
sort_keys=sort_keys,
sort_dirs=sort_dirs,
filters=filters)
filters=filters,
parameters=parameters)
def list_protectable_dependents(self,
ctxt, protectable_id=None,
@ -129,13 +130,15 @@ class ProtectionAPI(object):
def show_protectable_instance(self,
ctxt, protectable_type=None,
protectable_id=None):
protectable_id=None,
parameters=None):
cctxt = self.client.prepare(version='1.0')
return cctxt.call(
ctxt,
'show_protectable_instance',
protectable_type=protectable_type,
protectable_id=protectable_id)
protectable_id=protectable_id,
parameters=parameters)
def show_provider(self,
ctxt, provider_id=None):