Commit df995e7f by Kálmán Viktor

dashboard: restart, reset and migrate buttons

parent 61cfbebd
......@@ -458,7 +458,7 @@ class TemplateForm(forms.ModelForm):
template = InstanceTemplate.objects.get(pk=parent)
parent = template.__dict__
fields = ["system", "name", "num_cores", "boot_menu", "ram_size",
"priority", "state", "access_method", "raw_data",
"priority", "access_method", "raw_data",
"arch", "description"]
for f in fields:
self.initial[f] = parent[f]
......
......@@ -331,3 +331,17 @@ a.hover-black {
display: block;
}
#vm-migrate-node-list {
list-style: none;
}
#vm-migrate-node-list li {
padding-bottom: 10px;
}
.vm-migrate-node-property {
display: block;
padding-left: 15px;
}
/* for functions in both vm list and vm detail */
$(function() {
/* vm migrate */
$('.vm-migrate').click(function(e) {
var vm = $(this).data("vm-pk");
$.ajax({
type: 'GET',
url: '/dashboard/vm/' + vm + '/migrate/',
success: function(data) {
$('body').append(data);
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
});
}
});
return false;
});
});
{% load i18n %}
{% load sizefieldtags %}
<form method="POST" action="{% url "dashboard.views.vm-migrate" pk=vm %}">
{% 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 %}
</ul>
<button type="submit" class="btn btn-primary btn-sm"><i class="icon-truck"></i> Migrate</button>
</form>
......@@ -6,7 +6,6 @@
<div class="page-header">
<div class="pull-right" style="padding-top: 15px;">
<a title="Rename" href="#" class="btn btn-default btn-xs vm-details-rename-button"><i class="icon-pencil"></i></a>
<a title="Pause == sleep?" href="#" class="btn btn-default btn-xs"><i class="icon-pause"></i></a>
<form style="display: inline;" method="POST" action="{% url "dashboard.views.detail" pk=instance.pk %}">
{% csrf_token %}
<input type="hidden" name="sleep" value="dummy"/>
......@@ -27,7 +26,19 @@
<input type="hidden" name="shut_down" value="dummy"/>
<button title="{% trans "Shut down" %}" class="btn btn-default btn-xs" type="submit"><i class="icon-off"></i></button>
</form>
<a title="Migrate" href="#" class="btn btn-default btn-xs"><i class="icon-truck"></i></a>
<form style="display: inline;" method="POST" action="{% url "dashboard.views.detail" pk=instance.pk %}">
{% csrf_token %}
<input type="hidden" name="reboot" value="dummy"/>
<button title="{% trans "Reboot (ctrl + alt + del)" %}" class="btn btn-default btn-xs" type="submit"><i class="icon-refresh"></i></button>
</form>
<form style="display: inline;" method="POST" action="{% url "dashboard.views.detail" pk=instance.pk %}">
{% csrf_token %}
<input type="hidden" name="reset" value="dummy"/>
<button title="{% trans "Reset (power cycle)" %}" class="btn btn-default btn-xs" type="submit"><i class="icon-bolt"></i></button>
</form>
<a title="Migrate" data-vm-pk="{{ instance.pk }}" href="{% url "dashboard.views.vm-migrate" pk=instance.pk %}" class="btn btn-default btn-xs vm-migrate">
<i class="icon-truck"></i>
</a>
<form style="display: inline;" method="POST" action="{% url "dashboard.views.detail" pk=instance.pk %}">
{% csrf_token %}
<input type="hidden" name="save_as" value="dummy"/>
......@@ -137,3 +148,8 @@
</div>
{% endblock %}
{% block extra_js %}
<script src="{{ STATIC_URL }}dashboard/vm-details.js"></script>
<script src="{{ STATIC_URL }}dashboard/vm-common.js"></script>
{% endblock %}
......@@ -5,7 +5,3 @@
<div id="activity-timeline" class="timeline">
{% include "dashboard/vm-detail/_activity-timeline.html" %}
</div>
{% block extra_js %}
<script src="{{ STATIC_URL }}dashboard/vm-details.js"></script>
{% endblock %}
......@@ -72,5 +72,6 @@
{% endblock %}
{% block extra_js %}
<script src="{{ STATIC_URL}}dashboard/vm-list.js"></script>
<script src="{{ STATIC_URL}}dashboard/vm-list.js"></script>
<script src="{{ STATIC_URL}}dashboard/vm-common.js"></script>
{% endblock %}
<a class="btn btn-default btn-xs" title data-original-title="Migrate">
<a href="{% url "dashboard.views.vm-migrate" pk=record.pk %}" class="btn btn-default btn-xs vm-migrate" data-vm-pk="{{ record.pk }}" title data-original-title="Migrate">
<i class="icon-truck"></i>
</a>
<a id="vm-list-rename-button" class="btn btn-default btn-xs" title data-original-title="Rename">
......
......@@ -8,7 +8,7 @@ from .views import (
TemplateList, LeaseDetail, NodeCreate, LeaseCreate, TemplateCreate,
FavouriteView, NodeStatus, GroupList, TemplateDelete, LeaseDelete,
VmGraphView, TemplateAclUpdateView, GroupDetailView, GroupDelete,
GroupAclUpdateView, GroupUserDelete, NodeGraphView
GroupAclUpdateView, GroupUserDelete, NodeGraphView, VmMigrateView,
)
urlpatterns = patterns(
......@@ -48,6 +48,8 @@ urlpatterns = patterns(
url(r'^vm/mass-delete/', VmMassDelete.as_view(),
name='dashboard.view.mass-delete-vm'),
url(r'^vm/(?P<pk>\d+)/activity/$', vm_activity),
url(r'^vm/(?P<pk>\d+)/migrate/$', VmMigrateView.as_view(),
name='dashboard.views.vm-migrate'),
url(r'^node/list/$', NodeList.as_view(), name='dashboard.views.node-list'),
url(r'^node/(?P<pk>\d+)/$', NodeDetailView.as_view(),
......
......@@ -1652,3 +1652,37 @@ class NodeGraphView(SuperuserRequiredMixin, GraphViewBase):
def get_object(self, request, pk):
return self.model.objects.get(id=pk)
class VmMigrateView(SuperuserRequiredMixin, TemplateView):
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/modal-wrapper.html']
else:
return ['dashboard/nojs-wrapper.html']
def get(self, request, form=None, *args, **kwargs):
context = self.get_context_data(**kwargs)
vm = Instance.objects.get(pk=kwargs['pk'])
context.update({
'template': 'dashboard/_vm-migrate.html',
'box_title': _('Migrate %(name)s' % {'name': vm.name}),
'ajax_title': True,
'vm': kwargs['pk'],
'nodes': [n for n in Node.objects.filter(enabled=True)
if n.state == "ONLINE"]
})
return self.render_to_response(context)
def post(self, *args, **kwargs):
node = self.request.POST.get("node")
vm = Instance.objects.get(pk=kwargs['pk'])
if node:
node = Node.objects.get(pk=node)
vm.migrate_async(to_node=node, user=self.request.user)
else:
messages.error(self.request, _("You didn't select a node!"))
return redirect("%s#activity" % vm.get_absolute_url())
......@@ -907,15 +907,15 @@ class Instance(AclBase, VirtualMachineDescModel, TimeStampedModel):
task_uuid=task_uuid, user=user):
queue_name = self.get_remote_queue_name('vm')
vm_tasks.restart.apply_async(args=[self.vm_name],
queue=queue_name
).get(timeout=timeout)
vm_tasks.reset.apply_async(args=[self.vm_name],
queue=queue_name
).get(timeout=timeout)
def reset_async(self, user=None):
"""Execute reset asynchronously.
"""
return local_tasks.restart.apply_async(args=[self, user],
queue="localhost.man")
return local_tasks.reset.apply_async(args=[self, user],
queue="localhost.man")
def reboot(self, user=None, task_uuid=None, timeout=5):
"""Reboot virtual machine with Ctrl+Alt+Del signal.
......
......@@ -235,6 +235,10 @@ class Node(TimeStampedModel):
def ram_usage(self):
return float(self.get_monitor_info()["memory.usage"]) / 100
@property
def byte_ram_usage(self):
return self.ram_usage * self.ram_size
def update_vm_states(self):
"""Update state of Instances running on this Node.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment