Commit b4bf105c by Kálmán Viktor

Merge branch 'master' into feature-request

Conflicts:
	circle/dashboard/static/dashboard/dashboard.less
parents 815d11ea f211db99
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
], ],
"dependencies": { "dependencies": {
"bootstrap": "~3.2.0", "bootstrap": "~3.2.0",
"fontawesome": "~4.2.0", "fontawesome": "~4.3.0",
"jquery": "~2.1.1", "jquery": "~2.1.1",
"no-vnc": "*", "no-vnc": "*",
"jquery-knob": "~1.2.9", "jquery-knob": "~1.2.9",
......
...@@ -169,7 +169,8 @@ PIPELINE_COMPILERS = ( ...@@ -169,7 +169,8 @@ PIPELINE_COMPILERS = (
'pipeline.compilers.less.LessCompiler', 'pipeline.compilers.less.LessCompiler',
) )
PIPELINE_CSS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor' PIPELINE_CSS_COMPRESSOR = 'pipeline.compressors.yuglify.YuglifyCompressor'
PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.slimit.SlimItCompressor' # PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.slimit.SlimItCompressor'
PIPELINE_JS_COMPRESSOR = None
PIPELINE_DISABLE_WRAPPER = True PIPELINE_DISABLE_WRAPPER = True
PIPELINE_LESS_ARGUMENTS = u'--include-path={}'.format(':'.join(STATICFILES_DIRS)) PIPELINE_LESS_ARGUMENTS = u'--include-path={}'.format(':'.join(STATICFILES_DIRS))
PIPELINE_CSS = { PIPELINE_CSS = {
...@@ -525,7 +526,7 @@ except: ...@@ -525,7 +526,7 @@ except:
AGENT_VERSION = None AGENT_VERSION = None
LOCALE_PATHS = (join(SITE_ROOT, 'locale'), ) LOCALE_PATHS = (join(SITE_ROOT, 'locale'), )
COMPANY_NAME = "BME IK 2014" COMPANY_NAME = get_env_variable("COMPANY_NAME", "BME IK 2015")
graphite_host = environ.get("GRAPHITE_HOST", None) graphite_host = environ.get("GRAPHITE_HOST", None)
graphite_port = environ.get("GRAPHITE_PORT", None) graphite_port = environ.get("GRAPHITE_PORT", None)
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from common.management.commands.watch import LessUtils from common.management.commands.watch import LessUtils
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import subprocess import subprocess
import os import os
import pyinotify import pyinotify
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from sys import exc_info from sys import exc_info
import logging import logging
......
# -*- coding: utf-8 -*-
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from arrow import locales
class HungarianLocale(locales.Locale):
names = ['hu', 'HU']
past = '{0} ezelőtt'
future = '{0} múlva'
timeframes = {
'now': 'éppen most',
'seconds': {
'past': 'másodpercekkel',
'future': 'pár másodperc'},
'minute': {'past': 'egy perccel', 'future': 'egy perc'},
'minutes': {'past': '{0} perccel', 'future': '{0} perc'},
'hour': {'past': 'egy órával', 'future': 'egy óra'},
'hours': {'past': '{0} órával', 'future': '{0} óra'},
'day': {
'past': 'egy nappal',
'future': 'egy nap'
},
'days': {
'past': '{0} nappal',
'future': '{0} nap'
},
'month': {'past': 'egy hónappal', 'future': 'egy hónap'},
'months': {'past': '{0} hónappal', 'future': '{0} hónap'},
'year': {'past': 'egy évvel', 'future': 'egy év'},
'years': {'past': '{0} évvel', 'future': '{0} év'},
}
month_names = ['', 'Január', 'Február', 'Március', 'Április', 'Május',
'Június', 'Július', 'Augusztus', 'Szeptember',
'Október', 'November', 'December']
month_abbreviations = ['', 'Jan', 'Febr', 'Márc', 'Ápr', 'Máj', 'Jún',
'Júl', 'Aug', 'Szept', 'Okt', 'Nov', 'Dec']
day_names = ['', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek',
'Szombat', 'Vasárnap']
day_abbreviations = ['', 'Hét', 'Kedd', 'Szer', 'Csüt', 'Pént',
'Szom', 'Vas']
meridians = {
'am': 'de',
'pm': 'du',
'AM': 'DE',
'PM': 'DU',
}
def _format_timeframe(self, timeframe, delta):
form = self.timeframes[timeframe]
if isinstance(form, dict):
if delta > 0:
form = form['future']
else:
form = form['past']
delta = abs(delta)
return form.format(delta)
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import autocomplete_light import autocomplete_light
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.html import escape from django.utils.html import escape
......
...@@ -1607,11 +1607,16 @@ class DataStoreForm(ModelForm): ...@@ -1607,11 +1607,16 @@ class DataStoreForm(ModelForm):
class DiskForm(ModelForm): class DiskForm(ModelForm):
created = forms.DateTimeField()
modified = forms.DateTimeField()
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(DiskForm, self).__init__(*args, **kwargs) super(DiskForm, self).__init__(*args, **kwargs)
for k, v in self.fields.iteritems(): for k, v in self.fields.iteritems():
v.widget.attrs['readonly'] = True v.widget.attrs['readonly'] = True
self.fields['created'].initial = self.instance.created
self.fields['modified'].initial = self.instance.modified
class Meta: class Meta:
model = Disk model = Disk
...@@ -651,9 +651,11 @@ textarea[name="new_members"] { ...@@ -651,9 +651,11 @@ textarea[name="new_members"] {
padding-left: 28px; padding-left: 28px;
} }
.dashboard-profile-vm-list a, .dashboard-profile-vm-list a:hover { .dashboard-profile-vm-list, .dashboard-profile-group-list {
a, a:hover {
text-decoration: none; text-decoration: none;
color: #555; color: #555;
}
} }
#group-detail-user-table td:nth-child(2) a, #group-detail-user-table td:nth-child(2) a,
...@@ -1288,3 +1290,9 @@ textarea[name="new_members"] { ...@@ -1288,3 +1290,9 @@ textarea[name="new_members"] {
max-width: 500px; max-width: 500px;
height: 150px; height: 150px;
} }
#disk-list-table {
td:last-child {
text-align: center;
}
}
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from os.path import splitext from os.path import splitext
import json import json
import logging import logging
......
...@@ -350,4 +350,5 @@ class DiskListTable(Table): ...@@ -350,4 +350,5 @@ class DiskListTable(Table):
fields = ("pk", "appliance", "filename", "size", "is_ready") fields = ("pk", "appliance", "filename", "size", "is_ready")
prefix = "disk-" prefix = "disk-"
order_by = ("-pk", ) order_by = ("-pk", )
per_page = 65536 per_page = 15
empty_text = _("No disk found.")
{% load i18n %} {% load i18n %}
{% load hro %} {% load hro %}
{% load arrowfilter %}
{% for n in page %} {% for n in page %}
<li class="notification-message" id="msg-{{n.id}}"> <li class="notification-message" id="msg-{{n.id}}">
<span class="notification-message-subject"> <span class="notification-message-subject">
{% if n.status == "new" %}<i class="fa fa-envelope-o"></i> {% endif %} {% if n.status == "new" %}<i class="fa fa-envelope-o"></i> {% endif %}
{{ n.subject|get_text:user }} {{ n.subject|get_text:user }}
</span> </span>
<span class="notification-message-date pull-right" title="{{n.created}}"> <span class="notification-message-date pull-right" title="{{n.created}}" data-container="body">
{{ n.created|timesince }} {{ n.created|arrowfilter:LANGUAGE_CODE }}
</span> </span>
<div style="clear: both;"></div> <div style="clear: both;"></div>
<div class="notification-message-text"> <div class="notification-message-text">
......
{% load i18n %} {% load i18n %}
{% load hro %} {% load hro %}
{% load arrowfilter %}
<div id="activity-timeline" class="timeline"> <div id="activity-timeline" class="timeline">
{% for a in activities %} {% for a in activities %}
<div class="activity" data-activity-id="{{ a.pk }}"> <div class="activity" data-activity-id="{{ a.pk }}">
...@@ -10,7 +11,8 @@ ...@@ -10,7 +11,8 @@
{{ a.readable_name.get_admin_text|capfirst }} {{ a.readable_name.get_admin_text|capfirst }}
</strong> </strong>
{{ a.started|date:"Y-m-d H:i" }}{% if a.user %}, {{ a.user }}{% endif %} <span title="{{ a.started }}">{{ a.started|arrowfilter:LANGUAGE_CODE }}</span>{% 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 %}
...@@ -21,7 +23,9 @@ ...@@ -21,7 +23,9 @@
</span> </span>
&ndash; &ndash;
{% if s.finished %} {% if s.finished %}
{{ s.finished|time:"H:i:s" }} <span title="{{ s.finished }}">
{{ s.finished|arrowfilter:LANGUAGE_CODE }}
</span>
{% else %} {% else %}
<i class="fa fa-refresh fa-spin" class="sub-activity-loading-icon"></i> <i class="fa fa-refresh fa-spin" class="sub-activity-loading-icon"></i>
{% endif %} {% endif %}
......
{% extends "dashboard/base.html" %} {% extends "dashboard/base.html" %}
{% load i18n %} {% load i18n %}
{% block title-page %}{% trans "Notifications" %}{% endblock %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
......
...@@ -11,24 +11,28 @@ ...@@ -11,24 +11,28 @@
<div class="col-md-{% if perms.auth.change_user %}8{% else %}12{% endif %}"> <div class="col-md-{% if perms.auth.change_user %}8{% else %}12{% endif %}">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<div class="pull-right">
{% if request.user.is_superuser %} {% if request.user.is_superuser %}
<a href="{{ login_token }}" <a href="{{ login_token }}" class="btn btn-danger btn-xs"
class="pull-right btn btn-danger btn-xs"
title="{% trans "Log in as this user. Recommended to open in an incognito window." %}"> title="{% trans "Log in as this user. Recommended to open in an incognito window." %}">
{% trans "Login as this user" %}</a> <i class="fa fa-user-secret"></i>
{% trans "Login as this user" %}
</a>
{% endif %} {% endif %}
<a class="pull-right btn btn-default btn-xs" href="{% url "dashboard.views.user-list" %}">{% trans "Back" %}</a> <a class="btn btn-default btn-xs" href="{% url "dashboard.views.user-list" %}">
{% trans "Back" %}</a>
</div>
<h3 class="no-margin"> <h3 class="no-margin">
<i class="fa fa-user"></i> <i class="fa fa-user"></i>
{% include "dashboard/_display-name.html" with user=profile show_org=True %} {% include "dashboard/_display-name.html" with user=profile show_org=True %}
</h3> </h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div> <div class="row">
<div class="" style="float: left"> <div class="col-sm-4">
<img id="dashboard-profile-avatar" src="{{ avatar_url }}" class="img-rounded"/> <img id="dashboard-profile-avatar" src="{{ avatar_url }}" class="img-rounded"/>
</div> </div>
<div class="" style="padding-left: 215px;"> <div class="col-sm-8">
<p>{% trans "Username" %}: {{ profile.username }}</p> <p>{% trans "Username" %}: {{ profile.username }}</p>
<p>{% trans "Organization ID" %}: {{ profile.profile.org_id|default:"-" }}</p> <p>{% trans "Organization ID" %}: {{ profile.profile.org_id|default:"-" }}</p>
<p>{% trans "First name" %}: {{ profile.first_name|default:"-" }}</p> <p>{% trans "First name" %}: {{ profile.first_name|default:"-" }}</p>
...@@ -48,7 +52,6 @@ ...@@ -48,7 +52,6 @@
<a href="{% url "dashboard.views.profile-preferences" %}">{% trans "Change my preferences" %}</a> <a href="{% url "dashboard.views.profile-preferences" %}">{% trans "Change my preferences" %}</a>
{% endif %} {% endif %}
</div> </div>
<div class="clearfix"></div>
</div> </div>
{% if perm_group_list %} {% if perm_group_list %}
...@@ -58,7 +61,7 @@ ...@@ -58,7 +61,7 @@
</h4> </h4>
<ul class="dashboard-profile-group-list"> <ul class="dashboard-profile-group-list">
{% for g in groups %} {% for g in groups %}
<li>{{ g.name }}</li> <li><a href="{{ g.profile.get_absolute_url }}">{{ g.name }}</a></li>
{% empty %} {% empty %}
{% trans "This user is not in any group." %} {% trans "This user is not in any group." %}
{% endfor %} {% endfor %}
......
...@@ -52,7 +52,9 @@ ...@@ -52,7 +52,9 @@
<small>{% trans "image files without disk object in the database" %}</small> <small>{% trans "image files without disk object in the database" %}</small>
</h3> </h3>
{% for o in orphan_disks %} {% for o in orphan_disks %}
<p>
{{ o }} {{ o }}
</p>
{% empty %} {% empty %}
{% trans "None" %} {% trans "None" %}
{% endfor %} {% endfor %}
...@@ -68,6 +70,33 @@ ...@@ -68,6 +70,33 @@
<h3 class="no-margin"><i class="fa fa-file"></i> {% trans "Disks" %}</h3> <h3 class="no-margin"><i class="fa fa-file"></i> {% trans "Disks" %}</h3>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="row">
<div class="col-md-9">
<ul class="nav nav-pills" style="margin: 5px 0 20px 0;">
<li class="disabled"><a href="#">{% trans "Filter by type" %}</a></li>
<li {% if not request.GET.filter %} class="active"{% endif %}>
<a href="{{ request.path }}?s={{ request.GET.s }}">{% trans "ALL" %}</a>
</li>
{% for f in filter_names %}
<li{% if request.GET.filter == f.0 %} class="active"{% endif %}>
<a href="?filter={{ f.0 }}&s={{ request.GET.s }}">{{ f.1|capfirst }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="col-md-3">
<form action="" method="GET" id="network-host-list-form">
<div class="input-group">
<input type="text" name="s" class="form-control"
value="{{ request.GET.s }}" placeholder="{% trans "Search..." %}"/>
<span class="input-group-btn">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</span>
<input type="hidden" name="filter" value="{{ request.GET.filter }}"/>
</div>
</form>
</div>
</div><!-- .row -->
<div class="table-responsive"> <div class="table-responsive">
{% render_table disk_table %} {% render_table disk_table %}
</div> </div>
......
{{ record.created|date }} {% load arrowfilter %}
<br /> <span title="{{ record.created }}">
{{ record.created|time }} {{ record.created|arrowfilter:LANGUAGE_CODE }}
</span>
{% load i18n %} {% load i18n %}
{% load hro %} {% load hro %}
{% load arrowfilter %}
<div id="activity-timeline" class="timeline"> <div id="activity-timeline" class="timeline">
{% for a in activities %} {% for a in activities %}
...@@ -18,7 +19,7 @@ ...@@ -18,7 +19,7 @@
- {{ a.percentage }}% - {{ a.percentage }}%
{% endif %} {% endif %}
</strong> </strong>
{% endspaceless %}{% if a.times < 2%} {{ a.started|date:"Y-m-d H:i" }}{% endif %}{% if a.user %}, {% endspaceless %}{% if a.times < 2 %} <span title="{{ a.started }}">{{ a.started|arrowfilter:LANGUAGE_CODE }}</span>{% endif %}{% if a.user %},
<a class="no-style-link" href="{% url "dashboard.views.profile" username=a.user.username %}"> <a class="no-style-link" href="{% url "dashboard.views.profile" username=a.user.username %}">
{% include "dashboard/_display-name.html" with user=a.user show_org=True %} {% include "dashboard/_display-name.html" with user=a.user show_org=True %}
</a> </a>
...@@ -40,7 +41,9 @@ ...@@ -40,7 +41,9 @@
<a href="{{ s.get_absolute_url }}"> <a href="{{ s.get_absolute_url }}">
{{ s.readable_name|get_text:user|capfirst }}</a></span> &ndash; {{ s.readable_name|get_text:user|capfirst }}</a></span> &ndash;
{% if s.finished %} {% if s.finished %}
{{ s.finished|time:"H:i:s" }} <span title="{{ s.finished }}">
{{ s.finished|arrowfilter:LANGUAGE_CODE }}
</span>
{% else %} {% else %}
<i class="fa fa-refresh fa-spin" class="sub-activity-loading-icon"></i> <i class="fa fa-refresh fa-spin" class="sub-activity-loading-icon"></i>
{% endif %} {% endif %}
......
{% load i18n %} {% load i18n %}
{% load arrowfilter %}
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<dl id="home_name_and_description"> <dl id="home_name_and_description">
...@@ -70,13 +71,13 @@ ...@@ -70,13 +71,13 @@
<dt>{% trans "Suspended at:" %}</dt> <dt>{% trans "Suspended at:" %}</dt>
<dd> <dd>
<span title="{{ instance.time_of_suspend }}"> <span title="{{ instance.time_of_suspend }}">
<i class="fa fa-moon-o"></i> {{ instance.time_of_suspend|timeuntil }} <i class="fa fa-moon-o"></i> {{ instance.time_of_suspend|arrowfilter:LANGUAGE_CODE }}
</span> </span>
</dd> </dd>
<dt>{% trans "Destroyed at:" %}</dt> <dt>{% trans "Destroyed at:" %}</dt>
<dd> <dd>
<span title="{{ instance.time_of_delete }}"> <span title="{{ instance.time_of_delete }}">
<i class="fa fa-times"></i> {{ instance.time_of_delete|timeuntil }} <i class="fa fa-times"></i> {{ instance.time_of_delete|arrowfilter:LANGUAGE_CODE }}
</span> </span>
</dd> </dd>
</dl> </dl>
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.template import Library
import arrow
from dashboard.arrow_local import HungarianLocale
for name in HungarianLocale.names:
arrow.locales._locales[name] = HungarianLocale
register = Library()
@register.filter
def arrowfilter(date, language='en'):
if not date:
return ''
adate = arrow.get(date)
return adate.humanize(locale=language)
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.template import Library from django.template import Library
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django import template from django import template
register = template.Library() register = template.Library()
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import unittest import unittest
from mock import patch, MagicMock from mock import patch, MagicMock
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
......
...@@ -61,8 +61,7 @@ class GroupCodeMixin(object): ...@@ -61,8 +61,7 @@ class GroupCodeMixin(object):
state = StateCache(request.session) state = StateCache(request.session)
conf = get_config(None, request) conf = get_config(None, request)
client = Saml2Client(conf, state_cache=state, client = Saml2Client(conf, state_cache=state,
identity_cache=IdentityCache(request.session), identity_cache=IdentityCache(request.session))
logger=logger)
subject_id = _get_subject_id(request.session) subject_id = _get_subject_id(request.session)
identity = client.users.get_identity(subject_id, identity = client.users.get_identity(subject_id,
check_not_on_or_after=False) check_not_on_or_after=False)
......
...@@ -16,13 +16,16 @@ ...@@ -16,13 +16,16 @@
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>. # with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
from django.contrib import messages
from django.views.generic import UpdateView
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from django.views.generic import UpdateView
from sizefield.utils import filesizeformat
from braces.views import SuperuserRequiredMixin from braces.views import SuperuserRequiredMixin
from sizefield.utils import filesizeformat
from common.models import WorkerNotFound
from storage.models import DataStore, Disk from storage.models import DataStore, Disk
from ..tables import DiskListTable from ..tables import DiskListTable
from ..forms import DataStoreForm, DiskForm from ..forms import DataStoreForm, DiskForm
...@@ -40,15 +43,53 @@ class StorageDetail(SuperuserRequiredMixin, UpdateView): ...@@ -40,15 +43,53 @@ class StorageDetail(SuperuserRequiredMixin, UpdateView):
context = super(StorageDetail, self).get_context_data(**kwargs) context = super(StorageDetail, self).get_context_data(**kwargs)
ds = self.get_object() ds = self.get_object()
try:
context['stats'] = self._get_stats() context['stats'] = self._get_stats()
context['missing_disks'] = ds.get_missing_disks() context['missing_disks'] = ds.get_missing_disks()
context['orphan_disks'] = ds.get_orphan_disks() context['orphan_disks'] = ds.get_orphan_disks()
qs = Disk.objects.filter(datastore=ds, destroyed=None) except WorkerNotFound:
messages.error(self.request, _("The DataStore is offline."))
context['disk_table'] = DiskListTable( context['disk_table'] = DiskListTable(
qs, request=self.request, self.get_table_data(), request=self.request,
template="django_tables2/table_no_page.html") template="django_tables2/with_pagination.html")
context['filter_names'] = (
('vm', _("virtual machine")),
('template', _("template")),
('none', _("none")),
)
return context return context
def get_table_data(self):
ds = self.get_object()
qs = Disk.objects.filter(datastore=ds, destroyed=None)
filter_name = self.request.GET.get("filter")
search = self.request.GET.get("s")
filter_queries = {
'vm': {
'instance_set__isnull': False,
},
'template': {
'template_set__isnull': False,
},
'none': {
'template_set__isnull': True,
'instance_set__isnull': True,
}
}
if filter_name:
qs = qs.filter(**filter_queries.get(filter_name, {}))
if search:
search = search.strip()
qs = qs.filter(Q(name__icontains=search) |
Q(filename__icontains=search))
return qs
def _get_stats(self): def _get_stats(self):
stats = self.object.get_statistics() stats = self.object.get_statistics()
free_space = int(stats['free_space']) free_space = int(stats['free_space'])
...@@ -72,3 +113,6 @@ class DiskDetail(SuperuserRequiredMixin, UpdateView): ...@@ -72,3 +113,6 @@ class DiskDetail(SuperuserRequiredMixin, UpdateView):
model = Disk model = Disk
form_class = DiskForm form_class = DiskForm
template_name = "dashboard/storage/disk.html" template_name = "dashboard/storage/disk.html"
def form_valid(self, form):
pass
#!/bin/echo Usage: fab --list -f #!/bin/echo Usage: fab --list -f
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import contextlib import contextlib
import datetime import datetime
...@@ -46,6 +64,14 @@ def bower(component=None): ...@@ -46,6 +64,14 @@ def bower(component=None):
@roles('portal') @roles('portal')
def flake8():
"Run portal tests"
with _workon("circle"), cd("~/circle/circle"):
run("flake8 . --exclude=migrations,bower_components,"
"south_migrations,static_collected --max-complexity 12")
@roles('portal')
def migrate(): def migrate():
"Run db migrations" "Run db migrations"
with _workon("circle"), cd("~/circle/circle"): with _workon("circle"), cd("~/circle/circle"):
......
# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from itertools import islice from itertools import islice
from socket import gethostname from socket import gethostname
import logging import logging
......
amqp==1.4.6 amqp==1.4.6
anyjson==0.3.3 anyjson==0.3.3
arrow==0.5.4
billiard==3.3.0.18 billiard==3.3.0.18
bpython==0.13.1 bpython==0.13.1
celery==3.1.17 celery==3.1.17
......
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