cinder-specs/specs/newton/discovering-system-capabilities.rst
Radoslaw Smigielski 92f9e7b8df Fix Sphinx warnings in existing Cinder specs
Sphinx throws warnings on two of existing spec files:

> cinder-specs/doc/source/specs/liberty/clone-image-in-glance-cinder-backend.rst:173:
  WARNING: Footnote [2] is not referenced.
> cinder-specs/doc/source/specs/newton/discovering-system-capabilities.rst:356:
  WARNING: Footnote [4] is not referenced.

These need to be fixed before we can switch to new way of building specs
as recomended by OpenStack Project Testing Interface:
https://governance.openstack.org/tc/reference/project-testing-interface.html#documentation

Change-Id: Ibe58c27303f49a72779f0d5ebdd52c001ee8b23c
Closes-Bug: 1810677
2019-01-06 19:42:06 +01:00

361 lines
14 KiB
ReStructuredText

..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
=================================================
New Core APIs for Discovering System Capabilities
=================================================
https://blueprints.launchpad.net/cinder/+spec/discovering-system-capabilities
There needs to be a way for Horizon to discover the capabilities of the remote
block storage deployment so that it can enable/disable the UI widgets
that exercise those capabilities. Consider the volume backup functionality
which may or may not be supported by a cinder deployment. If Horizon could
programmatically detect the presence of this capability, it can enable the
volume backup actions in the UI. This will obviate the need for the operator
to manually set appropriate fields in Horizon's config to signal the
availability of this feature, which is the case today. We propose adding
a set of APIs that would return the "capabilities" available to the current
user. These can be used by Horizon and other clients to configure themselves
without the need for config files that are manually kept in sync.
This blueprint grew out of the design discussion in [1]_ and [2]_ for the bug
#1334856 [3]_ filed by jgriffith.
Problem description
===================
Horizon allows users to create volume backups via the UI, if the underlying
cinder deployment supports the same. Not all cinder deployments support this
functionality, so Horizon needs a way to know when it is supported so that
it can show the UI elements for backup.
Today, Horizon uses [5]_ a config setting "enable_backup" for controlling the
enable status of volume backup operations in the UI. This needs to be manually
set/unset by the operator based on the status of the cinder-backup service.
This is not only cumbersome but also prone to operator error.
The volume backup API is implemented on the server side by the cinder-backup
service. This service is absent when the cinder deployment does not support
volume backups. This is the case, e.g., for devstack with default config.
The "os-services" API extension shows the state of all backend services.
This suggests a way by which Horizon could get to know the existence of the
cinder-backup service. However this has two problems. The first is that the
os-services API is admin-only whereas the backup operation is available to
even non-admin users. The second and more important problem is that not all
features have corresponding services or extension APIs that could be used to
compute the support for that feature in a similar way.
This problem raises its head in non UI domains also. Consider the OpenStack
Heat project. Heat templates allows the option of backing up a volume upon the
deletion of the corresponding volume resource in the template. However,
as there is no way to know whether backup capability is supported by a
Cinder deployment, this can result in late failures during a volume delete.
This ultimately prevents interoperability of orchestration templates across
clouds.
It is easy to see that the above problem is not limited to just the backup
feature but is much more general. Horizon needs a way to programmatically
know which capabilities are supported by the remote block storage service so
that it can enable only those UI widgets that deal with these capabilities
and disable others.
Use Cases
=========
The solution proposed in this spec allows building a dynamic, self-configuring
Horizon UI. This unburdens the operator from manually configuring Horizon and
constantly keeping it in sync with the capabilities of the Cinder deployment.
This solution can be immediately applied to solve the volume backup enable
status problem in Horizon. No longer will the operator need to set the
"enable_backup" in Horizon config; Horizon will programmatically get the
status using the proposed API.
Other capability which can similarly gain is the replication capability, which
is only supported by certain volume types (actually "volume backends", but
normally volume backends are more or less tied to volume types). Note that
feature will be listed by a different capability API than the one that lists
the backup feature. See details below.
The proposed set of APIs can also be used in custom UIs or user scripts for
the same reasons that we envision Horizon using it for.
Proposed change
===============
A new, public Block Storage microversion API that returns the set of all
capabilities for a particular user and resource. Note that the service (or
the deployment) itself is considered as a resource (the root resource).
The capabilities of a system can be defined at multiple levels. The
top-level capabilities such as backup capability are defined at the service
level (or the root resource level). So, the question "Does this cinder service
instance have backup capability?" makes sense by itself. Lower level
capabilities are defined on specific (REST) resources. For example,
replication feature is defined on a volume type. So, it doesn't make sense to
ask "Does this cinder service instance have the replication capability?";
instead, we need to ask "Does the volume type xyz have the replication
capability?".
While we can define a capabilities API for every resource, in practice it will
be required only a small number of resources. For the Cinder API, it is only
required today for the service and volume type resources.
It is not possible to avoid multiple levels of capability APIs. The
lower level capability APIs require input (the resource type) which is not
available at the top level.
The different levels of capability APIs also align with the natural
organization of any UI (e.g. Horizon). On the home page, the UI only shows
the widgets corresponding to top level capabilities. It is possible to
navigate to deeper levels by selecting widgets on the home page. For
example, selecting a particular volume type can lead a page showing widgets
that correspond to the capabilities of that particular volume type. By making
the calls to appropriate level capabilities API, Horizon can programmatically
configure itself at every level.
Note that a cinder instance may implement a particular feature but may not
allow a particular user to access the same. So, the capabilities API
should not only consider whether the service implements the particular feature
but also if the current user is privileged to access the same. The "privilege"
information is already available in the policy.json [4]_ file that maps different
operations to the users that can access them. So, any capapbility API
implementation must make use of this file.
The detection of whether a particular deployment/resource implements a
particular capability varies by the capability itself. For the backup
capability, it could be the presence of the cinder-backup service. For
replication feature, it could be statically set when the volume type is
created or it could be fetched from the driver somehow.
It is not possible to implement the capabilities API based solely on the info
in the policy.json [4]_ file as the policy file does not allow defining rules
per resource. For example, we can allow replication operation for all users
but we cannot constrain it to a specific volume type (which is deal breaker
since not all volume types support replication).
It is easy to see that all capabilities APIs should be public, i.e. accessible
by any user.
The key contribution of this BP is identifying and proposing an API pattern,
namely "one capability API per resource" (of course if some resource doesn't
need it, we don't need to define a capability API for it). This idea is simple
but powerful and also reusable across all OpenStack projects.
While this BP proposes an API pattern, we will only implement the top level
capabilities API. This will return only "volume-backup" for now but can be
augmented as new capabilities are added to Cinder at the service level. For
now, the detection of the backup capability would be similar to the
os-services extension. It will check if the cinder-backup service is enabled
or not by checking the services table from cinder database and if so return
"volume-backup" in the response.
A brief note on the presence of capabilities like APIs in Cinder today: There
is a "volume capabilities" extension API [6]_, but it is defined at the
service level (``/v2/{tenant_id}/capabilities/{hostname}``) rather than at
the volume type level. The "show volume type details" API [8]_ stuffs the
capabilities in a catch-all "extra_specs" property. If this BP is approved,
we will need to rationalize these existing APIs with the new capabilities
APIs that will be defined. This is not in scope for this sepc.
Alternatives
------------
* Make the existing os-services extension public: This will expose the private
cloud internals to the tenant. This is a security hole and hence makes this
alternative infeasible. Also, there may not be a 1:1 correspondence between
capabilities and services.
* Split the existing os-services extension API into public and private halves,
with the public part exposing limited information.
We could modify the services:index action to take a details=true/false
parameter: http://{cinder-endpoint}/v2/{tenant-id}/os-services?details=false
And define different policies for detail=true (admin_api) and detail=false
("" i.e. unrestricted).
* "volume_extension:services:index_with_details": "rule:admin_api"
* "volume_extension:services:index_without_details": ""
It is not clear if this can be implemented in a backward compatible way and
also whether there is precedence for splitting the policy of a single API
call based on parameters. Also, as mentioned above, there may not be a 1:1
correspondence between capabilities and services.
* Re-use the existing "list extensions" public API [7]_. This was proposed by
dulek in [2]_. First, there may not be a 1:1 correspondence between
capabilities and extensions (although it is true for the volume backup
case). Even if it were always true, the operator would need to prune
cinder.conf (manually!) so that it lists only those extensions that are
actually supported. As explained in [2]_, there is no easy way to do that.
Also, as noted by duncant, this breaks the existing semantics - many
deployments have the API extensions enabled (as it comes by default) without
the service being actually running. So the check return value would mean
different things on different systems.
Data model impact
-----------------
None. As explained, we use the existing services table for the volume backup
capability detection. Future capability additions may use different resources
and algorithms.
REST API impact
---------------
We give instances of the "capabilities API pattern" for three resources,
including the service itself.
* ``GET /v3.x/{tenant id}/capabilities``
Returns the set of capabilities of the underlying block storage deployment
at the service level.
Normal http response code(s): 200
Response is a list of capabilities. Each capability is a simple noun or
hyphenated compound noun. E.g:
.. code-block:: rest
{
"capabilities": [
{
"name": "volume-backup",
"description": "Allows creating backups of volumes."
},
{
"name": "other-capability",
"description": "Other capability description."
},
]
}
* ``GET /v3.x/{tenant_id}/types/{volume_type_id}/capabilities``
Returns the set of capabilities of a particular volume type.
Normal http response code(s): 200
Response is a list of capabilities. E.g:
.. code-block:: rest
{
"capabilities": [
{
"name": "replication",
"description": "Allows replication of volumes."
},
{
"name": "other-capability",
"description": "Other capability description."
},
]
}
* General example:
``GET /v3.x/{tenant_id}/<some-resource-collection>/{some-resource-instance}/capabilities``
Returns the set of capabilities of some-resource-instance.
Security impact
---------------
None. Exposing an abstract set of system capabilities should be safe. These
capabilities can be gleaned from the available actions in the UI in any case
(e.g. backup UI widget is visible implies volume backup capability exists).
Notifications impact
--------------------
None
Other end user impact
---------------------
This change is transparent to the user although the user can use this API in
a similar way as Horizon for custom UIs or management scripts.
Performance Impact
------------------
These are new APIs and should not affect any existing APIs
or code paths.
Other deployer impact
---------------------
Operator no longer has to manually set "enable_backup" in Horizon config
settings file. Back-compat story for this Horizon config change is out of
scope for this spec.
Developer impact
----------------
The developer will need to be aware of the capabilities API pattern and
evaluate if any new optional functionality he/she plans to add to a Cinder
service or a lower level resource (e.g. volume type) may benefit from
being exposed via this API. The developer may first need to define a
capability API for that resource.
Implementation
==============
Assignee(s)
-----------
Primary assignee:
dramakri
Work Items
----------
* Implement the proposed public microversion capabilities API at the
service level
* Implement at least the backup capability detection
* Add test cases
* Update API docs
Dependencies
============
None
Testing
=======
Unit and functional test cases need to be added to validate this new API.
Documentation Impact
====================
* New API and client call in Cinder needs to be documented.
* Changes to Horizon config setting needs to be documented.
References
==========
.. [1] http://lists.openstack.org/pipermail/openstack-dev/2015-October/077209.html
.. [2] http://lists.openstack.org/pipermail/openstack-dev/2016-April/092365.html
.. [3] https://bugs.launchpad.net/cinder/+bug/1334856
.. [4] https://github.com/openstack/cinder/blob/master/etc/cinder/policy.json
.. [5] http://docs.openstack.org/developer/horizon/topics/settings.html
.. [6] http://developer.openstack.org/api-ref-blockstorage-v2.html#capabilities-v2
.. [7] http://developer.openstack.org/api-ref-blockstorage-v2.html#volumes-v2-extensions
.. [8] http://developer.openstack.org/api-ref-blockstorage-v2.html#showVolumeType