Merge "Use microversion 2.60 when attaching a multiattach volume"

This commit is contained in:
Zuul 2018-04-25 13:55:23 +00:00 committed by Gerrit Code Review
commit 0d6061c47c
5 changed files with 87 additions and 9 deletions

View File

@ -90,7 +90,8 @@ class Volume(BaseCinderAPIResourceWrapper):
'snapshot_id', 'source_volid', 'attachments', 'tenant_name',
'consistencygroup_id', 'os-vol-host-attr:host',
'os-vol-tenant-attr:tenant_id', 'metadata',
'volume_image_metadata', 'encrypted', 'transfer']
'volume_image_metadata', 'encrypted', 'transfer',
'multiattach']
@property
def is_bootable(self):

View File

@ -32,7 +32,8 @@ MICROVERSION_FEATURES = {
"instance_description": ["2.19", "2.42"],
"remote_console_mks": ["2.8", "2.53"],
"servergroup_soft_policies": ["2.15", "2.60"],
"servergroup_user_info": ["2.13", "2.60"]
"servergroup_user_info": ["2.13", "2.60"],
"multiattach": ["2.60"]
},
"cinder": {
"consistency_groups": ["2.0", "3.10"],

View File

@ -70,6 +70,10 @@ def is_feature_available(request, features):
return bool(get_microversion(request, features))
class VolumeMultiattachNotSupported(horizon_exceptions.HorizonException):
status_code = 400
class VNCConsole(base.APIDictWrapper):
"""Wrapper for the "console" dictionary.
@ -792,9 +796,20 @@ def get_password(request, instance_id, private_key=None):
@profiler.trace
def instance_volume_attach(request, volume_id, instance_id, device):
return novaclient(request).volumes.create_server_volume(instance_id,
volume_id,
device)
from openstack_dashboard.api import cinder
# If we have a multiattach volume, we need to use microversion>=2.60.
volume = cinder.volume_get(request, volume_id)
if volume.multiattach:
version = get_microversion(request, 'multiattach')
if version:
client = novaclient(request, version)
else:
raise VolumeMultiattachNotSupported(
_('Multiattach volumes are not yet supported.'))
else:
client = novaclient(request)
return client.volumes.create_server_volume(
instance_id, volume_id, device)
@profiler.trace

View File

@ -18,6 +18,7 @@ from django.urls import reverse
from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.debug import sensitive_variables
import six
from horizon import exceptions
from horizon import forms
@ -231,11 +232,15 @@ class AttachVolume(forms.SelfHandlingForm):
"inst": instance_id,
"dev": attach.device}
messages.info(request, message)
except Exception:
except Exception as ex:
redirect = reverse('horizon:project:instances:index')
exceptions.handle(request,
_('Unable to attach volume.'),
redirect=redirect)
if isinstance(ex, api.nova.VolumeMultiattachNotSupported):
# Use the specific error from the specific message.
msg = six.text_type(ex)
else:
# Use a generic error message.
msg = _('Unable to attach volume.')
exceptions.handle(request, msg, redirect=redirect)
return True

View File

@ -5215,6 +5215,62 @@ class ConsoleManagerTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
self.mock_instance_volume_attach.assert_called_once_with(
helpers.IsHttpRequest(), volume.id, server.id, str(None))
@mock.patch.object(api.cinder, 'volume_list')
@mock.patch.object(api.cinder, 'volume_get')
@mock.patch.object(api.nova, 'get_microversion', return_value='2.60')
@mock.patch.object(api.nova, 'novaclient')
def test_volume_attach_post_multiattach(
self, mock_client, mock_get_microversion, mock_volume_get,
mock_volume_list):
# Tests that a multiattach volume must be attached with compute API
# microversion 2.60 and the feature is supported.
server = self.servers.first()
volumes = self.cinder_volumes.list()
volume = volumes[1]
volume.multiattach = True
mock_volume_list.return_value = volumes
mock_volume_get.return_value = volume
form_data = {"volume": volume.id,
"instance_id": server.id,
"device": None}
url = reverse('horizon:project:instances:attach_volume',
args=[server.id])
res = self.client.post(url, form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
mock_client.assert_called_once_with(mock.ANY, '2.60')
@mock.patch.object(api.cinder, 'volume_list')
@mock.patch.object(api.cinder, 'volume_get')
@mock.patch.object(api.nova, 'get_microversion', return_value=None)
@mock.patch.object(api.nova, 'novaclient')
def test_volume_attach_post_multiattach_feature_not_available(
self, mock_client, mock_get_microversion, mock_volume_get,
mock_volume_list):
# Tests that a multiattach volume must be attached with compute API
# microversion 2.60 and the feature is not available.
server = self.servers.first()
volumes = self.cinder_volumes.list()
volume = volumes[1]
volume.multiattach = True
mock_volume_list.return_value = volumes
mock_volume_get.return_value = volume
form_data = {"volume": volume.id,
"instance_id": server.id,
"device": None}
url = reverse('horizon:project:instances:attach_volume',
args=[server.id])
self.client.post(url, form_data)
# TODO(mriedem): Assert the actual error from the response but
# the test helpers don't seem to handle this case.
mock_client.assert_not_called()
@helpers.create_mocks({api.nova: ('instance_volumes_list',)})
def test_volume_detach_get(self):
server = self.servers.first()