Merge "Allow setting config drive option when launching instance"
This commit is contained in:
commit
a788b8c399
@ -539,7 +539,7 @@ def server_create(request, name, image, flavor, key_name, user_data,
|
||||
security_groups, block_device_mapping=None,
|
||||
block_device_mapping_v2=None, nics=None,
|
||||
availability_zone=None, instance_count=1, admin_pass=None,
|
||||
disk_config=None, meta=None):
|
||||
disk_config=None, config_drive=None, meta=None):
|
||||
return Server(novaclient(request).servers.create(
|
||||
name, image, flavor, userdata=user_data,
|
||||
security_groups=security_groups,
|
||||
@ -547,7 +547,8 @@ def server_create(request, name, image, flavor, key_name, user_data,
|
||||
block_device_mapping_v2=block_device_mapping_v2,
|
||||
nics=nics, availability_zone=availability_zone,
|
||||
min_count=instance_count, admin_pass=admin_pass,
|
||||
disk_config=disk_config, meta=meta), request)
|
||||
disk_config=disk_config, config_drive=config_drive,
|
||||
meta=meta), request)
|
||||
|
||||
|
||||
def server_delete(request, instance):
|
||||
|
@ -1,3 +1,2 @@
|
||||
{% load i18n %}
|
||||
<p>{% blocktrans %}Automatic: Entire disk is single partition and automatically resizes.{% endblocktrans %}</p>
|
||||
<p>{% blocktrans %}Manual: Faster build times but requires manual partitioning.{% endblocktrans %}</p>
|
||||
<p>{% blocktrans %}Specify advanced options to use when launching an instance.{% endblocktrans %}</p>
|
||||
|
@ -1214,6 +1214,7 @@ class InstanceTests(helpers.TestCase):
|
||||
custom_flavor_sort=None,
|
||||
only_one_network=False,
|
||||
disk_config=True,
|
||||
config_drive=True,
|
||||
test_with_profile=False):
|
||||
image = self.images.first()
|
||||
|
||||
@ -1250,6 +1251,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(disk_config)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(config_drive)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest))\
|
||||
.AndReturn(self.limits['absolute'])
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
@ -1344,6 +1347,12 @@ class InstanceTests(helpers.TestCase):
|
||||
else:
|
||||
self.assertNotContains(res, disk_config_field_label)
|
||||
|
||||
config_drive_field_label = 'Configuration Drive'
|
||||
if config_drive:
|
||||
self.assertContains(res, config_drive_field_label)
|
||||
else:
|
||||
self.assertNotContains(res, config_drive_field_label)
|
||||
|
||||
@django.test.utils.override_settings(
|
||||
OPENSTACK_HYPERVISOR_FEATURES={'can_set_password': False})
|
||||
def test_launch_instance_get_without_password(self):
|
||||
@ -1355,6 +1364,9 @@ class InstanceTests(helpers.TestCase):
|
||||
def test_launch_instance_get_no_disk_config_supported(self):
|
||||
self.test_launch_instance_get(disk_config=False)
|
||||
|
||||
def test_launch_instance_get_no_config_drive_supported(self):
|
||||
self.test_launch_instance_get(config_drive=False)
|
||||
|
||||
@django.test.utils.override_settings(
|
||||
CREATE_INSTANCE_FLAVOR_SORT={
|
||||
'key': 'id',
|
||||
@ -1411,6 +1423,7 @@ class InstanceTests(helpers.TestCase):
|
||||
block_device_mapping_v2=True,
|
||||
only_one_network=False,
|
||||
disk_config=True,
|
||||
config_drive=True,
|
||||
test_with_profile=False):
|
||||
api.nova.extension_supported('BlockDeviceMappingV2Boot',
|
||||
IsA(http.HttpRequest)) \
|
||||
@ -1446,6 +1459,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(disk_config)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(config_drive)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest))\
|
||||
.AndReturn(self.limits['absolute'])
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
@ -1500,6 +1515,7 @@ class InstanceTests(helpers.TestCase):
|
||||
quotas: ('tenant_quota_usages',)})
|
||||
def test_launch_instance_post(self,
|
||||
disk_config=True,
|
||||
config_drive=True,
|
||||
test_with_profile=False):
|
||||
flavor = self.flavors.first()
|
||||
image = self.images.first()
|
||||
@ -1552,6 +1568,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(disk_config)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(config_drive)
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn([])
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -1559,6 +1577,10 @@ class InstanceTests(helpers.TestCase):
|
||||
disk_config_value = u'AUTO'
|
||||
else:
|
||||
disk_config_value = None
|
||||
if config_drive:
|
||||
config_drive_value = True
|
||||
else:
|
||||
config_drive_value = None
|
||||
api.nova.server_create(IsA(http.HttpRequest),
|
||||
server.name,
|
||||
image.id,
|
||||
@ -1572,7 +1594,8 @@ class InstanceTests(helpers.TestCase):
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass=u'',
|
||||
disk_config=disk_config_value)
|
||||
disk_config=disk_config_value,
|
||||
config_drive=config_drive_value)
|
||||
quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
|
||||
.AndReturn(quota_usages)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
@ -1596,6 +1619,8 @@ class InstanceTests(helpers.TestCase):
|
||||
'count': 1}
|
||||
if disk_config:
|
||||
form_data['disk_config'] = 'AUTO'
|
||||
if config_drive:
|
||||
form_data['config_drive'] = True
|
||||
if test_with_profile:
|
||||
form_data['profile'] = self.policy_profiles.first().id
|
||||
url = reverse('horizon:project:instances:launch')
|
||||
@ -1607,6 +1632,9 @@ class InstanceTests(helpers.TestCase):
|
||||
def test_launch_instance_post_no_disk_config_supported(self):
|
||||
self.test_launch_instance_post(disk_config=False)
|
||||
|
||||
def test_launch_instance_post_no_config_drive_supported(self):
|
||||
self.test_launch_instance_post(config_drive=False)
|
||||
|
||||
@helpers.update_settings(
|
||||
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
|
||||
def test_launch_instance_post_with_profile(self):
|
||||
@ -1683,6 +1711,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -1699,7 +1729,8 @@ class InstanceTests(helpers.TestCase):
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass=u'',
|
||||
disk_config=u'AUTO')
|
||||
disk_config=u'AUTO',
|
||||
config_drive=True)
|
||||
quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
|
||||
.AndReturn(quota_usages)
|
||||
|
||||
@ -1721,7 +1752,8 @@ class InstanceTests(helpers.TestCase):
|
||||
'device_name': device_name,
|
||||
'network': self.networks.first().id,
|
||||
'count': 1,
|
||||
'disk_config': 'AUTO'}
|
||||
'disk_config': 'AUTO',
|
||||
'config_drive': True}
|
||||
if test_with_profile:
|
||||
form_data['profile'] = self.policy_profiles.first().id
|
||||
url = reverse('horizon:project:instances:launch')
|
||||
@ -1810,6 +1842,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -1829,7 +1863,8 @@ class InstanceTests(helpers.TestCase):
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass=u'',
|
||||
disk_config='MANUAL')
|
||||
disk_config='MANUAL',
|
||||
config_drive=True)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@ -1849,7 +1884,8 @@ class InstanceTests(helpers.TestCase):
|
||||
'volume_id': volume_choice,
|
||||
'device_name': device_name,
|
||||
'count': 1,
|
||||
'disk_config': 'MANUAL'}
|
||||
'disk_config': 'MANUAL',
|
||||
'config_drive': True}
|
||||
if test_with_profile:
|
||||
form_data['profile'] = self.policy_profiles.first().id
|
||||
url = reverse('horizon:project:instances:launch')
|
||||
@ -1917,6 +1953,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.keypair_list(IsA(http.HttpRequest)) \
|
||||
@ -2000,6 +2038,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
api.nova.tenant_absolute_limits(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.limits['absolute'])
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
@ -2091,6 +2131,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
cinder.volume_list(IgnoreArg()).AndReturn(self.volumes.list())
|
||||
api.nova.server_create(IsA(http.HttpRequest),
|
||||
server.name,
|
||||
@ -2105,7 +2147,8 @@ class InstanceTests(helpers.TestCase):
|
||||
availability_zone=avail_zone.zoneName,
|
||||
instance_count=IsA(int),
|
||||
admin_pass='password',
|
||||
disk_config='AUTO') \
|
||||
disk_config='AUTO',
|
||||
config_drive=False) \
|
||||
.AndRaise(self.exceptions.keystone)
|
||||
quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
|
||||
.AndReturn(quota_usages)
|
||||
@ -2132,7 +2175,8 @@ class InstanceTests(helpers.TestCase):
|
||||
'count': 1,
|
||||
'admin_pass': 'password',
|
||||
'confirm_admin_pass': 'password',
|
||||
'disk_config': 'AUTO'}
|
||||
'disk_config': 'AUTO',
|
||||
'config_drive': False}
|
||||
if test_with_profile:
|
||||
form_data['profile'] = self.policy_profiles.first().id
|
||||
url = reverse('horizon:project:instances:launch')
|
||||
@ -2204,6 +2248,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -2303,6 +2349,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -2419,6 +2467,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -2546,6 +2596,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
cinder.volume_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.volumes.list())
|
||||
cinder.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
|
||||
@ -2743,6 +2795,8 @@ class InstanceTests(helpers.TestCase):
|
||||
api.nova.extension_supported('DiskConfig',
|
||||
IsA(http.HttpRequest)) \
|
||||
.AndReturn(True)
|
||||
api.nova.extension_supported('ConfigDrive',
|
||||
IsA(http.HttpRequest)).AndReturn(True)
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.flavors.list())
|
||||
api.nova.flavor_list(IsA(http.HttpRequest)) \
|
||||
@ -2863,6 +2917,9 @@ class InstanceTests(helpers.TestCase):
|
||||
|
||||
self.assertTemplateUsed(res, views.WorkflowView.template_name)
|
||||
|
||||
config_drive_field_label = 'Configuration Drive'
|
||||
self.assertNotContains(res, config_drive_field_label)
|
||||
|
||||
@helpers.create_stubs({api.nova: ('server_get',
|
||||
'flavor_list',)})
|
||||
def test_instance_resize_get_server_get_exception(self):
|
||||
|
@ -724,11 +724,18 @@ class SetNetwork(workflows.Step):
|
||||
|
||||
|
||||
class SetAdvancedAction(workflows.Action):
|
||||
disk_config = forms.ChoiceField(label=_("Disk Partition"),
|
||||
required=False)
|
||||
disk_config = forms.ChoiceField(label=_("Disk Partition"), required=False,
|
||||
help_text=_("Automatic: The entire disk is a single partition and "
|
||||
"automatically resizes. Manual: Results in faster build "
|
||||
"times but requires manual partitioning."))
|
||||
config_drive = forms.BooleanField(label=_("Configuration Drive"),
|
||||
required=False, help_text=_("Configure OpenStack to write metadata to "
|
||||
"a special configuration drive that "
|
||||
"attaches to the instance when it boots."))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(SetAdvancedAction, self).__init__(request, *args, **kwargs)
|
||||
def __init__(self, request, context, *args, **kwargs):
|
||||
super(SetAdvancedAction, self).__init__(request, context,
|
||||
*args, **kwargs)
|
||||
try:
|
||||
if not api.nova.extension_supported("DiskConfig", request):
|
||||
del self.fields['disk_config']
|
||||
@ -737,6 +744,12 @@ class SetAdvancedAction(workflows.Action):
|
||||
config_choices = [("AUTO", _("Automatic")),
|
||||
("MANUAL", _("Manual"))]
|
||||
self.fields['disk_config'].choices = config_choices
|
||||
# Only show the Config Drive option for the Launch Instance
|
||||
# workflow (not Resize Instance) and only if the extension
|
||||
# is supported.
|
||||
if context.get('workflow_slug') != 'launch_instance' or (
|
||||
not api.nova.extension_supported("ConfigDrive", request)):
|
||||
del self.fields['config_drive']
|
||||
except Exception:
|
||||
exceptions.handle(request, _('Unable to retrieve extensions '
|
||||
'information.'))
|
||||
@ -749,7 +762,16 @@ class SetAdvancedAction(workflows.Action):
|
||||
|
||||
class SetAdvanced(workflows.Step):
|
||||
action_class = SetAdvancedAction
|
||||
contributes = ("disk_config",)
|
||||
contributes = ("disk_config", "config_drive",)
|
||||
|
||||
def prepare_action_context(self, request, context):
|
||||
context = super(SetAdvanced, self).prepare_action_context(request,
|
||||
context)
|
||||
# Add the workflow slug to the context so that we can tell which
|
||||
# workflow is being used when creating the action. This step is
|
||||
# used by both the Launch Instance and Resize Instance workflows.
|
||||
context['workflow_slug'] = self.workflow.slug
|
||||
return context
|
||||
|
||||
|
||||
class LaunchInstance(workflows.Workflow):
|
||||
@ -850,7 +872,8 @@ class LaunchInstance(workflows.Workflow):
|
||||
availability_zone=avail_zone,
|
||||
instance_count=int(context['count']),
|
||||
admin_pass=context['admin_pass'],
|
||||
disk_config=context.get('disk_config'))
|
||||
disk_config=context.get('disk_config'),
|
||||
config_drive=context.get('config_drive'))
|
||||
return True
|
||||
except Exception:
|
||||
exceptions.handle(request)
|
||||
|
Loading…
Reference in New Issue
Block a user