summaryrefslogtreecommitdiff
path: root/nova/volume
diff options
context:
space:
mode:
authorMatt Riedemann <mriedem.os@gmail.com>2017-05-31 12:37:55 -0400
committerMatt Riedemann <mriedem.os@gmail.com>2017-06-08 10:30:53 -0400
commitd655179182b708aa8566b810b77951e1cb3aab19 (patch)
tree6718d20e9b7c119ec78ac1baff90b3855234cb07 /nova/volume
parent6c58884030a016bc88ee0019902a64937b1dbced (diff)
downloadnova-d655179182b708aa8566b810b77951e1cb3aab19.tar.gz
Use microversions for new style volume attachments
This adds the ability to do version discovery with Cinder to know if we can make requests at a specific microversion, like 3.27 in the case of creating/updating/deleting volume attachments. We will use this to attempt an attachment_create at 3.27 when attaching a volume to an instance and if 3.27 is not available then the calling code will need to handle CinderAPIVersionNotAvailable and fallback to the old style attachment flow. For new style attachments, everything will be keyed off the BlockDeviceMapping.attachment_id field being set if we successfully created the attachment using 3.27, so the attachment_create method is really the only one that should care about microversions initially. Part of blueprint cinder-new-attach-apis Change-Id: I9b6ab9f71cc58d4514127f5ea61789f187487828
Diffstat (limited to 'nova/volume')
-rw-r--r--nova/volume/cinder.py42
1 files changed, 39 insertions, 3 deletions
diff --git a/nova/volume/cinder.py b/nova/volume/cinder.py
index 6d87b62de8..b2fa315128 100644
--- a/nova/volume/cinder.py
+++ b/nova/volume/cinder.py
@@ -23,6 +23,7 @@ import copy
import functools
import sys
+from cinderclient import api_versions as cinder_api_versions
from cinderclient import client as cinder_client
from cinderclient import exceptions as cinder_exception
from keystoneauth1 import exceptions as keystone_exception
@@ -56,7 +57,37 @@ def reset_globals():
_SESSION = None
-def cinderclient(context):
+def _check_microversion(url, microversion):
+ """Checks to see if the requested microversion is supported by the current
+ version of python-cinderclient and the volume API endpoint.
+
+ :param url: Cinder API endpoint URL.
+ :param microversion: Requested microversion. If not available at the given
+ API endpoint URL, a CinderAPIVersionNotAvailable exception is raised.
+ :returns: The microversion if it is available. This can be used to
+ construct the cinder v3 client object.
+ :raises: CinderAPIVersionNotAvailable if the microversion is not available.
+ """
+ max_api_version = cinder_client.get_highest_client_server_version(url)
+ # get_highest_client_server_version returns a float which we need to cast
+ # to a str and create an APIVersion object to do our version comparison.
+ max_api_version = cinder_api_versions.APIVersion(str(max_api_version))
+ # Check if the max_api_version matches the requested minimum microversion.
+ if max_api_version.matches(microversion):
+ # The requested microversion is supported by the client and the server.
+ return microversion
+ raise exception.CinderAPIVersionNotAvailable(version=microversion)
+
+
+def cinderclient(context, microversion=None):
+ """Constructs a cinder client object for making API requests.
+
+ :param context: The nova request context for auth.
+ :param microversion: Optional microversion to check against the client.
+ This implies that Cinder v3 is required for any calls that require a
+ microversion. If the microversion is not available, this method will
+ raise an CinderAPIVersionNotAvailable exception.
+ """
global _SESSION
if not _SESSION:
@@ -89,13 +120,18 @@ def cinderclient(context):
raise exception.UnsupportedCinderAPIVersion(version=version)
if version == '2':
+ if microversion is not None:
+ # The Cinder v2 API does not support microversions.
+ raise exception.CinderAPIVersionNotAvailable(version=microversion)
LOG.warning("The support for the Cinder API v2 is deprecated, please "
"upgrade to Cinder API v3.")
if version == '3':
- # TODO(ildikov): Add microversion support for picking up the new
- # attach/detach API that was added in 3.27.
version = '3.0'
+ # Check to see a specific microversion is requested and if so, can it
+ # be handled by the backing server.
+ if microversion is not None:
+ version = _check_microversion(url, microversion)
return cinder_client.Client(version,
session=_SESSION,