diff --git a/circle/dashboard/forms.py b/circle/dashboard/forms.py index 80bad23..759e987 100644 --- a/circle/dashboard/forms.py +++ b/circle/dashboard/forms.py @@ -916,6 +916,20 @@ class VmDownloadDiskForm(OperationForm): return cleaned_data +class VmSetMasterInterfaceForm(OperationForm): + def __init__(self, *args, **kwargs): + choices = kwargs.pop('choices') + self.interface = kwargs.pop('default') + + super(VmSetMasterInterfaceForm, self).__init__(*args, **kwargs) + + self.fields['interface'] = forms.ModelChoiceField( + queryset=choices, initial=self.interface, required=True, + empty_label=None, label=_('Interface')) + if self.interface: + self.fields['interface'].widget = HiddenInput() + + class VmRemoveInterfaceForm(OperationForm): def __init__(self, *args, **kwargs): choices = kwargs.pop('choices') diff --git a/circle/dashboard/templates/dashboard/vm-detail/network.html b/circle/dashboard/templates/dashboard/vm-detail/network.html index ea2d2ba..f6e7b02 100644 --- a/circle/dashboard/templates/dashboard/vm-detail/network.html +++ b/circle/dashboard/templates/dashboard/vm-detail/network.html @@ -18,10 +18,17 @@ <h3 class="list-group-item-heading dashboard-vm-details-network-h3"> <i class="fa fa-{% if i.host %}globe{% else %}link{% endif %}"></i> {{ i.vlan.name }} {% if not i.host%}({% trans "unmanaged" %}){% endif %} + {% if i.is_master %}({% trans "master" %}){% endif %} {% if user.is_superuser and i.host %} <a href="{{ i.host.get_absolute_url }}" class="btn btn-default btn-xs">{% trans "edit" %}</a> {% endif %} + {% with op=op.set_master_interface %}{% if op %} + <span class="operation-wrapper"> + <a href="{{op.get_url}}?interface={{ i.pk }}" + class="btn btn-default btn-xs operation set-as-master">{% trans "set as master" %}</a> + </span> + {% endif %}{% endwith %} {% with op=op.remove_interface %}{% if op %} <span class="operation-wrapper"> <a href="{{op.get_url}}?interface={{ i.pk }}" diff --git a/circle/dashboard/views/vm.py b/circle/dashboard/views/vm.py index 294223a..a3343d3 100644 --- a/circle/dashboard/views/vm.py +++ b/circle/dashboard/views/vm.py @@ -61,7 +61,8 @@ from .util import ( ) from ..forms import ( AclUserOrGroupAddForm, VmResourcesForm, TraitsForm, RawDataForm, - VmAddInterfaceForm, VmCreateDiskForm, VmDownloadDiskForm, VmSaveForm, + VmAddInterfaceForm, VmCreateDiskForm, VmSetMasterInterfaceForm, + VmDownloadDiskForm, VmSaveForm, VmRenewForm, VmStateChangeForm, VmListSearchForm, VmCustomizeForm, VmDiskResizeForm, RedeployForm, VmDiskRemoveForm, VmMigrateForm, VmDeployForm, @@ -368,6 +369,32 @@ class VmAddInterfaceView(FormOperationMixin, VmOperationView): return val +class VmSetMasterInterfaceView(FormOperationMixin, VmOperationView): + + op = 'set_master_interface' + form_class = VmSetMasterInterfaceForm + show_in_toolbar = False + effect = 'success' + icon = 'globe' + with_reload = True + + def get_form_kwargs(self): + instance = self.get_op().instance + choices = instance.interface_set.all() + interface_pk = self.request.GET.get('interface') + if interface_pk: + try: + default = choices.get(pk=interface_pk) + except (ValueError, Interface.DoesNotExist): + raise Http404() + else: + default = None + + val = super(VmSetMasterInterfaceView, self).get_form_kwargs() + val.update({'choices': choices, 'default': default}) + return val + + class VmDiskModifyView(FormOperationMixin, VmOperationView): show_in_toolbar = False with_reload = True @@ -777,6 +804,7 @@ vm_ops = OrderedDict([ op='remove_disk', form_class=VmDiskRemoveForm, icon='times', effect="danger")), ('add_interface', VmAddInterfaceView), + ('set_master_interface', VmSetMasterInterfaceView), ('remove_interface', VmRemoveInterfaceView), ('remove_port', VmPortRemoveView), ('add_port', VmPortAddView),