Merge "Add disk config option support"

This commit is contained in:
Jenkins 2014-03-04 02:51:46 +00:00 committed by Gerrit Code Review
commit 12663d44ff
6 changed files with 106 additions and 40 deletions

View File

@ -76,7 +76,8 @@ class Server(base.APIResourceWrapper):
'image_name', 'VirtualInterfaces', 'flavor', 'key_name', 'fault',
'tenant_id', 'user_id', 'created', 'OS-EXT-STS:power_state',
'OS-EXT-STS:task_state', 'OS-EXT-SRV-ATTR:instance_name',
'OS-EXT-SRV-ATTR:host', 'OS-EXT-AZ:availability_zone']
'OS-EXT-SRV-ATTR:host', 'OS-EXT-AZ:availability_zone',
'OS-DCF:diskConfig']
def __init__(self, apiresource, request):
super(Server, self).__init__(apiresource)
@ -478,14 +479,16 @@ def keypair_list(request):
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):
availability_zone=None, instance_count=1, admin_pass=None,
disk_config=None):
return Server(novaclient(request).servers.create(
name, image, flavor, userdata=user_data,
security_groups=security_groups,
key_name=key_name, block_device_mapping=block_device_mapping,
block_device_mapping_v2=block_device_mapping_v2,
nics=nics, availability_zone=availability_zone,
min_count=instance_count, admin_pass=admin_pass), request)
min_count=instance_count, admin_pass=admin_pass,
disk_config=disk_config), request)
def server_delete(request, instance):
@ -553,9 +556,10 @@ def server_reboot(request, instance_id, soft_reboot=False):
novaclient(request).servers.reboot(instance_id, hardness)
def server_rebuild(request, instance_id, image_id, password=None):
def server_rebuild(request, instance_id, image_id, password=None,
disk_config=None):
return novaclient(request).servers.rebuild(instance_id, image_id,
password)
password, disk_config)
def server_update(request, instance_id, name):
@ -573,8 +577,9 @@ def server_live_migrate(request, instance_id, host, block_migration=False,
disk_over_commit)
def server_resize(request, instance_id, flavor, **kwargs):
novaclient(request).servers.resize(instance_id, flavor, **kwargs)
def server_resize(request, instance_id, flavor, disk_config=None, **kwargs):
novaclient(request).servers.resize(instance_id, flavor,
disk_config, **kwargs)
def server_confirm_resize(request, instance_id):

View File

@ -49,6 +49,8 @@ class RebuildInstanceForm(forms.SelfHandlingForm):
confirm_password = forms.CharField(label=_("Confirm Rebuild Password"),
required=False,
widget=forms.PasswordInput(render_value=False))
disk_config = forms.ChoiceField(label=_("Disk Partition"),
required=False)
def __init__(self, request, *args, **kwargs):
super(RebuildInstanceForm, self).__init__(request, *args, **kwargs)
@ -67,6 +69,10 @@ class RebuildInstanceForm(forms.SelfHandlingForm):
del self.fields['password']
del self.fields['confirm_password']
# Set our disk_config choices
config_choices = [("AUTO", _("Automatic")), ("MANUAL", _("Manual"))]
self.fields['disk_config'].choices = config_choices
def clean(self):
cleaned_data = super(RebuildInstanceForm, self).clean()
if 'password' in cleaned_data:
@ -84,8 +90,10 @@ class RebuildInstanceForm(forms.SelfHandlingForm):
instance = data.get('instance_id')
image = data.get('image')
password = data.get('password') or None
disk_config = data.get('disk_config', None)
try:
api.nova.server_rebuild(request, instance, image, password)
api.nova.server_rebuild(request, instance, image, password,
disk_config)
messages.success(request, _('Rebuilding instance %s.') % instance)
except Exception:
redirect = reverse('horizon:project:instances:index')

View File

@ -0,0 +1,3 @@
{% 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>

View File

@ -1091,7 +1091,8 @@ class InstanceTests(test.TestCase):
['<SetInstanceDetails: setinstancedetailsaction>',
'<SetAccessControls: setaccesscontrolsaction>',
'<SetNetwork: setnetworkaction>',
'<PostCreationStep: customizeaction>'])
'<PostCreationStep: customizeaction>',
'<SetAdvanced: setadvancedaction>'])
if custom_flavor_sort == 'id':
# Reverse sorted by id
@ -1257,7 +1258,8 @@ class InstanceTests(test.TestCase):
nics=nics,
availability_zone=avail_zone.zoneName,
instance_count=IsA(int),
admin_pass=u'')
admin_pass=u'',
disk_config=u'AUTO')
quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
.AndReturn(quota_usages)
api.nova.flavor_list(IsA(http.HttpRequest)) \
@ -1277,7 +1279,8 @@ class InstanceTests(test.TestCase):
'availability_zone': avail_zone.zoneName,
'volume_type': '',
'network': self.networks.first().id,
'count': 1}
'count': 1,
'disk_config': 'AUTO'}
url = reverse('horizon:project:instances:launch')
res = self.client.post(url, form_data)
@ -1366,7 +1369,8 @@ class InstanceTests(test.TestCase):
nics=nics,
availability_zone=avail_zone.zoneName,
instance_count=IsA(int),
admin_pass=u'')
admin_pass=u'',
disk_config=u'AUTO')
quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
.AndReturn(quota_usages)
@ -1386,7 +1390,8 @@ class InstanceTests(test.TestCase):
'volume_id': volume_choice,
'device_name': device_name,
'network': self.networks.first().id,
'count': 1}
'count': 1,
'disk_config': 'AUTO'}
url = reverse('horizon:project:instances:launch')
res = self.client.post(url, form_data)
@ -1481,7 +1486,8 @@ class InstanceTests(test.TestCase):
nics=nics,
availability_zone=avail_zone.zoneName,
instance_count=IsA(int),
admin_pass=u'')
admin_pass=u'',
disk_config='MANUAL')
self.mox.ReplayAll()
@ -1499,7 +1505,8 @@ class InstanceTests(test.TestCase):
'volume_type': 'volume_id',
'volume_id': volume_choice,
'device_name': device_name,
'count': 1}
'count': 1,
'disk_config': 'MANUAL'}
url = reverse('horizon:project:instances:launch')
res = self.client.post(url, form_data)
@ -1729,7 +1736,8 @@ class InstanceTests(test.TestCase):
nics=nics,
availability_zone=avail_zone.zoneName,
instance_count=IsA(int),
admin_pass='password') \
admin_pass='password',
disk_config='AUTO') \
.AndRaise(self.exceptions.keystone)
quotas.tenant_quota_usages(IsA(http.HttpRequest)) \
.AndReturn(quota_usages)
@ -1754,7 +1762,8 @@ class InstanceTests(test.TestCase):
'network': self.networks.first().id,
'count': 1,
'admin_pass': 'password',
'confirm_admin_pass': 'password'}
'confirm_admin_pass': 'password',
'disk_config': 'AUTO'}
url = reverse('horizon:project:instances:launch')
res = self.client.post(url, form_data)
@ -2327,9 +2336,10 @@ class InstanceTests(test.TestCase):
self.assertRedirectsNoFollow(res, INDEX_URL)
def _instance_resize_post(self, server_id, flavor_id):
def _instance_resize_post(self, server_id, flavor_id, disk_config):
formData = {'flavor': flavor_id,
'default_role': 'member'}
'default_role': 'member',
'disk_config': disk_config}
url = reverse('horizon:project:instances:resize',
args=[server_id])
return self.client.post(url, formData)
@ -2347,12 +2357,12 @@ class InstanceTests(test.TestCase):
.AndReturn(server)
api.nova.flavor_list(IsA(http.HttpRequest)) \
.AndReturn(self.flavors.list())
api.nova.server_resize(IsA(http.HttpRequest), server.id, flavor.id) \
.AndReturn([])
api.nova.server_resize(IsA(http.HttpRequest), server.id, flavor.id,
'AUTO').AndReturn([])
self.mox.ReplayAll()
res = self._instance_resize_post(server.id, flavor.id)
res = self._instance_resize_post(server.id, flavor.id, u'AUTO')
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
@ -2365,12 +2375,13 @@ class InstanceTests(test.TestCase):
.AndReturn(server)
api.nova.flavor_list(IsA(http.HttpRequest)) \
.AndReturn(self.flavors.list())
api.nova.server_resize(IsA(http.HttpRequest), server.id, flavor.id) \
.AndRaise(self.exceptions.nova)
api.nova.server_resize(IsA(http.HttpRequest), server.id, flavor.id,
'AUTO') \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
res = self._instance_resize_post(server.id, flavor.id)
res = self._instance_resize_post(server.id, flavor.id, 'AUTO')
self.assertRedirectsNoFollow(res, INDEX_URL)
@test.create_stubs({api.glance: ('image_list_detailed',)})
@ -2404,9 +2415,11 @@ class InstanceTests(test.TestCase):
self.test_rebuild_instance_get(expect_password_fields=False)
def _instance_rebuild_post(self, server_id, image_id,
password=None, confirm_password=None):
password=None, confirm_password=None,
disk_config=None):
form_data = {'instance_id': server_id,
'image': image_id}
'image': image_id,
'disk_config': disk_config}
if password is not None:
form_data.update(password=password)
if confirm_password is not None:
@ -2436,13 +2449,15 @@ class InstanceTests(test.TestCase):
api.nova.server_rebuild(IsA(http.HttpRequest),
server.id,
image.id,
password).AndReturn([])
password,
'AUTO').AndReturn([])
self.mox.ReplayAll()
res = self._instance_rebuild_post(server.id, image.id,
password=password,
confirm_password=password)
confirm_password=password,
disk_config='AUTO')
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
@ -2462,13 +2477,16 @@ class InstanceTests(test.TestCase):
api.nova.server_rebuild(IsA(http.HttpRequest),
server.id,
image.id,
None).AndRaise(self.exceptions.nova)
None,
'AUTO') \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
res = self._instance_rebuild_post(server.id, image.id,
password=None,
confirm_password=None)
confirm_password=None,
disk_config='AUTO')
self.assertRedirectsNoFollow(res, INDEX_URL)
@test.create_stubs(instance_rebuild_post_stubs)
@ -2490,7 +2508,8 @@ class InstanceTests(test.TestCase):
self.mox.ReplayAll()
res = self._instance_rebuild_post(server.id, image.id,
password=pass1,
confirm_password=pass2)
confirm_password=pass2,
disk_config='MANUAL')
self.assertContains(res, "Passwords do not match.")
@ -2510,13 +2529,15 @@ class InstanceTests(test.TestCase):
api.nova.server_rebuild(IsA(http.HttpRequest),
server.id,
image.id,
None).AndReturn([])
None,
'AUTO').AndReturn([])
self.mox.ReplayAll()
res = self._instance_rebuild_post(server.id, image.id,
password=u'',
confirm_password=u'')
confirm_password=u'',
disk_config=u'AUTO')
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
@ -2537,13 +2558,16 @@ class InstanceTests(test.TestCase):
api.nova.server_rebuild(IsA(http.HttpRequest),
server.id,
image.id,
password).AndRaise(self.exceptions.nova)
password,
'AUTO') \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
res = self._instance_rebuild_post(server.id, image.id,
password=password,
confirm_password=password)
confirm_password=password,
disk_config='AUTO')
self.assertRedirectsNoFollow(res, INDEX_URL)

View File

@ -623,6 +623,27 @@ class SetNetwork(workflows.Step):
return context
class SetAdvancedAction(workflows.Action):
disk_config = forms.ChoiceField(label=_("Disk Partition"),
required=False)
def __init__(self, request, *args, **kwargs):
super(SetAdvancedAction, self).__init__(request, *args, **kwargs)
# Set our disk_config choices
config_choices = [("AUTO", _("Automatic")), ("MANUAL", _("Manual"))]
self.fields['disk_config'].choices = config_choices
class Meta:
name = _("Advanced Options")
help_text_template = ("project/instances/"
"_launch_advanced_help.html")
class SetAdvanced(workflows.Step):
action_class = SetAdvancedAction
contributes = ("disk_config",)
class LaunchInstance(workflows.Workflow):
slug = "launch_instance"
name = _("Launch Instance")
@ -634,7 +655,8 @@ class LaunchInstance(workflows.Workflow):
SetInstanceDetails,
SetAccessControls,
SetNetwork,
PostCreationStep)
PostCreationStep,
SetAdvanced)
def format_status_message(self, message):
name = self.context.get('name', 'unknown instance')
@ -719,7 +741,8 @@ class LaunchInstance(workflows.Workflow):
nics=nics,
availability_zone=avail_zone,
instance_count=int(context['count']),
admin_pass=context['admin_pass'])
admin_pass=context['admin_pass'],
disk_config=context['disk_config'])
return True
except Exception:
exceptions.handle(request)

View File

@ -28,6 +28,8 @@ from openstack_dashboard import api
from openstack_dashboard.dashboards.project.instances \
import utils as instance_utils
from openstack_dashboard.dashboards.project.instances.workflows \
import create_instance
class SetFlavorChoiceAction(workflows.Action):
@ -93,7 +95,7 @@ class ResizeInstance(workflows.Workflow):
success_message = _('Preparing instance "%s" for resize.')
failure_message = _('Unable to resize instance "%s".')
success_url = "horizon:project:instances:index"
default_steps = (SetFlavorChoice,)
default_steps = (SetFlavorChoice, create_instance.SetAdvanced)
def format_status_message(self, message):
return message % self.context.get('name', 'unknown instance')
@ -102,8 +104,9 @@ class ResizeInstance(workflows.Workflow):
def handle(self, request, context):
instance_id = context.get('instance_id', None)
flavor = context.get('flavor', None)
disk_config = context.get('disk_config', None)
try:
api.nova.server_resize(request, instance_id, flavor)
api.nova.server_resize(request, instance_id, flavor, disk_config)
return True
except Exception:
exceptions.handle(request)