fix docstring warnings and errors

There are many warnings and errors that occur when the docs are
generated.

Co-Author-By: Danny Al-Gaaf <danny.al-gaaf@bisect.de>
Closes-Bug: 1556818
Change-Id: Ifebeb3904f136a56bd6fe6877220b279a1f98354
This commit is contained in:
Tom Cocozzello 2016-03-09 13:53:37 -06:00
parent b9e710659f
commit adfc7e5a3f
20 changed files with 199 additions and 124 deletions

View File

@ -49,14 +49,14 @@ Following components are present in the Glance architecture:
* **REST API** - Glance functionalities are exposed via REST. * **REST API** - Glance functionalities are exposed via REST.
* **Database Abstraction Layer (DAL)** - an application programming interface * **Database Abstraction Layer (DAL)** - an application programming interface
(API) that unifies the communication between Glance and databases. (API) that unifies the communication between Glance and databases.
* **Glance Domain Controller** - middleware that implements the main * **Glance Domain Controller** - middleware that implements the main
Glance functionalities such as authorization, notifications, policies, Glance functionalities such as authorization, notifications, policies,
database connections. database connections.
* **Glance Store** - used to organize interactions between Glance and various * **Glance Store** - used to organize interactions between Glance and various
data stores. data stores.
* **Registry Layer** - optional layer that is used to organise secure * **Registry Layer** - optional layer that is used to organise secure
communication between the domain and the DAL by using a separate service. communication between the domain and the DAL by using a separate service.

View File

@ -40,6 +40,7 @@ information. In order to configure Glance to use Keystone, the
the authentication token validation and retrieves actual user authentication the authentication token validation and retrieves actual user authentication
information. It can be found in the Keystone distribution. information. It can be found in the Keystone distribution.
Configuring Glance API to use Keystone Configuring Glance API to use Keystone
-------------------------------------- --------------------------------------
@ -59,8 +60,11 @@ an example for ``authtoken``::
The actual values for these variables will need to be set depending on The actual values for these variables will need to be set depending on
your situation. For more information, please refer to the Keystone your situation. For more information, please refer to the Keystone
`documentation`_ on the ``auth_token`` middleware, but in short: `documentation`_ on the ``auth_token`` middleware.
.. _documentation http://docs.openstack.org/developer/keystonemiddleware/middlewarearchitecture.html#configuration
.. _`documentation`: http://docs.openstack.org/developer/keystonemiddleware/middlewarearchitecture.html#configuration
In short:
* The ``auth_url`` variable points to the Keystone service. * The ``auth_url`` variable points to the Keystone service.
This information is used by the middleware to actually query Keystone about This information is used by the middleware to actually query Keystone about
@ -83,6 +87,7 @@ with ``authtoken`` and ``context``::
[pipeline:glance-api] [pipeline:glance-api]
pipeline = versionnegotiation authtoken context apiv1app pipeline = versionnegotiation authtoken context apiv1app
Configuring Glance Registry to use Keystone Configuring Glance Registry to use Keystone
------------------------------------------- -------------------------------------------

View File

@ -1718,10 +1718,10 @@ deployment. Without HMAC key the profiling will not be triggered even profiling
feature is enabled. feature is enabled.
**IMPORTANT NOTE**: previously HMAC keys (as well as enabled parameter) were **IMPORTANT NOTE**: previously HMAC keys (as well as enabled parameter) were
placed at /etc/glance/api-paste.ini and /etc/glance/registry-paste.ini files placed at `/etc/glance/api-paste.ini` and `/etc/glance/registry-paste.ini` files
for Glance API and Glance Registry services respectively. Starting with for Glance API and Glance Registry services respectively. Starting with
opsrofiler 0.3.1 release there is no need to set these arguments in the opsrofiler 0.3.1 release there is no need to set these arguments in the
*-paste.ini files. This functionality is still supported, although the `*-paste.ini` files. This functionality is still supported, although the
config values are having larger priority. config values are having larger priority.
The config value ``trace_sqlalchemy`` is used to determine whether fully enable The config value ``trace_sqlalchemy`` is used to determine whether fully enable

View File

@ -55,14 +55,16 @@ The workflow for the life of a spec-lite in Launchpad is as follows:
* File a bug with a small summary of what the request change is * File a bug with a small summary of what the request change is
following the format below: following the format below:
.. NOTE: add format
* The bug is triaged and tagged with the `spec-lite` tag. .. NOTE: add format
* The bug is evaluated and marked as `Triaged` to announce approval or
to `Won't fix` to announce rejection or `Invalid` to request a full * The bug is triaged and tagged with the `spec-lite` tag.
spec. * The bug is evaluated and marked as `Triaged` to announce approval or
* The bug is moved to `In Progress` once the code is up and ready to to `Won't fix` to announce rejection or `Invalid` to request a full
review. spec.
* The bug is moved to `Fix Committed` once the patch lands. * The bug is moved to `In Progress` once the code is up and ready to
review.
* The bug is moved to `Fix Committed` once the patch lands.
In summary: In summary:
@ -80,9 +82,9 @@ In summary:
The drivers team will be discussing the following bug reports during their IRC meeting: The drivers team will be discussing the following bug reports during their IRC meeting:
* `New RFE's <https://bugs.launchpad.net/glance/+bugs?field.status%3Alist=NEW&field.tag=spec-lite&field.importance%3Alist=WISHLIST>`_ * `New Glance RFE's <https://bugs.launchpad.net/glance/+bugs?field.status%3Alist=NEW&field.tag=spec-lite&field.importance%3Alist=WISHLIST>`_
* `New RFE's <https://bugs.launchpad.net/glance-store/+bugs?field.status%3Alist=NEW&field.tag=spec-lite&field.importance%3Alist=WISHLIST>`_ * `New Glance-Store RFE's <https://bugs.launchpad.net/glance-store/+bugs?field.status%3Alist=NEW&field.tag=spec-lite&field.importance%3Alist=WISHLIST>`_
* `New RFE's <https://bugs.launchpad.net/python-glanceclient/+bugs?field.status%3Alist=NEW&field.tag=spec-lite&field.importance%3Alist=WISHLIST>`_ * `New Glanceclient RFE's <https://bugs.launchpad.net/python-glanceclient/+bugs?field.status%3Alist=NEW&field.tag=spec-lite&field.importance%3Alist=WISHLIST>`_
Lite spec Submission Guidelines Lite spec Submission Guidelines

View File

@ -362,9 +362,9 @@ The first call should be a ``POST`` to ``http://glance.example.com/v1/images``,
which will result in a new image id being registered with a status of which will result in a new image id being registered with a status of
``queued``:: ``queued``::
{"image": {'image':
{"status": "queued", {'status': 'queued',
"id": "71c675ab-d94f-49cd-a114-e12490b328d9", 'id': '71c675ab-d94f-49cd-a114-e12490b328d9',
...} ...}
...} ...}

View File

@ -332,16 +332,19 @@ class Controller(controller.BaseController):
* size -- Size of image data in bytes * size -- Size of image data in bytes
:param req: The WSGI/Webob Request object :param req: The WSGI/Webob Request object
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'images': [ {'images': [
{'id': <ID>, {'id': <ID>,
'name': <NAME>, 'name': <NAME>,
'disk_format': <DISK_FORMAT>, 'disk_format': <DISK_FORMAT>,
'container_format': <DISK_FORMAT>, 'container_format': <DISK_FORMAT>,
'checksum': <CHECKSUM> 'checksum': <CHECKSUM>,
'size': <SIZE>}, ... 'size': <SIZE>}, {...}]
]} }
""" """
self._enforce(req, 'get_images') self._enforce(req, 'get_images')
params = self._get_query_params(req) params = self._get_query_params(req)
@ -357,24 +360,29 @@ class Controller(controller.BaseController):
Returns detailed information for all available images Returns detailed information for all available images
:param req: The WSGI/Webob Request object :param req: The WSGI/Webob Request object
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'images':
[{
'id': <ID>,
'name': <NAME>,
'size': <SIZE>,
'disk_format': <DISK_FORMAT>,
'container_format': <CONTAINER_FORMAT>,
'checksum': <CHECKSUM>,
'min_disk': <MIN_DISK>,
'min_ram': <MIN_RAM>,
'store': <STORE>,
'status': <STATUS>,
'created_at': <TIMESTAMP>,
'updated_at': <TIMESTAMP>,
'deleted_at': <TIMESTAMP>|<NONE>,
'properties': {'distro': 'Ubuntu 10.04 LTS', {...}}
}, {...}]
}
{'images': [
{'id': <ID>,
'name': <NAME>,
'size': <SIZE>,
'disk_format': <DISK_FORMAT>,
'container_format': <CONTAINER_FORMAT>,
'checksum': <CHECKSUM>,
'min_disk': <MIN_DISK>,
'min_ram': <MIN_RAM>,
'store': <STORE>,
'status': <STATUS>,
'created_at': <TIMESTAMP>,
'updated_at': <TIMESTAMP>,
'deleted_at': <TIMESTAMP>|<NONE>,
'properties': {'distro': 'Ubuntu 10.04 LTS', ...}}, ...
]}
""" """
if req.method == 'HEAD': if req.method == 'HEAD':
msg = (_("This operation is currently not permitted on " msg = (_("This operation is currently not permitted on "
@ -405,7 +413,7 @@ class Controller(controller.BaseController):
Extracts necessary query params from request. Extracts necessary query params from request.
:param req: the WSGI Request object :param req: the WSGI Request object
:retval dict of parameters that can be used by registry client :returns: dict of parameters that can be used by registry client
""" """
params = {'filters': self._get_filters(req)} params = {'filters': self._get_filters(req)}
@ -423,7 +431,7 @@ class Controller(controller.BaseController):
Return a dictionary of query param filters from the request Return a dictionary of query param filters from the request
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:retval a dict of key/value filters :returns: a dict of key/value filters
""" """
query_filters = {} query_filters = {}
for param in req.params: for param in req.params:
@ -443,7 +451,7 @@ class Controller(controller.BaseController):
:param req: The WSGI/Webob Request object :param req: The WSGI/Webob Request object
:param id: The opaque image identifier :param id: The opaque image identifier
:retval similar to 'show' method but without image_data :returns: similar to 'show' method but without image_data
:raises: HTTPNotFound if image metadata is not available to user :raises: HTTPNotFound if image metadata is not available to user
""" """
@ -634,7 +642,7 @@ class Controller(controller.BaseController):
:param image_meta: Mapping of metadata about image :param image_meta: Mapping of metadata about image
:raises: HTTPConflict if image already exists :raises: HTTPConflict if image already exists
:retval The location where the image was stored :returns: The location where the image was stored
""" """
scheme = req.headers.get('x-image-meta-store', scheme = req.headers.get('x-image-meta-store',
@ -734,7 +742,7 @@ class Controller(controller.BaseController):
:param req: The WSGI/Webob Request object :param req: The WSGI/Webob Request object
:param image_meta: Mapping of metadata about image :param image_meta: Mapping of metadata about image
:retval Mapping of updated image data :returns: Mapping of updated image data
""" """
location_data = self._upload(req, image_meta) location_data = self._upload(req, image_meta)
image_id = image_meta['id'] image_id = image_meta['id']
@ -938,7 +946,7 @@ class Controller(controller.BaseController):
:param request: The WSGI/Webob Request object :param request: The WSGI/Webob Request object
:param id: The opaque image identifier :param id: The opaque image identifier
:retval Returns the updated image information as a mapping :returns: Returns the updated image information as a mapping
""" """
self._enforce(req, 'modify_image') self._enforce(req, 'modify_image')
is_public = image_meta.get('is_public') is_public = image_meta.get('is_public')

View File

@ -62,12 +62,15 @@ class Controller(controller.BaseController):
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:param image_id: The opaque image identifier :param image_id: The opaque image identifier
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'members': [ {'members': [
{'member_id': <MEMBER>, {'member_id': <MEMBER>,
'can_share': <SHARE_PERMISSION>, ...}, ... 'can_share': <SHARE_PERMISSION>, ...}, ...
]} ]}
""" """
self._enforce(req, 'get_members') self._enforce(req, 'get_members')
self._raise_404_if_image_deleted(req, image_id) self._raise_404_if_image_deleted(req, image_id)
@ -128,13 +131,15 @@ class Controller(controller.BaseController):
def update(self, req, image_id, id, body=None): def update(self, req, image_id, id, body=None):
""" """
Adds a membership to the image, or updates an existing one. Adds a membership to the image, or updates an existing one.
If a body is present, it is a dict with the following format:: If a body is present, it is a dict with the following format
{"member": { .. code-block:: json
"can_share": [True|False]
{'member': {
'can_share': [True|False]
}} }}
If "can_share" is provided, the member's ability to share is If `can_share` is provided, the member's ability to share is
set accordingly. If it is not provided, existing memberships set accordingly. If it is not provided, existing memberships
remain unchanged and new memberships default to False. remain unchanged and new memberships default to False.
""" """
@ -169,12 +174,15 @@ class Controller(controller.BaseController):
def update_all(self, req, image_id, body): def update_all(self, req, image_id, body):
""" """
Replaces the members of the image with those specified in the Replaces the members of the image with those specified in the
body. The body is a dict with the following format:: body. The body is a dict with the following format
{"memberships": [ .. code-block:: json
{"member_id": <MEMBER_ID>,
["can_share": [True|False]]}, ... {'memberships': [
{'member_id': <MEMBER_ID>,
['can_share': [True|False]]}, ...
]} ]}
""" """
self._check_can_access_image_members(req.context) self._check_can_access_image_members(req.context)
self._enforce(req, 'modify_member') self._enforce(req, 'modify_member')
@ -206,12 +214,15 @@ class Controller(controller.BaseController):
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:param id: the opaque member identifier :param id: the opaque member identifier
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'shared_images': [ {'shared_images': [
{'image_id': <IMAGE>, {'image_id': <IMAGE>,
'can_share': <SHARE_PERMISSION>, ...}, ... 'can_share': <SHARE_PERMISSION>, ...}, ...
]} ]}
""" """
try: try:
members = registry.get_member_images(req.context, id) members = registry.get_member_images(req.context, id)

View File

@ -95,7 +95,9 @@ class ImageMembersController(object):
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:param image_id: the image identifier :param image_id: the image identifier
:param member_id: the member identifier :param member_id: the member identifier
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'member_id': <MEMBER>, {'member_id': <MEMBER>,
'image_id': <IMAGE>, 'image_id': <IMAGE>,
@ -137,11 +139,13 @@ class ImageMembersController(object):
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:param image_id: the image identifier :param image_id: the image identifier
:param member_id: the member identifier :param member_id: the member identifier
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'member_id': <MEMBER>, {'member_id': <MEMBER>,
'image_id': <IMAGE>, 'image_id': <IMAGE>,
'status': <MEMBER_STATUS> 'status': <MEMBER_STATUS>,
'created_at': .., 'created_at': ..,
'updated_at': ..} 'updated_at': ..}
@ -170,15 +174,18 @@ class ImageMembersController(object):
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:param image_id: The image identifier :param image_id: The image identifier
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'members': [ {'members': [
{'member_id': <MEMBER>, {'member_id': <MEMBER>,
'image_id': <IMAGE>, 'image_id': <IMAGE>,
'status': <MEMBER_STATUS> 'status': <MEMBER_STATUS>,
'created_at': .., 'created_at': ..,
'updated_at': ..}, .. 'updated_at': ..}, ..
]} ]}
""" """
image = self._lookup_image(req, image_id) image = self._lookup_image(req, image_id)
member_repo = self._get_member_repo(req, image) member_repo = self._get_member_repo(req, image)
@ -198,13 +205,16 @@ class ImageMembersController(object):
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:param image_id: The image identifier :param image_id: The image identifier
:retval The response body is a mapping of the following form:: :returns: The response body is a mapping of the following form
.. code-block:: json
{'member_id': <MEMBER>, {'member_id': <MEMBER>,
'image_id': <IMAGE>, 'image_id': <IMAGE>,
'status': <MEMBER_STATUS> 'status': <MEMBER_STATUS>
'created_at': .., 'created_at': ..,
'updated_at': ..} 'updated_at': ..}
""" """
try: try:
image = self._lookup_image(req, image_id) image = self._lookup_image(req, image_id)

View File

@ -68,6 +68,7 @@ class _OVF_Process(task.Task):
def _get_ova_iter_objects(self, uri): def _get_ova_iter_objects(self, uri):
"""Returns iterable object either for local file or uri """Returns iterable object either for local file or uri
:param uri: uri (remote or local) to the ova package we want to iterate :param uri: uri (remote or local) to the ova package we want to iterate
""" """
@ -134,9 +135,10 @@ class OVAImageExtractor(object):
Extracts a single disk image and OVF from OVA tar archive and calls Extracts a single disk image and OVF from OVA tar archive and calls
OVF parser method. OVF parser method.
:param ova: a file object containing the OVA file :param ova: a file object containing the OVA file
:returns: a tuple of extracted disk file object and dictionary of :returns: a tuple of extracted disk file object and dictionary of
properties parsed from the OVF file properties parsed from the OVF file
:raises: RuntimeError for malformed OVA and OVF files :raises: RuntimeError for malformed OVA and OVF files
""" """
with tarfile.open(fileobj=ova) as tar_file: with tarfile.open(fileobj=ova) as tar_file:
@ -163,6 +165,7 @@ class OVAImageExtractor(object):
The OVF file's qualified namespaces are removed from the included The OVF file's qualified namespaces are removed from the included
properties. properties.
:param ovf: a file object containing the OVF file :param ovf: a file object containing the OVF file
:returns: a tuple of disk filename and a properties dictionary :returns: a tuple of disk filename and a properties dictionary
:raises: RuntimeError for malformed OVF file :raises: RuntimeError for malformed OVF file

View File

@ -584,7 +584,7 @@ class BaseClient(object):
:param actual_params: dict of keys to filter :param actual_params: dict of keys to filter
:param allowed_params: list of keys that 'actual_params' will be :param allowed_params: list of keys that 'actual_params' will be
reduced to reduced to
:retval subset of 'params' dict :returns: subset of 'params' dict
""" """
try: try:
# expect 'filters' param to be a dict here # expect 'filters' param to be a dict here

View File

@ -86,6 +86,8 @@ class Controller(object):
This is the base controller for RPC based APIs. Commands This is the base controller for RPC based APIs. Commands
handled by this controller respect the following form: handled by this controller respect the following form:
.. code-block:: json
[{ [{
'command': 'method_name', 'command': 'method_name',
'kwargs': {...} 'kwargs': {...}
@ -94,8 +96,9 @@ class Controller(object):
The controller is capable of processing more than one command The controller is capable of processing more than one command
per request and will always return a list of results. per request and will always return a list of results.
:params raise_exc: Boolean that specifies whether to raise :param bool raise_exc: Specifies whether to raise
exceptions instead of "serializing" them. exceptions instead of "serializing" them.
""" """
def __init__(self, raise_exc=False): def __init__(self, raise_exc=False):
@ -106,13 +109,14 @@ class Controller(object):
""" """
Exports methods through the RPC Api. Exports methods through the RPC Api.
:params resource: Resource's instance to register. :param resource: Resource's instance to register.
:params filtered: List of methods that *can* be registered. Read :param filtered: List of methods that *can* be registered. Read
as "Method must be in this list". as "Method must be in this list".
:params excluded: List of methods to exclude. :param excluded: List of methods to exclude.
:params refiner: Callable to use as filter for methods. :param refiner: Callable to use as filter for methods.
:raises TypeError: If refiner is not callable. :raises TypeError: If refiner is not callable.
""" """
funcs = filter(lambda x: not x.startswith("_"), dir(resource)) funcs = filter(lambda x: not x.startswith("_"), dir(resource))
@ -216,13 +220,16 @@ class RPCClient(client.BaseClient):
""" """
Execute multiple commands in a single request. Execute multiple commands in a single request.
:params commands: List of commands to send. Commands :param commands: List of commands to send. Commands
must respect the following form: must respect the following form
.. code-block:: json
{ {
'command': 'method_name', 'command': 'method_name',
'kwargs': method_kwargs 'kwargs': method_kwargs
} }
""" """
body = self._serializer.to_json(commands) body = self._serializer.to_json(commands)
response = super(RPCClient, self).do_request('POST', response = super(RPCClient, self).do_request('POST',
@ -236,8 +243,8 @@ class RPCClient(client.BaseClient):
the outgoing body and builds the command that will the outgoing body and builds the command that will
be sent. be sent.
:params method: The remote python method to call :param method: The remote python method to call
:params kwargs: Dynamic parameters that will be :param kwargs: Dynamic parameters that will be
passed to the remote method. passed to the remote method.
""" """
content = self.bulk_request([{'command': method, content = self.bulk_request([{'command': method,

View File

@ -61,7 +61,7 @@ def from_migration_import(module_name, fromlist):
:param module_name: name of migration module to import from :param module_name: name of migration module to import from
(ex: 001_add_images_table) (ex: 001_add_images_table)
:param fromlist: list of items to import (ex: define_images_table) :param fromlist: list of items to import (ex: define_images_table)
:retval: module object :returns: module object
This bit of ugliness warrants an explanation: This bit of ugliness warrants an explanation:

View File

@ -284,7 +284,7 @@ class ImageCache(object):
:param image_file: Iterator retrieving image chunks :param image_file: Iterator retrieving image chunks
:param image_checksum: Checksum of image :param image_checksum: Checksum of image
:retval True if image file was cached, False otherwise :returns: True if image file was cached, False otherwise
""" """
if not self.driver.is_cacheable(image_id): if not self.driver.is_cacheable(image_id):
return False return False
@ -301,7 +301,7 @@ class ImageCache(object):
:param image_id: Image ID :param image_id: Image ID
:param image_file: Image file to cache :param image_file: Image file to cache
:retval True if image file was cached, False otherwise :returns: True if image file was cached, False otherwise
""" """
CHUNKSIZE = 64 * units.Mi CHUNKSIZE = 64 * units.Mi

View File

@ -161,10 +161,12 @@ class ImageFactoryProxy(glance.domain.proxy.ImageFactory):
class StoreLocations(collections.MutableSequence): class StoreLocations(collections.MutableSequence):
""" """
The proxy for store location property. It takes responsibility for: The proxy for store location property. It takes responsibility for::
1. Location uri correctness checking when adding a new location. 1. Location uri correctness checking when adding a new location.
2. Remove the image data from the store when a location is removed 2. Remove the image data from the store when a location is removed
from an image. from an image.
""" """
def __init__(self, image_proxy, value): def __init__(self, image_proxy, value):
self.image_proxy = image_proxy self.image_proxy = image_proxy

View File

@ -138,20 +138,25 @@ class Controller(object):
"""Return a basic filtered list of public, non-deleted images """Return a basic filtered list of public, non-deleted images
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:retval a mapping of the following form:: :returns: a mapping of the following form
.. code-block:: python
dict(images=[image_list]) dict(images=[image_list])
Where image_list is a sequence of mappings:: Where image_list is a sequence of mappings
.. code-block:: json
{ {
'id': <ID>, 'id': <ID>,
'name': <NAME>, 'name': <NAME>,
'size': <SIZE>, 'size': <SIZE>,
'disk_format': <DISK_FORMAT>, 'disk_format': <DISK_FORMAT>,
'container_format': <CONTAINER_FORMAT>, 'container_format': <CONTAINER_FORMAT>,
'checksum': <CHECKSUM> 'checksum': <CHECKSUM>
} }
""" """
params = self._get_query_params(req) params = self._get_query_params(req)
images = self._get_images(req.context, **params) images = self._get_images(req.context, **params)
@ -170,12 +175,29 @@ class Controller(object):
"""Return a filtered list of public, non-deleted images in detail """Return a filtered list of public, non-deleted images in detail
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:retval a mapping of the following form:: :returns: a mapping of the following form
dict(images=[image_list]) .. code-block:: json
{'images':
[{
'id': <ID>,
'name': <NAME>,
'size': <SIZE>,
'disk_format': <DISK_FORMAT>,
'container_format': <CONTAINER_FORMAT>,
'checksum': <CHECKSUM>,
'min_disk': <MIN_DISK>,
'min_ram': <MIN_RAM>,
'store': <STORE>,
'status': <STATUS>,
'created_at': <TIMESTAMP>,
'updated_at': <TIMESTAMP>,
'deleted_at': <TIMESTAMP>|<NONE>,
'properties': {'distro': 'Ubuntu 10.04 LTS', {...}}
}, {...}]
}
Where image_list is a sequence of mappings containing
all image model fields.
""" """
params = self._get_query_params(req) params = self._get_query_params(req)
@ -188,7 +210,7 @@ class Controller(object):
"""Extract necessary query parameters from http request. """Extract necessary query parameters from http request.
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:retval dictionary of filters to apply to list of images :returns: dictionary of filters to apply to list of images
""" """
params = { params = {
'filters': self._get_filters(req), 'filters': self._get_filters(req),
@ -217,7 +239,7 @@ class Controller(object):
"""Return a dictionary of query param filters from the request """Return a dictionary of query param filters from the request
:param req: the Request object coming from the wsgi layer :param req: the Request object coming from the wsgi layer
:retval a dict of key/value filters :returns: a dict of key/value filters
""" """
filters = {} filters = {}
properties = {} properties = {}
@ -360,8 +382,9 @@ class Controller(object):
:param req: wsgi Request object :param req: wsgi Request object
:param id: The opaque internal identifier for the image :param id: The opaque internal identifier for the image
:retval Returns 200 if delete was successful, a fault if not. On :returns: 200 if delete was successful, a fault if not. On
success, the body contains the deleted image information as a mapping. success, the body contains the deleted image
information as a mapping.
""" """
try: try:
deleted_image = self.db_api.image_destroy(req.context, id) deleted_image = self.db_api.image_destroy(req.context, id)
@ -390,9 +413,9 @@ class Controller(object):
:param req: wsgi Request object :param req: wsgi Request object
:param body: Dictionary of information about the image :param body: Dictionary of information about the image
:retval Returns the newly-created image information as a mapping, :returns: The newly-created image information as a mapping,
which will include the newly-created image's internal id which will include the newly-created image's internal id
in the 'id' field in the 'id' field
""" """
image_data = body['image'] image_data = body['image']
@ -441,7 +464,7 @@ class Controller(object):
:param body: Dictionary of information about the image :param body: Dictionary of information about the image
:param id: The opaque internal identifier for the image :param id: The opaque internal identifier for the image
:retval Returns the updated image information as a mapping, :returns: Returns the updated image information as a mapping,
""" """
image_data = body['image'] image_data = body['image']
from_state = body.get('from_state', None) from_state = body.get('from_state', None)

View File

@ -88,9 +88,9 @@ class Controller(object):
Replaces the members of the image with those specified in the Replaces the members of the image with those specified in the
body. The body is a dict with the following format:: body. The body is a dict with the following format::
{"memberships": [ {'memberships': [
{"member_id": <MEMBER_ID>, {'member_id': <MEMBER_ID>,
["can_share": [True|False]]}, ... ['can_share': [True|False]]}, ...
]} ]}
""" """
self._check_can_access_image_members(req.context) self._check_can_access_image_members(req.context)
@ -205,11 +205,11 @@ class Controller(object):
Adds a membership to the image, or updates an existing one. Adds a membership to the image, or updates an existing one.
If a body is present, it is a dict with the following format:: If a body is present, it is a dict with the following format::
{"member": { {'member': {
"can_share": [True|False] 'can_share': [True|False]
}} }}
If "can_share" is provided, the member's ability to share is If `can_share` is provided, the member's ability to share is
set accordingly. If it is not provided, existing memberships set accordingly. If it is not provided, existing memberships
remain unchanged and new memberships default to False. remain unchanged and new memberships default to False.
""" """

View File

@ -113,7 +113,7 @@ class ScrubDBQueue(object):
:param image_id: The opaque image identifier :param image_id: The opaque image identifier
:param location: The opaque image location :param location: The opaque image location
:retval A boolean value to indicate success or not :returns: A boolean value to indicate success or not
""" """
loc_id = location.get('id') loc_id = location.get('id')
if loc_id: if loc_id:
@ -151,7 +151,9 @@ class ScrubDBQueue(object):
def get_all_locations(self): def get_all_locations(self):
"""Returns a list of image id and location tuple from scrub queue. """Returns a list of image id and location tuple from scrub queue.
:retval a list of image id, location id and uri tuple from scrub queue :returns: a list of image id, location id and uri tuple from
scrub queue
""" """
ret = [] ret = []
@ -187,7 +189,7 @@ class ScrubDBQueue(object):
:param image_id: The opaque image identifier :param image_id: The opaque image identifier
:retval a boolean value to inform including or not :returns: a boolean value to inform including or not
""" """
try: try:
image = self.registry.get_image(image_id) image = self.registry.get_image(image_id)

View File

@ -608,20 +608,21 @@ class TestApi(functional.FunctionalTest):
def test_download_non_exists_image_raises_http_forbidden(self): def test_download_non_exists_image_raises_http_forbidden(self):
""" """
We test the following sequential series of actions: We test the following sequential series of actions::
0. POST /images with public image named Image1 0. POST /images with public image named Image1
and no custom properties and no custom properties
- Verify 201 returned - Verify 201 returned
1. HEAD image 1. HEAD image
- Verify HTTP headers have correct information we just added - Verify HTTP headers have correct information we just added
2. GET image 2. GET image
- Verify all information on image we just added is correct - Verify all information on image we just added is correct
3. DELETE image1 3. DELETE image1
- Delete the newly added image - Delete the newly added image
4. GET image 4. GET image
- Verify that 403 HTTPForbidden exception is raised prior to - Verify that 403 HTTPForbidden exception is raised prior to
404 HTTPNotFound 404 HTTPNotFound
""" """
self.cleanup() self.cleanup()
self.start_servers(**self.__dict__.copy()) self.start_servers(**self.__dict__.copy())

View File

@ -228,7 +228,7 @@ class TestApi(base.ApiTest):
0. GET /images 0. GET /images
- Verify no public images - Verify no public images
1. POST /images with public image named Image1 with no location 1. POST /images with public image named Image1 with no location
attribute and no image data. attribute and no image data.
- Verify 201 returned - Verify 201 returned
2. GET /images 2. GET /images
- Verify one public image - Verify one public image

View File

@ -138,9 +138,10 @@ class TestArtifactsLoader(utils.BaseTestCase):
""" """
A test to show that plugin-load specific options in artifacts.conf A test to show that plugin-load specific options in artifacts.conf
are correctly processed: are correctly processed:
* no plugins can be loaded if load_enabled = False
* if available_plugins list is given only plugins specified can be * no plugins can be loaded if load_enabled = False
be loaded * if available_plugins list is given only plugins specified can be
be loaded
""" """
self.config(load_enabled=False) self.config(load_enabled=False)
self.assertRaises(exception.ArtifactLoadError, self.assertRaises(exception.ArtifactLoadError,