Commit 5b01216a by Kálmán Viktor

dashboard: views + templates

parent aef328d4
{% load i18n %}
{% load crispy_forms_tags %}
{% block question %}
<p>
{% blocktrans with op=op.name %}
Do you want to perform the following operation: <strong>{{op}}</strong>?
{% endblocktrans %}
</p>
<p class="text-info">{{op.description}}</p>
{% endblock %}
<form method="POST" action="{{url}}">{% csrf_token %}
{% for i in instances %}
<div class="panel panel-default mass-op-panel">
<i class="fa {{ i.get_status_icon }} fa-fw"></i>
{{ i.name }} ({{ i.pk }})
<div style="float: right;" title="{{ i.disabled }}">
<i class="fa status-icon
{% if i.disabled %}fa-minus-square minus{% else %}fa-check-square check{% endif %}">
</i>
</div>
</div>
<input type="checkbox" name="vm" value="{{ i.pk }}" {% if not i.disabled %}checked{% endif %}
style="display: none;"/>
{% endfor %}
<div class="pull-right">
<a class="btn btn-default" href="{% url "dashboard.views.vm-list" %}"
data-dismiss="modal">{% trans "Cancel" %}</a>
<button class="btn btn-{{ opview.effect }}" type="submit" id="op-form-send">
{% if opview.icon %}<i class="fa fa-{{opview.icon}}"></i> {% endif %}{{ opview.name|capfirst }}
</button>
</div>
</form>
<style>
.mass-op-panel {
padding: 6px 10px;
}
.mass-op-panel .check {
color: #449d44;
}
.mass-op-panel .minus {
color: #d9534f;
}
.mass-op-panel .status-icon {
font-size: 1.5em;
}
</style>
...@@ -23,6 +23,13 @@ ...@@ -23,6 +23,13 @@
</div> </div>
</form> </form>
</div> </div>
<p>
{% for o in ops %}
<a href="{{ o.get_url }}" class="btn btn-xs btn-{{ o.effect }}" title="{{ o.name }}">
<i class="fa fa-{{ o.icon }}"></i>
</a>
{% endfor %}
</p>
<div class="panel-body vm-list-group-control"> <div class="panel-body vm-list-group-control">
<p> <p>
<strong>{% trans "Group actions" %}</strong> <strong>{% trans "Group actions" %}</strong>
......
...@@ -49,7 +49,6 @@ from .views import ( ...@@ -49,7 +49,6 @@ from .views import (
autocomplete_light.autodiscover() autocomplete_light.autodiscover()
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^$', IndexView.as_view(), name="dashboard.index"), url(r'^$', IndexView.as_view(), name="dashboard.index"),
url(r'^lease/(?P<pk>\d+)/$', LeaseDetail.as_view(), url(r'^lease/(?P<pk>\d+)/$', LeaseDetail.as_view(),
...@@ -74,7 +73,7 @@ urlpatterns = patterns( ...@@ -74,7 +73,7 @@ urlpatterns = patterns(
url(r"^template/delete/(?P<pk>\d+)/$", TemplateDelete.as_view(), url(r"^template/delete/(?P<pk>\d+)/$", TemplateDelete.as_view(),
name="dashboard.views.template-delete"), name="dashboard.views.template-delete"),
url(r'^vm/(?P<pk>\d+)/op/', include('dashboard.vm.urls')), url(r'^vm/', include('dashboard.vm.urls')),
url(r'^vm/(?P<pk>\d+)/remove_port/(?P<rule>\d+)/$', PortDelete.as_view(), url(r'^vm/(?P<pk>\d+)/remove_port/(?P<rule>\d+)/$', PortDelete.as_view(),
name='dashboard.views.remove-port'), name='dashboard.views.remove-port'),
url(r'^vm/(?P<pk>\d+)/$', VmDetailView.as_view(), url(r'^vm/(?P<pk>\d+)/$', VmDetailView.as_view(),
......
...@@ -986,6 +986,91 @@ def get_operations(instance, user): ...@@ -986,6 +986,91 @@ def get_operations(instance, user):
return ops return ops
class MassOperationView(OperationView):
template_name = 'dashboard/mass-operate.html'
effect = "info"
@classmethod
def get_urlname(cls):
return 'dashboard.vm.mass-op.%s' % cls.op
@classmethod
def get_url(cls):
return reverse("dashboard.vm.mass-op.%s" % cls.op)
def get_op(self, instance=None):
if instance:
return getattr(instance, self.op)
else:
return Instance._ops[self.op]
def get_context_data(self, **kwargs):
ctx = super(MassOperationView, self).get_context_data(**kwargs)
instances = self.request.GET.getlist("vm")
instances = Instance.objects.filter(pk__in=instances)
ctx['instances'] = self._check_instances(instances, self.request.user)
return ctx
def check_auth(self):
pass
def get_object(self):
return None
def _check_instances(self, instances, user):
vms = []
for i in instances:
try:
self._op_checks(i, user)
except HumanReadableException as e:
setattr(i, "disabled", e.get_user_text())
except SuspiciousOperation:
continue
except PermissionDenied:
setattr(i, "disabled", "No permission")
except Exception:
setattr(i, "disabled", "Wrong state error, probably")
vms.append(i)
return vms
def post(self, request, *args, **kwargs):
user = self.request.user
vms = request.POST.getlist("vm")
instances = Instance.objects.filter(pk__in=vms)
for i in instances:
try:
op = self._op_checks(i, user)
op.async(user=user)
except HumanReadableException as e:
e.send_message(request)
except Exception as e:
pass
return redirect(reverse("dashboard.views.vm-list"))
def _op_checks(self, instance, user):
objects_of_user = Instance.get_objects_with_level("user", user)
if instance not in objects_of_user:
raise SuspiciousOperation()
op = self.get_op(instance)
op.check_auth(user)
op.check_precond()
return op
vm_mass_ops = OrderedDict([
('deploy', MassOperationView.factory(
op='deploy', icon='play', effect='success')),
('wake_up', MassOperationView.factory(
op='wake_up', icon='sun-o', effect='success')),
('sleep', MassOperationView.factory(
op='sleep', icon='moon-o', effect='info')),
('destroy', MassOperationView.factory(
op='destroy', icon='times', effect='danger')),
])
class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView): class NodeDetailView(LoginRequiredMixin, SuperuserRequiredMixin, DetailView):
template_name = "dashboard/node-detail.html" template_name = "dashboard/node-detail.html"
model = Node model = Node
...@@ -1557,6 +1642,11 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView): ...@@ -1557,6 +1642,11 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView):
'owner': "owner__username", 'owner': "owner__username",
} }
def get_context_data(self, *args, **kwargs):
context = super(VmList, self).get_context_data(*args, **kwargs)
context['ops'] = [v for k, v in vm_mass_ops.iteritems()]
return context
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
if self.request.is_ajax(): if self.request.is_ajax():
favs = Instance.objects.filter( favs = Instance.objects.filter(
......
...@@ -17,9 +17,17 @@ ...@@ -17,9 +17,17 @@
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from ..views import vm_ops from ..views import vm_ops, vm_mass_ops
urlpatterns = patterns('', urlpatterns = patterns(
*(url(r'^%s/$' % op, v.as_view(), name=v.get_urlname()) '',
for op, v in vm_ops.iteritems())) *(url(r'^(?P<pk>\d+)/op/%s/$' % op, v.as_view(), name=v.get_urlname())
for op, v in vm_ops.iteritems())
)
urlpatterns += patterns(
'',
*(url(r'^mass_op/%s/$' % op, v.as_view(), name=v.get_urlname())
for op, v in vm_mass_ops.iteritems())
)
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