diff --git a/circle/dashboard/forms.py b/circle/dashboard/forms.py index b2a8f4a..f3570f4 100644 --- a/circle/dashboard/forms.py +++ b/circle/dashboard/forms.py @@ -943,6 +943,20 @@ class VmAddInterfaceForm(forms.Form): return helper +class VmDeployForm(forms.Form): + + def __init__(self, *args, **kwargs): + choices = kwargs.pop('choices', None) + + super(VmDeployForm, self).__init__(*args, **kwargs) + + if choices is not None: + self.fields.insert(0, 'node', forms.ModelChoiceField( + queryset=choices, label=_('Node'), help_text=_( + "Deploy virtual machine to this node " + "(blank allows scheduling automatically)."))) + + class CircleAuthenticationForm(AuthenticationForm): # fields: username, password diff --git a/circle/dashboard/views/vm.py b/circle/dashboard/views/vm.py index 38f3dfe..46f08b9 100644 --- a/circle/dashboard/views/vm.py +++ b/circle/dashboard/views/vm.py @@ -60,7 +60,7 @@ from ..forms import ( VmAddInterfaceForm, VmCreateDiskForm, VmDownloadDiskForm, VmSaveForm, VmRenewForm, VmStateChangeForm, VmListSearchForm, VmCustomizeForm, TransferOwnershipForm, VmDiskResizeForm, RedeployForm, VmDiskRemoveForm, - VmMigrateForm, + VmMigrateForm, VmDeployForm, ) from ..models import Favourite, Profile @@ -605,7 +605,6 @@ class VmStateChangeView(FormOperationMixin, VmOperationView): op = 'emergency_change_state' icon = 'legal' effect = 'danger' - show_in_toolbar = True form_class = VmStateChangeForm wait_for_result = 0.5 @@ -628,9 +627,23 @@ class RedeployView(FormOperationMixin, VmOperationView): wait_for_result = 0.5 +class VmDeployView(FormOperationMixin, VmOperationView): + op = 'deploy' + icon = 'play' + effect = 'success' + form_class = VmDeployForm + + def get_form_kwargs(self): + kwargs = super(VmOperationView, self).get_form_kwargs() + if self.request.user.is_superuser: + online = (n.pk for n in + Node.objects.filter(enabled=True) if n.online) + kwargs['choices'] = Node.objects.filter(pk__in=online) + return kwargs + + vm_ops = OrderedDict([ - ('deploy', VmOperationView.factory( - op='deploy', icon='play', effect='success')), + ('deploy', VmDeployView), ('wake_up', VmOperationView.factory( op='wake_up', icon='sun-o', effect='success')), ('sleep', VmOperationView.factory( diff --git a/circle/vm/operations.py b/circle/vm/operations.py index 9555341..90daf03 100644 --- a/circle/vm/operations.py +++ b/circle/vm/operations.py @@ -324,10 +324,14 @@ class DeployOperation(InstanceOperation): "deployed to node: %(node)s"), node=self.instance.node) - def _operation(self, activity): + def _operation(self, activity, node=None): # Allocate VNC port and host node self.instance.allocate_vnc_port() - self.instance.allocate_node() + if node is not None: + self.instance.node = node + self.instance.save() + else: + self.instance.allocate_node() # Deploy virtual images self.instance._deploy_disks(parent_activity=activity)