Commit 032c38d9 by Őry Máté

dashboard: add vm-activity view

parent f068fe84
...@@ -79,6 +79,14 @@ html { ...@@ -79,6 +79,14 @@ html {
color: #fff; color: #fff;
} }
.timeline .activity-active .timeline-icon {
background-color: black!important;
}
.timeline a {
color: black;
}
.timeline-icon.timeline-warning { .timeline-icon.timeline-warning {
border-color: #c09853; border-color: #c09853;
border-style: solid; border-style: solid;
...@@ -100,6 +108,10 @@ html { ...@@ -100,6 +108,10 @@ html {
border-left: 3px solid green; border-left: 3px solid green;
} }
.sub-activity-active {
border-left: 8px solid black;
}
.sub-activity-failed { .sub-activity-failed {
border-left: 3px solid #d9534f; border-left: 3px solid #d9534f;
} }
......
{% extends "dashboard/base.html" %}
{% load i18n %}
{% block content %}
<div class="body-content">
<div class="page-header">
<h1>
{{ object.instance.name }}: {{ object.get_readable_name }}
</h1>
</div>
<div class="row">
<div class="col-md-4" id="vm-info-pane">
<div class="big">
<span id="vm-activity-state" class="label label-{% if object.get_status_id == 'wait' %}info{% else %}{% if object.succeeded %}success{% else %}error{% endif %}{% endif %}">
<span>{{ object.get_status_id|upper }}</span>
</span>
</div>
<div id="vm-activity-context" class="timeline">
{% include "dashboard/vm-detail/_activity-timeline.html" with active=object %}
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<!--<div class="panel-heading"><h2 class="panel-title">{% trans "Activity" %}</h2></div> -->
<div class="panel-body">
<dl>
<dt>{% trans "activity code" %}</dt>
<dd>{{object.activity_code}}</dd>
<dt>{% trans "instance" %}</dt>
<dd><a href="{{object.instance.get_absolute_url}}">{{object.instance}}</a></dd>
<dt>{% trans "time" %}</dt>
<dd>{{object.started|default:'n/a'}} → {{object.finished|default:'n/a'}}</dd>
<dt>{% trans "user" %}</dt>
<dd>{{object.user|default:'(system)'}}</dd>
<dt>{% trans "type" %}</dt>
<dd>
{% if object.parent %}
{% blocktrans with url=object.parent.get_absolute_url name=object.parent %}
subactivity of <a href="{{url}}">{{name}}</a>
{% endblocktrans %}
{% else %}{% trans "top level activity" %}{% endif %}
</dd>
<dt>{% trans "task uuid" %}</dt>
<dd>{{ object.task_uuid|default:'n/a' }}</dd>
<dt>{% trans "status" %}</dt>
<dd>{{ object.get_status_id }}</dd>
<dt>{% trans "result" %}</dt>
<dd><textarea class="form-control">{{object.result}}</textarea></dd>
<dt>{% trans "resultant state" %}</dt>
<dd>{{object.resultant_state|default:'n/a'}}</dd>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% load i18n %} {% load i18n %}
{% for a in activities %} {% for a in activities %}
<div class="activity" data-activity-id="{{ a.pk }}"> <div class="activity{% if a.pk == active.pk %} activity-active{%endif%}" data-activity-id="{{ a.pk }}">
<span class="timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}"> <span class="timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}">
<i class="{% if not a.finished %} icon-refresh icon-spin {% else %}icon-plus{% endif %}"></i> <i class="{% if not a.finished %} icon-refresh icon-spin {% else %}icon-plus{% endif %}"></i>
</span> </span>
<strong{% if user.is_superuser and a.result %} title="{{ a.result }}"{% endif %}> <strong{% if user.is_superuser and a.result %} title="{{ a.result }}"{% endif %}>
{{ a.get_readable_name }} {% if user.is_superuser %}<a href="{{ a.get_absolute_url }}">{% endif %}
{{ a.get_readable_name }}{% if user.is_superuser %}</a>{% endif %}
</strong> </strong>
{{ a.started|date:"Y-m-d H:i" }}{% if a.user %}, {{ a.user }}{% endif %} {{ a.started|date:"Y-m-d H:i" }}{% if a.user %}, {{ a.user }}{% endif %}
{% if a.children.count > 0 %} {% if a.children.count > 0 %}
<div class="sub-timeline"> <div class="sub-timeline">
{% for s in a.children.all %} {% for s in a.children.all %}
<div data-activity-id="{{ s.pk }}" class="sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}"> <div data-activity-id="{{ s.pk }}" class="sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}{% if s.pk == active.pk %} sub-activity-active{% endif %}">
<span{% if user.is_superuser and s.result %} title="{{ s.result }}"{% endif %}> <span{% if user.is_superuser and s.result %} title="{{ s.result }}"{% endif %}>
{{ s.get_readable_name }}</span> &ndash; {% if user.is_superuser %}<a href="{{ s.get_absolute_url }}">{% endif %}
{{ s.get_readable_name }}{% if user.is_superuser %}</a>{% endif %}</span> &ndash;
{% if s.finished %} {% if s.finished %}
{{ s.finished|time:"H:i:s" }} {{ s.finished|time:"H:i:s" }}
{% else %} {% else %}
......
...@@ -3,15 +3,15 @@ from django.conf.urls import patterns, url ...@@ -3,15 +3,15 @@ from django.conf.urls import patterns, url
from vm.models import Instance from vm.models import Instance
from .views import ( from .views import (
AclUpdateView, DiskAddView, FavouriteView, GroupAclUpdateView, GroupDelete, AclUpdateView, DiskAddView, FavouriteView, GroupAclUpdateView, GroupDelete,
GroupDetailView, GroupList, GroupUserDelete, IndexView, LeaseCreate, GroupDetailView, GroupList, GroupUserDelete, IndexView,
LeaseDelete, LeaseDetail, MyPreferencesView, NodeAddTraitView, NodeCreate, InstanceActivityDetail, LeaseCreate, LeaseDelete, LeaseDetail,
NodeDelete, NodeDetailView, NodeFlushView, NodeGraphView, NodeList, MyPreferencesView, NodeAddTraitView, NodeCreate, NodeDelete,
NodeStatus, NotificationView, PortDelete, TemplateAclUpdateView, NodeDetailView, NodeFlushView, NodeGraphView, NodeList, NodeStatus,
TemplateCreate, TemplateDelete, TemplateDetail, TemplateList, NotificationView, PortDelete, TemplateAclUpdateView, TemplateCreate,
TransferOwnershipConfirmView, TransferOwnershipView, vm_activity, VmCreate, TemplateDelete, TemplateDetail, TemplateList, TransferOwnershipConfirmView,
VmDelete, VmDetailView, VmDetailVncTokenView, VmGraphView, VmList, TransferOwnershipView, vm_activity, VmCreate, VmDelete, VmDetailView,
VmMassDelete, VmMigrateView, VmRenewView, DiskRemoveView, VmDetailVncTokenView, VmGraphView, VmList, VmMassDelete, VmMigrateView,
get_disk_download_status, VmRenewView, DiskRemoveView, get_disk_download_status,
) )
urlpatterns = patterns( urlpatterns = patterns(
...@@ -57,6 +57,8 @@ urlpatterns = patterns( ...@@ -57,6 +57,8 @@ urlpatterns = patterns(
name='dashboard.views.vm-migrate'), name='dashboard.views.vm-migrate'),
url(r'^vm/(?P<pk>\d+)/renew/((?P<key>.*)/?)$', VmRenewView.as_view(), url(r'^vm/(?P<pk>\d+)/renew/((?P<key>.*)/?)$', VmRenewView.as_view(),
name='dashboard.views.vm-renew'), name='dashboard.views.vm-renew'),
url(r'^vm/activity/(?P<pk>\d+)/$', InstanceActivityDetail.as_view(),
name='dashboard.views.vm-activity'),
url(r'^node/list/$', NodeList.as_view(), name='dashboard.views.node-list'), url(r'^node/list/$', NodeList.as_view(), name='dashboard.views.node-list'),
url(r'^node/(?P<pk>\d+)/$', NodeDetailView.as_view(), url(r'^node/(?P<pk>\d+)/$', NodeDetailView.as_view(),
......
...@@ -2195,3 +2195,16 @@ def get_disk_download_status(request, pk): ...@@ -2195,3 +2195,16 @@ def get_disk_download_status(request, pk):
}), }),
content_type="application/json", content_type="application/json",
) )
class InstanceActivityDetail(SuperuserRequiredMixin, DetailView):
model = InstanceActivity
template_name = 'dashboard/instanceactivity_detail.html'
def get_context_data(self, **kwargs):
ctx = super(InstanceActivityDetail, self).get_context_data(**kwargs)
ctx['activities'] = (
self.object.instance.activity_log.filter(parent=None).
order_by('-started').select_related('user').
prefetch_related('children'))
return ctx
...@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals ...@@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
from contextlib import contextmanager from contextlib import contextmanager
from logging import getLogger from logging import getLogger
from django.core.urlresolvers import reverse
from django.db.models import CharField, ForeignKey from django.db.models import CharField, ForeignKey
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
...@@ -42,9 +43,20 @@ class InstanceActivity(ActivityModel): ...@@ -42,9 +43,20 @@ class InstanceActivity(ActivityModel):
return '{}({})'.format(self.activity_code, return '{}({})'.format(self.activity_code,
self.instance) self.instance)
def get_absolute_url(self):
return reverse('dashboard.views.vm-activity', args=[self.pk])
def get_readable_name(self): def get_readable_name(self):
return self.activity_code.split('.')[-1].replace('_', ' ').capitalize() return self.activity_code.split('.')[-1].replace('_', ' ').capitalize()
def get_status_id(self):
if self.succeeded is None:
return 'wait'
elif self.succeeded:
return 'success'
else:
return 'failed'
@classmethod @classmethod
def create(cls, code_suffix, instance, task_uuid=None, user=None, def create(cls, code_suffix, instance, task_uuid=None, user=None,
concurrency_check=True): concurrency_check=True):
......
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