Merge "Use microversion 2.60 when attaching a multiattach volume"
This commit is contained in:
commit
0d6061c47c
|
@ -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):
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue