Clarify future changes in docs
The README was discussing future design decisions as if they were already implemented. This can be confusing for new users. This separates that discussion into a separate doc page and clarifies its intentions. Also, fix sphinx doc build warnings. Change-Id: Ie66b60d972cae25a9805804ad17632aed0932627
This commit is contained in:
parent
83acc22166
commit
0af29bda2f
180
README.rst
180
README.rst
@ -1,5 +1,5 @@
|
|||||||
shade
|
Introduction
|
||||||
=====
|
============
|
||||||
|
|
||||||
shade is a simple client library for operating OpenStack clouds. The
|
shade is a simple client library for operating OpenStack clouds. The
|
||||||
key word here is *simple*. Clouds can do many many many things - but there are
|
key word here is *simple*. Clouds can do many many many things - but there are
|
||||||
@ -17,18 +17,18 @@ library, and adding logic and features that the OpenStack Infra team had
|
|||||||
developed to run client applications at scale, it turned out that we'd written
|
developed to run client applications at scale, it turned out that we'd written
|
||||||
nine-tenths of what we'd need to have a standalone library.
|
nine-tenths of what we'd need to have a standalone library.
|
||||||
|
|
||||||
example
|
Example
|
||||||
-------
|
=======
|
||||||
|
|
||||||
Sometimes an example is nice.
|
Sometimes an example is nice.
|
||||||
::
|
::
|
||||||
|
|
||||||
from shade import *
|
import shade
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Initialize cloud
|
# Initialize cloud
|
||||||
# Cloud configs are read with os-client-config
|
# Cloud configs are read with os-client-config
|
||||||
cloud = openstack_cloud(cloud='mordred')
|
cloud = shade.openstack_cloud(cloud='mordred')
|
||||||
|
|
||||||
# OpenStackCloud object has an interface exposing OpenStack services methods
|
# OpenStackCloud object has an interface exposing OpenStack services methods
|
||||||
print cloud.list_servers()
|
print cloud.list_servers()
|
||||||
@ -50,171 +50,3 @@ Sometimes an example is nice.
|
|||||||
attachments = cinder.volumes.get(volume_id).attachments
|
attachments = cinder.volumes.get(volume_id).attachments
|
||||||
print attachments
|
print attachments
|
||||||
|
|
||||||
|
|
||||||
Object Design
|
|
||||||
=============
|
|
||||||
|
|
||||||
Shade is a library for managing resources, not for operating APIs. As such,
|
|
||||||
it is the resource in question that is the primary object and not the service
|
|
||||||
that may or may not provide that resource, much as we may feel warm and fuzzy
|
|
||||||
to one of the services.
|
|
||||||
|
|
||||||
Every resource at minimum has CRUD functions. Additionally, every resource
|
|
||||||
action should have a "do this task blocking" or "request that the cloud start
|
|
||||||
this action and give me a way to check its status" The creation and deletion
|
|
||||||
of Resources will be handled by a ResourceManager that is attached to the Cloud
|
|
||||||
::
|
|
||||||
|
|
||||||
class Cloud:
|
|
||||||
ResourceManager<Server> server
|
|
||||||
servers = server
|
|
||||||
ResourceManager<FloatingIp> floating_ip
|
|
||||||
floating_ips = floating_ip
|
|
||||||
ResourceManager<Image> image
|
|
||||||
images = image
|
|
||||||
ResourceManager<Role> role
|
|
||||||
roles = role
|
|
||||||
ResourceManager<Volume> volume
|
|
||||||
volumes = volume
|
|
||||||
|
|
||||||
getting, listing and searching
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
In addition to creating a resource, there are different ways of getting your
|
|
||||||
hands on a resource. A `get`, a `list` and a `search`.
|
|
||||||
|
|
||||||
`list` has the simplest semantics - it takes no parameters and simply returns
|
|
||||||
a list of all of the resources that exist.
|
|
||||||
|
|
||||||
`search` takes a set of parameters to match against and returns a list of
|
|
||||||
resources that match the parameters given. If no resources match, it returns
|
|
||||||
an empty list.
|
|
||||||
|
|
||||||
`get` takes the same set of parameters that `search` takes, but will only ever
|
|
||||||
return a single matching resource or None. If multiple resources are matched,
|
|
||||||
an exception will be raised.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
class ResourceManager<Resource>:
|
|
||||||
def get -> Resource
|
|
||||||
def list -> List<Resource>
|
|
||||||
def search -> List<Resource>
|
|
||||||
def create -> Resource
|
|
||||||
|
|
||||||
Cloud and ResourceManager interface
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
All ResourceManagers should accept a cache object passed in to their constructor
|
|
||||||
and should additionally pass that cache object to all Resource constructors.
|
|
||||||
The top-level cloud should create the cache object, then pass it to each of
|
|
||||||
the ResourceManagers when it creates them.
|
|
||||||
|
|
||||||
Client connection objects should exist and be managed at the Cloud level. A
|
|
||||||
backreference to the OpenStack cloud should be passed to every resource manager
|
|
||||||
so that ResourceManagers can get hold of the ones they need. For instance,
|
|
||||||
an Image ResourceManager would potentially need access to both the glance_client
|
|
||||||
and the swift_client.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
class ResourceManager
|
|
||||||
def __init__(self, cache, cloud)
|
|
||||||
class ServerManager(ResourceManager)
|
|
||||||
class OpenStackCloud
|
|
||||||
def __init__(self):
|
|
||||||
self.cache = dogpile.cache()
|
|
||||||
self.server = ServerManager(self.cache, self)
|
|
||||||
self.servers = self.server
|
|
||||||
|
|
||||||
Any resources that have an association action - such as servers and
|
|
||||||
floating_ips, should carry reciprocal methods on each resource with absolutely
|
|
||||||
no difference in behavior.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
class Server(Resource):
|
|
||||||
def connect_floating_ip:
|
|
||||||
class FloatingIp(Resource):
|
|
||||||
def connect_server:
|
|
||||||
|
|
||||||
Resource objects should have all of the accessor methods you'd expect, as well
|
|
||||||
as any other interesting rollup methods or actions. For instance, since
|
|
||||||
a keystone User can be enabled or disabled, one should expect that there
|
|
||||||
would be an enable() and a disable() method, and that those methods will
|
|
||||||
immediately operate the necessary REST apis. However, if you need to make 80
|
|
||||||
changes to a Resource, 80 REST calls may or may not be silly, so there should
|
|
||||||
also be a generic update() method which can be used to request the minimal
|
|
||||||
amount of REST calls needed to update the attributes to the requested values.
|
|
||||||
|
|
||||||
Resource objects should all have a to_dict method which will return a plain
|
|
||||||
flat dictionary of their attributes.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
class Resource:
|
|
||||||
def update(**new_values) -> Resource
|
|
||||||
def delete -> None, throws on error
|
|
||||||
|
|
||||||
Readiness
|
|
||||||
---------
|
|
||||||
|
|
||||||
`create`, `get`, and `attach` can return resources that are not yet ready. Each
|
|
||||||
method should take a `wait` and a `timeout` parameter, that will cause the
|
|
||||||
request for the resource to block until it is ready. However, the user may
|
|
||||||
want to poll themselves. Each resource should have an `is_ready` method which
|
|
||||||
will return True when the resource is ready. The `wait` method then can
|
|
||||||
actually be implemented in the base Resource class as an iterate timeout
|
|
||||||
loop around calls to `is_ready`. Every Resource should also have an
|
|
||||||
`is_failed` and an `is_deleted` method.
|
|
||||||
|
|
||||||
Optional Behavior
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Not all clouds expose all features. For instance, some clouds do not have
|
|
||||||
floating ips. Additionally, some clouds may have the feature but the user
|
|
||||||
account does not, which is effectively the same thing.
|
|
||||||
This should be handled in several ways:
|
|
||||||
|
|
||||||
If the user explicitly requests a resource that they do not have access to,
|
|
||||||
an error should be raised. For instance, if a user tries to create a floating
|
|
||||||
ip on a cloud that does not expose that feature to them, shade should throw
|
|
||||||
a "Your cloud does not let you do that" error.
|
|
||||||
|
|
||||||
If the resource concept can be can be serviced by multiple possible services,
|
|
||||||
shade should transparently try all of them. The discovery method should use
|
|
||||||
the dogpile.cache mechanism so that it can be avoided on subsequent tries. For
|
|
||||||
instance, if the user says "please upload this image", shade should figure
|
|
||||||
out which sequence of actions need to be performed and should get the job done.
|
|
||||||
|
|
||||||
If the resource isn't present on some clouds, but the overall concept the
|
|
||||||
resource represents is, a different resource should present the concept. For
|
|
||||||
instance, while some clouds do not have floating ips, if what the user wants
|
|
||||||
is "a server with an IP" - then the fact that one needs to request a floating
|
|
||||||
ip on some clouds is a detail, and the right thing for that to be is a quality
|
|
||||||
of a server and managed by the server resource. A floating ip resource should
|
|
||||||
really only be directly manipulated by the user if they were doing something
|
|
||||||
very floating-ip specific, such as moving a floating ip from one server to
|
|
||||||
another.
|
|
||||||
|
|
||||||
In short, it should be considered a MASSIVE bug in shade if the shade user
|
|
||||||
ever has to have in their own code "if cloud.has_capability("X") do_thing
|
|
||||||
else do_other_thing" - since that construct conveys some resource that shade
|
|
||||||
should really be able to model.
|
|
||||||
|
|
||||||
Functional Interface
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
shade should also provide a functional mapping to the object interface that
|
|
||||||
does not expose the object interface at all. For instance, fora resource type
|
|
||||||
`server`, one could expect the following.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
class OpenStackCloud:
|
|
||||||
def create_server
|
|
||||||
return self.server.create().to_dict()
|
|
||||||
def get_server
|
|
||||||
return self.server.get().to_dict()
|
|
||||||
def update_server
|
|
||||||
return self.server.get().update().to_dict()
|
|
||||||
|
176
doc/source/future.rst
Normal file
176
doc/source/future.rst
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
************************
|
||||||
|
Future Design Discussion
|
||||||
|
************************
|
||||||
|
|
||||||
|
This document discusses a new approach to the Shade library and how
|
||||||
|
we might wish for it to operate in a future, not-yet-developed version.
|
||||||
|
It presents a more object oriented approach, and design decisions that
|
||||||
|
we have learned and decided on while working on the current version.
|
||||||
|
|
||||||
|
Object Design
|
||||||
|
=============
|
||||||
|
|
||||||
|
Shade is a library for managing resources, not for operating APIs. As such,
|
||||||
|
it is the resource in question that is the primary object and not the service
|
||||||
|
that may or may not provide that resource, much as we may feel warm and fuzzy
|
||||||
|
to one of the services.
|
||||||
|
|
||||||
|
Every resource at minimum has CRUD functions. Additionally, every resource
|
||||||
|
action should have a "do this task blocking" or "request that the cloud start
|
||||||
|
this action and give me a way to check its status" The creation and deletion
|
||||||
|
of Resources will be handled by a ResourceManager that is attached to the Cloud
|
||||||
|
::
|
||||||
|
|
||||||
|
class Cloud:
|
||||||
|
ResourceManager<Server> server
|
||||||
|
servers = server
|
||||||
|
ResourceManager<FloatingIp> floating_ip
|
||||||
|
floating_ips = floating_ip
|
||||||
|
ResourceManager<Image> image
|
||||||
|
images = image
|
||||||
|
ResourceManager<Role> role
|
||||||
|
roles = role
|
||||||
|
ResourceManager<Volume> volume
|
||||||
|
volumes = volume
|
||||||
|
|
||||||
|
getting, listing and searching
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
In addition to creating a resource, there are different ways of getting your
|
||||||
|
hands on a resource. A `get`, a `list` and a `search`.
|
||||||
|
|
||||||
|
`list` has the simplest semantics - it takes no parameters and simply returns
|
||||||
|
a list of all of the resources that exist.
|
||||||
|
|
||||||
|
`search` takes a set of parameters to match against and returns a list of
|
||||||
|
resources that match the parameters given. If no resources match, it returns
|
||||||
|
an empty list.
|
||||||
|
|
||||||
|
`get` takes the same set of parameters that `search` takes, but will only ever
|
||||||
|
return a single matching resource or None. If multiple resources are matched,
|
||||||
|
an exception will be raised.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class ResourceManager<Resource>:
|
||||||
|
def get -> Resource
|
||||||
|
def list -> List<Resource>
|
||||||
|
def search -> List<Resource>
|
||||||
|
def create -> Resource
|
||||||
|
|
||||||
|
Cloud and ResourceManager interface
|
||||||
|
===================================
|
||||||
|
|
||||||
|
All ResourceManagers should accept a cache object passed in to their constructor
|
||||||
|
and should additionally pass that cache object to all Resource constructors.
|
||||||
|
The top-level cloud should create the cache object, then pass it to each of
|
||||||
|
the ResourceManagers when it creates them.
|
||||||
|
|
||||||
|
Client connection objects should exist and be managed at the Cloud level. A
|
||||||
|
backreference to the OpenStack cloud should be passed to every resource manager
|
||||||
|
so that ResourceManagers can get hold of the ones they need. For instance,
|
||||||
|
an Image ResourceManager would potentially need access to both the glance_client
|
||||||
|
and the swift_client.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class ResourceManager
|
||||||
|
def __init__(self, cache, cloud)
|
||||||
|
class ServerManager(ResourceManager)
|
||||||
|
class OpenStackCloud
|
||||||
|
def __init__(self):
|
||||||
|
self.cache = dogpile.cache()
|
||||||
|
self.server = ServerManager(self.cache, self)
|
||||||
|
self.servers = self.server
|
||||||
|
|
||||||
|
Any resources that have an association action - such as servers and
|
||||||
|
floating_ips, should carry reciprocal methods on each resource with absolutely
|
||||||
|
no difference in behavior.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class Server(Resource):
|
||||||
|
def connect_floating_ip:
|
||||||
|
class FloatingIp(Resource):
|
||||||
|
def connect_server:
|
||||||
|
|
||||||
|
Resource objects should have all of the accessor methods you'd expect, as well
|
||||||
|
as any other interesting rollup methods or actions. For instance, since
|
||||||
|
a keystone User can be enabled or disabled, one should expect that there
|
||||||
|
would be an enable() and a disable() method, and that those methods will
|
||||||
|
immediately operate the necessary REST apis. However, if you need to make 80
|
||||||
|
changes to a Resource, 80 REST calls may or may not be silly, so there should
|
||||||
|
also be a generic update() method which can be used to request the minimal
|
||||||
|
amount of REST calls needed to update the attributes to the requested values.
|
||||||
|
|
||||||
|
Resource objects should all have a to_dict method which will return a plain
|
||||||
|
flat dictionary of their attributes.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class Resource:
|
||||||
|
def update(**new_values) -> Resource
|
||||||
|
def delete -> None, throws on error
|
||||||
|
|
||||||
|
Readiness
|
||||||
|
---------
|
||||||
|
|
||||||
|
`create`, `get`, and `attach` can return resources that are not yet ready. Each
|
||||||
|
method should take a `wait` and a `timeout` parameter, that will cause the
|
||||||
|
request for the resource to block until it is ready. However, the user may
|
||||||
|
want to poll themselves. Each resource should have an `is_ready` method which
|
||||||
|
will return True when the resource is ready. The `wait` method then can
|
||||||
|
actually be implemented in the base Resource class as an iterate timeout
|
||||||
|
loop around calls to `is_ready`. Every Resource should also have an
|
||||||
|
`is_failed` and an `is_deleted` method.
|
||||||
|
|
||||||
|
Optional Behavior
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Not all clouds expose all features. For instance, some clouds do not have
|
||||||
|
floating ips. Additionally, some clouds may have the feature but the user
|
||||||
|
account does not, which is effectively the same thing.
|
||||||
|
This should be handled in several ways:
|
||||||
|
|
||||||
|
If the user explicitly requests a resource that they do not have access to,
|
||||||
|
an error should be raised. For instance, if a user tries to create a floating
|
||||||
|
ip on a cloud that does not expose that feature to them, shade should throw
|
||||||
|
a "Your cloud does not let you do that" error.
|
||||||
|
|
||||||
|
If the resource concept can be can be serviced by multiple possible services,
|
||||||
|
shade should transparently try all of them. The discovery method should use
|
||||||
|
the dogpile.cache mechanism so that it can be avoided on subsequent tries. For
|
||||||
|
instance, if the user says "please upload this image", shade should figure
|
||||||
|
out which sequence of actions need to be performed and should get the job done.
|
||||||
|
|
||||||
|
If the resource isn't present on some clouds, but the overall concept the
|
||||||
|
resource represents is, a different resource should present the concept. For
|
||||||
|
instance, while some clouds do not have floating ips, if what the user wants
|
||||||
|
is "a server with an IP" - then the fact that one needs to request a floating
|
||||||
|
ip on some clouds is a detail, and the right thing for that to be is a quality
|
||||||
|
of a server and managed by the server resource. A floating ip resource should
|
||||||
|
really only be directly manipulated by the user if they were doing something
|
||||||
|
very floating-ip specific, such as moving a floating ip from one server to
|
||||||
|
another.
|
||||||
|
|
||||||
|
In short, it should be considered a MASSIVE bug in shade if the shade user
|
||||||
|
ever has to have in their own code "if cloud.has_capability("X") do_thing
|
||||||
|
else do_other_thing" - since that construct conveys some resource that shade
|
||||||
|
should really be able to model.
|
||||||
|
|
||||||
|
Functional Interface
|
||||||
|
====================
|
||||||
|
|
||||||
|
shade should also provide a functional mapping to the object interface that
|
||||||
|
does not expose the object interface at all. For instance, for a resource type
|
||||||
|
`server`, one could expect the following.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
class OpenStackCloud:
|
||||||
|
def create_server
|
||||||
|
return self.server.create().to_dict()
|
||||||
|
def get_server
|
||||||
|
return self.server.get().to_dict()
|
||||||
|
def update_server
|
||||||
|
return self.server.get().update().to_dict()
|
@ -4,7 +4,7 @@
|
|||||||
contain the root `toctree` directive.
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
Welcome to shade's documentation!
|
Welcome to shade's documentation!
|
||||||
========================================================
|
=================================
|
||||||
|
|
||||||
Contents:
|
Contents:
|
||||||
|
|
||||||
@ -14,6 +14,7 @@ Contents:
|
|||||||
installation
|
installation
|
||||||
usage
|
usage
|
||||||
contributing
|
contributing
|
||||||
|
future
|
||||||
|
|
||||||
.. include:: ../../README.rst
|
.. include:: ../../README.rst
|
||||||
|
|
||||||
|
@ -3969,10 +3969,10 @@ class OperatorCloud(OpenStackCloud):
|
|||||||
|
|
||||||
:returns: a dict containing the services description, i.e. the
|
:returns: a dict containing the services description, i.e. the
|
||||||
following attributes::
|
following attributes::
|
||||||
- id: <service id>
|
- id: <service id>
|
||||||
- name: <service name>
|
- name: <service name>
|
||||||
- service_type: <service type>
|
- service_type: <service type>
|
||||||
- description: <service description>
|
- description: <service description>
|
||||||
|
|
||||||
:raises: ``OpenStackCloudException`` if something goes wrong during the
|
:raises: ``OpenStackCloudException`` if something goes wrong during the
|
||||||
openstack API call.
|
openstack API call.
|
||||||
@ -4028,10 +4028,10 @@ class OperatorCloud(OpenStackCloud):
|
|||||||
|
|
||||||
:returns: a dict containing the services description, i.e. the
|
:returns: a dict containing the services description, i.e. the
|
||||||
following attributes::
|
following attributes::
|
||||||
- id: <service id>
|
- id: <service id>
|
||||||
- name: <service name>
|
- name: <service name>
|
||||||
- service_type: <service type>
|
- service_type: <service type>
|
||||||
- description: <service description>
|
- description: <service description>
|
||||||
|
|
||||||
:raises: ``OpenStackCloudException`` if something goes wrong during the
|
:raises: ``OpenStackCloudException`` if something goes wrong during the
|
||||||
openstack API call or if multiple matches are found.
|
openstack API call or if multiple matches are found.
|
||||||
@ -4074,7 +4074,7 @@ class OperatorCloud(OpenStackCloud):
|
|||||||
|
|
||||||
:returns: a dict containing the endpoint description.
|
:returns: a dict containing the endpoint description.
|
||||||
|
|
||||||
:raise OpenStackCloudException: if the service cannot be found or if
|
:raises: OpenStackCloudException if the service cannot be found or if
|
||||||
something goes wrong during the openstack API call.
|
something goes wrong during the openstack API call.
|
||||||
"""
|
"""
|
||||||
# ToDo: support v3 api (dguerri)
|
# ToDo: support v3 api (dguerri)
|
||||||
@ -4122,11 +4122,11 @@ class OperatorCloud(OpenStackCloud):
|
|||||||
|
|
||||||
:returns: a list of dict containing the endpoint description. Each dict
|
:returns: a list of dict containing the endpoint description. Each dict
|
||||||
contains the following attributes::
|
contains the following attributes::
|
||||||
- id: <endpoint id>
|
- id: <endpoint id>
|
||||||
- region: <endpoint region>
|
- region: <endpoint region>
|
||||||
- public_url: <endpoint public url>
|
- public_url: <endpoint public url>
|
||||||
- internal_url: <endpoint internal url> (optional)
|
- internal_url: <endpoint internal url> (optional)
|
||||||
- admin_url: <endpoint admin url> (optional)
|
- admin_url: <endpoint admin url> (optional)
|
||||||
|
|
||||||
:raises: ``OpenStackCloudException``: if something goes wrong during
|
:raises: ``OpenStackCloudException``: if something goes wrong during
|
||||||
the openstack API call.
|
the openstack API call.
|
||||||
@ -4143,11 +4143,11 @@ class OperatorCloud(OpenStackCloud):
|
|||||||
|
|
||||||
:returns: a dict containing the endpoint description. i.e. a dict
|
:returns: a dict containing the endpoint description. i.e. a dict
|
||||||
containing the following attributes::
|
containing the following attributes::
|
||||||
- id: <endpoint id>
|
- id: <endpoint id>
|
||||||
- region: <endpoint region>
|
- region: <endpoint region>
|
||||||
- public_url: <endpoint public url>
|
- public_url: <endpoint public url>
|
||||||
- internal_url: <endpoint internal url> (optional)
|
- internal_url: <endpoint internal url> (optional)
|
||||||
- admin_url: <endpoint admin url> (optional)
|
- admin_url: <endpoint admin url> (optional)
|
||||||
"""
|
"""
|
||||||
return _utils._get_entity(self.search_endpoints, id, filters)
|
return _utils._get_entity(self.search_endpoints, id, filters)
|
||||||
|
|
||||||
@ -4258,9 +4258,9 @@ class OperatorCloud(OpenStackCloud):
|
|||||||
|
|
||||||
:returns: a list of dicts containing the domain description. Each dict
|
:returns: a list of dicts containing the domain description. Each dict
|
||||||
contains the following attributes::
|
contains the following attributes::
|
||||||
- id: <domain id>
|
- id: <domain id>
|
||||||
- name: <domain name>
|
- name: <domain name>
|
||||||
- description: <domain description>
|
- description: <domain description>
|
||||||
|
|
||||||
:raises: ``OpenStackCloudException``: if something goes wrong during
|
:raises: ``OpenStackCloudException``: if something goes wrong during
|
||||||
the openstack API call.
|
the openstack API call.
|
||||||
@ -4280,10 +4280,9 @@ class OperatorCloud(OpenStackCloud):
|
|||||||
|
|
||||||
:returns: a dict containing the domain description, or None if not
|
:returns: a dict containing the domain description, or None if not
|
||||||
found. Each dict contains the following attributes::
|
found. Each dict contains the following attributes::
|
||||||
- id: <domain id>
|
- id: <domain id>
|
||||||
- name: <domain name>
|
- name: <domain name>
|
||||||
- description: <domain description>
|
- description: <domain description>
|
||||||
|
|
||||||
|
|
||||||
:raises: ``OpenStackCloudException``: if something goes wrong during
|
:raises: ``OpenStackCloudException``: if something goes wrong during
|
||||||
the openstack API call.
|
the openstack API call.
|
||||||
|
Loading…
Reference in New Issue
Block a user