diff --git a/circle/dashboard/static/dashboard/vm-common.js b/circle/dashboard/static/dashboard/vm-common.js index 40cf29c..55599f3 100644 --- a/circle/dashboard/static/dashboard/vm-common.js +++ b/circle/dashboard/static/dashboard/vm-common.js @@ -18,6 +18,15 @@ $(function() { $('#create-modal').on('hidden.bs.modal', function() { $('#create-modal').remove(); }); + $('#vm-migrate-node-list li').click(function(e) { + var li = $(this).closest('li'); + if (li.find('input').attr('disabled')) + return true; + $('#vm-migrate-node-list li').removeClass('panel-primary'); + li.addClass('panel-primary').find('input').attr('checked', true); + return false; + }); + $('#vm-migrate-node-list li input:checked').closest('li').addClass('panel-primary'); } }); return false; diff --git a/circle/dashboard/templates/dashboard/_vm-migrate.html b/circle/dashboard/templates/dashboard/_vm-migrate.html index b1a93cc..e1ec92b 100644 --- a/circle/dashboard/templates/dashboard/_vm-migrate.html +++ b/circle/dashboard/templates/dashboard/_vm-migrate.html @@ -1,18 +1,26 @@ {% load i18n %} {% load sizefieldtags %} -<form method="POST" action="{% url "dashboard.views.vm-migrate" pk=vm %}"> +<form method="POST" action="{% url "dashboard.views.vm-migrate" pk=vm.pk %}"> {% csrf_token %} <ul id="vm-migrate-node-list"> - {% for n in nodes %} - <li> - <strong>{{ n }}</strong> - <input type="radio" name="node" value="{{ n.pk }}" style="float: right;"/> - <span class="vm-migrate-node-property">{% trans "CPU load" %}: {{ n.cpu_usage }}</span> - <span class="vm-migrate-node-property">{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}</span> - <div style="clear: both;"></div> - </li> - {% endfor %} + {% with current=vm.node.pk selected=vm.select_node.pk %} + {% for n in nodes %} + <li class="panel panel-default"><div class="panel-body"> + <label for="migrate-to-{{n.pk}}"> + <strong>{{ n }}</strong> + {% if current == n.pk %}<div class="label label-info">{% trans "current" %}</div>{% endif %} + {% if selected == n.pk %}<div class="label label-success">{% trans "recommended" %}</div>{% endif %} + </label> + <input id="migrate-to-{{n.pk}}" type="radio" name="node" value="{{ n.pk }}" style="float: right;" + {% if current == n.pk %}disabled="disabled"{% endif %} + {% if selected == n.pk %}checked="checked"{% endif %} /> + <span class="vm-migrate-node-property">{% trans "CPU load" %}: {{ n.cpu_usage }}</span> + <span class="vm-migrate-node-property">{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}</span> + <div style="clear: both;"></div> + </div></li> + {% endfor %} + {% endwith %} </ul> <button type="submit" class="btn btn-primary btn-sm"><i class="icon-truck"></i> Migrate</button> </form> diff --git a/circle/dashboard/views.py b/circle/dashboard/views.py index 0b6ead1..e21ffc1 100644 --- a/circle/dashboard/views.py +++ b/circle/dashboard/views.py @@ -1731,7 +1731,7 @@ class VmMigrateView(SuperuserRequiredMixin, TemplateView): 'template': 'dashboard/_vm-migrate.html', 'box_title': _('Migrate %(name)s' % {'name': vm.name}), 'ajax_title': True, - 'vm': kwargs['pk'], + 'vm': vm, 'nodes': [n for n in Node.objects.filter(enabled=True) if n.state == "ONLINE"] }) diff --git a/circle/vm/models/instance.py b/circle/vm/models/instance.py index 97b6602..7adebfe 100644 --- a/circle/vm/models/instance.py +++ b/circle/vm/models/instance.py @@ -583,10 +583,13 @@ class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel): self.pw)) self.save() - def __schedule_vm(self, act): - """Schedule the virtual machine. + def select_node(self): + """Returns the node the VM should be deployed or migrated to. + """ + return scheduler.select_node(self, Node.objects.all()) - :param self: The virtual machine. + def __schedule_vm(self, act): + """Schedule the virtual machine as part of a higher level activity. :param act: Parent activity. """ @@ -596,7 +599,7 @@ class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel): # Schedule if self.node is None: - self.node = scheduler.select_node(self, Node.objects.all()) + self.node = self.select_node() self.save()