Commit 0d188bd6 by Őry Máté

Merge branch 'release-13.03.1' into releases

parents e0757a88 a5e7ec7a
...@@ -34,6 +34,10 @@ nosetests.xml ...@@ -34,6 +34,10 @@ nosetests.xml
.project .project
.pydevproject .pydevproject
# Compiled CSS/JS resources
*.css
*.min.js
# Other # Other
*.swp *.swp
*~ *~
......
SHELL := /bin/bash SHELL := /bin/bash
jsfiles += one/static/script/cloud.min.js
jsfiles += one/static/script/util.min.js
jsfiles += one/static/script/store.min.js
cssfiles += one/static/style/style.css
default: migrate collectstatic mo restart default: migrate generatestatic collectstatic mo restart
pulldef: pull default pulldef: pull default
pull: pull:
...@@ -14,6 +18,8 @@ po: ...@@ -14,6 +18,8 @@ po:
migrate: migrate:
./manage.py migrate ./manage.py migrate
generatestatic: $(jsfiles) $(cssfiles)
collectstatic: collectstatic:
./manage.py collectstatic --noinput ./manage.py collectstatic --noinput
...@@ -22,4 +28,10 @@ mo: ...@@ -22,4 +28,10 @@ mo:
for i in */; do cd $$i; ls locale &>/dev/null && ../manage.py compilemessages || true; cd ..; done for i in */; do cd $$i; ls locale &>/dev/null && ../manage.py compilemessages || true; cd ..; done
restart: restart:
sudo /etc/init.d/apache2 reload sudo /etc/init.d/apache2 reload || sudo restart django
%.min.js: %.js
uglifyjs $< > $@
%.css: %.less
lessc one/static/style/style.less > one/static/style/style.css
from cloud.settings import DEBUG
def process_debug(req):
return {'DEBUG': DEBUG}
...@@ -5,7 +5,7 @@ DEBUG = True ...@@ -5,7 +5,7 @@ DEBUG = True
TEMPLATE_DEBUG = DEBUG TEMPLATE_DEBUG = DEBUG
ADMINS = ( ADMINS = (
('IK', 'cloud@iit.bme.hu'), ('IK', 'cloud@cloud.ik.bme.hu'),
) )
MANAGERS = ADMINS MANAGERS = ADMINS
...@@ -73,6 +73,7 @@ STATICFILES_DIRS = ( ...@@ -73,6 +73,7 @@ STATICFILES_DIRS = (
# Always use forward slashes, even on Windows. # Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths. # Don't forget to use absolute paths, not relative paths.
'/opt/webadmin/cloud/one/static', '/opt/webadmin/cloud/one/static',
'/opt/webadmin/cloud/cloud/static',
) )
# List of finder classes that know how to find static files in # List of finder classes that know how to find static files in
...@@ -109,6 +110,17 @@ ROOT_URLCONF = 'cloud.urls' ...@@ -109,6 +110,17 @@ ROOT_URLCONF = 'cloud.urls'
# Python dotted path to the WSGI application used by Django's runserver. # Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'cloud.wsgi.application' WSGI_APPLICATION = 'cloud.wsgi.application'
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'cloud.context_processors.process_debug',
)
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows. # Always use forward slashes, even on Windows.
...@@ -186,6 +198,8 @@ CELERY_ROUTES = { ...@@ -186,6 +198,8 @@ CELERY_ROUTES = {
'firewall.tasks.reload_firewall_task': {'queue': 'firewall'}, 'firewall.tasks.reload_firewall_task': {'queue': 'firewall'},
'firewall.tasks.reload_dhcp_task': {'queue': 'dhcp'}, 'firewall.tasks.reload_dhcp_task': {'queue': 'dhcp'},
'firewall.tasks.reload_blacklist_task': {'queue': 'firewall'}, 'firewall.tasks.reload_blacklist_task': {'queue': 'firewall'},
'firewall.tasks.Periodic': {'queue': 'local'},
'one.tasks.SendMailTask': {'queue': 'local'},
} }
store_settings = { store_settings = {
...@@ -200,7 +214,6 @@ store_settings = { ...@@ -200,7 +214,6 @@ store_settings = {
"store_public": "store.ik.bme.hu", "store_public": "store.ik.bme.hu",
} }
firewall_settings = { firewall_settings = {
"default_vlangroup": "publikus", "default_vlangroup": "publikus",
"reload_sleep": "10", "reload_sleep": "10",
...@@ -210,6 +223,9 @@ firewall_settings = { ...@@ -210,6 +223,9 @@ firewall_settings = {
"dns_ttl": "300", "dns_ttl": "300",
} }
EMAIL_HOST='152.66.243.92' # giccero ipv4
CLOUD_URL='https://cloud.ik.bme.hu/'
try: try:
from cloud.local_settings import * from cloud.local_settings import *
except: except:
......
<!DOCTYPE html>
<html lang="hu">
<head>
<title>IK Cloud</title>
<link href="https://fonts.googleapis.com/css?family=Titillium+Web&amp;subset=latin,latin-ext" rel="stylesheet" type="text/css" />
<link rel="icon" type="image/png" href="/static/favicon.png" />
<link href="/static/style/style.css" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div id="header">
<h1><a href="/">IK Cloud</a></h1>
</div>
<div id="content">
<div id="http-error">
<h1>Karbantartás – Maintenance</h1>
<p lang="hu">
Az oldal ideiglenesen nem érhető el karbantartás miatt. Elnézést kérünk a kellemetlenségekért.
</p>
<p lang="en">
The site is temporarily down for maintenance. We apologize for any inconvinience.
</p>
</div>
<div class="clear"></div>
</div>
<footer>
<a href="/sites/legal/">Impresszum</a> |
<a href="/sites/policy/">Szabályzat</a> |
<a href="/sites/help/">Súgó</a> |
<a href="/sites/support/">Támogatás</a> |
cloud <em>(kukac)</em> ik.bme.hu
</footer>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-39125666-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>
{% extends "base.html" %}
{% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %}
{% block js %}
<script type="text/javascript" src="{% static "script/store.js" %}"></script>
<style>
.contentblock p{
margin: 15px;
text-align: justify;
}
.contentblock img{
margin: 0px auto;
display: block;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.3);
border-radius: 5px;
text-align: center;
vertical-align: middle;
}
.boxes a:link,
a:visited {
color: black;
}
.boxes strong {
font-size: .9em;
}
</style>
{% endblock %}
{% block content %}
<div class="boxes">
<div class="contentblock" id="state">
<h2>A projektről</h2>
<div>
<p>Az <strong>IK Cloud</strong> a BME IK és IIT együttműködésében, a VIK
támogatásával hosszabb ideje folyó munka során jött létre.
A kutatás célja <strong>a cloud oktatási-kutatási célú felhasználásának</strong>
vonzóvá tétele.
</p>
<p>
A nagy kapacitású virtuális infrastruktúra azonban új lehetőséget is nyújt.
<strong>Igény szerint</strong> indíthatóak virtuális gépek:
gördülékennyé válik a tantermi és otthoni <strong>hallgatói munka,</strong>
a kutatási <strong>projektek dinamikus IT támogatása.</strong>
</p>
<p><img src="{% static "info/cloud-migration.png" %}" /></p>
<p>A rendszerünk segítségével <strong>kiváltható</strong> a tanszéken
működő öregedő szerverpark jelentős része.</p>
</div>
</div>
</div>
<div class="boxes">
<div class="contentblock" id="state">
<h2>Virtuális labor</h2>
<div>
<p><img src="{% static "info/cloud-lab.png" %}" /></p>
<p>Lehetőség van <strong>tantárgyra szabott környezet</strong> biztosítására
a tantermi mérések vagy az otthoni feladatok elvégzéséhez, vagy az
önkiszolgáló felületen pillanatok alatt indítható <strong>projektek, önálló
labor, szakdolgozat, diplomaterv, vagy TDK-munka</strong> segítéséhez
virtuális gép.</p>
<p style="text-align:center;"><a
href="{% url one.views.home %}">Próbálja ki a rendszert
most!</a></p>
</div>
</div>
<div class="contentblock" id="state" lang="en">
<h2>About the project</h2>
<div>
<p>The project aims to harness the power of cloud computing in
education and research. Our self service portal helps migrating
old servers, and on-demand launching appliances prepared by the
teacher.</p>
</p>
</div>
</div>
</div>
{% endblock %}
{% extends "base.html" %}
{% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %}
{% block content %}
<div class="irasmu">
<p>A súgó elkészültéig kérjük szíves türelmüket.</p>
<p>Addig is ajánljuk figyelmükbe a rendszer <a href="/info/">rövid ismertetőjét</a>, a használat módját részletező <a href="/sites/policy/">szabályzatot</a>, valamint a felület számos pontján megjelenő <img src="{% static "icons/information-frame.png" %}" alt="Súgó" /> ikonnal jelölt információdobozokat.</p>
<p>Amennyiben kérdése maradt, örömmel segítünk a <a href="/sites/support/">támogatás</a> oldalon leírt elérhetőségeinken.</p>
</div>
{% endblock %}
{% extends "base.html" %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% block content %}
<div class="irasmu">
<p>Az IK Cloud a BME IK és IIT együttműködésében, a VIK támogatásával létrejött rendszer, amelyben az IIT oktatói és hallgatói szükség szerint vehetnek igénybe virtuális erőforrásokat.
</p>
<p>Az oldal üzemeltetője a BME Közigazgatási Informatikai Központ.</p>
<p>A rendszer fejlesztésében részt vettek:
Bach Dániel,
Dányi Bence,
Dudás Ádám,
Guba Sándor,
Őry Máté és
dr. Szeberényi Imre.</p>
<p>A rendszer HP hardveren, Ubuntu operációs rendszeren, KVM virtualizációval, Open vSwitch virtuális hálózaton, libvirt köztes réteggel, OpenNebula cloud menedzserrel, Django alapú webportállal működik.</p>
<p>Some icons by <a href="http://p.yusukekamiyamane.com/">Yusuke Kamiyamane</a>. Licensed under a <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License</a>.</p>
</div>
{% endblock %}
{% extends "base.html" %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% block content %}
<div class="irasmu">
<p>Az IK Cloud a BME IK és IIT együttműködésében, a VIK támogatásával létrejött rendszer, amelyben az IIT oktatói és hallgatói szükség szerint vehetnek igénybe <strong>virtuális erőforrásokat</strong>.</p>
<p>Az IIT géptermeiben telepített kliensszoftver segítségével az oktató által előkészített és kiajánlott <strong>virtuális környezetet a hallgató</strong> a számára megszabott <strong>kvóta keretein belül</strong> igény szerint indíthatja.</p>
<p>A HSZK géptermeiben a kliensszoftver jelenleg nincs telepítve, de a virtuális gépek indítása, a fájlok elérése webböngészővel is teljes értékű; míg a gépekhez való csatlakozás kézzel elvégezhető.</p>
<p>Lehetőség van a gépteremben elkezdett munka otthoni folytatására is a korábban elindított környezetben. A rendszer segítségével az otthoni feladatot végző hallgató is elkerülheti az összetett szoftverkörnyezet telepítésével járó kellemetlenségeket, figyelmét a szakmai munkára irányíthatja.</p>
<p>A rendszer segítséget nyújt önálló labor, szakdolgozat, diplomaterv vagy tdk-munka készítésénél is: a munkához szükséges virtuális gépeket az önkiszolgáló rendszeren keresztül azonnal használatba lehet venni.</p>
<p>Az elindított virtuális gépekre az adott operációs rendszeren szokásos módon lehet távolról csatlakozni: Windows esetén RDP (távoli asztal), Linux esetén SSH, vagy grafikusan NoMachine NX segítségével. A kapcsolódást a géptermekben telepített kliensszoftver még kényelmesebbé teszi.</p>
<p>Az elindított gépeken a <strong>felhasználói adattár</strong> automatikusan csatolásra kerül. Minden munkát itt érdemes végezni, mivel az a gép leállítása után is elérhető marad.</p>
<p>A felhasználók a rendszert jelen önkiszolgáló felületen keresztül érhetik el, amelybe az egyetemi címtárszolgáltatás (eduID) segítségével léphetnek be. A továbblépéssel elfogadják a következőekben összefoglalt <strong>felhasználási feltételeket</strong>.</p>
<ul>
<li>A rendszer <strong>nem használható</strong> semmilyen jogszabályba, vagy <a href="http://net.bme.hu/regula/">egyetemi</a> <strong>szabályzatba ütköző tevékenységre</strong>.</li>
<li><strong>Kizárólag tanulmányi</strong> vagy <strong>kutatási tevékenységhez</strong> használható erőforrás.</li>
<li>Bár a rendszer használata térítésmentes, a <strong>felesleges gépek leállítása</strong> a felhasználó kötelessége.</li>
<li>Minden gép indítása <strong>határidő kijelölésével</strong> történik. A határidő lejártával <strong>a gépet megállítjuk</strong>. Amennyiben a felhasználó a megállítást követően (a törlési határidő leteltéig) nem kéri meghosszabbítását, a gépet és <strong>minden rajta lévő adatot törlünk!</strong></li>
<li>A felhasználó felelőssége a futtatott rendszer biztonságos üzemeltetése, a hosszabb időn át futó gépek frissítése.</li>
<li>A rendszert üzemeltető BME IK lehetőségeihez mérten mindent megtesz a szolgáltatásbiztos üzemért, az egyetemi infrastruktúra sajátosságai miatt előforduló üzemszünetekre azonban számítani kell. A BME IK az üzemeltetés kapcsán a folyamatos üzem sérüléséért vagy adatvesztésért <strong>minden felelősséget kizár</strong>. Ezeknek megfelelően szükség esetén a biztonsági mentés és a magas rendelkezésre állású környezet kialakítása a felhasználóra hárul.</li>
</ul>
<p>A szabályok betartása közös érdekünk. Reméljük, hogy a rendszerünk használata megkönnyíti munkájukat, melyhez sok sikert kívánunk!</p>
</div>
{% endblock %}
{% extends "base.html" %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% block content %}
<div class="irasmu">
<p>A rendszer használatával kapcsolatos kérdéseket, általános észrevételeket a <tt>cloud <em>(kukac)</em>
ik.bme.hu</tt> e-mail címen várjuk.
Ugyancsak örömmel fogadjuk a rendszer használatával kapcsolatos beszámolókat.</p>
<p>A rendszerben talált hibákat (vagy azok gyanúját), valamint ötleteit, javaslatait kérjük,
<a href="https://giccero.cloud.ik.bme.hu/trac/cloud/newticket" rel="nofollow">
hibajegy felvételével</a> jelezze.
</p>
</div>
{% endblock %}
...@@ -5,107 +5,91 @@ admin.autodiscover() ...@@ -5,107 +5,91 @@ admin.autodiscover()
import one.views import one.views
import firewall.views import firewall.views
#import store.views # import store.views
js_info_dict = { js_info_dict = {
'packages': ('one', ), 'packages': ('one', ),
} }
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/doc/', include('django.contrib.admindocs.urls'), ),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls), ),
url(r'^$', 'one.views.home', name='home'),
url(r'^login/$', 'school.views.login', name='login'),
url(r'^logout/$', 'school.views.logout', name='logout'), url(r'^login/$', 'school.views.login', name='login', ),
url(r'^vm/new/(?P<template>\d+)/$', 'one.views.vm_new', name='vm_new'), url(r'^logout/$', 'school.views.logout', name='logout', ),
url(r'^ajax/vm/new/(?P<template>\d+)/$', 'one.views.vm_new_ajax',
name='vm_new_ajax'), url(r'^$', 'one.views.index', ),
url(r'^vm/new/s(?P<share>\d+)/$', 'one.views.vm_new', name='vm_new'), url(r'^info/$', 'one.views.info', ),
url(r'^vm/show/(?P<iid>\d+)/$', 'one.views.vm_show', name='vm_show'), url(r'^home/$', 'one.views.home', ),
url(r'^vm/delete/(?P<iid>\d+)/$', 'one.views.vm_delete', url(r'^vm/new/(?P<template>\d+)/$', 'one.views.vm_new',
name='vm_delete'), name='new_vm_from_template'),
url(r'^vm/stop/(?P<iid>\d+)/$', 'one.views.vm_stop', name='vm_stop'), url(r'^ajax/vm/new/(?P<template>\d+)/$', 'one.views.vm_new_ajax', ),
url(r'^vm/unshare/(?P<id>\d+)/$', 'one.views.vm_unshare', url(r'^vm/new/s(?P<share>\d+)/$', 'one.views.vm_new',
name='vm_unshare'), name='new_vm_form_share'),
url(r'^vm/resume/(?P<iid>\d+)/$', 'one.views.vm_resume', url(r'^vm/show/(?P<iid>\d+)/$', 'one.views.vm_show', ),
name='vm_resume'), url(r'^vm/delete/(?P<iid>\d+)/$', 'one.views.vm_delete', ),
url(r'^vm/power_off/(?P<iid>\d+)/$', 'one.views.vm_power_off', url(r'^vm/stop/(?P<iid>\d+)/$', 'one.views.vm_stop', ),
name='vm_power_off'), url(r'^vm/unshare/(?P<id>\d+)/$', 'one.views.vm_unshare', ),
url(r'^vm/restart/(?P<iid>\d+)/$', 'one.views.vm_restart', url(r'^vm/resume/(?P<iid>\d+)/$', 'one.views.vm_resume', ),
name='vm_restart'), url(r'^vm/power_off/(?P<iid>\d+)/$', 'one.views.vm_power_off', ),
url(r'^vm/restart/(?P<iid>\d+)/$', 'one.views.vm_restart', ),
url(r'^vm/renew/(?P<which>(suspend|delete))/(?P<iid>\d+)/$', url(r'^vm/renew/(?P<which>(suspend|delete))/(?P<iid>\d+)/$',
'one.views.vm_renew', name='vm_renew'), 'one.views.vm_renew', ),
url(r'^vm/port_add/(?P<iid>\d+)/$', 'one.views.vm_port_add', url(r'^vm/port_add/(?P<iid>\d+)/$', 'one.views.vm_port_add', ),
name='vm_port_add'),
url(r'^vm/port_del/(?P<iid>\d+)/(?P<proto>tcp|udp)/(?P<public>\d+)/$', url(r'^vm/port_del/(?P<iid>\d+)/(?P<proto>tcp|udp)/(?P<public>\d+)/$',
'one.views.vm_port_del', name='vm_port_del'), 'one.views.vm_port_del', ),
url(r'^vm/saveas/(?P<vmid>\d+)$', 'one.views.vm_saveas', url(r'^ajax/shareEdit/(?P<id>\d+)/$', 'one.views.ajax_share_edit_wizard',
name='vm_saveas'), name='ajax_share_edit_wizard'),
url(r'^vm/credentials/(?P<iid>\d+)$', 'one.views.vm_credentials', url(r'^vm/saveas/(?P<vmid>\d+)$', 'one.views.vm_saveas', ),
name='vm_credentials'), url(r'^vm/credentials/(?P<iid>\d+)$', 'one.views.vm_credentials', ),
url(r'^reload/$', 'firewall.views.reload_firewall', url(r'^ajax/templateWizard/$', 'one.views.ajax_template_wizard', ),
name='reload_firewall'), url(r'^ajax/templateEditWizard/(?P<id>\d+)/$', 'one.views.ajax_template_edit_wizard', ),
url(r'^fwapi/$', 'firewall.views.firewall_api', url(r'^ajax/share/(?P<id>\d+)/$', 'one.views.ajax_share_wizard', ),
name='firewall_api'),
url(r'^store/$', 'store.views.index', name='store_index'),
url(r'^store/gui/$', 'store.views.gui', name='store_gui'),
url(r'^store/top/$', 'store.views.toplist', name='store_top'),
url(r'^ajax/store/top/$', 'store.views.ajax_toplist',
name='axat_store_top'),
url(r'^ajax/templateWizard$', 'one.views.ajax_template_wizard',
name='ajax_template_wizard'),
url(r'^ajax/share/(?P<id>\d+)/$', 'one.views.ajax_share_wizard',
name='ajax_share_wizard'),
url(r'^ajax/share/(?P<id>\d+)/(?P<gid>\d+)$', url(r'^ajax/share/(?P<id>\d+)/(?P<gid>\d+)$',
'one.views.ajax_share_wizard', name='ajax_share_wizard'), 'one.views.ajax_share_wizard', ),
url(r'^ajax/template/delete/$', 'one.views.ajax_template_delete',
name='ajax_template_delete'),
url(r'^ajax/template_name_unique/(?P<name>.*)$',
'one.views.ajax_template_name_unique',
name='ajax_template_name_unique'),
url(r'^ajax/store/list$', 'store.views.ajax_listfolder',
name='store_ajax_listfolder'),
url(r'^ajax/store/download$', 'store.views.ajax_download',
name='store_ajax_download'),
url(r'^ajax/store/upload$', 'store.views.ajax_upload',
name='store_ajax_upload'),
url(r'^ajax/store/delete$', 'store.views.ajax_delete',
name='store_ajax_delete'),
url(r'^ajax/store/newFolder$', 'store.views.ajax_new_folder',
name='store_ajax_new_folder'),
url(r'^ajax/store/quota$', 'store.views.ajax_quota',
name='store_ajax_quota'),
url(r'^ajax/store/rename$', 'store.views.ajax_rename',
name='store_ajax_rename'),
url(r'^ajax/vm/status/(?P<iid>\d+)$', url(r'^ajax/vm/status/(?P<iid>\d+)$',
'one.views.vm_ajax_instance_status', 'one.views.vm_ajax_instance_status', ),
name='vm_ajax_instance_status'),
url(r'^ajax/vm/rename/(?P<iid>\d+)/$', url(r'^ajax/vm/rename/(?P<iid>\d+)/$',
'one.views.vm_ajax_rename', 'one.views.vm_ajax_rename', ),
name='vm_ajax_rename'), url(r'^key/add/$', 'one.views.key_add', ),
url(r'^language/(?P<lang>[-A-Za-z]+)/$', 'school.views.language', url(r'^ajax/key/delete/$', 'one.views.key_ajax_delete', ),
name='language'), url(r'^ajax/key/reset/$', 'one.views.key_ajax_reset', ),
url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), url(r'^ajax/template/delete/$', 'one.views.ajax_template_delete', ),
url(r'^b/(?P<token>.*)/$', 'one.views.boot_token', name='boot_token'), url(r'^ajax/template_name_unique/$',
'one.views.ajax_template_name_unique', ),
url(r'^reload/$', 'firewall.views.reload_firewall', ),
url(r'^fwapi/$', 'firewall.views.firewall_api', ),
url(r'^store/$', 'store.views.index', ),
url(r'^store/gui/$', 'store.views.gui', ),
url(r'^store/top/$', 'store.views.toplist', ),
url(r'^ajax/store/top/$', 'store.views.ajax_toplist', ),
url(r'^ajax/store/list$', 'store.views.ajax_listfolder', ),
url(r'^ajax/store/download$', 'store.views.ajax_download', ),
url(r'^ajax/store/upload$', 'store.views.ajax_upload', ),
url(r'^ajax/store/delete$', 'store.views.ajax_delete', ),
url(r'^ajax/store/newFolder$', 'store.views.ajax_new_folder', ),
url(r'^ajax/store/quota$', 'store.views.ajax_quota', ),
url(r'^ajax/store/rename$', 'store.views.ajax_rename', ),
url(r'^language/(?P<lang>[-A-Za-z]+)/$', 'school.views.language', ),
url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict, ),
url(r'^b/(?P<token>.*)/$', 'one.views.boot_token', ),
url(r'^group/show/(?P<gid>\d+)/$', 'school.views.group_show', url(r'^group/show/(?P<gid>\d+)/$', 'school.views.group_show',
name='group_show'), name='group_show'),
url(r'^group/new/$', 'school.views.group_new', name='group_new'), url(r'^group/new/$', 'school.views.group_new', ),
url(r'^ajax/group/(?P<gid>\d+)/add/$', url(r'^ajax/group/(?P<gid>\d+)/add/$',
'school.views.group_ajax_add_new_member', 'school.views.group_ajax_add_new_member', ),
name='group_ajax_add_new_member'),
url(r'^ajax/group/(?P<gid>\d+)/addOwner/$', url(r'^ajax/group/(?P<gid>\d+)/addOwner/$',
'school.views.group_ajax_add_new_owner', 'school.views.group_ajax_add_new_owner', ),
name='group_ajax_add_new_owner'),
url(r'^ajax/group/(?P<gid>\d+)/remove/$', url(r'^ajax/group/(?P<gid>\d+)/remove/$',
'school.views.group_ajax_remove_member', 'school.views.group_ajax_remove_member', ),
name='group_ajax_remove_member'), url(r'^ajax/group/delete/$', 'school.views.group_ajax_delete', ),
url(r'^ajax/group/delete/$', 'school.views.group_ajax_delete', url(r'^ajax/group/autocomplete/$',
name='group_ajax_delete'), 'school.views.group_ajax_owner_autocomplete', ),
url(r'^ajax/group/autocomplete/$', 'school.views.group_ajax_owner_autocomplete', url(r'^stat/$', 'one.views.stat'),
name='group_ajax_autocomplete'), url(r'^sites/(?P<site>[a-zA-Z0-9]+)/$', 'one.views.sites'),
url(r'^key/add/$', 'one.views.key_add', name='key_add'), url(r'^accounts/(?P<site>profile)/$', 'one.views.sites'),
url(r'^ajax/key/delete/$', 'one.views.key_ajax_delete',
name='key_ajax_delete'),
url(r'^ajax/key/reset/$', 'one.views.key_ajax_reset',
name='key_ajax_reset'),
) )
...@@ -13,7 +13,7 @@ class RecordInline(contrib.admin.TabularInline): ...@@ -13,7 +13,7 @@ class RecordInline(contrib.admin.TabularInline):
class HostAdmin(admin.ModelAdmin): class HostAdmin(admin.ModelAdmin):
list_display = ('hostname', 'vlan', 'ipv4', 'ipv6', 'pub_ipv4', 'mac', list_display = ('hostname', 'vlan', 'ipv4', 'ipv6', 'pub_ipv4', 'mac',
'shared_ip', 'owner', 'description', 'reverse', 'groups_l') 'shared_ip', 'owner', 'description', 'reverse', 'list_groups')
ordering = ('hostname', ) ordering = ('hostname', )
list_filter = ('owner', 'vlan', 'groups') list_filter = ('owner', 'vlan', 'groups')
search_fields = ('hostname', 'description', 'ipv4', 'ipv6', 'mac') search_fields = ('hostname', 'description', 'ipv4', 'ipv6', 'mac')
...@@ -21,7 +21,7 @@ class HostAdmin(admin.ModelAdmin): ...@@ -21,7 +21,7 @@ class HostAdmin(admin.ModelAdmin):
inlines = (RuleInline, RecordInline) inlines = (RuleInline, RecordInline)
@staticmethod @staticmethod
def groups_l(instance): def list_groups(instance):
"""Returns instance's groups' names as a comma-separated list.""" """Returns instance's groups' names as a comma-separated list."""
names = [group.name for group in instance.groups.all()] names = [group.name for group in instance.groups.all()]
return u', '.join(names) return u', '.join(names)
...@@ -45,34 +45,36 @@ class RuleAdmin(admin.ModelAdmin): ...@@ -45,34 +45,36 @@ class RuleAdmin(admin.ModelAdmin):
def color_desc(self, instance): def color_desc(self, instance):
"""Returns a colorful description of the instance.""" """Returns a colorful description of the instance."""
para = '</span>' return (u'<span style="color: #FF0000;">[%(type)s]</span> '
if instance.dport: u'%(src)s<span style="color: #0000FF;"> ▸ </span>%(dst)s '
para = 'dport=%s %s' % (instance.dport, para) u'%(para)s %(desc)s') % {
if instance.sport: 'type': instance.r_type,
para = 'sport=%s %s' % (instance.sport, para) 'src': (instance.foreign_network.name
if instance.proto: if instance.direction == '1' else instance.r_type),
para = 'proto=%s %s' % (instance.proto, para) 'dst': (instance.r_type if instance.direction == '1'
para = u'<span style="color: #00FF00;">' + para else instance.foreign_network.name),
return ( 'para': (u'<span style="color: #00FF00;">' +
u'<span style="color: #FF0000;">[%s]</span> ' % instance.r_type + (('proto=%s ' % instance.proto)
(u'%s<span style="color: #0000FF;"> ▸ </span>%s' % if instance.proto else '') +
((instance.foreign_network.name, instance.r_type) (('sport=%s ' % instance.sport)
if instance.direction == '1' else if instance.sport else '') +
(instance.r_type, instance.foreign_network.name))) + (('dport=%s ' % instance.dport)
' ' + para + ' ' + instance.description) if instance.dport else '') +
'</span>'),
'desc': instance.description}
color_desc.allow_tags = True color_desc.allow_tags = True
def vlan_l(self, instance): @staticmethod
def vlan_l(instance):
"""Returns instance's VLANs' names as a comma-separated list.""" """Returns instance's VLANs' names as a comma-separated list."""
retval = [] names = [vlan.name for vlan in instance.foreign_network.vlans.all()]
for vlan in instance.foreign_network.vlans.all(): return u', '.join(names)
retval.append(vlan.name)
return u', '.join(retval)
def used_in(self, instance): @staticmethod
def used_in(instance):
for field in [instance.vlan, instance.vlangroup, instance.host, for field in [instance.vlan, instance.vlangroup, instance.host,
instance.hostgroup, instance.firewall]: instance.hostgroup, instance.firewall]:
if field is not None: if field:
return unicode(field) + ' ' + field._meta.object_name return unicode(field) + ' ' + field._meta.object_name
...@@ -92,15 +94,15 @@ class DomainAdmin(admin.ModelAdmin): ...@@ -92,15 +94,15 @@ class DomainAdmin(admin.ModelAdmin):
class RecordAdmin(admin.ModelAdmin): class RecordAdmin(admin.ModelAdmin):
list_display = ('name_', 'type', 'address_', 'ttl', 'host', 'owner') list_display = ('name_', 'type', 'address_', 'ttl', 'host', 'owner')
def address_(self, instance): @staticmethod
def address_(instance):
a = instance.get_data() a = instance.get_data()
if a: return a['address'] if a else None
return a['address']
def name_(self, instance): @staticmethod
def name_(instance):
a = instance.get_data() a = instance.get_data()
if a: return a['name'] if a else None
return a['name']
class BlacklistAdmin(admin.ModelAdmin): class BlacklistAdmin(admin.ModelAdmin):
list_display = ('ipv4', 'reason', 'created_at', 'modified_at') list_display = ('ipv4', 'reason', 'created_at', 'modified_at')
......
...@@ -2,6 +2,7 @@ from django.core.exceptions import ValidationError ...@@ -2,6 +2,7 @@ from django.core.exceptions import ValidationError
from django.forms import fields from django.forms import fields
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.ipv6 import is_valid_ipv6_address
from south.modelsinspector import add_introspection_rules from south.modelsinspector import add_introspection_rules
import re import re
...@@ -35,26 +36,46 @@ class MACAddressField(models.Field): ...@@ -35,26 +36,46 @@ class MACAddressField(models.Field):
add_introspection_rules([], ["firewall\.fields\.MACAddressField"]) add_introspection_rules([], ["firewall\.fields\.MACAddressField"])
def val_alfanum(value): def val_alfanum(value):
"""Check whether the parameter is a valid alphanumeric value.""" """Validate whether the parameter is a valid alphanumeric value."""
if alfanum_re.search(value) is None: if not alfanum_re.match(value):
raise ValidationError( raise ValidationError(_(u'%s - only letters, numbers, underscores '
_(u'%s - only letters, numbers, underscores and hyphens are ' 'and hyphens are allowed!') % value)
'allowed!') % value)
def is_valid_domain(value):
"""Check whether the parameter is a valid domain name."""
return domain_re.match(value) is not None
def val_domain(value): def val_domain(value):
"""Check wheter the parameter is a valid domin.""" """Validate whether the parameter is a valid domin name."""
if domain_re.search(value) is None: if not is_valid_domain(value):
raise ValidationError(_(u'%s - invalid domain') % value) raise ValidationError(_(u'%s - invalid domain name') % value)
def is_valid_reverse_domain(value):
"""Check whether the parameter is a valid reverse domain name."""
return reverse_domain_re.match(value) is not None
def val_reverse_domain(value): def val_reverse_domain(value):
"""Check whether the parameter is a valid reverse domain.""" """Validate whether the parameter is a valid reverse domain name."""
if not reverse_domain_re.search(value): if not is_valid_reverse_domain(value):
raise ValidationError(u'%s - reverse domain' % value) raise ValidationError(u'%s - invalid reverse domain name' % value)
def is_valid_ipv4_address(value):
"""Check whether the parameter is a valid IPv4 address."""
return ipv4_re.match(value) is not None
def val_ipv4(value):
"""Validate whether the parameter is a valid IPv4 address."""
if not is_valid_ipv4_address(value):
raise ValidationError(_(u'%s - not an IPv4 address') % value)
def val_ipv6(value):
"""Validate whether the parameter is a valid IPv6 address."""
if not is_valid_ipv6_address(value):
raise ValidationError(_(u'%s - not an IPv6 address') % value)
def ipv4_2_ipv6(ipv4): def ipv4_2_ipv6(ipv4):
"""Convert IPv4 address string to IPv6 address string.""" """Convert IPv4 address string to IPv6 address string."""
val_ipv4(ipv4)
m = ipv4_re.match(ipv4) m = ipv4_re.match(ipv4)
if m is None:
raise ValidationError(_(u'%s - not an IPv4 address') % ipv4)
return ("2001:738:2001:4031:%s:%s:%s:0" % return ("2001:738:2001:4031:%s:%s:%s:0" %
(m.group(1), m.group(2), m.group(3))) (m.group(1), m.group(2), m.group(3)))
...@@ -10,7 +10,7 @@ from datetime import datetime, timedelta ...@@ -10,7 +10,7 @@ from datetime import datetime, timedelta
from django.db.models import Q from django.db.models import Q
class firewall: class Firewall:
IPV6=False IPV6=False
RULES = None RULES = None
RULES_NAT = [] RULES_NAT = []
...@@ -36,14 +36,15 @@ class firewall: ...@@ -36,14 +36,15 @@ class firewall:
def iptables(self, s): def iptables(self, s):
"""Append rule.""" """Append rule to filter table."""
self.RULES.append(s) self.RULES.append(s)
def iptablesnat(self, s): def iptablesnat(self, s):
"""Append rule to NAT table."""
self.RULES_NAT.append(s) self.RULES_NAT.append(s)
def host2vlan(self, host, rule): def host2vlan(self, host, rule):
if rule.foreign_network is None: if not rule.foreign_network:
return return
if self.IPV6 and host.ipv6: if self.IPV6 and host.ipv6:
...@@ -76,7 +77,7 @@ class firewall: ...@@ -76,7 +77,7 @@ class firewall:
def fw2vlan(self, rule): def fw2vlan(self, rule):
if rule.foreign_network is None: if not rule.foreign_network:
return return
dport_sport = self.dportsport(rule) dport_sport = self.dportsport(rule)
...@@ -92,7 +93,7 @@ class firewall: ...@@ -92,7 +93,7 @@ class firewall:
'LOG_ACC' if rule.accept else 'LOG_DROP')) 'LOG_ACC' if rule.accept else 'LOG_DROP'))
def vlan2vlan(self, l_vlan, rule): def vlan2vlan(self, l_vlan, rule):
if rule.foreign_network is None: if not rule.foreign_network:
return return
dport_sport = self.dportsport(rule) dport_sport = self.dportsport(rule)
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Blacklist.host'
db.add_column('firewall_blacklist', 'host',
self.gf('django.db.models.fields.related.ForeignKey')(to=orm['firewall.Host'], null=True, blank=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Blacklist.host'
db.delete_column('firewall_blacklist', 'host_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'firewall.blacklist': {
'Meta': {'object_name': 'Blacklist'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'reason': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'snort_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'default': "'tempban'", 'max_length': '10'})
},
'firewall.domain': {
'Meta': {'object_name': 'Domain'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
},
'firewall.firewall': {
'Meta': {'object_name': 'Firewall'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
},
'firewall.group': {
'Meta': {'object_name': 'Group'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
'firewall.host': {
'Meta': {'object_name': 'Host'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'pub_ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Vlan']"})
},
'firewall.record': {
'Meta': {'object_name': 'Record'},
'address': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Host']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '6'})
},
'firewall.rule': {
'Meta': {'object_name': 'Rule'},
'accept': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'direction': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
'dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'extra': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'firewall': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Firewall']"}),
'foreign_network': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ForeignRules'", 'to': "orm['firewall.VlanGroup']"}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Host']"}),
'hostgroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'nat': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'nat_dport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'proto': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True', 'blank': 'True'}),
'r_type': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'sport': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.Vlan']"}),
'vlangroup': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'rules'", 'null': 'True', 'to': "orm['firewall.VlanGroup']"})
},
'firewall.vlan': {
'Meta': {'object_name': 'Vlan'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['firewall.Domain']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'interface': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'ipv4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'ipv6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'net4': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'net6': ('django.db.models.fields.GenericIPAddressField', [], {'unique': 'True', 'max_length': '39'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'prefix4': ('django.db.models.fields.IntegerField', [], {'default': '16'}),
'prefix6': ('django.db.models.fields.IntegerField', [], {'default': '80'}),
'reverse_domain': ('django.db.models.fields.TextField', [], {}),
'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
},
'firewall.vlangroup': {
'Meta': {'object_name': 'VlanGroup'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'vlans': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['firewall']
\ No newline at end of file
...@@ -8,7 +8,6 @@ from firewall.fields import * ...@@ -8,7 +8,6 @@ from firewall.fields import *
from south.modelsinspector import add_introspection_rules from south.modelsinspector import add_introspection_rules
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
from cloud.settings import firewall_settings as settings from cloud.settings import firewall_settings as settings
from django.utils.ipv6 import is_valid_ipv6_address
from django.db.models.signals import post_save from django.db.models.signals import post_save
import re import re
...@@ -54,27 +53,23 @@ class Rule(models.Model): ...@@ -54,27 +53,23 @@ class Rule(models.Model):
return self.desc() return self.desc()
def clean(self): def clean(self):
count = 0 fields = [self.vlan, self.vlangroup, self.host, self.hostgroup,
for field in [self.vlan, self.vlangroup, self.host, self.hostgroup, self.firewall]
self.firewall]: selected_fields = [field for field in fields if field]
if field is None: if len(selected_fields) > 1:
count = count + 1 raise ValidationError(_('Only one field can be selected.'))
if count != 4:
raise ValidationError('jaj')
def desc(self): def desc(self):
para = u"" return u'[%(type)s] %(src)s ▸ %(dst)s %(para)s %(desc)s' % {
if(self.dport): 'type': self.r_type,
para = "dport=%s %s" % (self.dport, para) 'src': (unicode(self.foreign_network) if self.direction == '1'
if(self.sport): else self.r_type),
para = "sport=%s %s" % (self.sport, para) 'dst': (self.r_type if self.direction == '1'
if(self.proto): else unicode(self.foreign_network)),
para = "proto=%s %s" % (self.proto, para) 'para': ((("proto=%s " % self.proto) if self.proto else '') +
return (u'[' + self.r_type + u'] ' + (("sport=%s " % self.sport) if self.sport else '') +
(unicode(self.foreign_network) + u' ▸ ' + self.r_type (("dport=%s " % self.dport) if self.dport else '')),
if self.direction == '1' else self.r_type + u' ▸ ' + 'desc': self.description}
unicode(self.foreign_network)) + u' ' + para + u' ' +
self.description)
class Vlan(models.Model): class Vlan(models.Model):
vid = models.IntegerField(unique=True) vid = models.IntegerField(unique=True)
...@@ -169,7 +164,7 @@ class Host(models.Model): ...@@ -169,7 +164,7 @@ class Host(models.Model):
"address as your own IPv4.")) "address as your own IPv4."))
self.full_clean() self.full_clean()
super(Host, self).save(*args, **kwargs) super(Host, self).save(*args, **kwargs)
if id is None: if not id:
Record(domain=self.vlan.domain, host=self, type='A', Record(domain=self.vlan.domain, host=self, type='A',
owner=self.owner).save() owner=self.owner).save()
if self.ipv6: if self.ipv6:
...@@ -179,8 +174,9 @@ class Host(models.Model): ...@@ -179,8 +174,9 @@ class Host(models.Model):
def enable_net(self): def enable_net(self):
self.groups.add(Group.objects.get(name="netezhet")) self.groups.add(Group.objects.get(name="netezhet"))
def add_port(self, proto, public, private): def add_port(self, proto, public, private = 0):
proto = "tcp" if (proto == "tcp") else "udp" proto = "tcp" if proto == "tcp" else "udp"
if self.shared_ip:
if public < 1024: if public < 1024:
raise ValidationError(_("Only ports above 1024 can be used.")) raise ValidationError(_("Only ports above 1024 can be used."))
for host in Host.objects.filter(pub_ipv4=self.pub_ipv4): for host in Host.objects.filter(pub_ipv4=self.pub_ipv4):
...@@ -191,22 +187,27 @@ class Host(models.Model): ...@@ -191,22 +187,27 @@ class Host(models.Model):
proto=proto, nat=True, accept=True, r_type="host", proto=proto, nat=True, accept=True, r_type="host",
nat_dport=private, host=self, foreign_network=VlanGroup. nat_dport=private, host=self, foreign_network=VlanGroup.
objects.get(name=settings["default_vlangroup"])) objects.get(name=settings["default_vlangroup"]))
else:
if self.rules.filter(proto=proto, dport=public):
raise ValidationError(_("Port %s %s is already in use.") %
(proto, public))
rule = Rule(direction='1', owner=self.owner, dport=public,
proto=proto, nat=False, accept=True, r_type="host",
host=self, foreign_network=VlanGroup.objects
.get(name=settings["default_vlangroup"]))
rule.full_clean() rule.full_clean()
rule.save() rule.save()
def del_port(self, proto, public): def del_port(self, proto, public):
self.rules.filter(owner=self.owner, proto=proto, nat=True, self.rules.filter(owner=self.owner, proto=proto, host=self,
dport=public).delete() dport=public).delete()
def list_ports(self): def list_ports(self):
retval = [] return [{'proto': rule.proto,
for rule in self.rules.filter(owner=self.owner, nat=True): 'public': rule.dport,
retval.append({'proto': rule.proto, 'public': rule.dport, 'private': rule.nat_dport} for rule in
'private': rule.nat_dport}) self.rules.filter(owner=self.owner)]
return retval
def del_rules(self):
self.rules.filter(owner=self.owner).delete()
def get_fqdn(self): def get_fqdn(self):
return self.hostname + u'.' + unicode(self.vlan.domain) return self.hostname + u'.' + unicode(self.vlan.domain)
...@@ -249,79 +250,95 @@ class Record(models.Model): ...@@ -249,79 +250,95 @@ class Record(models.Model):
def desc(self): def desc(self):
a = self.get_data() a = self.get_data()
if a: return (u' '.join([a['name'], a['type'], a['address']])
return a['name'] + u' ' + a['type'] + u' ' + a['address'] if a else _('(empty)'))
return '(empty)'
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.full_clean() self.full_clean()
super(Record, self).save(*args, **kwargs) super(Record, self).save(*args, **kwargs)
def clean(self): def clean(self):
if self.name and self.name.endswith(u'.'): if self.name:
raise ValidationError(_("Domain can't be terminated with a dot.")) self.name = self.name.rstrip(".") # remove trailing dots
if self.host and self.type in ['CNAME', 'A', 'AAAA']: if self.host:
if self.type == 'CNAME': if self.type in ['A', 'AAAA']:
if not self.name or self.address: if self.address:
raise ValidationError(_("Only the 'name' field should " raise ValidationError(_("Can't specify address for "
"be filled with a CNAME record if a host is " "A or AAAA records if host is set!"))
"set.")) if self.name:
elif self.name or self.address: raise ValidationError(_("Can't specify name for "
raise ValidationError(_("'name' and 'address' can't be " "A or AAAA records if host is set!"))
"specified with an A or AAAA record if a host is " elif self.type == 'CNAME':
"set.")) if not self.name:
else: raise ValidationError(_("Name must be specified for "
"CNAME records if host is set!"))
if self.address:
raise ValidationError(_("Can't specify address for "
"CNAME records if host is set!"))
else: # if self.host is None
if not self.address: if not self.address:
raise ValidationError(_("'address' field must be filled.")) raise ValidationError(_("Address must be specified!"))
if self.type == 'A': if self.type == 'A':
if not ipv4_re.match(self.address): val_ipv4(self.address)
raise ValidationError(_("Not a valid IPv4 address."))
elif self.type in ['CNAME', 'NS', 'PTR', 'TXT']:
if not domain_re.match(self.address):
raise ValidationError(_("Not a valid domain."))
elif self.type == 'AAAA': elif self.type == 'AAAA':
if not is_valid_ipv6_address(self.address): val_ipv6(self.address)
raise ValidationError(_("Not a valid IPv6 address.")) elif self.type in ['CNAME', 'NS', 'PTR', 'TXT']:
val_domain(self.address)
elif self.type == 'MX': elif self.type == 'MX':
mx = self.address.split(':', 1) mx = self.address.split(':', 1)
if not (len(mx) == 2 and mx[0].isdigit() and if not (len(mx) == 2 and mx[0].isdigit() and
domain_re.match(mx[1])): domain_re.match(mx[1])):
raise ValidationError(_("Invalid address. " raise ValidationError(_("Bad address format. "
"Valid format: <priority>:<hostname>")) "Should be: <priority>:<hostname>"))
else: else:
raise ValidationError(_("Unknown record.")) raise ValidationError(_("Unknown record type."))
def get_data(self): def __get_name(self):
retval = { 'name': self.name, 'type': self.type, 'ttl': self.ttl, if self.host and self.type != 'MX':
'address': self.address } if self.type in ['A', 'AAAA']:
if self.host and self.type in ['CNAME', 'A', 'AAAA']: return self.host.get_fqdn()
elif self.type == 'CNAME':
return self.name + '.' + unicode(self.domain)
else:
return self.name
else: # if self.host is None
if self.name:
return self.name + '.' + unicode(self.domain)
else:
return unicode(self.domain)
def __get_address(self):
if self.host:
if self.type == 'A': if self.type == 'A':
retval['address'] = (self.host.pub_ipv4 return (self.host.pub_ipv4
if self.host.pub_ipv4 and not self.host.shared_ip if self.host.pub_ipv4 and not self.host.shared_ip
else self.host.ipv4) else self.host.ipv4)
retval['name'] = self.host.get_fqdn()
elif self.type == 'AAAA': elif self.type == 'AAAA':
if not self.host.ipv6: return self.host.ipv6
return None
retval['address'] = self.host.ipv6
retval['name'] = self.host.get_fqdn()
elif self.type == 'CNAME': elif self.type == 'CNAME':
retval['address'] = self.host.get_fqdn() return self.host.get_fqdn()
retval['name'] = self.name + u'.' + unicode(self.domain) # otherwise:
else: return self.address
if not self.name:
retval['name'] = unicode(self.domain) def get_data(self):
else: name = self.__get_name()
retval['name'] = self.name + u'.' + unicode(self.domain) address = self.__get_address()
if not (retval['address'] and retval['name']): if self.host and self.type == 'AAAA' and not self.host.ipv6:
return None return None
return retval elif not address or not name:
return None
else:
return {'name': name,
'type': self.type,
'ttl': self.ttl,
'address': address}
class Blacklist(models.Model): class Blacklist(models.Model):
CHOICES_type = (('permban', 'permanent ban'), ('tempban', 'temporary ban'), ('whitelist', 'whitelist')) CHOICES_type = (('permban', 'permanent ban'), ('tempban', 'temporary ban'), ('whitelist', 'whitelist'), ('tempwhite', 'tempwhite'))
ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True) ipv4 = models.GenericIPAddressField(protocol='ipv4', unique=True)
host = models.ForeignKey('Host', blank=True, null=True)
reason = models.TextField(blank=True) reason = models.TextField(blank=True)
snort_message = models.TextField(blank=True) snort_message = models.TextField(blank=True)
type = models.CharField(max_length=10, choices=CHOICES_type, default='tempban') type = models.CharField(max_length=10, choices=CHOICES_type, default='tempban')
......
...@@ -19,44 +19,47 @@ def reload_dhcp_task(data): ...@@ -19,44 +19,47 @@ def reload_dhcp_task(data):
def reload_blacklist_task(data): def reload_blacklist_task(data):
pass pass
class Periodic(PeriodicTask):
run_every = timedelta(seconds=10)
def run(self, **kwargs):
if cache.get('dns_lock'):
cache.delete("dns_lock")
reload_dns_task.delay(dns())
print "dns ujratoltese kesz"
if cache.get('dhcp_lock'):
cache.delete("dhcp_lock")
reload_dhcp_task.delay(dhcp())
print "dhcp ujratoltese kesz"
if cache.get('firewall_lock'):
cache.delete("firewall_lock")
ipv4 = Firewall().get()
ipv6 = Firewall(True).get()
reload_firewall_task.delay(ipv4, ipv6)
print "firewall ujratoltese kesz"
if cache.get('blacklist_lock'):
cache.delete("blacklist_lock")
reload_blacklist_task.delay(list(ipset()))
print "blacklist ujratoltese kesz"
class ReloadTask(Task): class ReloadTask(Task):
def run(self, type='Host'): def run(self, type='Host'):
sleep=False
if type in ["Host", "Records", "Domain", "Vlan"]: if type in ["Host", "Records", "Domain", "Vlan"]:
lock = lambda: cache.add("dns_lock", "true", 9) cache.add("dns_lock", "true", 30)
if lock():
if not sleep:
sleep = True
time.sleep(10)
reload_dns_task.delay(dns())
if type == "Host": if type == "Host":
lock = lambda: cache.add("dhcp_lock", "true", 9) cache.add("dhcp_lock", "true", 30)
if lock():
if not sleep:
sleep = True
time.sleep(10)
reload_dhcp_task.delay(dhcp())
if type in ["Host", "Rule", "Firewall"]: if type in ["Host", "Rule", "Firewall"]:
lock = lambda: cache.add("firewall_lock", "true", 9) cache.add("firewall_lock", "true", 30)
if lock():
if not sleep:
sleep = True
time.sleep(10)
ipv4 = firewall().get()
ipv6 = firewall(True).get()
reload_firewall_task.delay(ipv4, ipv6)
if type == "Blacklist": if type == "Blacklist":
lock = lambda: cache.add("blacklist_lock", "true", 9) cache.add("blacklist_lock", "true", 30)
if lock():
if not sleep:
sleep = True
time.sleep(10)
reload_blacklist_task.delay(list(ipset()))
print type print type
...@@ -16,21 +16,19 @@ class MockGroups: ...@@ -16,21 +16,19 @@ class MockGroups:
def all(self): def all(self):
return self.groups return self.groups
class HostAdminNoGroupTestCase(TestCase): class HostAdminTestCase(TestCase):
def runTest(self): def test_no_groups(self):
instance = MockInstance([]) instance = MockInstance([])
l = HostAdmin.groups_l(instance) l = HostAdmin.list_groups(instance)
self.assertEqual(l, "") self.assertEqual(l, "")
class HostAdminSingleGroupTestCase(TestCase): def test_sigle_group(self):
def runTest(self):
instance = MockInstance([MockGroup("alma")]) instance = MockInstance([MockGroup("alma")])
l = HostAdmin.groups_l(instance) l = HostAdmin.list_groups(instance)
self.assertEqual(l, "alma") self.assertEqual(l, "alma")
class HostAdminMultipleGroupsTestCase(TestCase): def test_multiple_groups(self):
def runTest(self):
instance = MockInstance([MockGroup("alma"), instance = MockInstance([MockGroup("alma"),
MockGroup("korte"), MockGroup("szilva")]) MockGroup("korte"), MockGroup("szilva")])
l = HostAdmin.groups_l(instance) l = HostAdmin.list_groups(instance)
self.assertEqual(l, "alma, korte, szilva") self.assertEqual(l, "alma, korte, szilva")
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import render_to_response
from firewall.models import * from firewall.models import *
from firewall.fw import * from firewall.fw import *
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
...@@ -9,23 +8,27 @@ from django.db import IntegrityError ...@@ -9,23 +8,27 @@ from django.db import IntegrityError
from tasks import * from tasks import *
from celery.task.control import inspect from celery.task.control import inspect
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.template.loader import render_to_string
from cloud.settings import CLOUD_URL as url
from django.utils import translation
import re import re
import base64 import base64
import json import json
import sys import sys
import datetime
from django.utils.timezone import utc
from one.tasks import SendMailTask
def reload_firewall(request): def reload_firewall(request):
if request.user.is_authenticated(): if request.user.is_authenticated():
if request.user.is_superuser: if request.user.is_superuser:
html = ((_("Dear %s, you've signed in as administrator!") % html = (_("Dear %s, you've signed in as administrator!<br />"
request.user.username) + "<br />" + "Reloading in 10 seconds...") % request.user.username)
_("Reloading in 10 seconds..."))
ReloadTask.delay() ReloadTask.delay()
else: else:
html = (_("Dear %s, you've signed in!") html = (_("Dear %s, you've signed in!") % request.user.username)
% request.user.username)
else: else:
html = _("Dear anonymous, you've not signed in yet!") html = _("Dear anonymous, you've not signed in yet!")
return HttpResponse(html) return HttpResponse(html)
...@@ -41,16 +44,29 @@ def firewall_api(request): ...@@ -41,16 +44,29 @@ def firewall_api(request):
if command == "blacklist": if command == "blacklist":
obj, created = Blacklist.objects.get_or_create(ipv4=data["ip"]) obj, created = Blacklist.objects.get_or_create(ipv4=data["ip"])
if created:
obj.reason=data["reason"] obj.reason=data["reason"]
obj.snort_message=data["snort_message"] obj.snort_message=data["snort_message"]
if created:
try:
obj.host = models.Host.objects.get(ipv4=data["ip"])
user = obj.host.owner
lang = user.person_set.all()[0].language
translation.activate(lang)
msg = render_to_string('mails/notification-ban-now.txt', { 'user': user, 'bl': obj, 'instance:': obj.host.instance_set.get(), 'url': url} )
SendMailTask.delay(to=obj.host.owner.email, subject='[IK Cloud] %s' % obj.host.instance_set.get().name, msg=msg, sender=u'cloud@ik.bme.hu')
except (Host.DoesNotExist, ValidationError, IntegrityError, AttributeError):
pass
print obj.modified_at + datetime.timedelta(minutes=5)
print datetime.datetime.utcnow().replace(tzinfo=utc)
if obj.type == 'tempwhite' and obj.modified_at + datetime.timedelta(minutes=1) < datetime.datetime.utcnow().replace(tzinfo=utc):
obj.type = 'tempban'
obj.save() obj.save()
return HttpResponse(unicode(_("OK"))); return HttpResponse(unicode(_("OK")))
if not (data["vlan"] == "vm-net" or data["vlan"] == "war"): if not (data["vlan"] == "vm-net" or data["vlan"] == "war"):
raise Exception(_("Only vm-net and war can be used.")) raise Exception(_("Only vm-net and war can be used."))
data["hostname"] = re.sub(r' ','_', data["hostname"]) data["hostname"] = re.sub(r' ', '_', data["hostname"])
if command == "create": if command == "create":
data["owner"] = "opennebula" data["owner"] = "opennebula"
...@@ -78,14 +94,13 @@ def firewall_api(request): ...@@ -78,14 +94,13 @@ def firewall_api(request):
host = models.Host.objects.get(hostname=data["hostname"], host = models.Host.objects.get(hostname=data["hostname"],
owner=owner) owner=owner)
host.del_rules()
host.delete() host.delete()
else: else:
raise Exception(_("Unknown command.")) raise Exception(_("Unknown command."))
except (ValidationError, IntegrityError, AttributeError, Exception) as e: except (ValidationError, IntegrityError, AttributeError, Exception) as e:
return HttpResponse(_("Something went wrong!\n%s\n") % e); return HttpResponse(_("Something went wrong!\n%s\n") % e)
except: except:
return HttpResponse(_("Something went wrong!\n")); return HttpResponse(_("Something went wrong!\n"))
return HttpResponse(unicode(_("OK"))); return HttpResponse(unicode(_("OK")))
...@@ -10,4 +10,4 @@ sed -i 's/^<volume user=.*//' /etc/security/pam_mount.conf.xml ...@@ -10,4 +10,4 @@ sed -i 's/^<volume user=.*//' /etc/security/pam_mount.conf.xml
rm -rf ~cloud/{.bash_history,.ssh/id_rsa} rm -rf ~cloud/{.bash_history,.ssh/id_rsa}
rm -rf ~root/{.bash_history} rm -rf ~root/{.bash_history}
rm -rf /etc/ssh/ssh_host_* rm -rf /etc/ssh/ssh_host_*
rm -rf /usr/NX/home/nx/.ssh/known_hosts
...@@ -3,6 +3,12 @@ ...@@ -3,6 +3,12 @@
echo "En vagyok a $0 !" echo "En vagyok a $0 !"
hostname "$HOSTNAME" hostname "$HOSTNAME"
echo "$HOSTNAME" > /etc/hostname
if [ "$DISTRO" == "ubuntu" ]; then
echo "$HOSTNAME" > /etc/hostname
fi
if [ "$DISTRO" == "redhat" ]; then
echo -e -n "NETWORKING=yes\nHOSTNAME=$HOSTNAME\n" > /etc/sysconfig/network
fi
sed "s/\(127\.0\.1\.1\).*/\1\t$HOSTNAME/" -i /etc/hosts sed "s/\(127\.0\.1\.1\).*/\1\t$HOSTNAME/" -i /etc/hosts
...@@ -13,6 +13,7 @@ echo ok "$ipv4 $ipv6 $gw4 $gw6" ...@@ -13,6 +13,7 @@ echo ok "$ipv4 $ipv6 $gw4 $gw6"
/etc/init.d/network-manager stop /etc/init.d/network-manager stop
ifdown eth0 || ifconfig eth0 0 down ifdown eth0 || ifconfig eth0 0 down
if [ "$DISTRO" == "ubuntu" ]; then
cat > /etc/network/interfaces << EOF cat > /etc/network/interfaces << EOF
auto lo auto lo
iface lo inet loopback iface lo inet loopback
...@@ -30,4 +31,28 @@ EOF ...@@ -30,4 +31,28 @@ EOF
ifup eth0 ifup eth0
fi
if [ "$DISTRO" == "redhat" ]; then
cat > /etc/sysconfig/network-scripts/ifcfg-eth0 << EOF
DEVICE="eth0"
BOOTPROTO="none"
IPV6INIT="yes"
NM_CONTROLLED="no"
ONBOOT="yes"
TYPE="Ethernet"
DNS1="152.66.243.60"
PEERDNS="yes"
IPADDR="$ipv4"
NETMASK="255.255.0.0"
GATEWAY=$gw4
IPV6ADDR="$ipv6/80"
IPV6_DEFAULTGW="$gw6"
EOF
ifup eth0
fi
...@@ -5,8 +5,14 @@ echo "En vagyok a $0 !" ...@@ -5,8 +5,14 @@ echo "En vagyok a $0 !"
mkdir -p "$HOME/.ssh" mkdir -p "$HOME/.ssh"
echo "$SSHPRIV" > $HOME/.ssh/id_rsa echo "$SSHPRIV" > $HOME/.ssh/id_rsa
chmod 600 "$HOME/.ssh/id_rsa" chmod 600 "$HOME/.ssh/id_rsa"
echo "$SSHPUB" >> "$HOME/.ssh/authorized_keys"
mkdir "$HOME/sshfs" mkdir "$HOME/sshfs"
chown "$USER:$USER" -R "$HOME" chown "$USER:$USER" -R "$HOME"
sed -i 's/^<volume user=.*//' /etc/security/pam_mount.conf.xml sed -i 's/^sshfs.*//' /etc/fstab
sed -i "s/^\(<\/pam_mount>.*\)/<volume user=\"$USER\" fstype=\"fuse\" path=\"sshfs#${NEPTUN}@${SERVER}:home\" mountpoint=\"~\/sshfs\" options=\"nonempty,reconnect,StrictHostKeyChecking=no\" \/>\n\1/" /etc/security/pam_mount.conf.xml cat >> /etc/fstab <<END
sshfs#${NEPTUN}@${SERVER}:home $HOME/sshfs fuse defaults,idmap=user,reconnect,_netdev,uid=1000,gid=1000,allow_other,StrictHostKeyChecking=no,IdentityFile=$HOME/.ssh/id_rsa 0 0
END
mount "$HOME/sshfs"
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
echo "En vagyok a $0 !" echo "En vagyok a $0 !"
wget -q -O /dev/null "$BOOTURL" ( while ! wget -T 2 -t 1 -q --no-check-certificate -O /dev/null "$BOOTURL" ; do sleep 5; done ) &
disown $!
...@@ -4,6 +4,15 @@ export BASEDIR=$(dirname $0) ...@@ -4,6 +4,15 @@ export BASEDIR=$(dirname $0)
export USER="cloud" export USER="cloud"
export HOME=$(awk -F: -v u=$USER '$1==u{print $6}' /etc/passwd) export HOME=$(awk -F: -v u=$USER '$1==u{print $6}' /etc/passwd)
if [ -f /etc/lsb-release ]; then
export DISTRO=ubuntu
fi
if [ -f /etc/redhat-release ]; then
export DISTRO=redhat
fi
echo $DISTRO
mkdir -p "$BASEDIR/mnt" mkdir -p "$BASEDIR/mnt"
cd "$BASEDIR" cd "$BASEDIR"
......
...@@ -16,40 +16,5 @@ ...@@ -16,40 +16,5 @@
"email": "", "email": "",
"date_joined": "2013-01-16T12:36:01Z" "date_joined": "2013-01-16T12:36:01Z"
} }
},
{
"pk": 9,
"model": "one.template",
"fields": {
"name": "Ubuntu 12.04 desktop",
"created_at": "2013-01-31T10:11:08Z",
"access_type": "nx",
"instance_type": 3,
"owner": 1,
"disk": 1,
"network": 2
}
},
{
"pk": 10,
"model": "one.template",
"fields": {
"name": "Windows 7",
"created_at": "2013-01-31T10:11:21Z",
"access_type": "rdp",
"instance_type": 2,
"owner": 1,
"disk": 1,
"network": 2
}
},
{
"pk": 2,
"model": "one.network",
"fields": {
"name": "VM-NET",
"nat": true,
"public": false
}
} }
] ]
...@@ -5,15 +5,15 @@ for i in cloudstore toplist django ...@@ -5,15 +5,15 @@ for i in cloudstore toplist django
do do
sudo stop $i || true sudo stop $i || true
done done
set -x
cd /opt/webadmin/cloud sudo apt-get install rabbitmq-server gettext
./manage.py syncdb --noinput sudo rabbitmqctl delete_user guest || true
./manage.py migrate sudo rabbitmqctl add_user nyuszi teszt || true
./manage.py loaddata miscellaneous/dump.json sudo rabbitmqctl add_vhost django || true
./manage.py loaddata miscellaneous/devenv/dev.json sudo rabbitmqctl set_permissions -p django nyuszi '.*' '.*' '.*' || true
./manage.py update
./manage.py loaddata miscellaneous/devenv/dev.json
set +x sudo cp /opt/webadmin/cloud/miscellaneous/devenv/boot_url.py /opt/
#Set up store server #Set up store server
rm -rf /var/www/* rm -rf /var/www/*
...@@ -44,6 +44,18 @@ do ...@@ -44,6 +44,18 @@ do
sudo start $i sudo start $i
done done
set -x
cd /opt/webadmin/cloud
./manage.py syncdb --noinput
./manage.py migrate
./manage.py loaddata miscellaneous/dump.json
./manage.py loaddata miscellaneous/devenv/dev.json
./manage.py update
./manage.py loaddata miscellaneous/devenv/dev.json
set +x
cd /opt/webadmin/cloud/miscellaneous/devenv cd /opt/webadmin/cloud/miscellaneous/devenv
sudo cp vimrc.local /etc/vim/vimrc.local sudo cp vimrc.local /etc/vim/vimrc.local
...@@ -52,16 +64,11 @@ sudo cp vimrc.local /etc/vim/vimrc.local ...@@ -52,16 +64,11 @@ sudo cp vimrc.local /etc/vim/vimrc.local
cd /opt/webadmin/cloud cd /opt/webadmin/cloud
./manage.py changepassword test ./manage.py changepassword test
git config --global alias.prettylog 'log --graph --all --decorate --date-order --pretty="%C(yellow)%h%Cred%d%Creset - %C(cyan)%an %Creset: %s %Cgreen(%cr)"' git config --global alias.prettylog 'log --graph --all --decorate --date-order --pretty="%C(yellow)%h%Cred%d%Creset - %C(cyan)%an %Creset: %s %Cgreen(%ar)"'
git config --global alias.civ 'commit --interactive --verbose'
git config --global color.ui true git config --global color.ui true
git config --global core.editor vim git config --global core.editor vim
true true
sudo apt-get install rabbitmq-server
sudo rabbitmqctl delete_user guest
sudo rabbitmqctl add_user nyuszi teszt
sudo rabbitmqctl add_vhost django
sudo rabbitmqctl set_permissions -p django nyuszi '.*' '.*' '.*'
...@@ -7,4 +7,6 @@ set et ...@@ -7,4 +7,6 @@ set et
set sw=4 set sw=4
set ai set ai
set smarttab set smarttab
set textwidth=76
set colorcolumn=76
...@@ -138,12 +138,12 @@ ...@@ -138,12 +138,12 @@
"model": "auth.user", "model": "auth.user",
"fields": { "fields": {
"username": "test", "username": "test",
"first_name": "Teszt", "first_name": "",
"last_name": "Elek", "last_name": "",
"is_active": true, "is_active": true,
"is_superuser": true, "is_superuser": true,
"is_staff": true, "is_staff": true,
"last_login": "2013-02-15T23:25:57Z", "last_login": "2013-03-01T18:37:22Z",
"groups": [], "groups": [],
"user_permissions": [], "user_permissions": [],
"email": "", "email": "",
...@@ -341,6 +341,227 @@ ...@@ -341,6 +341,227 @@
}, },
{ {
"pk": 1, "pk": 1,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 1,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 1
}
},
{
"pk": 2,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 2,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 2
}
},
{
"pk": 3,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 3,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 3
}
},
{
"pk": 4,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 4,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 4
}
},
{
"pk": 5,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 5,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 5
}
},
{
"pk": 6,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 6,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 6
}
},
{
"pk": 7,
"model": "one.userclouddetails",
"fields": {
"share_quota": 100,
"ssh_key": 7,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 7
}
},
{
"pk": 8,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 8,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 12
}
},
{
"pk": 9,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 9,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 13
}
},
{
"pk": 10,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 10,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 14
}
},
{
"pk": 11,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 11,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 15
}
},
{
"pk": 12,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 12,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 16
}
},
{
"pk": 13,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 13,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 17
}
},
{
"pk": 14,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 14,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 18
}
},
{
"pk": 15,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 15,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 20
}
},
{
"pk": 16,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 16,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 21
}
},
{
"pk": 17,
"model": "one.userclouddetails",
"fields": {
"share_quota": 0,
"ssh_key": 17,
"disk_quota": 2048,
"instance_quota": 20,
"ssh_private_key": "-----xxx PRIVATE KEY-----",
"smb_password": "kamu",
"user": 22
}
},
{
"pk": 1,
"model": "one.sshkey", "model": "one.sshkey",
"fields": { "fields": {
"user": 1, "user": 1,
...@@ -556,193 +777,47 @@ ...@@ -556,193 +777,47 @@
} }
}, },
{ {
"pk": 11, "pk": 2,
"model": "one.share",
"fields": {
"group": 1,
"name": "Ubuntu 12s.04 desktop",
"created_at": "2013-02-11T14:35:46Z",
"instance_limit": 10,
"template": 17,
"owner": 7,
"per_user_limit": 1,
"type": "LAB",
"description": ""
}
},
{
"pk": 13,
"model": "one.share",
"fields": {
"group": 1,
"name": "Ubuntu 12s.04 desktop",
"created_at": "2013-02-12T10:05:08Z",
"instance_limit": 2,
"template": 17,
"owner": 7,
"per_user_limit": 4,
"type": "LAB",
"description": ""
}
},
{
"pk": 15,
"model": "one.share",
"fields": {
"group": 2,
"name": "Ubuntu 12s.04 desktop",
"created_at": "2013-02-12T20:36:46Z",
"instance_limit": 10,
"template": 17,
"owner": 7,
"per_user_limit": 1,
"type": "LAB",
"description": ""
}
},
{
"pk": 16,
"model": "one.share",
"fields": {
"group": 2,
"name": "Windows 7",
"created_at": "2013-02-12T20:38:33Z",
"instance_limit": 10,
"template": 10,
"owner": 7,
"per_user_limit": 1,
"type": "LAB",
"description": "Ez j\u00f3 cuccos"
}
},
{
"pk": 17,
"model": "one.share", "model": "one.share",
"fields": { "fields": {
"group": 2, "group": 2,
"name": "Windows 7", "name": "Ubuntu 12.04 Min",
"created_at": "2013-02-12T20:38:36Z", "created_at": "2013-03-01T17:03:01Z",
"instance_limit": 10, "instance_limit": 10,
"template": 10, "template": 11,
"owner": 7, "owner": 7,
"per_user_limit": 1, "per_user_limit": 10,
"type": "LAB", "type": "LAB",
"description": "Ez j\u00f3 cuccos" "description": "This is the basic test image for the developer environment."
}
},
{
"pk": 1,
"model": "one.disk",
"fields": {
"name": "Copy of ttylinux - kvm"
}
},
{
"pk": 2,
"model": "one.disk",
"fields": {
"name": "template-10"
}
},
{
"pk": 3,
"model": "one.disk",
"fields": {
"name": "template-11-298"
} }
}, },
{ {
"pk": 4, "pk": 4,
"model": "one.disk", "model": "one.disk",
"fields": { "fields": {
"name": "template-12-300" "name": "MinimalISO-Ubuntu"
} }
}, },
{ {
"pk": 5, "pk": 3,
"model": "one.disk", "model": "one.disk",
"fields": { "fields": {
"name": "template-13-301" "name": "ttylinux-iperf"
} }
}, },
{ {
"pk": 6, "pk": 6,
"model": "one.disk", "model": "one.disk",
"fields": { "fields": {
"name": "template-14-303" "name": "Ubuntu install"
} }
}, },
{ {
"pk": 7, "pk": 3,
"model": "one.disk",
"fields": {
"name": "template-15-308"
}
},
{
"pk": 8,
"model": "one.disk",
"fields": {
"name": "template-16-309"
}
},
{
"pk": 9,
"model": "one.disk",
"fields": {
"name": "template-17-310"
}
},
{
"pk": 10,
"model": "one.disk",
"fields": {
"name": "template-19-318"
}
},
{
"pk": 11,
"model": "one.disk",
"fields": {
"name": "template-21-321"
}
},
{
"pk": 12,
"model": "one.disk",
"fields": {
"name": "template-29-326"
}
},
{
"pk": 13,
"model": "one.disk",
"fields": {
"name": "template-31-330"
}
},
{
"pk": 14,
"model": "one.disk",
"fields": {
"name": "template-32-331"
}
},
{
"pk": 2,
"model": "one.network",
"fields": {
"name": "VM-NET",
"nat": true,
"public": false
}
},
{
"pk": 1,
"model": "one.network", "model": "one.network",
"fields": { "fields": {
"name": "wifi", "name": "vm-net",
"nat": true, "nat": false,
"public": false "public": false
} }
}, },
...@@ -777,522 +852,304 @@ ...@@ -777,522 +852,304 @@
} }
}, },
{ {
"pk": 9, "pk": 11,
"model": "one.template",
"fields": {
"name": "Ubuntu 12.04 desktop",
"created_at": "2013-01-31T10:11:08Z",
"description": "",
"system": "",
"access_type": "nx",
"instance_type": 3,
"state": "NEW",
"owner": 1,
"disk": 1,
"public": true,
"network": 2
}
},
{
"pk": 10,
"model": "one.template",
"fields": {
"name": "Windows 7",
"created_at": "2013-01-31T10:11:21Z",
"description": "Ez j\u00f3 cuccos",
"system": "Windows 7 Entersp\u00e1jzi 64 bites",
"access_type": "rdp",
"instance_type": 2,
"state": "READY",
"owner": 1,
"disk": 1,
"public": true,
"network": 2
}
},
{
"pk": 17,
"model": "one.template",
"fields": {
"name": "Ubuntu 12s.04 desktop",
"created_at": "2013-02-10T21:45:05Z",
"description": "",
"system": "",
"access_type": "nx",
"instance_type": 2,
"state": "READY",
"owner": 7,
"disk": 9,
"public": false,
"network": 2
}
},
{
"pk": 19,
"model": "one.template",
"fields": {
"name": "Ubuntu 12.04 desktop a",
"created_at": "2013-02-12T14:45:50Z",
"description": "h",
"system": "",
"access_type": "nx",
"instance_type": 2,
"state": "READY",
"owner": 7,
"disk": 10,
"public": false,
"network": 2
}
},
{
"pk": 21,
"model": "one.template",
"fields": {
"name": "Windows 7asdasd",
"created_at": "2013-02-12T20:31:13Z",
"description": "Ez j\u00f3 cuccos \u00e9s nagy l\u00f3fasz",
"system": "Windows 7 Entersp\u00e1jzi 64 bites",
"access_type": "rdp",
"instance_type": 1,
"state": "READY",
"owner": 7,
"disk": 11,
"public": false,
"network": 2
}
},
{
"pk": 29,
"model": "one.template", "model": "one.template",
"fields": { "fields": {
"name": "Ubuntu 12.04 desktop 22", "name": "Ubuntu 12.04 Min",
"created_at": "2013-02-12T23:59:54Z", "created_at": "2013-03-01T16:24:14Z",
"description": "", "description": "This is the basic test image for the developer environment.",
"system": "", "system": "Ubuntu 12.04",
"access_type": "nx", "access_type": "ssh",
"instance_type": 3, "instance_type": 3,
"state": "READY", "state": "READY",
"owner": 7, "owner": 7,
"disk": 12, "disk": 6,
"public": false, "public": true,
"network": 2 "network": 3
}
},
{
"pk": 32,
"model": "one.template",
"fields": {
"name": "Windows 7asdasd 30",
"created_at": "2013-02-13T00:40:52Z",
"description": "Ez j\u00f3 cuccos \u00e9s nagy l\u00f3fasz",
"system": "Windows 7 Entersp\u00e1jzi 64 bites",
"access_type": "rdp",
"instance_type": 1,
"state": "READY",
"owner": 7,
"disk": 14,
"public": false,
"network": 2
} }
}, },
{ {
"pk": 307, "pk": 1,
"model": "one.instance", "model": "one.instance",
"fields": { "fields": {
"name": "test Windows 7 (50)", "name": "test Ubuntu 12.04 Min (43)",
"time_of_suspend": null, "time_of_suspend": "2013-03-01T21:24:43Z",
"ip": "10.9.1.14", "ip": "192.168.1.11",
"created_at": "2013-02-10T21:31:53Z", "created_at": "2013-03-01T16:25:31Z",
"share": null, "share": null,
"waiting": false, "waiting": false,
"firewall_host": null, "firewall_host": null,
"active_since": null, "active_since": "2013-03-01T16:24:53Z",
"state": "DONE", "state": "DONE",
"template": 10, "template": 11,
"owner": 7, "owner": 7,
"time_of_delete": null, "time_of_delete": "2013-03-16T16:24:43Z",
"one_id": 50, "one_id": 43,
"pw": "VqKJq3hFLV" "pw": "CbD7ExQZQz"
} }
}, },
{ {
"pk": 310, "pk": 2,
"model": "one.instance", "model": "one.instance",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (53)", "name": "test Ubuntu 12.04 Min (44)",
"time_of_suspend": null, "time_of_suspend": "2013-03-01T21:28:39Z",
"ip": "10.9.1.15", "ip": "192.168.1.10",
"created_at": "2013-02-10T21:45:05Z", "created_at": "2013-03-01T16:28:39Z",
"share": null, "share": null,
"waiting": false, "waiting": false,
"firewall_host": null, "firewall_host": 872,
"active_since": null, "active_since": null,
"state": "DONE", "state": "DONE",
"template": 17, "template": 11,
"owner": 7, "owner": 7,
"time_of_delete": null, "time_of_delete": "2013-03-16T16:28:39Z",
"one_id": 53, "one_id": 44,
"pw": "WdwrHAxtPj" "pw": "b2GdusYand"
} }
}, },
{ {
"pk": 312, "pk": 5,
"model": "one.instance", "model": "one.instance",
"fields": { "fields": {
"name": "test Windows 7 (55)", "name": "test Ubuntu 12.04 Min (47)",
"time_of_suspend": null, "time_of_suspend": "2013-03-01T21:44:30Z",
"ip": "10.9.1.15", "ip": "192.168.1.11",
"created_at": "2013-02-11T13:06:54Z", "created_at": "2013-03-01T16:54:49Z",
"share": null, "share": null,
"waiting": false, "waiting": false,
"firewall_host": null, "firewall_host": null,
"active_since": null, "active_since": "2013-03-01T16:44:53Z",
"state": "DONE", "state": "DONE",
"template": 10, "template": 11,
"owner": 7, "owner": 7,
"time_of_delete": null, "time_of_delete": "2013-03-16T16:44:30Z",
"one_id": 55, "one_id": 47,
"pw": "2cDZdDjkP8" "pw": "rpRaZwaQDD"
} }
}, },
{ {
"pk": 314, "pk": 6,
"model": "one.instance", "model": "one.instance",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (57)", "name": "test Ubuntu 12.04 Min (48)",
"time_of_suspend": "2013-02-12T15:00:35Z", "time_of_suspend": "2013-03-01T21:45:48Z",
"ip": "10.9.1.16", "ip": "192.168.1.12",
"created_at": "2013-02-12T19:36:54Z", "created_at": "2013-03-01T16:54:52Z",
"share": 11, "share": null,
"waiting": false, "waiting": false,
"firewall_host": null, "firewall_host": null,
"active_since": null, "active_since": "2013-03-01T16:45:52Z",
"state": "DONE", "state": "DONE",
"template": 17, "template": 11,
"owner": 7, "owner": 7,
"time_of_delete": "2013-02-27T10:00:35Z", "time_of_delete": "2013-03-16T16:45:48Z",
"one_id": 57, "one_id": 48,
"pw": "YLNvyFBMNa" "pw": "VuWps4bkuW"
} }
}, },
{ {
"pk": 315, "pk": 1,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (58)", "code": "root",
"time_of_suspend": "2013-02-12T15:01:35Z", "user": null,
"ip": "10.9.1.17", "language": "hu"
"created_at": "2013-02-12T21:57:50Z",
"share": 11,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 17,
"owner": 7,
"time_of_delete": "2013-02-27T10:01:35Z",
"one_id": 58,
"pw": "mfQk6wxMJB"
} }
}, },
{ {
"pk": 316, "pk": 2,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (59)", "code": "bd",
"time_of_suspend": "2013-02-12T15:05:22Z", "user": null,
"ip": "10.9.1.18", "language": "hu"
"created_at": "2013-02-12T22:33:18Z", }
"share": 13, },
"waiting": false, {
"firewall_host": null, "pk": 3,
"active_since": null, "model": "school.person",
"state": "DONE", "fields": {
"template": 17, "code": "mate",
"owner": 7, "user": null,
"time_of_delete": "2013-02-27T10:05:22Z", "language": "hu"
"one_id": 59, }
"pw": "fdrrRxm33W" },
{
"pk": 4,
"model": "school.person",
"fields": {
"code": "tarokkk",
"user": null,
"language": "hu"
}
},
{
"pk": 5,
"model": "school.person",
"fields": {
"code": "opennebula",
"user": null,
"language": "hu"
}
},
{
"pk": 6,
"model": "school.person",
"fields": {
"code": "lennon",
"user": null,
"language": "hu"
} }
}, },
{ {
"pk": 317, "pk": 7,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (60)", "code": "test",
"time_of_suspend": "2013-02-13T01:14:28Z", "user": 7,
"ip": "10.9.1.19", "language": "hu"
"created_at": "2013-02-12T20:43:59Z",
"share": 13,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 17,
"owner": 7,
"time_of_delete": "2013-02-27T20:14:42Z",
"one_id": 60,
"pw": "WZ6pQatURa"
} }
}, },
{ {
"pk": 318, "pk": 8,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12.04 desktop a (61)", "code": "JI1M92",
"time_of_suspend": "2013-02-12T19:45:50Z", "user": null,
"ip": "10.9.1.20", "language": "hu"
"created_at": "2013-02-12T23:25:17Z",
"share": null,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 19,
"owner": 7,
"time_of_delete": "2013-02-27T14:45:50Z",
"one_id": 61,
"pw": "zpYJBjErtQ"
} }
}, },
{ {
"pk": 320, "pk": 9,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (63)", "code": "TFDAZ6",
"time_of_suspend": "2013-02-13T01:30:46Z", "user": null,
"ip": "10.9.1.22", "language": "hu"
"created_at": "2013-02-12T23:36:02Z",
"share": null,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 17,
"owner": 7,
"time_of_delete": "2013-02-27T20:30:46Z",
"one_id": 63,
"pw": "wZRvZZXbxd"
} }
}, },
{ {
"pk": 321, "pk": 10,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Windows 7asdasd (64)", "code": "K7YLW5",
"time_of_suspend": "2013-02-13T01:31:13Z", "user": null,
"ip": "10.9.1.23", "language": "hu"
"created_at": "2013-02-12T23:33:09Z",
"share": null,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 21,
"owner": 7,
"time_of_delete": "2013-02-27T20:31:13Z",
"one_id": 64,
"pw": "6y6Mbh779P"
} }
}, },
{ {
"pk": 324, "pk": 11,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Windows 7 (67)", "code": "UYD1S5",
"time_of_suspend": "2013-02-13T01:44:44Z", "user": null,
"ip": "10.9.1.26", "language": "hu"
"created_at": "2013-02-12T22:33:49Z",
"share": null,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 10,
"owner": 7,
"time_of_delete": "2013-02-27T20:44:44Z",
"one_id": 67,
"pw": "YjQxeHaNkh"
} }
}, },
{ {
"pk": 326, "pk": 12,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12.04 desktop 22 (69)", "code": "FFRUNU",
"time_of_suspend": "2013-02-13T04:59:54Z", "user": null,
"ip": "10.9.1.27", "language": "hu"
"created_at": "2013-02-12T23:59:54Z",
"share": null,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 29,
"owner": 7,
"time_of_delete": "2013-02-27T23:59:54Z",
"one_id": 69,
"pw": "yXuM8pSNCZ"
} }
}, },
{ {
"pk": 328, "pk": 13,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (71)", "code": "HUT3L3",
"time_of_suspend": "2013-02-13T05:14:35Z", "user": null,
"ip": "10.9.1.27", "language": "hu"
"created_at": "2013-02-13T00:15:24Z",
"share": 11,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 17,
"owner": 7,
"time_of_delete": "2013-02-28T00:14:35Z",
"one_id": 71,
"pw": "KmP82kfFp6"
} }
}, },
{ {
"pk": 329, "pk": 14,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12.04 desktop a (72)", "code": "ORL3EA",
"time_of_suspend": "2013-02-13T05:18:34Z", "user": null,
"ip": "10.9.1.27", "language": "hu"
"created_at": "2013-02-13T00:18:59Z",
"share": null,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 19,
"owner": 7,
"time_of_delete": "2013-02-28T00:18:34Z",
"one_id": 72,
"pw": "99czHqQFp6"
} }
}, },
{ {
"pk": 331, "pk": 15,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Windows 7asdasd 30 (74)", "code": "B6AFNQ",
"time_of_suspend": "2013-02-13T05:40:52Z", "user": null,
"ip": "10.9.1.27", "language": "hu"
"created_at": "2013-02-13T00:40:52Z",
"share": null,
"waiting": false,
"firewall_host": null,
"active_since": "2013-02-13T00:42:18Z",
"state": "DONE",
"template": 32,
"owner": 7,
"time_of_delete": "2013-02-28T00:40:52Z",
"one_id": 74,
"pw": "2YPTmTzHsR"
} }
}, },
{ {
"pk": 332, "pk": 16,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (75)", "code": "UKWBFI",
"time_of_suspend": "2013-02-13T05:42:34Z", "user": null,
"ip": "10.9.1.27", "language": "hu"
"created_at": "2013-02-13T00:42:34Z",
"share": 11,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 17,
"owner": 7,
"time_of_delete": "2013-02-28T00:42:34Z",
"one_id": 75,
"pw": "RZfD72Jgmn"
} }
}, },
{ {
"pk": 333, "pk": 17,
"model": "one.instance", "model": "school.person",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (76)", "code": "K2JL24",
"time_of_suspend": "2013-02-13T05:54:47Z", "user": null,
"ip": "10.9.1.28", "language": "hu"
"created_at": "2013-02-13T00:54:47Z",
"share": null,
"waiting": false,
"firewall_host": 843,
"active_since": null,
"state": "DONE",
"template": 17,
"owner": 7,
"time_of_delete": "2013-02-28T00:54:47Z",
"one_id": 76,
"pw": "HnYSzsMxZX"
} }
}, },
{ {
"pk": 347, "pk": 1,
"model": "one.instance", "model": "school.semester",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (79)", "start": "2013-02-01",
"time_of_suspend": null, "end": "2013-06-01",
"ip": "10.9.1.31", "name": "asd"
"created_at": "2013-02-15T23:35:45Z",
"share": 11,
"waiting": false,
"firewall_host": null,
"active_since": null,
"state": "DONE",
"template": 17,
"owner": 7,
"time_of_delete": null,
"one_id": 79,
"pw": "6CaERLLwLg"
} }
}, },
{ {
"pk": 372, "pk": 1,
"model": "one.instance", "model": "school.group",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (104)", "course": null,
"time_of_suspend": "2013-02-19T23:34:19Z", "semester": 1,
"ip": "10.9.1.14", "owners": [],
"created_at": "2013-02-19T18:34:19Z", "name": "asd",
"share": 11, "members": []
"waiting": false,
"firewall_host": 877,
"active_since": null,
"state": "ACTIVE",
"template": 17,
"owner": 7,
"time_of_delete": "2013-03-06T18:34:19Z",
"one_id": 104,
"pw": "U4XAAEhDRT"
} }
}, },
{ {
"pk": 374, "pk": 2,
"model": "one.instance", "model": "school.group",
"fields": { "fields": {
"name": "test Ubuntu 12s.04 desktop (105)", "course": null,
"time_of_suspend": "2013-02-19T23:43:17Z", "semester": 1,
"ip": "10.9.1.15", "owners": [
"created_at": "2013-02-19T18:43:17Z", 7
"share": 13, ],
"waiting": false, "name": "asd",
"firewall_host": 878, "members": [
"active_since": null, 1,
"state": "PENDING", 2,
"template": 17, 3,
"owner": 7, 4,
"time_of_delete": "2013-03-06T18:43:17Z", 5,
"one_id": 105, 6,
"pw": "55W5neEvpx" 7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17
]
} }
}, },
{ {
...@@ -2371,57 +2228,7 @@ ...@@ -2371,57 +2228,7 @@
} }
}, },
{ {
"pk": 1262, "pk": 1217,
"model": "firewall.rule",
"fields": {
"r_type": "host",
"direction": "1",
"vlan": null,
"description": "",
"proto": "tcp",
"firewall": null,
"created_at": "2013-02-13T00:54:47Z",
"extra": "",
"modified_at": "2013-02-13T00:54:47Z",
"owner": 7,
"accept": true,
"dport": 22284,
"host": 843,
"nat_dport": 22,
"hostgroup": null,
"nat": true,
"foreign_network": 2,
"sport": null,
"vlangroup": null
}
},
{
"pk": 1263,
"model": "firewall.rule",
"fields": {
"r_type": "host",
"direction": "1",
"vlan": null,
"description": "",
"proto": "tcp",
"firewall": null,
"created_at": "2013-02-19T18:40:00Z",
"extra": "",
"modified_at": "2013-02-19T18:40:00Z",
"owner": 7,
"accept": true,
"dport": 22270,
"host": 877,
"nat_dport": 22,
"hostgroup": null,
"nat": true,
"foreign_network": 2,
"sport": null,
"vlangroup": null
}
},
{
"pk": 1264,
"model": "firewall.rule", "model": "firewall.rule",
"fields": { "fields": {
"r_type": "host", "r_type": "host",
...@@ -2430,16 +2237,16 @@ ...@@ -2430,16 +2237,16 @@
"description": "", "description": "",
"proto": "tcp", "proto": "tcp",
"firewall": null, "firewall": null,
"created_at": "2013-02-19T18:43:17Z", "created_at": "2013-03-01T16:28:39Z",
"extra": "", "extra": "",
"modified_at": "2013-02-19T18:43:17Z", "modified_at": "2013-03-01T16:28:39Z",
"owner": 7, "owner": 7,
"accept": true, "accept": true,
"dport": 22271, "dport": 22,
"host": 878, "host": 872,
"nat_dport": 22, "nat_dport": null,
"hostgroup": null, "hostgroup": null,
"nat": true, "nat": false,
"foreign_network": 2, "foreign_network": 2,
"sport": null, "sport": null,
"vlangroup": null "vlangroup": null
...@@ -4703,29 +4510,6 @@ ...@@ -4703,29 +4510,6 @@
} }
}, },
{ {
"pk": 843,
"model": "firewall.host",
"fields": {
"comment": "",
"vlan": 10,
"reverse": null,
"created_at": "2013-02-13T00:54:47Z",
"hostname": "id-333_user-test",
"modified_at": "2013-02-13T00:54:47Z",
"location": "",
"pub_ipv4": "152.66.243.62",
"mac": "02:00:0a:09:01:1c",
"shared_ip": true,
"ipv4": "10.9.1.28",
"groups": [
4
],
"ipv6": "2001:738:2001:4031:9:1:28:0",
"owner": 7,
"description": ""
}
},
{
"pk": 846, "pk": 846,
"model": "firewall.host", "model": "firewall.host",
"fields": { "fields": {
...@@ -4909,7 +4693,7 @@ ...@@ -4909,7 +4693,7 @@
"shared_ip": true, "shared_ip": true,
"ipv4": "10.9.1.111", "ipv4": "10.9.1.111",
"groups": [], "groups": [],
"ipv6": "21001:738:2001:4031:9:1:11:0", "ipv6": "2001:738:2001:4031:9:1:111:0",
"owner": 7, "owner": 7,
"description": "" "description": ""
} }
...@@ -4936,47 +4720,24 @@ ...@@ -4936,47 +4720,24 @@
} }
}, },
{ {
"pk": 877, "pk": 872,
"model": "firewall.host",
"fields": {
"comment": "",
"vlan": 10,
"reverse": null,
"created_at": "2013-02-19T18:34:19Z",
"hostname": "id-372_user-test",
"modified_at": "2013-02-19T18:34:19Z",
"location": "",
"pub_ipv4": "152.66.243.62",
"mac": "02:00:0a:09:01:0e",
"shared_ip": true,
"ipv4": "10.9.1.14",
"groups": [
4
],
"ipv6": "2001:738:2001:4031:9:1:14:0",
"owner": 7,
"description": ""
}
},
{
"pk": 878,
"model": "firewall.host", "model": "firewall.host",
"fields": { "fields": {
"comment": "", "comment": "",
"vlan": 10, "vlan": 10,
"reverse": null, "reverse": null,
"created_at": "2013-02-19T18:43:17Z", "created_at": "2013-03-01T16:28:39Z",
"hostname": "id-374_user-test", "hostname": "cloud-2",
"modified_at": "2013-02-19T18:43:17Z", "modified_at": "2013-03-01T16:28:39Z",
"location": "", "location": "",
"pub_ipv4": "152.66.243.62", "pub_ipv4": null,
"mac": "02:00:0a:09:01:0f", "mac": "02:00:c0:a8:01:0a",
"shared_ip": true, "shared_ip": false,
"ipv4": "10.9.1.15", "ipv4": "192.168.1.10",
"groups": [ "groups": [
4 4
], ],
"ipv6": "2001:738:2001:4031:9:1:15:0", "ipv6": "2001:738:2001:4031:168:1:10:0",
"owner": 7, "owner": 7,
"description": "" "description": ""
} }
...@@ -6357,79 +6118,15 @@ ...@@ -6357,79 +6118,15 @@
} }
}, },
{ {
"pk": 175, "pk": 105,
"model": "firewall.record",
"fields": {
"domain": 8,
"name": null,
"created_at": "2013-02-13T00:54:47Z",
"address": null,
"modified_at": "2013-02-13T00:54:47Z",
"host": 843,
"ttl": 600,
"owner": 7,
"type": "A",
"description": ""
}
},
{
"pk": 176,
"model": "firewall.record",
"fields": {
"domain": 8,
"name": null,
"created_at": "2013-02-13T00:54:47Z",
"address": null,
"modified_at": "2013-02-13T00:54:47Z",
"host": 843,
"ttl": 600,
"owner": 7,
"type": "AAAA",
"description": ""
}
},
{
"pk": 177,
"model": "firewall.record",
"fields": {
"domain": 8,
"name": null,
"created_at": "2013-02-19T18:40:00Z",
"address": null,
"modified_at": "2013-02-19T18:40:00Z",
"host": 877,
"ttl": 600,
"owner": 7,
"type": "A",
"description": ""
}
},
{
"pk": 178,
"model": "firewall.record",
"fields": {
"domain": 8,
"name": null,
"created_at": "2013-02-19T18:40:00Z",
"address": null,
"modified_at": "2013-02-19T18:40:00Z",
"host": 877,
"ttl": 600,
"owner": 7,
"type": "AAAA",
"description": ""
}
},
{
"pk": 179,
"model": "firewall.record", "model": "firewall.record",
"fields": { "fields": {
"domain": 8, "domain": 8,
"name": null, "name": null,
"created_at": "2013-02-19T18:43:17Z", "created_at": "2013-03-01T16:28:39Z",
"address": null, "address": null,
"modified_at": "2013-02-19T18:43:17Z", "modified_at": "2013-03-01T16:28:39Z",
"host": 878, "host": 872,
"ttl": 600, "ttl": 600,
"owner": 7, "owner": 7,
"type": "A", "type": "A",
...@@ -6437,15 +6134,15 @@ ...@@ -6437,15 +6134,15 @@
} }
}, },
{ {
"pk": 180, "pk": 106,
"model": "firewall.record", "model": "firewall.record",
"fields": { "fields": {
"domain": 8, "domain": 8,
"name": null, "name": null,
"created_at": "2013-02-19T18:43:17Z", "created_at": "2013-03-01T16:28:39Z",
"address": null, "address": null,
"modified_at": "2013-02-19T18:43:17Z", "modified_at": "2013-03-01T16:28:39Z",
"host": 878, "host": 872,
"ttl": 600, "ttl": 600,
"owner": 7, "owner": 7,
"type": "AAAA", "type": "AAAA",
...@@ -6939,6 +6636,15 @@ ...@@ -6939,6 +6636,15 @@
} }
}, },
{ {
"pk": 55,
"model": "south.migrationhistory",
"fields": {
"applied": "2013-02-25T18:31:52Z",
"app_name": "firewall",
"migration": "0028_auto__del_field_vlan_domain"
}
},
{
"pk": 56, "pk": 56,
"model": "south.migrationhistory", "model": "south.migrationhistory",
"fields": { "fields": {
...@@ -7011,6 +6717,15 @@ ...@@ -7011,6 +6717,15 @@
} }
}, },
{ {
"pk": 64,
"model": "south.migrationhistory",
"fields": {
"applied": "2013-03-01T16:20:57Z",
"app_name": "firewall",
"migration": "0031_auto__add_field_blacklist_snort_message__add_field_blacklist_type"
}
},
{
"pk": 7, "pk": 7,
"model": "django.queue", "model": "django.queue",
"fields": { "fields": {
......
#!/bin/bash #!/bin/bash
/opt/webadmin/cloud/manage.py dumpdata -e admin -e one.userclouddetails -e school -e auth.permission -e contenttypes -e sessions -e djcelery --format=json --indent=2|grep -v '"password":'|sed -e 's/^.*"smb_password":.*$/"smb_password": "kamu",/' -e 's/BEGIN RSA PRIVATE.*END RSA/xxx/' >/opt/webadmin/cloud/miscellaneous/dump.json /opt/webadmin/cloud/manage.py dumpdata -e admin -e auth.permission -e contenttypes -e sessions -e djcelery --format=json --indent=2|grep -v '"password":'|sed -e 's/^.*"smb_password":.*$/"smb_password": "kamu",/' -e 's/BEGIN RSA PRIVATE.*END RSA/xxx/' >/opt/webadmin/cloud/miscellaneous/dump.json
...@@ -6,11 +6,19 @@ import os ...@@ -6,11 +6,19 @@ import os
import sys import sys
import gtk import gtk
import gobject import gobject
from multiprocessing import Manager, Process
import threading
import signal
import time
class RDP: class RDP:
def __init__(self, uri): def __init__(self, uri):
gobject.threads_init() gobject.threads_init()
self.scheme, self.username, self.password, self.host, self.port = uri.split(':',4) self.scheme, self.username, self.password, self.host, self.port = uri.split(':',4)
self.manager = Manager()
self.global_vars = self.manager.Namespace()
self.global_vars.pid = 0
self.box = gtk.MessageDialog(parent=None, flags=gtk.DIALOG_MODAL, type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_CANCEL, message_format="Connecting to RDP...")
def dialog_box(self,text): def dialog_box(self,text):
# Window = gtk.Window() # Window = gtk.Window()
# Window.set_size_request(250, 100) # Window.set_size_request(250, 100)
...@@ -19,12 +27,27 @@ class RDP: ...@@ -19,12 +27,27 @@ class RDP:
# window.set_title("Message dialogs") # window.set_title("Message dialogs")
md = gtk.MessageDialog(parent=None, type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_CLOSE, message_format=text) md = gtk.MessageDialog(parent=None, type=gtk.MESSAGE_INFO, buttons=gtk.BUTTONS_CLOSE, message_format=text)
md.run() md.run()
print "After run"
md.destroy() md.destroy()
def connect(self): def connect(self):
#rdp:cloud:qYSv3eQJYY:152.66.243.62:23037 #rdp:cloud:qYSv3eQJYY:152.66.243.62:23037
if self.scheme == "rdp": if self.scheme == "rdp":
self.connect_rdp() #print self.global_vars.pid
p = threading.Thread(target=self.connect_rdp, args=[self.global_vars])
p.start()
while self.global_vars.pid == 0:
time.sleep(1)
#print "Rdesktop pid: "+str(self.global_vars.pid)
#print self.box
return_value = self.box.run()
#print "Box return value: "+str(return_value)
if return_value != -5:
#p.terminate()
if self.global_vars.pid > 0:
os.kill(self.global_vars.pid, signal.SIGKILL)
#print "Join"
p.join()
elif self.scheme == "nx": elif self.scheme == "nx":
self.connect_nx() self.connect_nx()
elif self.scheme == "sshterm": elif self.scheme == "sshterm":
...@@ -49,15 +72,13 @@ class RDP: ...@@ -49,15 +72,13 @@ class RDP:
except: except:
self.dialog_box("Unable to connect to host: "+self.host+" at port "+self.port) self.dialog_box("Unable to connect to host: "+self.host+" at port "+self.port)
def connect_rdp(self): def connect_rdp(self,global_vars):
rdp_command = ["rdesktop", "-khu", "-E", "-P", "-0", "-f", "-u", self.username, "-p", self.password, self.host+":"+self.port] rdp_command = ["rdesktop", "-khu", "-E", "-P", "-0", "-f", "-u", self.username, "-p", self.password, self.host+":"+self.port]
try: proc = subprocess.Popen(rdp_command, stdout = subprocess.PIPE)
proc = subprocess.check_call(rdp_command, stdout = subprocess.PIPE) global_vars.pid = proc.pid
except subprocess.CalledProcessError as e: proc.wait()
if e.returncode != 1: self.box.response(-5)
print e global_vars.pid = 0
print e.returncode
self.dialog_box("Unable to connect to host: "+self.host+" at port "+self.port)
def connect_nx(self): def connect_nx(self):
#Generate temproary config #Generate temproary config
......
from setuptools import setup, find_packages from setuptools import setup, find_packages
setup( setup(
name = "CloudGUI", name = "CloudGUI",
version = "0.1", version = "0.2",
packages = ['cloudgui',], packages = ['cloudgui',],
scripts = ['cloud','rdp',], scripts = ['cloud','rdp',],
) )
#!/usr/bin/python
import xmltodict
import xml.dom.minidom as minidom
import sys
import json
import math
xml = sys.stdin.read()
data = minidom.parseString(xml)
node = data.documentElement
hosts = data.getElementsByTagName("HOST")
#CPU stat
cpu_usage = 0
used_cpu = 0
cpu_max = 0
#Memory stat
mem_usage = 0
used_mem = 0
mem_max = 0
#Running VMs
running_vms = 0
for host in hosts:
share = host.getElementsByTagName("HOST_SHARE")[0]
cpu_max += int(share.getElementsByTagName("MAX_CPU")[0].childNodes[0].data)
used_cpu += int(share.getElementsByTagName("USED_CPU")[0].childNodes[0].data)
cpu_usage += int(share.getElementsByTagName("CPU_USAGE")[0].childNodes[0].data)
mem_usage += int(share.getElementsByTagName("MEM_USAGE")[0].childNodes[0].data)
used_mem += int(share.getElementsByTagName("USED_MEM")[0].childNodes[0].data)
mem_max += int(share.getElementsByTagName("MAX_MEM")[0].childNodes[0].data)
running_vms += int(share.getElementsByTagName("RUNNING_VMS")[0].childNodes[0].data)
if cpu_usage < used_cpu:
alloc_cpu = 0
free_cpu = (cpu_max - used_cpu)
else:
alloc_cpu = (cpu_usage - used_cpu)
free_cpu = (cpu_max - alloc_cpu - used_cpu)
#Round memory values
mem_usage = mem_usage / 1024
used_mem = used_mem / 1024
mem_max = mem_max / 1024
if mem_max < (1024*5):
dimension = "MB"
else:
mem_usage = mem_usage / 1024
used_mem = used_mem / 1024
mem_max = mem_max / 1024
dimension = "GB"
mem_usage = round(mem_usage, 2)
used_mem = round(used_mem, 2)
mem_max = round(mem_max, 2)
if mem_usage < used_mem:
alloc_mem = 0
free_mem = (mem_max - used_mem)
else:
alloc_mem = (mem_usage - used_mem)
free_mem = (mem_max - alloc_mem - used_mem)
used_mem = used_mem
cpu_dict = {'FREE_CPU' : free_cpu, 'ALLOC_CPU' : alloc_cpu , 'USED_CPU' :
used_cpu}
mem_dict = {'FREE_MEM' : free_mem, 'ALLOC_MEM' : alloc_mem , 'USED_MEM' :
used_mem}
print json.dumps({ 'CPU' : cpu_dict, 'MEM' : mem_dict, 'VMS' : running_vms,
'DIMENSION' : dimension})
#!/bin/bash
export HOME='/var/www'
export LANG='en_US.UTF-8'
export LANGUAGE='en_US:en'
export LOGNAME='www-data'
export MAIL='/var/mail/www-data'
export PATH='/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games'
export PWD='/var/www'
export SHELL='/bin/sh'
export TERM='screen'
export USER='www-data'
#export ONE_LOCATION='/var/lib/opennebula'
export PATH="$PATH:$ONE_LOCATION/bin"
sudo -u oneadmin -i onehost list -x | /opt/webadmin/cloud/miscellaneous/stat/stat_dom.py
<HOST_POOL>
<HOST>
<ID>2</ID>
<NAME>mega6</NAME>
<STATE>2</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1362046632</LAST_MON_TIME>
<CLUSTER_ID>100</CLUSTER_ID>
<CLUSTER>mega</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>12582912</MEM_USAGE>
<CPU_USAGE>470</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>32937584</MAX_MEM>
<MAX_CPU>1600</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>22752516</FREE_MEM>
<FREE_CPU>1580</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>10185068</USED_MEM>
<USED_CPU>19</USED_CPU>
<RUNNING_VMS>9</RUNNING_VMS>
</HOST_SHARE>
<VMS>
<ID>421</ID>
<ID>532</ID>
<ID>549</ID>
<ID>678</ID>
<ID>714</ID>
<ID>1243</ID>
<ID>1251</ID>
<ID>1260</ID>
<ID>1268</ID>
</VMS>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[2266]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 2 : MONITOR FAILURE 2 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Feb 8 22:17:17 2013]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[1580.8]]></FREECPU>
<FREEMEMORY><![CDATA[22752516]]></FREEMEMORY>
<HOSTNAME><![CDATA[mega6]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU E5520 @ 2.27GHz]]></MODELNAME>
<NETRX><![CDATA[215302575491]]></NETRX>
<NETTX><![CDATA[1574216791392]]></NETTX>
<TOTALCPU><![CDATA[1600]]></TOTALCPU>
<TOTALMEMORY><![CDATA[32937584]]></TOTALMEMORY>
<USEDCPU><![CDATA[19.2]]></USEDCPU>
<USEDMEMORY><![CDATA[10185068]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>3</ID>
<NAME>blade1</NAME>
<STATE>4</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1358424142</LAST_MON_TIME>
<CLUSTER_ID>101</CLUSTER_ID>
<CLUSTER>blade</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>0</MEM_USAGE>
<CPU_USAGE>0</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>16433792</MAX_MEM>
<MAX_CPU>800</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>16040424</FREE_MEM>
<FREE_CPU>800</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>393368</USED_MEM>
<USED_CPU>0</USED_CPU>
<RUNNING_VMS>0</RUNNING_VMS>
</HOST_SHARE>
<VMS/>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[2333]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 3 : MONITOR FAILURE 3 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Dec 28 10:28:37 2012]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[800.0]]></FREECPU>
<FREEMEMORY><![CDATA[16040424]]></FREEMEMORY>
<HOSTNAME><![CDATA[blade1]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU E5345 @ 2.33GHz]]></MODELNAME>
<NETRX><![CDATA[2032199762]]></NETRX>
<NETTX><![CDATA[519158530]]></NETTX>
<TOTALCPU><![CDATA[800]]></TOTALCPU>
<TOTALMEMORY><![CDATA[16433792]]></TOTALMEMORY>
<USEDCPU><![CDATA[0.0]]></USEDCPU>
<USEDMEMORY><![CDATA[393368]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>9</ID>
<NAME>blade2</NAME>
<STATE>4</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1358424142</LAST_MON_TIME>
<CLUSTER_ID>101</CLUSTER_ID>
<CLUSTER>blade</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>0</MEM_USAGE>
<CPU_USAGE>0</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>10240668</MAX_MEM>
<MAX_CPU>200</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>9983120</FREE_MEM>
<FREE_CPU>200</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>257548</USED_MEM>
<USED_CPU>0</USED_CPU>
<RUNNING_VMS>0</RUNNING_VMS>
</HOST_SHARE>
<VMS/>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[3333]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 9 : MONITOR FAILURE 9 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Dec 28 10:28:37 2012]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[200.0]]></FREECPU>
<FREEMEMORY><![CDATA[9983120]]></FREEMEMORY>
<HOSTNAME><![CDATA[blade2]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU X5260 @ 3.33GHz]]></MODELNAME>
<NETRX><![CDATA[2252084768]]></NETRX>
<NETTX><![CDATA[10595986496]]></NETTX>
<TOTALCPU><![CDATA[200]]></TOTALCPU>
<TOTALMEMORY><![CDATA[10240668]]></TOTALMEMORY>
<USEDCPU><![CDATA[0.0]]></USEDCPU>
<USEDMEMORY><![CDATA[257548]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>10</ID>
<NAME>blade3</NAME>
<STATE>4</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1358424142</LAST_MON_TIME>
<CLUSTER_ID>101</CLUSTER_ID>
<CLUSTER>blade</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>0</MEM_USAGE>
<CPU_USAGE>0</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>16433792</MAX_MEM>
<MAX_CPU>800</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>12401604</FREE_MEM>
<FREE_CPU>796</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>4032188</USED_MEM>
<USED_CPU>4</USED_CPU>
<RUNNING_VMS>0</RUNNING_VMS>
</HOST_SHARE>
<VMS/>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[2333]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 10 : MONITOR FAILURE 10 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Dec 28 22:10:28 2012]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[796.0]]></FREECPU>
<FREEMEMORY><![CDATA[12401604]]></FREEMEMORY>
<HOSTNAME><![CDATA[blade3]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU E5345 @ 2.33GHz]]></MODELNAME>
<NETRX><![CDATA[95424749266]]></NETRX>
<NETTX><![CDATA[284788515663]]></NETTX>
<TOTALCPU><![CDATA[800]]></TOTALCPU>
<TOTALMEMORY><![CDATA[16433792]]></TOTALMEMORY>
<USEDCPU><![CDATA[4.0]]></USEDCPU>
<USEDMEMORY><![CDATA[4032188]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>11</ID>
<NAME>mega5</NAME>
<STATE>2</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1362046208</LAST_MON_TIME>
<CLUSTER_ID>100</CLUSTER_ID>
<CLUSTER>mega</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>17825792</MEM_USAGE>
<CPU_USAGE>950</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>32937648</MAX_MEM>
<MAX_CPU>1600</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>17099428</FREE_MEM>
<FREE_CPU>1392</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>15838220</USED_MEM>
<USED_CPU>208</USED_CPU>
<RUNNING_VMS>9</RUNNING_VMS>
</HOST_SHARE>
<VMS>
<ID>432</ID>
<ID>540</ID>
<ID>541</ID>
<ID>667</ID>
<ID>690</ID>
<ID>760</ID>
<ID>799</ID>
<ID>1227</ID>
<ID>1263</ID>
</VMS>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[2266]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 11 : MONITOR FAILURE 11 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Feb 8 22:13:44 2013]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[1392.0]]></FREECPU>
<FREEMEMORY><![CDATA[17099428]]></FREEMEMORY>
<HOSTNAME><![CDATA[mega5]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU E5520 @ 2.27GHz]]></MODELNAME>
<NETRX><![CDATA[63650381314]]></NETRX>
<NETTX><![CDATA[33549680144]]></NETTX>
<TOTALCPU><![CDATA[1600]]></TOTALCPU>
<TOTALMEMORY><![CDATA[32937648]]></TOTALMEMORY>
<USEDCPU><![CDATA[208.0]]></USEDCPU>
<USEDMEMORY><![CDATA[15838220]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>12</ID>
<NAME>mega4</NAME>
<STATE>2</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1362046491</LAST_MON_TIME>
<CLUSTER_ID>100</CLUSTER_ID>
<CLUSTER>mega</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>15728640</MEM_USAGE>
<CPU_USAGE>660</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>49454996</MAX_MEM>
<MAX_CPU>2400</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>38047512</FREE_MEM>
<FREE_CPU>2395</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>11407484</USED_MEM>
<USED_CPU>4</USED_CPU>
<RUNNING_VMS>10</RUNNING_VMS>
</HOST_SHARE>
<VMS>
<ID>460</ID>
<ID>538</ID>
<ID>539</ID>
<ID>543</ID>
<ID>607</ID>
<ID>877</ID>
<ID>1200</ID>
<ID>1255</ID>
<ID>1262</ID>
<ID>1269</ID>
</VMS>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[1600]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 12 : MONITOR FAILURE 12 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Feb 8 22:17:17 2013]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[2395.2]]></FREECPU>
<FREEMEMORY><![CDATA[38047512]]></FREEMEMORY>
<HOSTNAME><![CDATA[mega4]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU X5675 @ 3.07GHz]]></MODELNAME>
<NETRX><![CDATA[154783474539]]></NETRX>
<NETTX><![CDATA[112244748012]]></NETTX>
<TOTALCPU><![CDATA[2400]]></TOTALCPU>
<TOTALMEMORY><![CDATA[49454996]]></TOTALMEMORY>
<USEDCPU><![CDATA[4.80000000000018]]></USEDCPU>
<USEDMEMORY><![CDATA[11407484]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>13</ID>
<NAME>mega3</NAME>
<STATE>2</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1362046405</LAST_MON_TIME>
<CLUSTER_ID>100</CLUSTER_ID>
<CLUSTER>mega</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>28835840</MEM_USAGE>
<CPU_USAGE>890</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>49454996</MAX_MEM>
<MAX_CPU>2400</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>27997516</FREE_MEM>
<FREE_CPU>2395</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>21457480</USED_MEM>
<USED_CPU>4</USED_CPU>
<RUNNING_VMS>10</RUNNING_VMS>
</HOST_SHARE>
<VMS>
<ID>403</ID>
<ID>412</ID>
<ID>440</ID>
<ID>458</ID>
<ID>459</ID>
<ID>550</ID>
<ID>591</ID>
<ID>609</ID>
<ID>759</ID>
<ID>908</ID>
</VMS>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[1600]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 13 : MONITOR FAILURE 13 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Feb 8 22:15:24 2013]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[2395.2]]></FREECPU>
<FREEMEMORY><![CDATA[27997516]]></FREEMEMORY>
<HOSTNAME><![CDATA[mega3]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU X5675 @ 3.07GHz]]></MODELNAME>
<NETRX><![CDATA[179556365753]]></NETRX>
<NETTX><![CDATA[84194722741]]></NETTX>
<TOTALCPU><![CDATA[2400]]></TOTALCPU>
<TOTALMEMORY><![CDATA[49454996]]></TOTALMEMORY>
<USEDCPU><![CDATA[4.80000000000018]]></USEDCPU>
<USEDMEMORY><![CDATA[21457480]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>15</ID>
<NAME>mega1</NAME>
<STATE>2</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1362046705</LAST_MON_TIME>
<CLUSTER_ID>100</CLUSTER_ID>
<CLUSTER>mega</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>36700160</MEM_USAGE>
<CPU_USAGE>1085</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>49520964</MAX_MEM>
<MAX_CPU>2400</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>18859800</FREE_MEM>
<FREE_CPU>2371</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>30661164</USED_MEM>
<USED_CPU>28</USED_CPU>
<RUNNING_VMS>12</RUNNING_VMS>
</HOST_SHARE>
<VMS>
<ID>408</ID>
<ID>534</ID>
<ID>535</ID>
<ID>536</ID>
<ID>537</ID>
<ID>542</ID>
<ID>626</ID>
<ID>685</ID>
<ID>696</ID>
<ID>708</ID>
<ID>880</ID>
<ID>1201</ID>
</VMS>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[1600]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 15 : MONITOR FAILURE 15 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Feb 8 22:20:20 2013]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[2371.2]]></FREECPU>
<FREEMEMORY><![CDATA[18859800]]></FREEMEMORY>
<HOSTNAME><![CDATA[mega1]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU X5670 @ 2.93GHz]]></MODELNAME>
<NETRX><![CDATA[46593679744]]></NETRX>
<NETTX><![CDATA[36440944329]]></NETTX>
<TOTALCPU><![CDATA[2400]]></TOTALCPU>
<TOTALMEMORY><![CDATA[49520964]]></TOTALMEMORY>
<USEDCPU><![CDATA[28.8000000000002]]></USEDCPU>
<USEDMEMORY><![CDATA[30661164]]></USEDMEMORY>
</TEMPLATE>
</HOST>
<HOST>
<ID>16</ID>
<NAME>mega2</NAME>
<STATE>2</STATE>
<IM_MAD>im_kvm</IM_MAD>
<VM_MAD>vmm_kvm</VM_MAD>
<VN_MAD>ovswitch</VN_MAD>
<LAST_MON_TIME>1362046476</LAST_MON_TIME>
<CLUSTER_ID>100</CLUSTER_ID>
<CLUSTER>mega</CLUSTER>
<HOST_SHARE>
<DISK_USAGE>0</DISK_USAGE>
<MEM_USAGE>16777216</MEM_USAGE>
<CPU_USAGE>550</CPU_USAGE>
<MAX_DISK>0</MAX_DISK>
<MAX_MEM>49455072</MAX_MEM>
<MAX_CPU>2400</MAX_CPU>
<FREE_DISK>0</FREE_DISK>
<FREE_MEM>39782788</FREE_MEM>
<FREE_CPU>2376</FREE_CPU>
<USED_DISK>0</USED_DISK>
<USED_MEM>9672284</USED_MEM>
<USED_CPU>24</USED_CPU>
<RUNNING_VMS>9</RUNNING_VMS>
</HOST_SHARE>
<VMS>
<ID>1189</ID>
<ID>1195</ID>
<ID>1198</ID>
<ID>1229</ID>
<ID>1244</ID>
<ID>1256</ID>
<ID>1257</ID>
<ID>1259</ID>
<ID>1261</ID>
</VMS>
<TEMPLATE>
<ARCH><![CDATA[x86_64]]></ARCH>
<CPUSPEED><![CDATA[1600]]></CPUSPEED>
<ERROR>
<MESSAGE><![CDATA[Error monitoring host 16 : MONITOR FAILURE 16 -
]]></MESSAGE>
<TIMESTAMP><![CDATA[Fri Feb 8 22:15:24 2013]]></TIMESTAMP>
</ERROR>
<FREECPU><![CDATA[2376.0]]></FREECPU>
<FREEMEMORY><![CDATA[39782788]]></FREEMEMORY>
<HOSTNAME><![CDATA[mega2]]></HOSTNAME>
<HYPERVISOR><![CDATA[kvm]]></HYPERVISOR>
<MODELNAME><![CDATA[Intel(R) Xeon(R) CPU X5670 @ 2.93GHz]]></MODELNAME>
<NETRX><![CDATA[12341402713]]></NETRX>
<NETTX><![CDATA[4465978862]]></NETTX>
<TOTALCPU><![CDATA[2400]]></TOTALCPU>
<TOTALMEMORY><![CDATA[49455072]]></TOTALMEMORY>
<USEDCPU><![CDATA[24.0]]></USEDCPU>
<USEDMEMORY><![CDATA[9672284]]></USEDMEMORY>
</TEMPLATE>
</HOST>
</HOST_POOL>
...@@ -8,6 +8,7 @@ import uuid ...@@ -8,6 +8,7 @@ import uuid
import subprocess import subprocess
import ConfigParser import ConfigParser
from pwd import getpwnam from pwd import getpwnam
import multiprocessing
# Get configuration file # Get configuration file
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
...@@ -100,23 +101,13 @@ def cmd_download(request, neptun, home_path): ...@@ -100,23 +101,13 @@ def cmd_download(request, neptun, home_path):
if not dl_path.startswith(home_path): if not dl_path.startswith(home_path):
abort(400, 'Invalid download path.') abort(400, 'Invalid download path.')
dl_hash = str(uuid.uuid4()) dl_hash = str(uuid.uuid4())
if( os.path.isfile(dl_path) ): dl_pub = os.path.join(ROOT_WWW_FOLDER, dl_hash)
os.symlink(dl_path, ROOT_WWW_FOLDER+'/'+dl_hash) if os.path.isfile(dl_path):
# Debug os.symlink(dl_path, dl_pub)
# redirect('http://store.cloud.ik.bme.hu:8080/dl/'+dl_hash)
return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash}) return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash})
else: else:
try: shutil.make_archive(dl_pub, 'zip', dl_path)
os.makedirs(TEMP_DIR+'/'+neptun, 0700) return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash+'.zip'})
except:
pass
folder_name = os.path.basename(dl_path)
temp_path = TEMP_DIR+'/'+neptun+'/'+folder_name+'.zip'
with open(os.devnull, "w") as fnull:
# zip -rqDj vmi.zip /home/tarokkk/vpn-ik
result = subprocess.call(['/usr/bin/zip', '-rqDj', temp_path, dl_path], stdout = fnull, stderr = fnull)
os.symlink(temp_path, ROOT_WWW_FOLDER+'/'+dl_hash)
return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash})
COMMANDS['DOWNLOAD'] = cmd_download COMMANDS['DOWNLOAD'] = cmd_download
# UPLOAD # UPLOAD
...@@ -127,7 +118,10 @@ def cmd_upload(request, neptun, home_path): ...@@ -127,7 +118,10 @@ def cmd_upload(request, neptun, home_path):
abort(400, 'Invalid upload path.') abort(400, 'Invalid upload path.')
if os.path.exists(up_path) == True and os.path.isdir(up_path): if os.path.exists(up_path) == True and os.path.isdir(up_path):
up_hash = str(uuid.uuid4()) up_hash = str(uuid.uuid4())
os.symlink(up_path, ROOT_WWW_FOLDER+'/'+up_hash) link = ROOT_WWW_FOLDER + '/' + up_hash
os.symlink(up_path, link)
passwd = getpwnam(neptun)
os.lchown(link, passwd.pw_uid, passwd.pw_gid)
return json.dumps({ 'LINK' : SITE_URL+'/ul/'+up_hash}) return json.dumps({ 'LINK' : SITE_URL+'/ul/'+up_hash})
else: else:
abort(400, 'Upload directory not exists!') abort(400, 'Upload directory not exists!')
...@@ -285,40 +279,48 @@ def upload_allow(hash_num): ...@@ -285,40 +279,48 @@ def upload_allow(hash_num):
response.set_header('Access-Control-Allow-Headers', 'Content-Type, Content-Range, Content-Disposition, Content-Description') response.set_header('Access-Control-Allow-Headers', 'Content-Type, Content-Range, Content-Disposition, Content-Description')
return 'ok' return 'ok'
def _upload_save(uid, gid, input, path):
os.setegid(gid)
os.seteuid(uid)
try:
with open(path, 'wb', 0600) as output:
while True:
chunk = input.read(256*1024)
if not chunk:
break
output.write(chunk)
finally:
input.close()
@route('/ul/<hash_num>', method='POST') @route('/ul/<hash_num>', method='POST')
def upload(hash_num): def upload(hash_num):
if not os.path.exists(ROOT_WWW_FOLDER+'/'+hash_num): link = ROOT_WWW_FOLDER+'/'+hash_num
if not os.path.exists(link):
abort (404, 'Token not found!') abort (404, 'Token not found!')
try: try:
file_data = request.files.data file_data = request.files.data
file_name = file_data.filename file_name = file_data.filename
except: except:
if os.path.exists(ROOT_WWW_FOLDER+'/'+hash_num): if os.path.exists(link):
os.remove(ROOT_WWW_FOLDER+'/'+hash_num) os.remove(link)
abort(400, 'No file was specified!') abort(400, 'No file was specified!')
up_path = os.path.realpath(ROOT_WWW_FOLDER+'/'+hash_num+'/'+file_name) up_path = os.path.realpath(link + '/' + file_name)
if os.path.exists(up_path): if os.path.exists(up_path):
abort(400, 'File already exists') abort(400, 'File already exists')
# Check if upload path valid
if not up_path.startswith('/home'): if not up_path.startswith('/home'):
abort(400, 'Invalid path.') abort(400, 'Invalid path.')
linkstat = os.stat(link)
os.remove(ROOT_WWW_FOLDER+'/'+hash_num) os.remove(link)
# Get the real upload path p = multiprocessing.Process(target=_upload_save,
# Delete the hash link args=(linkstat.st_uid, linkstat.st_gid, file_data.file, up_path, ))
# Get the username from path for proper ownership try:
username=up_path.split('/', 3)[2] p.start()
# os.setegid(getpwnam(username).pw_gid) p.join()
# os.seteuid(getpwnam(username).pw_uid) finally:
# TODO setuid subcommand p.terminate()
# Check if file exist (root can overwrite anything not safe) if p.exitcode:
with open(up_path , 'wb') as f: abort(400, 'Write failed.')
datalength = 0
for chunk in fbuffer(file_data.file, chunk_size=1048576):
f.write(chunk)
datalength += len(chunk)
os.chown(up_path, getpwnam(username).pw_uid, getpwnam(username).pw_gid)
os.chmod(up_path, 0644)
try: try:
redirect_address = request.headers.get('Referer') redirect_address = request.headers.get('Referer')
except: except:
...@@ -327,19 +329,11 @@ def upload(hash_num): ...@@ -327,19 +329,11 @@ def upload(hash_num):
response.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') response.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
response.set_header('Access-Control-Allow-Headers', 'Content-Type, Content-Range, Content-Disposition, Content-Description') response.set_header('Access-Control-Allow-Headers', 'Content-Type, Content-Range, Content-Disposition, Content-Description')
redirect(redirect_address) redirect(redirect_address)
#return 'Upload finished: '+file_name+' - '+str(datalength)+' Byte'
# Return hard quota from quota # Return hard quota from quota
def hard_quota(quota): def hard_quota(quota):
return str(int(int(quota)*1.25)) return str(int(int(quota)*1.25))
# Define filebuffer for big uploads
def fbuffer(f, chunk_size=4096):
while True:
chunk = f.read(chunk_size)
if not chunk: break
yield chunk
# Update users .ssh/authorized_keys # Update users .ssh/authorized_keys
def updateSSHAuthorizedKeys(username, key_list): def updateSSHAuthorizedKeys(username, key_list):
user_uid=getpwnam(username).pw_uid user_uid=getpwnam(username).pw_uid
......
...@@ -23,17 +23,30 @@ class DetailsInline(contrib.admin.StackedInline): ...@@ -23,17 +23,30 @@ class DetailsInline(contrib.admin.StackedInline):
can_delete = False can_delete = False
class MyUserAdmin(contrib.auth.admin.UserAdmin): class MyUserAdmin(contrib.auth.admin.UserAdmin):
list_display = ('username', 'full_name', 'email', 'date_joined', 'instance_count') list_display = ('username', 'full_name', 'email', 'date_joined', 'instance_count', 'course_groups')
list_filter = ('is_superuser', 'is_active', 'groups', 'person__course_groups', )
try: try:
inlines = inlines + (PersonInline, SshKeyInline, DetailsInline) inlines = inlines + (PersonInline, SshKeyInline, DetailsInline)
except NameError: except NameError:
inlines = (PersonInline, SshKeyInline, DetailsInline) inlines = (PersonInline, SshKeyInline, DetailsInline)
def instance_count(self, obj): def instance_count(self, obj):
return obj.instance_set.count() return _("%(sum)d (%(active)d active)") % { 'sum': obj.instance_set.count(),
'active' :obj.instance_set.filter(state='ACTIVE').count(), }
def course_groups(self, obj):
try:
return ", ".join(obj.person_set.all()[0].course_groups.all())
except:
return None
def full_name(self, obj): def full_name(self, obj):
return u"%s %s" % (obj.last_name, obj.first_name) return u"%s %s" % (obj.last_name, obj.first_name)
full_name.admin_order_field = 'last_name' full_name.admin_order_field = 'last_name'
ordering = ["-date_joined"]
contrib.admin.site.unregister(contrib.auth.models.User) contrib.admin.site.unregister(contrib.auth.models.User)
......
# -*- coding: utf-8 -*-
from django_extensions.management.jobs import HourlyJob from django_extensions.management.jobs import HourlyJob
import datetime
from django.utils.timezone import utc
from one.models import Instance
from django.template.loader import render_to_string
from one.tasks import SendMailTask
from django.utils.translation import ugettext_lazy as _
from cloud.settings import CLOUD_URL as url
from django.utils import translation
class Job(HourlyJob): class Job(HourlyJob):
help = "Suspend/delete expired Instances." help = "Suspend/delete expired Instances."
def calc(self, orig, days=0, hours=0):
return (orig + datetime.timedelta(days=days, hours=hours)).replace(minute=0, second=0, microsecond=0)
def execute(self): def execute(self):
# executing empty sample job TODO now = datetime.datetime.utcnow().replace(tzinfo=utc)
d = {
'1m': self.calc(orig=now, days=30),
'2w': self.calc(orig=now, days=14),
'1w': self.calc(orig=now, days=7),
'1d': self.calc(orig=now, days=1),
'1h': self.calc(orig=now, hours=1),
}
# for i in d:
# print i+':'+unicode(d[i])
# delete
for i in Instance.objects.filter(state__in=['ACTIVE', 'STOPPED'], time_of_delete__isnull=False):
try:
translation.activate(i.owner.person_set.get().language)
except:
pass
# print u'%s delete: %s' % (i.name, i.time_of_delete)
delete = i.time_of_delete.replace(minute=0, second=0, microsecond=0)
continue
if i.time_of_delete < now:
# msg = render_to_string('mails/notification-delete-now.txt', { 'user': i.owner, 'instance': i, 'url': url } )
# SendMailTask.delay(to=i.owner.email, subject='[IK Cloud] %s' % i.name, msg=msg)
pass pass
else:
for t in d:
if delete == d[t]:
msg = render_to_string('mails/notification-delete.txt', { 'user': i.owner, 'instance': i, 'url': url } )
SendMailTask.delay(to=i.owner.email, subject='[IK Cloud] %s' % i.name, msg=msg)
# suspend
for i in Instance.objects.filter(state='ACTIVE', time_of_suspend__isnull=False):
try:
translation.activate(i.owner.person_set.get().language)
except:
pass
# print u'%s suspend: %s' % (i.name, i.time_of_suspend)
suspend = i.time_of_suspend.replace(minute=0, second=0, microsecond=0)
if i.time_of_suspend < now:
msg = render_to_string('mails/notification-suspend-now.txt', { 'user': i.owner, 'instance': i, 'url': url } )
SendMailTask.delay(to=i.owner.email, subject='[IK Cloud] %s' % i.name, msg=msg)
i.stop()
else:
for t in d:
if suspend == d[t]:
msg = render_to_string('mails/notification-suspend.txt', { 'user': i.owner, 'instance': i, 'url': url } )
SendMailTask.delay(to=i.owner.email, subject='[IK Cloud] %s' % i.name, msg=msg)
...@@ -2,9 +2,11 @@ from one.models import * ...@@ -2,9 +2,11 @@ from one.models import *
from django_extensions.management.jobs import HourlyJob from django_extensions.management.jobs import HourlyJob
class Job(HourlyJob): class Job(HourlyJob):
help = "Update Disks and Networks from OpenNebula." help = "Update Disks, Networks and Instances from OpenNebula."
def execute(self): def execute(self):
Disk.update() Disk.update()
Network.update() Network.update()
for i in Instance.objects.filter(state__in=['ACTIVE', 'STOPPED'], time_of_delete__isnull=False):
i.update_state()
pass pass
...@@ -7,8 +7,8 @@ msgid "" ...@@ -7,8 +7,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-02-21 18:06+0100\n" "POT-Creation-Date: 2013-03-07 18:16+0100\n"
"PO-Revision-Date: 2013-02-21 18:07+0100\n" "PO-Revision-Date: 2013-03-07 17:40+0100\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Hungarian <cloud@ik.bme.hu>\n" "Language-Team: Hungarian <cloud@ik.bme.hu>\n"
"Language: hu\n" "Language: hu\n"
...@@ -18,27 +18,32 @@ msgstr "" ...@@ -18,27 +18,32 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Lokalize 1.4\n" "X-Generator: Lokalize 1.4\n"
#: admin.py:11 models.py:317 models.py:364 #: admin.py:11 models.py:318 models.py:365
msgid "owner" msgid "owner"
msgstr "tulajdonos" msgstr "tulajdonos"
#: admin.py:45 #: admin.py:35
#, python-format
msgid "%(sum)d (%(active)d active)"
msgstr "%(sum)d (%(active)d aktív)"
#: admin.py:58
msgid "Update status" msgid "Update status"
msgstr "Állapot frissítése" msgstr "Állapot frissítése"
#: admin.py:51 #: admin.py:64
msgid "Submit VM" msgid "Submit VM"
msgstr "VM beküldése" msgstr "VM beküldése"
#: admin.py:57 #: admin.py:70
msgid "Delete VM" msgid "Delete VM"
msgstr "VM törlése" msgstr "VM törlése"
#: admin.py:63 #: admin.py:76
msgid "Suspend VM" msgid "Suspend VM"
msgstr "VM felfüggesztése" msgstr "VM felfüggesztése"
#: admin.py:69 #: admin.py:82
msgid "Resume VM" msgid "Resume VM"
msgstr "VM folytatása" msgstr "VM folytatása"
...@@ -105,8 +110,8 @@ msgid "" ...@@ -105,8 +110,8 @@ msgid ""
"and store login (2048+ bit RSA preferred). Example: <code>ssh-rsa AAAAB..." "and store login (2048+ bit RSA preferred). Example: <code>ssh-rsa AAAAB..."
"QtQ== john</code>." "QtQ== john</code>."
msgstr "" msgstr ""
"<a href=\"/info/ssh/\">SSH nyilvános kulcs OpenSSH formátumban</a> az SSH " "<a href=\"/info/ssh/\">SSH nyilvános kulcs OpenSSH formátumban</a> az SSH\n"
"bejelentkezéshez – ajánlás: 2048+ bites RSA. Példa: <code><code>ssh-rsa " "bejelentkezéshez – ajánlás: 2048+ bites RSA. Példa: <code><code>ssh-rsa\n"
"AAAAB...QtQ== jozsi</a>." "AAAAB...QtQ== jozsi</a>."
#: models.py:154 #: models.py:154
...@@ -121,11 +126,11 @@ msgstr "új" ...@@ -121,11 +126,11 @@ msgstr "új"
msgid "perparing" msgid "perparing"
msgstr "előkészítés" msgstr "előkészítés"
#: models.py:159 models.py:303 #: models.py:159 models.py:304
msgid "saving" msgid "saving"
msgstr "mentés" msgstr "mentés"
#: models.py:159 models.py:304 #: models.py:159 models.py:305
msgid "ready" msgid "ready"
msgstr "kész" msgstr "kész"
...@@ -153,16 +158,16 @@ msgstr "szerver" ...@@ -153,16 +158,16 @@ msgstr "szerver"
msgid "For long-term server use." msgid "For long-term server use."
msgstr "Hosszú távú, szerver-felhasználáshoz." msgstr "Hosszú távú, szerver-felhasználáshoz."
#: models.py:175 models.py:218 models.py:252 models.py:291 models.py:308 #: models.py:175 models.py:218 models.py:253 models.py:292 models.py:309
#: models.py:359 #: models.py:360
msgid "name" msgid "name"
msgstr "név" msgstr "név"
#: models.py:176 models.py:325 #: models.py:176 models.py:326
msgid "description" msgid "description"
msgstr "leírás" msgstr "leírás"
#: models.py:180 models.py:320 models.py:367 #: models.py:180 models.py:321 models.py:368
msgid "created at" msgid "created at"
msgstr "létrehozás ideje" msgstr "létrehozás ideje"
...@@ -182,236 +187,245 @@ msgstr "felhasználónkénti korlát" ...@@ -182,236 +187,245 @@ msgstr "felhasználónkénti korlát"
msgid "Maximal count of instances launchable by a single user." msgid "Maximal count of instances launchable by a single user."
msgstr "Egy felhasználó által indítható példányok száma." msgstr "Egy felhasználó által indítható példányok száma."
#: models.py:253 #: models.py:254
msgid "NAT" msgid "NAT"
msgstr "NAT" msgstr "NAT"
#: models.py:254 #: models.py:255
msgid "If network address translation is done." msgid "If network address translation is done."
msgstr "Hálózati címfordítás történik-e." msgstr "Hálózati címfordítás történik-e."
#: models.py:255 models.py:323 #: models.py:256 models.py:324
msgid "public" msgid "public"
msgstr "publikus" msgstr "publikus"
#: models.py:256 #: models.py:257
msgid "If internet gateway is available." msgid "If internet gateway is available."
msgstr "Van-e elérheti internetes útválasztás." msgstr "Van-e elérheti internetes útválasztás."
#: models.py:292 #: models.py:293
msgid "CPU cores." msgid "CPU cores."
msgstr "CPU magok száma." msgstr "CPU magok száma."
#: models.py:293 #: models.py:294
msgid "Mebibytes of memory." msgid "Mebibytes of memory."
msgstr "Memória mérete mebibyte-ban." msgstr "Memória mérete mebibyte-ban."
#: models.py:294 #: models.py:295
msgid "credits" msgid "credits"
msgstr "kredit" msgstr "kredit"
#: models.py:295 #: models.py:296
msgid "Price of instance." msgid "Price of instance."
msgstr "Példány értéke." msgstr "Példány értéke."
#: models.py:303 #: models.py:304
msgid "new" msgid "new"
msgstr "új" msgstr "új"
#: models.py:311 #: models.py:312
msgid "access method" msgid "access method"
msgstr "elérési mód" msgstr "elérési mód"
#: models.py:312 #: models.py:313
msgid "disk" msgid "disk"
msgstr "lemez" msgstr "lemez"
#: models.py:314 #: models.py:315
msgid "instance type" msgid "instance type"
msgstr "példánytípus" msgstr "példánytípus"
#: models.py:315 #: models.py:316
msgid "network" msgid "network"
msgstr "hálózat" msgstr "hálózat"
#: models.py:324 #: models.py:325
msgid "If other users can derive templates of this one." msgid "If other users can derive templates of this one."
msgstr "Más felhasználók készíthetnek-e ez alapján új sablonokat." msgstr "Más felhasználók készíthetnek-e ez alapján új sablonokat."
#: models.py:326 #: models.py:327
msgid "operating system" msgid "operating system"
msgstr "operációs rendszer" msgstr "operációs rendszer"
#: models.py:327 #: models.py:328
#, python-format #, python-format
msgid "Name of operating system in format like \"%s\"." msgid "Name of operating system in format like \"%s\"."
msgstr "Operációs rendszer neve a következő formában: „%s”." msgstr "Operációs rendszer neve a következő formában: „%s”."
#: models.py:331 models.py:362 #: models.py:332 models.py:363
msgid "template" msgid "template"
msgstr "sablon" msgstr "sablon"
#: models.py:332 #: models.py:333
msgid "templates" msgid "templates"
msgstr "sablonok" msgstr "sablonok"
#: models.py:361 #: models.py:362
msgid "IP address" msgid "IP address"
msgstr "IP cím" msgstr "IP cím"
#: models.py:369 #: models.py:370
msgid "deployable" msgid "deployable"
msgstr "beküldhető" msgstr "beküldhető"
#: models.py:370 #: models.py:371
msgid "pending" msgid "pending"
msgstr "várakozó" msgstr "várakozó"
#: models.py:371 #: models.py:372
msgid "done" msgid "done"
msgstr "kész" msgstr "kész"
#: models.py:372 #: models.py:373
msgid "active" msgid "active"
msgstr "aktív" msgstr "aktív"
#: models.py:373 #: models.py:374
msgid "unknown" msgid "unknown"
msgstr "ismeretlen" msgstr "ismeretlen"
#: models.py:374 #: models.py:375
msgid "suspended" msgid "suspended"
msgstr "felfüggesztett" msgstr "felfüggesztett"
#: models.py:375 #: models.py:376
msgid "failed" msgid "failed"
msgstr "hiba" msgstr "hiba"
#: models.py:378 #: models.py:379
msgid "active since" msgid "active since"
msgstr "aktívvá válás ideje" msgstr "aktívvá válás ideje"
#: models.py:379 #: models.py:380
msgid "Time stamp of successful boot report." msgid "Time stamp of successful boot report."
msgstr "A sikeres indulás jelentésének időpontja." msgstr "A sikeres indulás jelentésének időpontja."
#: models.py:381 #: models.py:382
msgid "host in firewall" msgid "host in firewall"
msgstr "gép a tűzfalban" msgstr "gép a tűzfalban"
#: models.py:382 #: models.py:383
msgid "password" msgid "password"
msgstr "jelszó" msgstr "jelszó"
#: models.py:383 #: models.py:384
msgid "Original password of instance" msgid "Original password of instance"
msgstr "A példány eredeti jelszava." msgstr "A példány eredeti jelszava."
#: models.py:385 #: models.py:386
msgid "OpenNebula ID" msgid "OpenNebula ID"
msgstr "OpenNebula ID" msgstr "OpenNebula ID"
#: models.py:387 #: models.py:388
msgid "share" msgid "share"
msgstr "megosztás" msgstr "megosztás"
#: models.py:389 templates/box/vm/entry.html:57 #: models.py:390 templates/box/vm/entry.html:58
msgid "time of suspend" msgid "time of suspend"
msgstr "felfüggesztés ideje" msgstr "felfüggesztés ideje"
#: models.py:391 templates/box/vm/entry.html:67 #: models.py:392 templates/box/vm/entry.html:68
msgid "time of delete" msgid "time of delete"
msgstr "törlés ideje" msgstr "törlés ideje"
#: models.py:395 #: models.py:396
msgid "instance" msgid "instance"
msgstr "példány" msgstr "példány"
#: models.py:396 #: models.py:397
msgid "instances" msgid "instances"
msgstr "példányok" msgstr "példányok"
#: views.py:68 #: models.py:416
msgid "None"
msgstr "Nincs"
#: views.py:84
msgid "Invalid template ID." msgid "Invalid template ID."
msgstr "Nincs ilyen sablon." msgstr "Nincs ilyen sablon."
#: views.py:71 #: views.py:87
msgid "There are running instances of this template." msgid "There are running instances of this template."
msgstr "A sablonnak még vannak futó példányai." msgstr "A sablonnak még vannak futó példányai."
#: views.py:73 #: views.py:89
msgid "Template is still shared." msgid "Template is still shared."
msgstr "A sablon még meg van osztva." msgstr "A sablon még meg van osztva."
#: views.py:75 #: views.py:91
msgid "You don't have permission to delete this template." msgid "You don't have permission to delete this template."
msgstr "Nincs joga törölni a sablont." msgstr "Nincs joga törölni a sablont."
#: views.py:78 #: views.py:94
msgid "Template successfully deleted." msgid "Template successfully deleted."
msgstr "A sablon törlése sikeres." msgstr "A sablon törlése sikeres."
#: views.py:80 #: views.py:96
msgid "Unexpected error happened." msgid "Unexpected error happened."
msgstr "Váratlan hiba történt." msgstr "Váratlan hiba történt."
#: views.py:94 #: views.py:114
msgid "Could not get Virtual Machine credentials." msgid "Could not get Virtual Machine credentials."
msgstr "Nem találhatóak a virutális gép adatai." msgstr "Nem találhatóak a virutális gép adatai."
#: views.py:95 views.py:434 #: views.py:115 views.py:531
msgid "Failed to power off virtual machine." msgid "Failed to power off virtual machine."
msgstr "A virtuális gép kikapcsolása sikertelen." msgstr "A virtuális gép kikapcsolása sikertelen."
#: views.py:123 #: views.py:164 views.py:211
msgid "You do not have any free share quota." msgid "You do not have any free share quota."
msgstr "Nincs szabad kvótája." msgstr "Nincs szabad kvótája."
#: views.py:157 #: views.py:198 views.py:232
msgid "You do not have enough free share quota." msgid "You do not have enough free share quota."
msgstr "Nincs elég szabad kvótája." msgstr "Nincs elég szabad kvótája."
#: views.py:162 #: views.py:203
#, python-format #, python-format
msgid "Successfully shared %s." msgid "Successfully shared %s."
msgstr "„%s” megosztása sikeres." msgstr "„%s” megosztása sikeres."
#: views.py:176 #: views.py:241
#, python-format
msgid "Successfully edited share %s."
msgstr "„%s” megosztás szerkesztése sikeres."
#: views.py:253
msgid "Template is being saved..." msgid "Template is being saved..."
msgstr "A sablon mentése folyamatban van…" msgstr "A sablon mentése folyamatban van…"
#: views.py:207 #: views.py:284
msgid "" msgid ""
"You do not have any free quota. You can not launch this until you stop an " "You do not have any free quota. You can not launch this until you stop an "
"other instance." "other instance."
msgstr "" msgstr ""
"Nincs szabad kvótája. Addig nem tud gépet indítani, amíg le nem állít egyet." "Nincs szabad kvótája. Addig nem tud gépet indítani, amíg le nem állít egyet."
#: views.py:211 #: views.py:288
msgid "" msgid ""
"The share does not have any free quota. You can not launch this until " "The share does not have any free quota. You can not launch this until "
"someone stops an instance." "someone stops an instance."
msgstr "" msgstr ""
"Ennek a megosztásnak elfogyott a kvótája. Nem tudja addig elindítani, amíg " "Ennek a megosztásnak elfogyott a kvótája. Nem tudja addig elindítani, amíg\n"
"valaki le nem állít egy példányt." "valaki le nem állít egy példányt."
#: views.py:214 #: views.py:291
msgid "" msgid ""
"You do not have any free quota for this share. You can not launch this until " "You do not have any free quota for this share. You can not launch this until "
"you stop an other instance." "you stop an other instance."
msgstr "" msgstr ""
"Nincs szabad kvótája ehhez a megosztáshoz. Nem tudja addig elindítani, amíg " "Nincs szabad kvótája ehhez a megosztáshoz. Nem tudja addig elindítani, amíg\n"
"nem állít le egy másik példányt." "nem állít le egy másik példányt."
#: views.py:217 #: views.py:294
msgid "You are not a member of the share group." msgid "You are not a member of the share group."
msgstr "Nem tagja a megosztás csoportjának." msgstr "Nem tagja a megosztás csoportjának."
#: views.py:238 #: views.py:315
msgid "Can not create template." msgid "Can not create template."
msgstr "Sablon létrehozása sikertelen." msgstr "Sablon létrehozása sikertelen."
#: views.py:243 #: views.py:320
msgid "" msgid ""
"You have no permission to try this instance without a share. Launch a new " "You have no permission to try this instance without a share. Launch a new "
"instance through a share." "instance through a share."
...@@ -419,336 +433,399 @@ msgstr "" ...@@ -419,336 +433,399 @@ msgstr ""
"Nincs joga a sablon kipróbálására megosztás nélkül. Próbálja egy megosztáson " "Nincs joga a sablon kipróbálására megosztás nélkül. Próbálja egy megosztáson "
"keresztül." "keresztül."
#: views.py:256 #: views.py:335
msgid "Failed to create virtual machine." msgid "Failed to create virtual machine."
msgstr "A virtuális gép indítása sikertelen." msgstr "A virtuális gép indítása sikertelen."
#: views.py:332 #: views.py:425
msgid "Port number is in a restricted domain (22000 to 24000)." msgid "Port number is in a restricted domain (22000 to 24000)."
msgstr "A megadott port foglalt tartományba esik (22000-től 24000-ig)." msgstr "A megadott port foglalt tartományba esik (22000-től 24000-ig)."
#: views.py:335 #: views.py:432
#, python-format #, python-format
msgid "Port %d successfully added." msgid "Port %d successfully added."
msgstr "%d számú port hozzáadása sikeres." msgstr "%d számú port hozzáadása sikeres."
#: views.py:337 #: views.py:434
msgid "Adding port failed." msgid "Adding port failed."
msgstr "Port hozzáadása sikertelen." msgstr "Port hozzáadása sikertelen."
#: views.py:353 #: views.py:450
#, python-format #, python-format
msgid "Port %d successfully removed." msgid "Port %s successfully removed."
msgstr "%d számú port eltávolítása sikeres." msgstr "%s számú port eltávolítása sikeres."
#: views.py:355 #: views.py:452
msgid "Removing port failed." msgid "Removing port failed."
msgstr "Port eltávolítása sikertelen." msgstr "Port eltávolítása sikertelen."
#: views.py:365 #: views.py:462
msgid "Virtual machine is successfully deleted." msgid "Virtual machine is successfully deleted."
msgstr "A virtuális gép törlése sikeres." msgstr "A virtuális gép törlése sikeres."
#: views.py:367 #: views.py:464
msgid "Failed to delete virtual machine." msgid "Failed to delete virtual machine."
msgstr "A virtuális gép törlése sikertelen." msgstr "A virtuális gép törlése sikertelen."
#: views.py:389 #: views.py:486
msgid "There are machines running of this share." msgid "There are machines running of this share."
msgstr "A sablonnak még vannak futó példányai." msgstr "A sablonnak még vannak futó példányai."
#: views.py:392 #: views.py:489
msgid "Share is successfully removed." msgid "Share is successfully removed."
msgstr "Megosztás eltávolítása sikeres." msgstr "Megosztás eltávolítása sikeres."
#: views.py:394 #: views.py:491
msgid "Failed to remove share." msgid "Failed to remove share."
msgstr "Megosztás törlése sikertelen." msgstr "Megosztás törlése sikertelen."
#: views.py:402 #: views.py:499
msgid "Virtual machine is successfully stopped." msgid "Virtual machine is successfully stopped."
msgstr "A virtuális gép sikeresen leállt." msgstr "A virtuális gép sikeresen leállt."
#: views.py:404 #: views.py:501
msgid "Failed to stop virtual machine." msgid "Failed to stop virtual machine."
msgstr "A virtuális gép leállítása sikertelen." msgstr "A virtuális gép leállítása sikertelen."
#: views.py:412 #: views.py:509
msgid "Virtual machine is successfully resumed." msgid "Virtual machine is successfully resumed."
msgstr "A virtuális gép sikeresen folytatva." msgstr "A virtuális gép sikeresen folytatva."
#: views.py:414 #: views.py:511
msgid "Failed to resume virtual machine." msgid "Failed to resume virtual machine."
msgstr "A virtuális gép visszatöltése sikertelen." msgstr "A virtuális gép visszatöltése sikertelen."
#: views.py:422 #: views.py:519
msgid "Virtual machine is successfully renewed." msgid "Virtual machine is successfully renewed."
msgstr "A virtuális gép sikeresen meghosszabbítva." msgstr "A virtuális gép sikeresen meghosszabbítva."
#: views.py:424 #: views.py:521
msgid "Failed to renew virtual machine." msgid "Failed to renew virtual machine."
msgstr "A virtuális gép meghosszabbítása sikertelen." msgstr "A virtuális gép meghosszabbítása sikertelen."
#: views.py:432 #: views.py:529
msgid "Virtual machine is successfully powered off." msgid "Virtual machine is successfully powered off."
msgstr "A virtuális gép kikapcsolása sikeres." msgstr "A virtuális gép kikapcsolása sikeres."
#: views.py:442 #: views.py:539
msgid "Virtual machine is successfully restarted." msgid "Virtual machine is successfully restarted."
msgstr "A virtuális gép újraindítása sikeres." msgstr "A virtuális gép újraindítása sikeres."
#: views.py:444 #: views.py:541
msgid "Failed to restart virtual machine." msgid "Failed to restart virtual machine."
msgstr "A virtuális gép újraindítása sikertelen." msgstr "A virtuális gép újraindítása sikertelen."
#: views.py:459 #: views.py:559
msgid "Failed to add public key" msgid "Failed to add public key."
msgstr "Nyilvános kulcs hozzáadása sikertelen." msgstr "Nyilvános kulcs hozzáadása sikertelen."
#: views.py:469 #: views.py:561
msgid "Public key successfully added."
msgstr "Nyilvános kulcs hozzáadása sikeres."
#: views.py:572
msgid "Failed to delete public key" msgid "Failed to delete public key"
msgstr "Nyilvános kulcs törlése sikertelen." msgstr "Nyilvános kulcs törlése sikertelen."
#: views.py:480 #: views.py:584
msgid "Failed to reset keys" msgid "Failed to reset keys"
msgstr "Kulcsok újragenerálása" msgstr "Kulcsok újragenerálása"
#: templates/404.html:7 templates/404.html.py:10 #: templates/404.html:8 templates/500.html:8
msgid ":(" msgid ":("
msgstr ":(" msgstr ":("
#: templates/new-share.html:7 #: templates/404.html:10
#, python-format msgid "The requested page does not exists... Please go away..."
msgid "Sharing template: %(t)s" msgstr "A kért oldal nem található. Nincs itt semmi látnivaló."
msgstr "Sablon megosztása: %(t)s"
#: templates/new-share.html:11 #: templates/500.html:10
msgid "Choose a group" msgid "Internal Server Error... Please leave the server alone..."
msgstr "Válasszon csoportot" msgstr "Kiszolgálóoldali hiba. A manóba!"
#: templates/new-share.html:13 #: templates/base.html:35
msgid "You have no groups." msgid "Logged in:"
msgstr "Még nincs egy csoportja sem." msgstr "Bejelentkezve:"
#: templates/new-share.html:17 #: templates/base.html:36
msgid "Group" msgid "Logout"
msgstr "Csoport" msgstr "Kijelentkezés"
#: templates/base.html:38
msgid "Admin"
msgstr "Admin"
#: templates/base.html:41
msgid "Login"
msgstr "Bejelentkezés"
#: templates/base.html:73
msgid "Legal notice"
msgstr "Impresszum"
#: templates/base.html:74
msgid "Policy"
msgstr "Szabályzat"
#: templates/base.html:75 templates/show.html:114
#: templates/vm-credentials.html:12 templates/box/file/box.html:14
#: templates/box/template/box.html:15 templates/box/vm/box.html:15
msgid "Help"
msgstr "Súgó"
#: templates/new-share.html:32 templates/new-template-flow.html:15 #: templates/base.html:76
msgid "Support"
msgstr "Támogatás"
#: templates/edit-share.html:7
#, python-format
msgid "Editing share: %(t)s"
msgstr "Megosztás szerkesztése: %(t)s"
#: templates/edit-share.html:9 templates/edit-template-flow.html:8
#: templates/new-share.html:32 templates/new-template-flow.html:16
msgid "Change the parameters as needed." msgid "Change the parameters as needed."
msgstr "Változtassa meg a paramétereket szükség szerint." msgstr "Változtassa meg a paramétereket szükség szerint."
#: templates/new-share.html:35 #: templates/edit-share.html:12 templates/new-share.html:35
msgid "Name of share" msgid "Name of share"
msgstr "Megosztás neve" msgstr "Megosztás neve"
#: templates/new-share.html:40 templates/box/file/entry.html:31 #: templates/edit-share.html:17 templates/new-share.html:40
#: templates/box/vm/box.html:87 templates/box/vm/entry.html:28 #: templates/box/file/entry.html:32 templates/box/vm/box.html:93
#: templates/box/vm/entry.html:29
msgid "Type" msgid "Type"
msgstr "Típus" msgstr "Típus"
#: templates/new-share.html:58 templates/box/vm/box.html:91 #: templates/edit-share.html:34 templates/new-share.html:58
#: templates/box/vm/box.html:97
#, python-format #, python-format
msgid "Suspend after %(time)s." msgid "Suspend after %(time)s."
msgstr "Felfüggesztés %(time)s után." msgstr "Felfüggesztés %(time)s után."
#: templates/new-share.html:61 templates/box/vm/box.html:95 #: templates/edit-share.html:37 templates/new-share.html:61
#: templates/box/vm/box.html:101
#, python-format #, python-format
msgid "Delete after %(time)s." msgid "Delete after %(time)s."
msgstr "Törlés %(time)s után." msgstr "Törlés %(time)s után."
#: templates/new-share.html:68 #: templates/edit-share.html:44 templates/new-share.html:68
msgid "Maximal count of instances" msgid "Maximal count of instances"
msgstr "Példányok maximális száma" msgstr "Példányok maximális száma"
#: templates/new-share.html:73 #: templates/edit-share.html:49 templates/new-share.html:73
msgid "Maximal count of instaces/user" msgid "Maximal count of instaces/user"
msgstr "Példányok max. száma/felhasználó" msgstr "Példányok max. száma/felhasználó"
#: templates/new-share.html:79 templates/new-template-flow.html:49 #: templates/edit-share.html:55 templates/edit-template-flow.html:42
#: templates/box/template/box.html:107 templates/box/template/entry.html:32 #: templates/new-share.html:79 templates/new-template-flow.html:50
#: templates/box/vm/box.html:99 #: templates/box/template/box.html:123 templates/box/template/entry.html:32
#: templates/box/vm/box.html:105
msgid "Description" msgid "Description"
msgstr "Leírás" msgstr "Leírás"
#: templates/new-share.html:85 templates/new-template-flow-1.html:43 #: templates/edit-share.html:61 templates/edit-template-flow.html:48
#: templates/new-template-flow.html:55 #: templates/new-share.html:85 templates/new-template-flow-1.html:44
#: templates/new-template-flow.html:56
msgid "Cancel" msgid "Cancel"
msgstr "Mégsem" msgstr "Mégsem"
#: templates/new-share.html:86 templates/box/template/box.html:65 #: templates/edit-share.html:62 templates/edit-template-flow.html:49
#: templates/box/template/box.html.py:66 #: templates/show.html:49 templates/box/file/box.html:112
#: templates/box/template/summary.html:46 msgid "Save"
#: templates/box/template/summary.html:47 templates/box/vm/entry.html:33 msgstr "Mentés"
#: templates/edit-template-flow.html:7
msgid "Edit template"
msgstr "Sablon szerkesztése"
#: templates/edit-template-flow.html:11 templates/new-template-flow.html:19
msgid "Name"
msgstr "Név"
#: templates/edit-template-flow.html:17 templates/new-template-flow.html:25
#: templates/box/template/box.html:114 templates/box/template/entry.html:23
#: templates/box/vm/box.html:84 templates/box/vm/entry.html:44
msgid "Size"
msgstr "Méret"
#: templates/edit-template-flow.html:33 templates/new-template-flow.html:41
#, python-format
msgid "%(n)s core"
msgid_plural "%(n)s cores"
msgstr[0] "%(n)s mag"
msgstr[1] "%(n)s mag"
#: templates/new-share.html:7
#, python-format
msgid "Sharing template: %(t)s"
msgstr "Sablon megosztása: %(t)s"
#: templates/new-share.html:11
msgid "Choose a group"
msgstr "Válasszon csoportot"
#: templates/new-share.html:13
msgid "You have no groups."
msgstr "Még nincs egy csoportja sem."
#: templates/new-share.html:17
msgid "Group"
msgstr "Csoport"
#: templates/new-share.html:86 templates/box/template/box.html:71
#: templates/box/template/box.html.py:72
#: templates/box/template/summary.html:60
#: templates/box/template/summary.html:61 templates/box/vm/entry.html:34
msgid "Share" msgid "Share"
msgstr "Megosztás" msgstr "Megosztás"
#: templates/new-template-flow-1.html:11 templates/new-template-flow.html:11 #: templates/new-template-flow-1.html:12 templates/new-template-flow.html:12
#, python-format #, python-format
msgid "%(step)s/%(all)s" msgid "%(step)s/%(all)s"
msgstr "%(step)s/%(all)s" msgstr "%(step)s/%(all)s"
#: templates/new-template-flow-1.html:14 templates/new-template-flow.html:14 #: templates/new-template-flow-1.html:15 templates/new-template-flow.html:15
#, python-format #, python-format
msgid "Step %(step)s" msgid "Step %(step)s"
msgstr "%(step)s. lépés" msgstr "%(step)s. lépés"
#: templates/new-template-flow-1.html:16 #: templates/new-template-flow-1.html:17
msgid "Please choose the base system you want to customize." msgid "Please choose the base system you want to customize."
msgstr "Válasszon egy alaprendszert, amelyet testre kíván szabni." msgstr "Válasszon egy alaprendszert, amelyet testre kíván szabni."
#: templates/new-template-flow-1.html:21 #: templates/new-template-flow-1.html:22
msgid "There are no available templates." msgid "There are no available templates."
msgstr "Nincs elérhető sablon." msgstr "Nincs elérhető sablon."
#: templates/new-template-flow-1.html:31 templates/box/template/box.html:56 #: templates/new-template-flow-1.html:32 templates/box/template/box.html:62
msgid "locked" msgid "locked"
msgstr "zárolt" msgstr "zárolt"
#: templates/new-template-flow-1.html:32 templates/box/template/box.html:57 #: templates/new-template-flow-1.html:33 templates/box/template/box.html:63
msgid "This is a shared template." msgid "This is a shared template."
msgstr "Ez egy megosztott sablon." msgstr "Ez egy megosztott sablon."
#: templates/new-template-flow-1.html:44 #: templates/new-template-flow-1.html:45
msgid "Next &raquo;" msgid "Next &raquo;"
msgstr "Tovább &raquo;" msgstr "Tovább &raquo;"
#: templates/new-template-flow.html:18 #: templates/new-template-flow.html:57
msgid "Name"
msgstr "Név"
#: templates/new-template-flow.html:24 templates/box/template/box.html:98
#: templates/box/template/entry.html:23 templates/box/vm/box.html:78
#: templates/box/vm/entry.html:43
msgid "Size"
msgstr "Méret"
#: templates/new-template-flow.html:40
#, python-format
msgid "%(n)s core"
msgid_plural "%(n)s cores"
msgstr[0] "%(n)s mag"
msgstr[1] "%(n)s mag"
#: templates/new-template-flow.html:56
msgid "Launch master instance" msgid "Launch master instance"
msgstr "Mesterpéldány indítása" msgstr "Mesterpéldány indítása"
#: templates/show.html:28 #: templates/show.html:43
msgid "This is a master image for your new template." msgid "This is a master image for your new template."
msgstr "Ez egy mestergép az új sablonhoz." msgstr "Ez egy mestergép az új sablonhoz."
#: templates/show.html:34 templates/box/file/box.html:106 #: templates/show.html:54
msgid "Save"
msgstr "Mentés"
#: templates/show.html:39
msgid "Connect to the machine." msgid "Connect to the machine."
msgstr "Csatlakozzon a géphez." msgstr "Csatlakozzon a géphez."
#: templates/show.html:41 #: templates/show.html:56
msgid "Do all the needed installation/customization." msgid "Do all the needed installation/customization."
msgstr "Végezze el a szükséges telepítést, testreszabást." msgstr "Végezze el a szükséges telepítést, testreszabást."
#: templates/show.html:44 #: templates/show.html:59
msgid "Log off (keep the machine running)." msgid "Log off (keep the machine running)."
msgstr "Jelentkezzen ki (a gépet NE állítsa le)." msgstr "Jelentkezzen ki (a gépet NE állítsa le)."
#: templates/show.html:47 #: templates/show.html:62
msgid "Click on the \"save\" button on the right." msgid "Click on the \"save\" button on the right."
msgstr "Kattintson jobboldalt a „mentés” gombra." msgstr "Kattintson jobboldalt a „mentés” gombra."
#: templates/show.html:50 #: templates/show.html:65
msgid "The machine will be shut down and its disk saved." msgid "The machine will be shut down and its disk saved."
msgstr "A gép leáll, lemeze mentésre kerül." msgstr "A gép leáll, lemeze mentésre kerül."
#: templates/show.html:53 #: templates/show.html:68
msgid "You can share the template with your groups." msgid "You can share the template with your groups."
msgstr "Megoszthatja a sablont csoportjaival." msgstr "Megoszthatja a sablont csoportjaival."
#: templates/show.html:65 #: templates/show.html:80
msgid "Starting..." msgid "Starting..."
msgstr "Indítás…" msgstr "Indítás…"
#: templates/show.html:71 #: templates/show.html:85
msgid "Saving..."
msgstr "Mentés…"
#: templates/show.html:91
msgid "Running" msgid "Running"
msgstr "Fut" msgstr "Fut"
#: templates/show.html:75 #: templates/show.html:95
msgid "Stopped" msgid "Stopped"
msgstr "Leállítva" msgstr "Leállítva"
#: templates/show.html:78 #: templates/show.html:98
msgid "Deleted" msgid "Deleted"
msgstr "Törölve" msgstr "Törölve"
#: templates/show.html:81 #: templates/show.html:101
msgid "Unexpected error occured" msgid "Unexpected error occured"
msgstr "Váratlan hiba történt" msgstr "Váratlan hiba történt"
#: templates/show.html:86 #: templates/show.html:106
msgid "Login credentials" msgid "Login credentials"
msgstr "Belépési adatok" msgstr "Belépési adatok"
#: templates/show.html:94 templates/vm-credentials.html:11 #: templates/show.html:117
#: templates/box/file/box.html:12 templates/box/template/box.html:13
#: templates/box/vm/box.html:13
msgid "Help"
msgstr "Súgó"
#: templates/show.html:97
msgid "" msgid ""
"This is a list about the network ports\n" "This is a list about the network ports\n"
" forwarded to the public internet." " forwarded to the public internet."
msgstr "Ez a nyilvános internet felé továbbított hálózati portok listája." msgstr "Ez a nyilvános internet felé továbbított hálózati portok listája."
#: templates/show.html:99 #: templates/show.html:119
msgid "" msgid ""
"You can access the given private port of\n" "You can access the given private port of\n"
" the VM trough the public address of the network.\n" " the VM trough the public address of the network.\n"
" " " "
msgstr "A VM megadott belső portját elérheti a hálózat külső címén keresztül." msgstr ""
"A VM megadott belső portját elérheti a hálózat külső címén keresztül.\n"
" "
#: templates/show.html:102 #: templates/show.html:122
msgid "" msgid ""
"On the IPV6 network you can access the\n" "On the IPV6 network you can access the\n"
" listed private ports direcly using the VM's global IPV6\n" " listed private ports direcly using the VM's global IPV6\n"
" address (connections to other ports are dropped).\n" " address (connections to other ports are dropped).\n"
" " " "
msgstr "" msgstr ""
"Az IPV6 hálózaton a megadott belső portokat közvetlenül érheti el a VM " "Az IPV6 hálózaton a megadott belső portokat közvetlenül érheti el a VM\n"
"globális IPV6 címén (a többi portra érkező kapcsolatokat eldobjuk)." "globális IPV6 címén (a többi portra érkező kapcsolatokat eldobjuk).\n"
" "
#: templates/show.html:108 #: templates/show.html:128
msgid "Port administration" msgid "Port administration"
msgstr "Portok kezelése" msgstr "Portok kezelése"
#: templates/show.html:114 templates/vm-credentials.html:6 #: templates/show.html:134 templates/vm-credentials.html:7
msgid "Protocol" msgid "Protocol"
msgstr "Protokoll" msgstr "Protokoll"
#: templates/show.html:115 #: templates/show.html:135
msgid "Public port" msgid "Public port"
msgstr "Külső port" msgstr "Külső port"
#: templates/show.html:116 #: templates/show.html:136
msgid "Private port" msgid "Private port"
msgstr "Belső port" msgstr "Belső port"
#: templates/show.html:124 templates/box/template/box.html:82 #: templates/show.html:144 templates/box/template/box.html:91
#: templates/box/template/summary.html:20 templates/box/vm/summary.html:39 #: templates/box/template/summary.html:24 templates/box/vm/summary.html:40
#: templates/box/vm/summary.html.py:40 templates/box/vm/summary.html:49 #: templates/box/vm/summary.html.py:41 templates/box/vm/summary.html:50
#: templates/box/vm/summary.html.py:50 templates/box/vm/summary.html:56 #: templates/box/vm/summary.html.py:51 templates/box/vm/summary.html:57
#: templates/box/vm/summary.html.py:57 templates/box/vm/summary.html:60 #: templates/box/vm/summary.html.py:58 templates/box/vm/summary.html:61
#: templates/box/vm/summary.html.py:61 #: templates/box/vm/summary.html.py:62
msgid "Delete" msgid "Delete"
msgstr "Törlés" msgstr "Törlés"
#: templates/show.html:142 #: templates/show.html:164
msgid "Add" msgid "Add"
msgstr "Hozzáadás" msgstr "Hozzáadás"
#: templates/vm-credentials.html:15 #: templates/vm-credentials.html:16
msgid "" msgid ""
"You can access Linux machines through\n" "You can access Linux machines through\n"
" the SSH protocol (we recommend\n" " the SSH protocol (we recommend\n"
...@@ -759,134 +836,137 @@ msgid "" ...@@ -759,134 +836,137 @@ msgid ""
" " " "
msgstr "" msgstr ""
"A Linux gépeket az SSH protokollon érheti el. Windowshoz a <a href=\"http://" "A Linux gépeket az SSH protokollon érheti el. Windowshoz a <a href=\"http://"
"www.chiark.greenend.org.uk/~sgtatham/putty/\">PuTTY</a>-ot, minden más " "www.chiark.greenend.org.uk/~sgtatham/putty/\">PuTTY</a>-ot, minden más\n"
"rendszerhez az OpenSSH klienst ajánljuk." "rendszerhez az OpenSSH klienst ajánljuk.\n"
" "
#: templates/vm-credentials.html:21 #: templates/vm-credentials.html:22
msgid "" msgid ""
"Graphical log in is also supported with\n" "Graphical log in is also supported with\n"
" the <a href=\"http://www.nomachine.com/download.php" " the <a href=\"http://www.nomachine.com/download.php"
"\">\n" "\">\n"
" NoMachine NX Client</a> application." " NoMachine NX Client</a> application."
msgstr "" msgstr ""
"Grafikus bejelentkezés a <a href=\"http://www.nomachine.com/download.php\"> " "Grafikus bejelentkezés a <a href=\"http://www.nomachine.com/download.php\">\n"
"NoMachine NX Client</a> alkalmazással lehetséges." "NoMachine NX Client</a> alkalmazással lehetséges."
#: templates/vm-credentials.html:26 #: templates/vm-credentials.html:27
msgid "" msgid ""
"You can access Windows machines through\n" "You can access Windows machines through\n"
" the remote desktop protocol." " the remote desktop protocol."
msgstr "A Windows gépeket a távoli asztal protokollon érheti el." msgstr "A Windows gépeket a távoli asztal protokollon érheti el."
#: templates/vm-credentials.html:28 #: templates/vm-credentials.html:29
msgid "" msgid ""
"We recommend the built-in remote desktop\n" "We recommend the built-in remote desktop\n"
" client for Windows and Remmina for Linux." " client for Windows and Remmina for Linux."
msgstr "" msgstr ""
"Windowshoz a beépített távoli asztali kapcsolat alkalmazást, Linuxhoz a " "Windowshoz a beépített távoli asztali kapcsolat alkalmazást, Linuxhoz a\n"
"Remminát ajánljuk." "Remminát ajánljuk."
#: templates/vm-credentials.html:37 #: templates/vm-credentials.html:38
msgid "IP" msgid "IP"
msgstr "IP" msgstr "IP"
#: templates/vm-credentials.html:41 #: templates/vm-credentials.html:42
msgid "Port" msgid "Port"
msgstr "Port" msgstr "Port"
#: templates/vm-credentials.html:45 #: templates/vm-credentials.html:46
msgid "Username" msgid "Username"
msgstr "Felhasználónév" msgstr "Felhasználónév"
#: templates/vm-credentials.html:49 #: templates/vm-credentials.html:50
msgid "Password" msgid "Password"
msgstr "Jelszó" msgstr "Jelszó"
#: templates/box/file/box.html:7 #: templates/box/file/box.html:8
msgid "Data store" msgid "Data store"
msgstr "Adattár" msgstr "Adattár"
#: templates/box/file/box.html:15 #: templates/box/file/box.html:17
msgid "This is your global data store." msgid "This is your global data store."
msgstr "Ez az ön központi adattárja." msgstr "Ez az ön központi adattárja."
#: templates/box/file/box.html:16 #: templates/box/file/box.html:18
msgid "" msgid ""
"You can access it from all your own virtual machines,\n" "You can access it from all your own virtual machines,\n"
" the lab client, this web interface, or through SFTP protocol.\n" " the lab client, this web interface, or through SFTP protocol.\n"
" " " "
msgstr "" msgstr ""
"A fájlokat elérheti az összes virtuális gépéről, a laborkliensről, erről a " "A fájlokat elérheti az összes virtuális gépéről, a laborkliensről, erről\n"
"webes felületről, vagy SFTP protokollon." "a webes felületről, vagy SFTP protokollon.\n"
" "
#: templates/box/file/box.html:19 #: templates/box/file/box.html:21
msgid "" msgid ""
"This directory is mounted on Windows machines as Z:\n" "This directory is mounted on Windows machines as Z:\n"
" drive, and on Linux ones as ~/sshfs." " drive, and on Linux ones as ~/sshfs."
msgstr "" msgstr ""
"A windowsos gépeken a Z: meghajtóra, Linuxon a ~/sshfs katalógusba van " "A windowsos gépeken a Z: meghajtóra, Linuxon a ~/sshfs katalógusba\n"
"csatolva." "vancsatolva."
#: templates/box/file/box.html:21 #: templates/box/file/box.html:23
msgid "" msgid ""
"If you log in on lab machines (currently Ubuntu only),\n" "If you log in on lab machines (currently Ubuntu only),\n"
" you can see this folder also as ~/sshfs." " you can see this folder also as ~/sshfs."
msgstr "" msgstr ""
"Ha a laborgépekre bejelentkezik (jelenleg csak Ubuntu alatt), akkor a " "Ha a laborgépekre bejelentkezik (jelenleg csak Ubuntu alatt), akkor\n"
"fájlokat szintén a ~/sshfs katalógusban találja." "afájlokat szintén a ~/sshfs katalógusban találja."
#: templates/box/file/box.html:23 #: templates/box/file/box.html:25
#, python-format #, python-format
msgid "" msgid ""
"You can also use an SFTP client (eg.\n" "You can also use an SFTP client (eg.\n"
" WinSCP) to access your files at %(serv)s. You will need to register " " WinSCP) to access your files at %(serv)s. You will need to "
"a\n" "register a\n"
" public key bellow." " public key bellow."
msgstr "" msgstr ""
"SFTP klienst (pl. WinSCP) is használhat a %(serv)s címre csatlakozva. Ehhez " "SFTP klienst (pl. WinSCP) is használhat a %(serv)s címre csatlakozva.\n"
"alább tudja nyilvános kulcsát regisztrálni." "Ehhezalább tudja nyilvános kulcsát regisztrálni."
#: templates/box/file/box.html:31 templates/box/template/box.html:26
#: templates/box/vm/box.html:26
msgid "Show/hide box"
msgstr "Doboz megjelenítése/rejtése"
#: templates/box/file/box.html:60 #: templates/box/file/box.html:66
msgid "No files." msgid "No files."
msgstr "Nincs megjeleníthető fájl." msgstr "Nincs megjeleníthető fájl."
#: templates/box/file/box.html:73 #: templates/box/file/box.html:79
msgid "Create folder" msgid "Create folder"
msgstr "Mappa létrehozása" msgstr "Mappa létrehozása"
#: templates/box/file/box.html:75 #: templates/box/file/box.html:81
msgid "Name of new folder" msgid "Name of new folder"
msgstr "Új mappa neve" msgstr "Új mappa neve"
#: templates/box/file/box.html:83 #: templates/box/file/box.html:95
msgid "Toplist"
msgstr "Legújabb fájlok"
#: templates/box/file/box.html:89
msgid "Manage keys" msgid "Manage keys"
msgstr "Kulcsok kezelése" msgstr "Kulcsok kezelése"
#: templates/box/file/box.html:98 #: templates/box/file/box.html:104
msgid "Add public key" msgid "Add public key"
msgstr "Nyilvános kulcs hozzáadása" msgstr "Nyilvános kulcs hozzáadása"
#: templates/box/file/box.html:105 #: templates/box/file/box.html:111
msgid "Public key in OpenSSH format" msgid "Public key in OpenSSH format"
msgstr "Nyilvános kulcs OpenSSH formátumban" msgstr "Nyilvános kulcs OpenSSH formátumban"
#: templates/box/file/box.html:113 #: templates/box/file/box.html:119
msgid "Reset key" msgid "Reset key"
msgstr "Kulcsok újragenerálása" msgstr "Kulcsok újragenerálása"
#: templates/box/file/box.html:122 #: templates/box/file/box.html:128
msgid "File upload" msgid "File upload"
msgstr "Fájlfeltöltés" msgstr "Fájlfeltöltés"
#: templates/box/file/box.html:128 #: templates/box/file/box.html:134
msgid "Drag and drop files here to start uploading." msgid "Drag and drop files here to start uploading."
msgstr "Húzza ide a fájlt a feltöltés megkezdéséhez." msgstr "Húzza ide a fájlt a feltöltés megkezdéséhez."
#: templates/box/file/box.html:130 #: templates/box/file/box.html:136
msgid "" msgid ""
"You can also use the <a href=\"#\" id=\"old-upload\">the traditional upload " "You can also use the <a href=\"#\" id=\"old-upload\">the traditional upload "
"form</a>." "form</a>."
...@@ -894,222 +974,402 @@ msgstr "" ...@@ -894,222 +974,402 @@ msgstr ""
"Használhatja a <a href=\"#\" id=\"old-upload\">hagyományos feltöltő űrlapot</" "Használhatja a <a href=\"#\" id=\"old-upload\">hagyományos feltöltő űrlapot</"
"a> is." "a> is."
#: templates/box/file/box.html:132 #: templates/box/file/box.html:138
msgid "Upload limit is 1GB per file!" msgid "Upload limit is 1GB per file!"
msgstr "A feltöltési limit 1GiB fájlonként!" msgstr "A feltöltési limit 1GiB fájlonként!"
#: templates/box/file/box.html:136 #: templates/box/file/box.html:142
msgid "Error: File is bigger than 1GB!" msgid "Error: File is bigger than 1GB!"
msgstr "Hiba: a fájl nagyobb 1 GiB-nál." msgstr "Hiba: a fájl nagyobb 1 GiB-nál."
#: templates/box/file/box.html:137 #: templates/box/file/box.html:143
msgid "Error: Upload server is not available!" msgid "Error: Upload server is not available!"
msgstr "Hiba: a feltöltő kiszolgáló nem érhető el." msgstr "Hiba: a feltöltő kiszolgáló nem érhető el."
#: templates/box/file/box.html:138 #: templates/box/file/box.html:144
msgid "Error: File already exists!" msgid "Error: File already exists!"
msgstr "Hiba: a fájl már létezik." msgstr "Hiba: a fájl már létezik."
#: templates/box/file/box.html:157 #: templates/box/file/box.html:163
msgid "File quota" msgid "File quota"
msgstr "Fájlkvóta" msgstr "Fájlkvóta"
#: templates/box/file/box.html:157 #: templates/box/file/box.html:163
msgid "Used space" msgid "Used space"
msgstr "Használt terület" msgstr "Használt terület"
#: templates/box/file/box.html:158 #: templates/box/file/box.html:164
msgid "soft limit" msgid "soft limit"
msgstr "puha limit" msgstr "puha limit"
#: templates/box/file/box.html:160 #: templates/box/file/box.html:166
msgid "hard limit" msgid "hard limit"
msgstr "kemény limit" msgstr "kemény limit"
#: templates/box/file/entry.html:11 #: templates/box/file/entry.html:12
msgid "rename" msgid "rename"
msgstr "átnevezés" msgstr "átnevezés"
#: templates/box/file/entry.html:14 #: templates/box/file/entry.html:15
msgid "remove" msgid "remove"
msgstr "eltávolítás" msgstr "eltávolítás"
#: templates/box/file/entry.html:17 #: templates/box/file/entry.html:18
msgid "download" msgid "download"
msgstr "letöltés" msgstr "letöltés"
#: templates/box/file/entry.html:27 #: templates/box/file/entry.html:28
msgid "Last modification" msgid "Last modification"
msgstr "Utolsó módosítás" msgstr "Utolsó módosítás"
#: templates/box/key/entry.html:18 templates/box/template/summary.html:50 #: templates/box/key/entry.html:19 templates/box/template/summary.html:64
#: templates/box/template/summary.html:51 #: templates/box/template/summary.html:65
msgid "Remove" msgid "Remove"
msgstr "Törlés" msgstr "Törlés"
#: templates/box/template/box.html:7 #: templates/box/template/box.html:8
msgid "Templates" msgid "Templates"
msgstr "Sablonok" msgstr "Sablonok"
#: templates/box/template/box.html:16 #: templates/box/template/box.html:18
msgid "This is the list of your own templates." msgid "This is the list of your own templates."
msgstr "Ez a saját sablonjainak listája." msgstr "Ez a saját sablonjainak listája."
#: templates/box/template/box.html:17 #: templates/box/template/box.html:19
msgid "Templates are customized versions of the base images." msgid "Templates are customized versions of the base images."
msgstr "A sablonok alaprendszerek testre szabott változatai." msgstr "A sablonok alaprendszerek testre szabott változatai."
#: templates/box/template/box.html:18 #: templates/box/template/box.html:20
msgid "" msgid ""
"You can install all the needed software on a master\n" "You can install all the needed software on a master\n"
" machine, and it will be ready to run by your students in minutes.\n" " machine, and it will be ready to run by your students in "
"minutes.\n"
" " " "
msgstr "" msgstr ""
"Telepítheti az összes szükséges szoftvert egy mestergépen, és az így készült " "Telepítheti az összes szükséges szoftvert egy mestergépen, és az így\n"
"sablon pár perc múltán készen is állhat a hallgatók számára." "készült sablon pár perc múltán készen is állhat a hallgatók számára.\n"
" "
#: templates/box/template/box.html:34 #: templates/box/template/box.html:40
msgid "You have no own templates." msgid "You have no own templates."
msgstr "Még nincs egy sablonja sem." msgstr "Még nincs egy sablonja sem."
#: templates/box/template/box.html:36 #: templates/box/template/box.html:42
msgid "" msgid ""
"Create a new one, and share it with your students. Or you can also use a " "Create a new one, and share it with your students. Or you can also use a "
"common one." "common one."
msgstr "" msgstr ""
"Hozzon létre egyet, és ossza meg hallgatóival. Vagy használjon egy közöset." "Hozzon létre egyet, és ossza meg hallgatóival. Vagy használjon egy közöset."
#: templates/box/template/box.html:62 templates/box/template/summary.html:40 #: templates/box/template/box.html:68 templates/box/template/summary.html:54
msgid "Try" msgid "Try"
msgstr "Kipróbálás" msgstr "Kipróbálás"
#: templates/box/template/box.html:63 templates/box/template/summary.html:41 #: templates/box/template/box.html:69 templates/box/template/summary.html:55
msgid "Start" msgid "Start"
msgstr "Indítás" msgstr "Indítás"
#: templates/box/template/box.html:93 templates/box/template/entry.html:18 #: templates/box/template/box.html:88 templates/box/template/summary.html:21
#: templates/box/vm/box.html:73 templates/box/vm/entry.html:23 #: templates/box/template/summary.html:50
#: templates/box/template/summary.html:51
#: templates/box/template/summary.html:57
#: templates/box/template/summary.html:58
msgid "Edit"
msgstr "Szerkesztés"
#: templates/box/template/box.html:99 templates/box/template/summary.html:32
msgid "No description available"
msgstr "Nincs leírás"
#: templates/box/template/box.html:109 templates/box/template/entry.html:18
#: templates/box/vm/box.html:79 templates/box/vm/entry.html:24
msgid "System" msgid "System"
msgstr "Rendszer" msgstr "Rendszer"
#: templates/box/template/box.html:112 templates/box/template/entry.html:37 #: templates/box/template/box.html:128 templates/box/template/entry.html:37
#: templates/box/vm/entry.html:52 #: templates/box/vm/entry.html:53
msgid "Created at" msgid "Created at"
msgstr "Létrehozás ideje" msgstr "Létrehozás ideje"
#: templates/box/template/box.html:117 templates/box/template/entry.html:42 #: templates/box/template/box.html:133 templates/box/template/entry.html:42
msgid "Running instances" msgid "Running instances"
msgstr "Futó példányok" msgstr "Futó példányok"
#: templates/box/template/box.html:131 #: templates/box/template/box.html:147
#, python-format #, python-format
msgid "Share quota: %(used)s/%(all)s" msgid "Share quota: %(used)s/%(all)s"
msgstr "Megosztó kvóta: %(used)s/%(all)s" msgstr "Megosztó kvóta: %(used)s/%(all)s"
#: templates/box/template/summary.html:43 #: templates/box/vm/box.html:8
#: templates/box/template/summary.html:44
#: templates/box/template/summary.html:53
#: templates/box/template/summary.html:54
msgid "Edit"
msgstr "Szerkesztés"
#: templates/box/vm/box.html:7
msgid "Virtual machines" msgid "Virtual machines"
msgstr "Virtuális gépek" msgstr "Virtuális gépek"
#: templates/box/vm/box.html:16 #: templates/box/vm/box.html:18
msgid "This is the list of your running virtual machines." msgid "This is the list of your running virtual machines."
msgstr "Ez az ön futó virtuális gépeinek listája." msgstr "Ez az ön futó virtuális gépeinek listája."
#: templates/box/vm/box.html:17 #: templates/box/vm/box.html:19
msgid "" msgid ""
"You can launch a new VM instance if it is shared by\n" "You can launch a new VM instance if it is shared by\n"
" a teacher for one of your groups." " a teacher for one of your groups."
msgstr "" msgstr ""
"Egy VM példányt akkor tud elindítani, ha egy oktató megosztotta egy olyan " "Egy VM példányt akkor tud elindítani, ha egy oktató megosztotta egy olyan\n"
"csoporttal, amelynek tagja." "csoporttal, amelynek tagja."
#: templates/box/vm/box.html:19 #: templates/box/vm/box.html:21
msgid "" msgid ""
"Please note, that users and shares both have a limit\n" "Please note, that users and shares both have a limit\n"
" of launchable instances." " of launchable instances."
msgstr "" msgstr ""
"Vegye figyelembe, hogy a felhasználóknak és az egyes megosztásoknak is " "Vegye figyelembe, hogy a felhasználóknak és az egyes megosztásoknak is\n"
"korlátozva van a futtatható példányszám." "korlátozva van a futtatható példányszám."
#: templates/box/vm/box.html:34 #: templates/box/vm/box.html:40
msgid "You have not started any machines yet." msgid "You have not started any machines yet."
msgstr "Még nem indított egy gépet sem." msgstr "Még nem indított egy gépet sem."
#: templates/box/vm/box.html:36 #: templates/box/vm/box.html:42
msgid "Choose a template, and you can use the system in a minute." msgid "Choose a template, and you can use the system in a minute."
msgstr "Válasszon egy sablont, és egy percen belül használhatja a rendszert." msgstr "Válasszon egy sablont, és egy percen belül használhatja a rendszert."
#: templates/box/vm/box.html:45 #: templates/box/vm/box.html:51
msgid "Start new machine" msgid "Start new machine"
msgstr "Új gép indítása" msgstr "Új gép indítása"
#: templates/box/vm/box.html:50 #: templates/box/vm/box.html:56
msgid "Available shares" msgid "Available shares"
msgstr "Elérhető megosztások" msgstr "Elérhető megosztások"
#: templates/box/vm/box.html:52 #: templates/box/vm/box.html:58
msgid "Choose one of the following shared templates to launch." msgid "Choose one of the following shared templates to launch."
msgstr "Válasszon egyet az alábbi megosztott sablonok közül." msgstr "Válasszon egyet az alábbi megosztott sablonok közül."
#: templates/box/vm/box.html:108 #: templates/box/vm/box.html:114
msgid "Quota reached" msgid "Quota reached"
msgstr "Kvóta betelt" msgstr "Kvóta betelt"
#: templates/box/vm/box.html:108 #: templates/box/vm/box.html:114
msgid "Launch" msgid "Launch"
msgstr "Indítás" msgstr "Indítás"
#: templates/box/vm/box.html:128 #: templates/box/vm/box.html:134
#, python-format #, python-format
msgid "Personal quota: %(used)s/%(all)s" msgid "Personal quota: %(used)s/%(all)s"
msgstr "Személyes kvóta: %(used)s/%(all)s" msgstr "Személyes kvóta: %(used)s/%(all)s"
#: templates/box/vm/entry.html:18 #: templates/box/vm/entry.html:19
msgid "Hostname" msgid "Hostname"
msgstr "Gépnév" msgstr "Gépnév"
#: templates/box/vm/entry.html:38 #: templates/box/vm/entry.html:39
msgid "Template" msgid "Template"
msgstr "Sablon" msgstr "Sablon"
#: templates/box/vm/entry.html:59 templates/box/vm/entry.html.py:60 #: templates/box/vm/entry.html:60 templates/box/vm/entry.html.py:61
msgid "Renew suspend time" msgid "Renew suspend time"
msgstr "Felfüggesztési idő meghosszabbítása" msgstr "Felfüggesztési idő meghosszabbítása"
#: templates/box/vm/entry.html:69 templates/box/vm/entry.html.py:70 #: templates/box/vm/entry.html:70 templates/box/vm/entry.html.py:71
msgid "Renew deletion time" msgid "Renew deletion time"
msgstr "Törlési idő meghosszabbítása" msgstr "Törlési idő meghosszabbítása"
#: templates/box/vm/entry.html:78 templates/box/vm/summary.html:15 #: templates/box/vm/entry.html:79 templates/box/vm/summary.html:16
msgid "More details" msgid "More details"
msgstr "További részletek" msgstr "További részletek"
#: templates/box/vm/summary.html:25 templates/box/vm/summary.html.py:26 #: templates/box/vm/summary.html:26 templates/box/vm/summary.html.py:27
msgid "Edit name" msgid "Edit name"
msgstr "Név szerkesztése" msgstr "Név szerkesztése"
#: templates/box/vm/summary.html:33 templates/box/vm/summary.html.py:34 #: templates/box/vm/summary.html:34 templates/box/vm/summary.html.py:35
msgid "Connect" msgid "Connect"
msgstr "Csatlakozás" msgstr "Csatlakozás"
#: templates/box/vm/summary.html:36 templates/box/vm/summary.html.py:37 #: templates/box/vm/summary.html:37 templates/box/vm/summary.html.py:38
msgid "Pause" msgid "Pause"
msgstr "Felfüggesztés" msgstr "Felfüggesztés"
#: templates/box/vm/summary.html:42 #: templates/box/vm/summary.html:43
msgid "Restart" msgid "Restart"
msgstr "Újraindítás" msgstr "Újraindítás"
#: templates/box/vm/summary.html:53 templates/box/vm/summary.html.py:54 #: templates/box/vm/summary.html:54 templates/box/vm/summary.html.py:55
msgid "Resume" msgid "Resume"
msgstr "Folytatás" msgstr "Folytatás"
#: templates/mails/base.txt:2
#, python-format
msgid ""
"\n"
"Dear %(name)s,\n"
"\n"
msgstr ""
"\n"
"Kedves %(name)s!\n"
"\n"
#: templates/mails/notification-ban-now.txt:6
#, python-format
msgid ""
"\n"
"Our network intrusion detection system showed that your machine\n"
"\"%(vm)s\" pursues the following forbidden network activity: %(reason)s.\n"
"\n"
"\"%(vm)s\" has been BANNED from all network activity\n"
"including remote desktop and shell connection.\n"
"\n"
"Details:\n"
"%(snort_message)s\n"
msgstr ""
"\n"
"A hálózatibehatolás-érzékelő rendszerünk jelzése szerint az ön „%(vm)s”\n"
"nevű gépe a következő tiltott hálózati aktivitást folytatja: %(reason)s.\n"
"\n"
"A(z) „%(vm)s” gép minden hálózati aktivitása TILTÁSRA került, beleértve a \n"
"távoli asztali- és shellkapcsolatokat.\n"
"\n"
"Részletek: %(snort_message)s\n"
#: templates/mails/notification-ban-now.txt:18
#, python-format
msgid ""
"\n"
"Please, reply to this notification, or delete the instance on the\n"
"cloud portal: %(url)s\n"
msgstr ""
"\n"
"Kérjük, válaszoljon erre a figyelmeztetésre, vagy törölje a gépet a\n"
"cloud\n"
"portálon: %(url)s\n"
#: templates/mails/notification-delete-now.txt:6
#, python-format
msgid ""
"\n"
"Your %(state)s virtual machine \"%(vm)s\" has been DELETED\n"
"at %(date)s.\n"
msgstr ""
"\n"
"Az ön „%(vm)s” nevű %(state)s állapotú virtuális gépét TÖRÖLTÜK\n"
"%(date)s időpontban.\n"
#: templates/mails/notification-delete-now.txt:11
msgid ""
"\n"
"The disk image is IRRECOVERABLY REMOVED.\n"
msgstr ""
"\n"
"A lemezkép VISSZAÁLLÍTHATATLANUL TÖRLÉSRE került.\n"
#: templates/mails/notification-delete-now.txt:15
#, python-format
msgid ""
"\n"
"You can start a new instance of the template on the cloud portal:\n"
"%(url)s\n"
msgstr ""
"\n"
"Elindíthatja a sablon egy új példányát a cloud portálon:\n"
"%(url)s\n"
#: templates/mails/notification-delete.txt:6
#, python-format
msgid ""
"\n"
"Your %(state)s virtual machine \"%(vm)s\" is going to be DELETED\n"
"at %(date)s (in %(time)s).\n"
msgstr ""
"\n"
"Az ön „%(vm)s” nevű %(state)s állapotú virtuális gépe TÖRLÉSRE\n"
"kerül %(date)s időpontban (%(time)s múlva).\n"
#: templates/mails/notification-delete.txt:11
msgid ""
"\n"
"The disk image will be IRRECOVERABLY REMOVED.\n"
msgstr ""
"\n"
"A lemezkép HELYREÁLLÍTHATATLANUL TÖRLÉSRE kerül.\n"
#: templates/mails/notification-delete.txt:15
#, python-format
msgid ""
"\n"
"You can renew or delete the instance on the cloud portal:\n"
"%(url)s\n"
msgstr ""
"\n"
"Megújíthatja vagy törölheti a példányt a cloud portálon:\n"
"%(url)s\n"
#: templates/mails/notification-suspend-now.txt:6
#, python-format
msgid ""
"\n"
"Your %(state)s virtual machine \"%(vm)s\" has been STOPPED\n"
"at %(date)s.\n"
msgstr ""
"\n"
"Az ön „%(vm)s” nevű %(state)s állapotú gépe FELFÜGGESZTÉSRE\n"
"került %(date)s időpontban.\n"
#: templates/mails/notification-suspend-now.txt:11
#, python-format
msgid ""
"\n"
"The disk and memory image is stored, and you can resume it\n"
"until the final expiration time (%(deldate)s).\n"
msgstr ""
"\n"
"A lemez- és memóriaképet tároljuk, így a végleges lejárati\n"
"időig (%(deldate)s) folytathatja a futtatását.\n"
#: templates/mails/notification-suspend-now.txt:16
#: templates/mails/notification-suspend.txt:16
#, python-format
msgid ""
"\n"
"You can also renew or delete the instance on the cloud portal:\n"
"%(url)s\n"
msgstr ""
"\n"
"Megújíthatja vagy törölheti a példányt a cloud portálon:\n"
"%(url)s\n"
#: templates/mails/notification-suspend.txt:6
#, python-format
msgid ""
"\n"
"Your %(state)s virtual machine \"%(vm)s\" is going to be STOPPED\n"
"at %(date)s (in %(time)s).\n"
msgstr ""
"\n"
"Az ön „%(vm)s” nevű %(state)s állapotú gépe FELFÜGGESZTÉSRE\n"
"kerül %(date)s időpontban (%(time)s múlva).\n"
#: templates/mails/notification-suspend.txt:11
#, python-format
msgid ""
"\n"
"The disk and memory image will be stored, and you can resume it\n"
"until the final expiration time (%(deldate)s).\n"
msgstr ""
"\n"
"A lemez- és memóriaképet tárolni fogjuk, így a végleges lejárati\n"
"időig (%(deldate)s) folytathatja a futtatását.\n"
#~ msgid "Impressum"
#~ msgstr "Impresszum"
#~ msgid "Delete notification"
#~ msgstr "Figyelmeztetés törlésről"
#~ msgid "Stop notification"
#~ msgstr "Figyelmeztetés felfüggesztésről"
#~ msgid "Toplist"
#~ msgstr "Legújabb fájlok"
#~ msgid "Public keys" #~ msgid "Public keys"
#~ msgstr "Nyilvános kulcsok" #~ msgstr "Nyilvános kulcsok"
......
...@@ -6,8 +6,8 @@ msgid "" ...@@ -6,8 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-02-21 18:06+0100\n" "POT-Creation-Date: 2013-03-07 18:16+0100\n"
"PO-Revision-Date: 2013-02-21 18:09+0100\n" "PO-Revision-Date: 2013-03-07 17:02+0100\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Hungarian <cloud@ik.bme.hu>\n" "Language-Team: Hungarian <cloud@ik.bme.hu>\n"
"Language: hu\n" "Language: hu\n"
...@@ -17,108 +17,117 @@ msgstr "" ...@@ -17,108 +17,117 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Lokalize 1.4\n" "X-Generator: Lokalize 1.4\n"
#: static/script/cloud.js:24 #: static/script/cloud.js:24 static/script/cloud.min.js:1
msgid "Are you sure deleting key?" msgid "Are you sure deleting key?"
msgstr "Biztosan törli a kulcsot?" msgstr "Biztosan törli a kulcsot?"
#: static/script/cloud.js:24 static/script/cloud.js.c:246 #: static/script/cloud.js:24 static/script/cloud.js.c:296
#: static/script/cloud.js:320 static/script/cloud.js.c:533 #: static/script/cloud.js:370 static/script/cloud.js.c:623
#: static/script/store.js:273 #: static/script/cloud.min.js:1 static/script/store.js:288
#: static/script/store.min.js:1
msgid "Delete" msgid "Delete"
msgstr "Törlés" msgstr "Törlés"
#: static/script/cloud.js:36 #: static/script/cloud.js:36 static/script/cloud.min.js:1
msgid "" msgid ""
"Are you sure about reseting store credentials?<br /> You will lose your " "Are you sure about reseting store credentials?<br /> You will lose your "
"access to your store account on your existing virtual machines!" "access to your store account on your existing virtual machines!"
msgstr "" msgstr ""
"Biztosan újragenerálja az adattár-kulcsait?<br /> " "Biztosan újragenerálja az adattár-kulcsait?<br /> El fogja veszteni az "
"El fogja veszteni az adattár-hozzáférést a már futó virtuális gépekből!" "adattár-hozzáférést a már futó virtuális gépekből!"
#: static/script/cloud.js:36 #: static/script/cloud.js:36 static/script/cloud.min.js:1
msgid "Reset" msgid "Reset"
msgstr "Újragenerálás" msgstr "Újragenerálás"
#: static/script/cloud.js:65 static/script/store.js:309 #: static/script/cloud.js:75 static/script/cloud.min.js:1
#: static/script/store.js:323 static/script/store.min.js:1
msgid "Rename" msgid "Rename"
msgstr "Átnevezés" msgstr "Átnevezés"
#: static/script/cloud.js:221 static/script/store.js:273 #: static/script/cloud.js:271 static/script/cloud.min.js:1
#: static/script/store.js:288 static/script/store.min.js:1
msgid "Cancel" msgid "Cancel"
msgstr "Mégsem" msgstr "Mégsem"
#: static/script/cloud.js:235 #: static/script/cloud.js:285 static/script/cloud.min.js:1
#, c-format #, c-format
msgid "Are you sure stopping %s?" msgid "Are you sure stopping %s?"
msgstr "Biztosan felfüggeszti a következőt: %s?" msgstr "Biztosan felfüggeszti a következőt: %s?"
#: static/script/cloud.js:236 #: static/script/cloud.js:286 static/script/cloud.min.js:1
msgid "Stop" msgid "Stop"
msgstr "Felfüggesztés" msgstr "Felfüggesztés"
#: static/script/cloud.js:245 #: static/script/cloud.js:295 static/script/cloud.min.js:1
#, c-format #, c-format
msgid "Are you sure deleting %s?" msgid "Are you sure deleting %s?"
msgstr "Biztosan törli a következőt: %s?" msgstr "Biztosan törli a következőt: %s?"
#: static/script/cloud.js:255 #: static/script/cloud.js:305 static/script/cloud.min.js:1
#, c-format #, c-format
msgid "Are you sure restarting %s?" msgid "Are you sure restarting %s?"
msgstr "Biztosan újraindítja a következőt: %s?" msgstr "Biztosan újraindítja a következőt: %s?"
#: static/script/cloud.js:256 #: static/script/cloud.js:306 static/script/cloud.min.js:1
msgid "Restart" msgid "Restart"
msgstr "Újraindítás" msgstr "Újraindítás"
#: static/script/cloud.js:319 #: static/script/cloud.js:369 static/script/cloud.min.js:1
#, c-format #, c-format
msgid "Are you sure deleting this %s template?" msgid "Are you sure deleting this %s template?"
msgstr "Biztosan törli a következő sablont: %s?" msgstr "Biztosan törli a következő sablont: %s?"
#: static/script/cloud.js:452 static/script/cloud.js.c:459 #: static/script/cloud.js:547 static/script/cloud.js.c:550
#: static/script/cloud.min.js:1
msgid "Add owner" msgid "Add owner"
msgstr "Tulajdonos hozzáadása" msgstr "Tulajdonos hozzáadása"
#: static/script/cloud.js:457 #: static/script/cloud.js:550 static/script/cloud.min.js:1
msgid "Unknown" msgid "Unknown"
msgstr "Ismeretlen" msgstr "Ismeretlen"
#: static/script/cloud.js:533 #: static/script/cloud.js:623 static/script/cloud.min.js:1
#, c-format #, c-format
msgid "Are you sure deleting <strong>%s</strong>" msgid "Are you sure deleting <strong>%s</strong>"
msgstr "Törli a következő fájlt: <strong>%s</strong>" msgstr "Törli a következő fájlt: <strong>%s</strong>"
#: static/script/store.js:57 static/script/store.js.c:66 #: static/script/store.js:52 static/script/store.js.c:61
#: static/script/store.js:75 static/script/store.js.c:205 #: static/script/store.js:70 static/script/store.js.c:220
#: static/script/store.js:267 #: static/script/store.js:282 static/script/store.min.js:1
msgid "file" msgid "file"
msgstr "fájl" msgstr "fájl"
#: static/script/store.js:268 #: static/script/store.js:125 static/script/store.min.js:1
msgid "Toplist"
msgstr "Legújabb fájlok"
#: static/script/store.js:127 static/script/store.min.js:1
msgid "Back to the root folder"
msgstr "Vissza a gyökérmappába"
#: static/script/store.js:283 static/script/store.min.js:1
#, c-format #, c-format
msgid "You are removing the file <strong>%s</strong>." msgid "You are removing the file <strong>%s</strong>."
msgstr "Törli a következő fájlt: <strong>%s</strong>." msgstr "Törli a következő fájlt: <strong>%s</strong>."
#: static/script/store.js:270 #: static/script/store.js:285 static/script/store.min.js:1
#, c-format #, c-format
msgid "You are removing the folder <strong>%s</strong> (and its content)." msgid "You are removing the folder <strong>%s</strong> (and its content)."
msgstr "Törli a következő könyvtárat és tartalmát: <strong>%s</strong>." msgstr "Törli a következő könyvtárat és tartalmát: <strong>%s</strong>."
#: static/script/store.js:273 #: static/script/store.js:288 static/script/store.min.js:1
msgid "Are you sure?" msgid "Are you sure?"
msgstr "Biztos benne?" msgstr "Biztos benne?"
#: static/script/store.js:427 static/script/store.js.c:429 #: static/script/store.js:446 static/script/store.js.c:448
#: static/script/store.min.js:1
msgid "Upload" msgid "Upload"
msgstr "Feltöltés" msgstr "Feltöltés"
#: static/script/store.js:429 #: static/script/store.js:448 static/script/store.min.js:1
msgid "done, processing..." msgid "done, processing..."
msgstr "kész, feldolgozás..." msgstr "kész, feldolgozás..."
#, fuzzy
#~ msgid "Are you sure about reseting store credentials"
#~ msgstr "Biztosan újraindítja a következőt: %s?"
#~ msgid "Please choose a different name." #~ msgid "Please choose a different name."
#~ msgstr "Kérem, válasszon eltérő nevet." #~ msgstr "Kérem, válasszon eltérő nevet."
...@@ -14,7 +14,7 @@ from django.db.models.signals import post_save ...@@ -14,7 +14,7 @@ from django.db.models.signals import post_save
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from firewall.models import Host, Rule, Vlan from firewall.models import Host, Rule, Vlan, Record
from school.models import Person, Group from school.models import Person, Group
from store.api import StoreApi from store.api import StoreApi
from .util import keygen from .util import keygen
...@@ -224,7 +224,7 @@ class Disk(models.Model): ...@@ -224,7 +224,7 @@ class Disk(models.Model):
return u"%s (#%d)" % (self.name, self.id) return u"%s (#%d)" % (self.name, self.id)
@staticmethod @staticmethod
def update(): def update(delete=True):
"""Get and register virtual disks from OpenNebula.""" """Get and register virtual disks from OpenNebula."""
import subprocess import subprocess
proc = subprocess.Popen(["/opt/occi.sh", "storage", "list"], proc = subprocess.Popen(["/opt/occi.sh", "storage", "list"],
...@@ -244,6 +244,7 @@ class Disk(models.Model): ...@@ -244,6 +244,7 @@ class Disk(models.Model):
except: except:
Disk(id=id, name=name).save() Disk(id=id, name=name).save()
l.append(id) l.append(id)
if delete:
Disk.objects.exclude(id__in=l).delete() Disk.objects.exclude(id__in=l).delete()
class Network(models.Model): class Network(models.Model):
...@@ -400,34 +401,46 @@ class Instance(models.Model): ...@@ -400,34 +401,46 @@ class Instance(models.Model):
@models.permalink @models.permalink
def get_absolute_url(self): def get_absolute_url(self):
return ('vm_show', None, {'iid':self.id}) return ('one.views.vm_show', None, {'iid':self.id})
def get_port(self): def get_port(self, use_ipv6=False):
"""Get public port number for default access method.""" """Get public port number for default access method."""
proto = self.template.access_type proto = self.template.access_type
if self.template.network.nat: if self.template.network.nat and not use_ipv6:
return {"rdp": 23000, "nx": 22000, "ssh": 22000}[proto] + int(self.ip.split('.')[2]) * 256 + int(self.ip.split('.')[3]) return {"rdp": 23000, "nx": 22000, "ssh": 22000}[proto] + int(self.ip.split('.')[2]) * 256 + int(self.ip.split('.')[3])
else: else:
return {"rdp": 3389, "nx": 22, "ssh": 22}[proto] return {"rdp": 3389, "nx": 22, "ssh": 22}[proto]
def get_connect_host(self): def get_connect_host(self, use_ipv6=False):
"""Get public hostname.""" """Get public hostname."""
if self.firewall_host is None:
return _('None')
try:
if use_ipv6:
return self.firewall_host.record_set.filter(type='AAAA')[0].get_data()['name']
else:
if self.template.network.nat: if self.template.network.nat:
return 'cloud' ip = self.firewall_host.pub_ipv4
return Record.objects.filter(type='A', address=ip)[0].get_data()['name']
else: else:
return self.ip return self.firewall_host.record_set.filter(type='A')[0].get_data()['name']
except:
if self.template.network.nat:
return self.firewall_host.pub_ipv4
else:
return self.firewall_host.ipv4
def get_connect_uri(self): def get_connect_uri(self, use_ipv6=False):
"""Get access parameters in URI format.""" """Get access parameters in URI format."""
try: try:
proto = self.template.access_type proto = self.template.access_type
if proto == 'ssh': if proto == 'ssh':
proto = 'sshterm' proto = 'sshterm'
port = self.get_port() port = self.get_port(use_ipv6=use_ipv6)
host = self.get_connect_host() host = self.get_connect_host(use_ipv6=use_ipv6)
pw = self.pw pw = self.pw
return ("%(proto)s:cloud:%(pw)s:%(host)s:%(port)d" % return ("%(proto)s:cloud:%(pw)s:%(host)s:%(port)d" %
{"port": port, "proto": proto, "pw": pw, {"port": port, "proto": proto, "pw": pw,
"host": self.firewall_host.pub_ipv4}) "host": host})
except: except:
return return
...@@ -540,11 +553,13 @@ class Instance(models.Model): ...@@ -540,11 +553,13 @@ class Instance(models.Model):
inst.save() inst.save()
inst.update_state() inst.update_state()
host = Host(vlan=Vlan.objects.get(name=template.network.name), host = Host(vlan=Vlan.objects.get(name=template.network.name),
owner=owner, shared_ip=True) owner=owner)
host.hostname = hostname host.hostname = hostname
host.mac = x.getElementsByTagName("MAC")[0].childNodes[0].nodeValue host.mac = x.getElementsByTagName("MAC")[0].childNodes[0].nodeValue
host.ipv4 = inst.ip host.ipv4 = inst.ip
if inst.template.network.nat:
host.pub_ipv4 = Vlan.objects.get(name=template.network.name).snat_ip host.pub_ipv4 = Vlan.objects.get(name=template.network.name).snat_ip
host.shared_ip = True
host.ipv6 = "auto" host.ipv6 = "auto"
try: try:
host.save() host.save()
...@@ -575,7 +590,10 @@ class Instance(models.Model): ...@@ -575,7 +590,10 @@ class Instance(models.Model):
if self.firewall_host: if self.firewall_host:
h = self.firewall_host h = self.firewall_host
self.firewall_host = None self.firewall_host = None
try:
self.save() self.save()
except:
pass
h.delete() h.delete()
def _update_vm(self, template): def _update_vm(self, template):
...@@ -611,12 +629,12 @@ class Instance(models.Model): ...@@ -611,12 +629,12 @@ class Instance(models.Model):
self._change_state("POWEROFF") self._change_state("POWEROFF")
def restart(self): def restart(self):
self._change_state("RESET") self._change_state("RESET")
def renew(self, which): def renew(self, which='both'):
if which == 'suspend': if which in ['suspend', 'both']:
self.time_of_suspend = self.share.get_type()['suspendx'] self.time_of_suspend = self.share.get_type()['suspendx']
elif which == 'delete': if which in ['delete', 'both']:
self.time_of_delete = self.share.get_type()['deletex'] self.time_of_delete = self.share.get_type()['deletex']
else: if not (which in ['suspend', 'delete', 'both']):
raise ValueError('No such expiration type.') raise ValueError('No such expiration type.')
self.save() self.save()
def save_as(self): def save_as(self):
...@@ -633,7 +651,7 @@ class Instance(models.Model): ...@@ -633,7 +651,7 @@ class Instance(models.Model):
def check_if_is_save_as_done(self): def check_if_is_save_as_done(self):
if self.state != 'DONE': if self.state != 'DONE':
return False return False
Disk.update() Disk.update(delete=False)
imgname = "template-%d-%d" % (self.template.id, self.id) imgname = "template-%d-%d" % (self.template.id, self.id)
disks = Disk.objects.filter(name=imgname) disks = Disk.objects.filter(name=imgname)
if len(disks) != 1: if len(disks) != 1:
......
var toggleDetails; var toggleDetails;
$(function() { $(function() {
toggleDetails = cloud.throttle(function() { toggleDetails = cloud.throttle(function() {
if($(this).parent('.entry').hasClass('opened')) { if ($(this).parent('.entry').hasClass('opened')) {
$(this).parent('.entry').removeClass('opened'); $(this).parent('.entry').removeClass('opened');
$(this).next('.details').slideUp(700); $(this).next('.details').slideUp(700);
} else { } else {
...@@ -9,7 +9,7 @@ $(function() { ...@@ -9,7 +9,7 @@ $(function() {
$(this).next('.details').slideDown(700); $(this).next('.details').slideDown(700);
} }
}) })
$('a').click(function(e){ $('a').click(function(e) {
e.stopPropagation(); e.stopPropagation();
}); });
$('.delete-template').click(function(e) { $('.delete-template').click(function(e) {
...@@ -32,19 +32,19 @@ $(function() { ...@@ -32,19 +32,19 @@ $(function() {
}); });
}); });
}); });
$('#reset-key').click(function(e){ $('#reset-key').click(function(e) {
vm_confirm_popup(gettext('Are you sure about reseting store credentials?<br /> You will lose your access to your store account on your existing virtual machines!'), gettext('Reset'), function(){ vm_confirm_popup(gettext('Are you sure about reseting store credentials?<br /> You will lose your access to your store account on your existing virtual machines!'), gettext('Reset'), function() {
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: '/ajax/key/reset/', url: '/ajax/key/reset/',
success: function(){ success: function() {
window.location.reload(); window.location.reload();
} }
}) })
}); });
}); });
$('.entry .summary').click(toggleDetails); $('.entry .summary').click(toggleDetails);
if(window.navigator.userAgent.indexOf('cloud-gui') < 0) { if (window.navigator.userAgent.indexOf('cloud-gui') < 0) {
$('.connect-vm').click(function(e) { $('.connect-vm').click(function(e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
...@@ -59,7 +59,17 @@ $(function() { ...@@ -59,7 +59,17 @@ $(function() {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var id = $(this).data('id'); var id = $(this).data('id');
var handler = arguments.callee;
var oldName = $(this).data('name'); var oldName = $(this).data('name');
var content = $('#vm-' + id + '-name').html();
var self=this;
$(this).unbind('click').click(function(e){
e.preventDefault();
e.stopPropagation();
$(this).unbind('click').click(handler);
$('#vm-' + id + '-name-details').show();
$('#vm-' + id + '-name').html(content);
})
$('#vm-' + id + '-name-details').hide(); $('#vm-' + id + '-name-details').hide();
$('#vm-' + id + '-name').html('<input type="text" value="' + oldName + '" />\ $('#vm-' + id + '-name').html('<input type="text" value="' + oldName + '" />\
<input type="submit" value="' + gettext('Rename') + '" />'); <input type="submit" value="' + gettext('Rename') + '" />');
...@@ -79,6 +89,7 @@ $(function() { ...@@ -79,6 +89,7 @@ $(function() {
success: function(data) { success: function(data) {
$('#vm-' + id + '-name-details').removeAttr('style'); $('#vm-' + id + '-name-details').removeAttr('style');
$('#vm-' + id + '-name').text(data.name); $('#vm-' + id + '-name').text(data.name);
$(self).click(handler);
} }
}); });
}) })
...@@ -129,6 +140,19 @@ $(function() { ...@@ -129,6 +140,19 @@ $(function() {
}) })
$('#modal').show(); $('#modal').show();
}); });
$('.edit-template').click(function(e){
e.preventDefault();
e.stopPropagation();
var id=$(this).data('id');
$.ajax({
type: 'GET',
url: '/ajax/templateEditWizard/'+id+'/',
success: function(data){
$('#modal').show();
$('#modal-container').html(data);
}
});
});
$('#shadow').click(function() { $('#shadow').click(function() {
$('#modal').hide(); $('#modal').hide();
$('#modal-container').html(''); $('#modal-container').html('');
...@@ -141,7 +165,7 @@ $(function() { ...@@ -141,7 +165,7 @@ $(function() {
}) })
$('#modal').show(); $('#modal').show();
}); });
$('.template-unshare').click(function(e){ $('.template-unshare').click(function(e) {
e.stopPropagation(); e.stopPropagation();
}); });
$('#old-upload').click(function(e) { $('#old-upload').click(function(e) {
...@@ -154,7 +178,7 @@ $(function() { ...@@ -154,7 +178,7 @@ $(function() {
$(this).css('backgroundColor', function(w) { $(this).css('backgroundColor', function(w) {
return 'hsla(' + (120 - parseFloat(w) / 100 * 120).toFixed(0) + ', 100%, 50%, 0.2)'; return 'hsla(' + (120 - parseFloat(w) / 100 * 120).toFixed(0) + ', 100%, 50%, 0.2)';
}($(this)[0].style.width)); }($(this)[0].style.width));
if(parseInt($(this).css('width')) > 0) $(this).css('borderRight', function(w) { if (parseInt($(this).css('width')) > 0) $(this).css('borderRight', function(w) {
return '1px solid hsla(' + (120 - parseFloat(w) / 100 * 120).toFixed(0) + ', 100%, 30%, 0.4)'; return '1px solid hsla(' + (120 - parseFloat(w) / 100 * 120).toFixed(0) + ', 100%, 30%, 0.4)';
}($(this)[0].style.width)); }($(this)[0].style.width));
}); });
...@@ -183,14 +207,41 @@ $(function() { ...@@ -183,14 +207,41 @@ $(function() {
$('#new-group-members').change(updateSummary); $('#new-group-members').change(updateSummary);
}); });
$('.hidden-password').click(function() { $('.hidden-password').click(function() {
if($(this).attr('type') == 'password'){ if ($(this).attr('type') == 'password') {
$(this).attr('type', 'text'); $(this).attr('type', 'text');
$(this).addClass('shown'); $(this).addClass('shown');
} else { } else if (this.selectionStart - this.selectionEnd == 0) {
$(this).attr('type', 'password'); $(this).attr('type', 'password');
$(this).removeClass('shown'); $(this).removeClass('shown');
} }
}); });
$('.shares li').click(function(e) {
e.preventDefault();
e.stopPropagation();
e = $(this);
if (!e.hasClass('description')) {
if (e.next().is(':hidden')) {
e.next().slideDown(700);
} else {
e.next().slideUp(700);
}
} else {
e.slideUp(700);
}
});
$('.shares .edit').click(function(e) {
e.preventDefault();
e.stopPropagation();
$.ajax({
type: 'GET',
url: '/ajax/shareEdit/' + $(this).data('id') + '/',
success: function(data) {
$('#modal').show();
$('#modal-container').html(data);
}
})
})
$('.selected-summary').next().show(); $('.selected-summary').next().show();
/** /**
* Connect button new window * Connect button new window
...@@ -200,7 +251,7 @@ $(function() { ...@@ -200,7 +251,7 @@ $(function() {
$.get('/vm/credentials/' + id, function(data) { $.get('/vm/credentials/' + id, function(data) {
$('#modal-container').html(data); $('#modal-container').html(data);
$('#modal-container .hidden-password').click(function() { $('#modal-container .hidden-password').click(function() {
if($(this).attr('type') == 'password'){ if ($(this).attr('type') == 'password') {
$(this).attr('type', 'text'); $(this).attr('type', 'text');
$(this).addClass('shown'); $(this).addClass('shown');
} else { } else {
...@@ -286,7 +337,7 @@ $(function() { ...@@ -286,7 +337,7 @@ $(function() {
type: 'POST', type: 'POST',
url: '/vm/' + state + '/' + id + '/', url: '/vm/' + state + '/' + id + '/',
success: function(data, b, c) { success: function(data, b, c) {
if(state == "resume") { if (state == "resume") {
window.location.href = '/vm/show/' + id + "/"; window.location.href = '/vm/show/' + id + "/";
} else { } else {
window.location.reload(); window.location.reload();
...@@ -345,9 +396,9 @@ $(function() { ...@@ -345,9 +396,9 @@ $(function() {
function hide_group(id) { function hide_group(id) {
var hidden_groups = JSON.parse(window.localStorage.getItem('hidden_groups')) || {}; var hidden_groups = JSON.parse(window.localStorage.getItem('hidden_groups')) || {};
var hidden_groups_for_user = hidden_groups[current_user] || []; var hidden_groups_for_user = hidden_groups[current_user] || [];
for(var i in hidden_groups_for_user) { for (var i in hidden_groups_for_user) {
var hide = hidden_groups_for_user[i]; var hide = hidden_groups_for_user[i];
if(hide == id) return false; if (hide == id) return false;
} }
hidden_groups_for_user.push(id); hidden_groups_for_user.push(id);
hidden_groups[current_user] = hidden_groups_for_user; hidden_groups[current_user] = hidden_groups_for_user;
...@@ -358,7 +409,7 @@ $(function() { ...@@ -358,7 +409,7 @@ $(function() {
function hide_groups() { function hide_groups() {
var hidden_groups = JSON.parse(window.localStorage.getItem('hidden_groups')) || {}; var hidden_groups = JSON.parse(window.localStorage.getItem('hidden_groups')) || {};
var hidden_groups_for_user = hidden_groups[current_user] || []; var hidden_groups_for_user = hidden_groups[current_user] || [];
for(var i in hidden_groups_for_user) { for (var i in hidden_groups_for_user) {
var hide = hidden_groups_for_user[i]; var hide = hidden_groups_for_user[i];
$('#group-' + hide).hide(); $('#group-' + hide).hide();
} }
...@@ -373,9 +424,57 @@ $(function() { ...@@ -373,9 +424,57 @@ $(function() {
function hidden_group_count() { function hidden_group_count() {
var hidden_groups = JSON.parse(window.localStorage.getItem('hidden_groups')) || {}; var hidden_groups = JSON.parse(window.localStorage.getItem('hidden_groups')) || {};
return(hidden_groups[current_user] || []).length; return (hidden_groups[current_user] || []).length;
}
function toggle_box(id) {
var boxes = JSON.parse(window.localStorage.getItem('hidden_boxes')) || {};
var user_boxes = boxes[current_user] || [];
for (var i in user_boxes) {
var box = user_boxes[i];
if (box == id) {
user_boxes.splice(i, 1);
boxes[current_user] = user_boxes;
window.localStorage.setItem('hidden_boxes', JSON.stringify(boxes));
$('#toggle-box-' + id).attr('src', '/static/icons/eye-half.png');
$('#toggle-box-' + id).parent().parent().parent().next().slideDown(700);
return;
}
}
user_boxes.push(id);
boxes[current_user] = user_boxes;
$('#toggle-box-' + id).attr('src', '/static/icons/eye.png');
$('#toggle-box-' + id).parent().parent().parent().next().slideUp(700);
console.log($('#toggle-box-' + id).parent().parent().parent().next()[0])
window.localStorage.setItem('hidden_boxes', JSON.stringify(boxes));
}
function box_hidden(id) {
var boxes = JSON.parse(window.localStorage.getItem('hidden_boxes')) || {};
var user_boxes = boxes[current_user] || [];
for (var i in user_boxes) {
var box = user_boxes[i];
if (box == id) {
return true;
}
}
return false;
} }
if(hidden_group_count() == 0) {
$('.toggle-box').each(function() {
var id = $(this).data('id');
$(this).click(function() {
toggle_box(id);
});
if (box_hidden(id)) {
$(this).attr('src', '/static/icons/eye.png');
$(this).parent().parent().parent().next().hide();
} else {
$(this).attr('src', '/static/icons/eye-half.png');
}
})
if (hidden_group_count() == 0) {
$('#show-hidden-groups').hide(); $('#show-hidden-groups').hide();
} }
...@@ -383,7 +482,7 @@ $(function() { ...@@ -383,7 +482,7 @@ $(function() {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
hide_group($(this).data('id')); hide_group($(this).data('id'));
if($('#show-hidden-groups').is(':hidden')) { if ($('#show-hidden-groups').is(':hidden')) {
$('#show-hidden-groups').slideDown(700); $('#show-hidden-groups').slideDown(700);
} }
return false; return false;
...@@ -394,7 +493,7 @@ $(function() { ...@@ -394,7 +493,7 @@ $(function() {
show_hidden_groups(); show_hidden_groups();
$('#show-hidden-groups').slideUp(700); $('#show-hidden-groups').slideUp(700);
$('#groups > li').each(function() { $('#groups > li').each(function() {
if($(this).is(':hidden')) { if ($(this).is(':hidden')) {
$(this).slideDown(700); $(this).slideDown(700);
} }
}) })
...@@ -429,46 +528,38 @@ $(function() { ...@@ -429,46 +528,38 @@ $(function() {
}); });
$('#new-owner-form input').keyup(function() { $('#new-owner-form input').keyup(function() {
var timer; var timer;
return function(e){ return function(e) {
var val=$(this).val().split(' ')[0]; var val = $(this).val().split(' ')[0];
clearTimeout(timer); clearTimeout(timer);
timer=setTimeout(function(){ timer = setTimeout(function() {
if(val.length<1) return; if (val.length < 1) return;
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
data: 'q='+val, data: 'q=' + val,
url: '/ajax/group/autocomplete/', url: '/ajax/group/autocomplete/',
dataType: 'json', dataType: 'json',
success: function(data){ success: function(data) {
console.log(data); console.log(data);
$('#new-owner-autocomplete')[0].innerHTML='<ul>'; $('#new-owner-autocomplete')[0].innerHTML = '<ul>';
var el=$('#new-owner-autocomplete')[0]; var el = $('#new-owner-autocomplete')[0];
for(var i in data){ for (var i in data) {
var d=data[i]; var d = data[i];
el.innerHTML+='<li>' el.innerHTML += '<li>' + d.name + ': ' + d.neptun + ' <input type="button" value="' + gettext('Add owner') + '" data-neptun="' + d.neptun + '" />' + '<div class="clear"></div></li>';
+d.name+': ' }
+d.neptun if (data.length == 0) {
+' <input type="button" value="'+gettext('Add owner')+'" data-neptun="'+d.neptun+'" />' el.innerHTML += '<li>' + gettext('Unknown') + ': ' + val + ' <input type="button" value="' + gettext('Add owner') + '" data-neptun="' + val + '" />' + '<div class="clear"></div></li>';
+'<div class="clear"></div></li>'; }
} el.innerHTML += '</ul>';
if(data.length == 0){ $(el).find('input').each(function() {
el.innerHTML+='<li>' var self = this;
+gettext('Unknown')+': ' $(this).click(function(e) {
+val
+' <input type="button" value="'+gettext('Add owner')+'" data-neptun="'+val+'" />'
+'<div class="clear"></div></li>';
}
el.innerHTML+='</ul>';
$(el).find('input').each(function(){
var self=this;
$(this).click(function(e){
e.stopPropagation(); e.stopPropagation();
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
data: 'neptun='+$(self).data('neptun'), data: 'neptun=' + $(self).data('neptun'),
url: '/ajax/group/'+$('#new-owner').data('gid')+'/addOwner/', url: '/ajax/group/' + $('#new-owner').data('gid') + '/addOwner/',
dataType: 'json', dataType: 'json',
success: function(data){ success: function(data) {
window.location.reload(); window.location.reload();
} }
}) })
...@@ -476,7 +567,7 @@ $(function() { ...@@ -476,7 +567,7 @@ $(function() {
}) })
} }
}); });
},1000); }, 1000);
e.stopPropagation(); e.stopPropagation();
} }
}()); }());
......
...@@ -28,18 +28,13 @@ var cloud = (function(cloud) { ...@@ -28,18 +28,13 @@ var cloud = (function(cloud) {
return cloud.convert(self.quota.rawSoft(), 1); return cloud.convert(self.quota.rawSoft(), 1);
}); });
self.quota.usedBar = ko.computed(function() { self.quota.usedBar = ko.computed(function() {
return(self.quota.rawUsed() / self.quota.rawHard() * 100).toFixed(0) + '%'; return (self.quota.rawUsed() / self.quota.rawHard() * 100).toFixed(0) + '%';
}, self); }, self);
self.quota.softPos = ko.computed(function() { self.quota.softPos = ko.computed(function() {
return(self.quota.rawSoft() / self.quota.rawHard() * 100).toFixed(0) + '%'; return (self.quota.rawSoft() / self.quota.rawHard() * 100).toFixed(0) + '%';
}, self); }, self);
self.sortBy = ko.observable('name'); self.sortBy = ko.observable('name');
$('#current-location select').on('change', function() {
self.sortBy($('#current-location select').val());
sortFiles();
})
/** /**
* Loads the parent folder * Loads the parent folder
*/ */
...@@ -48,31 +43,31 @@ var cloud = (function(cloud) { ...@@ -48,31 +43,31 @@ var cloud = (function(cloud) {
loadFolder(s.substr(0, s.substr(0, s.length - 1).lastIndexOf('/') + 1)); loadFolder(s.substr(0, s.substr(0, s.length - 1).lastIndexOf('/') + 1));
}; };
var sortFiles = (function() { self.sortFiles = (function() {
self.files.sort({ self.files.sort({
name: function(a, b) { name: function(a, b) {
if(a.type === b.type) { if (a.type === b.type) {
return a.originalName.localeCompare(b.originalName); return a.originalName.localeCompare(b.originalName);
} }
if(a.type === gettext('file')) { if (a.type === gettext('file')) {
return 1; return 1;
} }
return -1; return -1;
}, },
date: function(a, b) { date: function(a, b) {
if(a.type === b.type) { if (a.type === b.type) {
return new Date(b.mTime).getTime() - new Date(a.mTime).getTime(); return new Date(b.mTime).getTime() - new Date(a.mTime).getTime();
} }
if(a.type === gettext('file')) { if (a.type === gettext('file')) {
return 1; return 1;
} }
return -1; return -1;
}, },
size: function(a, b) { size: function(a, b) {
if(a.type === b.type) { if (a.type === b.type) {
return b.originalSize - a.originalSize; return b.originalSize - a.originalSize;
} }
if(a.type === gettext('file')) { if (a.type === gettext('file')) {
return 1; return 1;
} }
return -1; return -1;
...@@ -91,7 +86,7 @@ var cloud = (function(cloud) { ...@@ -91,7 +86,7 @@ var cloud = (function(cloud) {
url: '/ajax/store/list', url: '/ajax/store/list',
dataType: 'json', dataType: 'json',
success: function(data) { success: function(data) {
if(!fast) { if (!fast) {
$('.file-list .real').css({ $('.file-list .real').css({
left: 0, left: 0,
position: 'relative' position: 'relative'
...@@ -113,7 +108,27 @@ var cloud = (function(cloud) { ...@@ -113,7 +108,27 @@ var cloud = (function(cloud) {
}) })
}); });
self.loadTopList = cloud.throttle(function() { var showToplist = ko.observable(false);
self.toggleToplist = cloud.throttle(function() {
if (!showToplist()) {
showToplist(true);
loadToplist();
} else {
showToplist(false);
self.currentPath('/');
loadFolder('/');
}
});
self.getToplistText = ko.computed(function() {
if (!showToplist()) {
return gettext('Toplist');
} else {
return gettext('Back to the root folder');
}
})
function loadToplist() {
self.currentPath('/'); self.currentPath('/');
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
...@@ -135,8 +150,8 @@ var cloud = (function(cloud) { ...@@ -135,8 +150,8 @@ var cloud = (function(cloud) {
}, 500); }, 500);
}); });
} }
})
}); });
}
/** /**
* After loadFolder completes, this function updates the UI * After loadFolder completes, this function updates the UI
...@@ -147,10 +162,10 @@ var cloud = (function(cloud) { ...@@ -147,10 +162,10 @@ var cloud = (function(cloud) {
var added = 0; var added = 0;
self.notInRoot(self.currentPath().lastIndexOf('/') !== 0); self.notInRoot(self.currentPath().lastIndexOf('/') !== 0);
self.files([]); self.files([]);
for(var i in data) { for (var i in data) {
addFile(data[i]); addFile(data[i]);
} }
sortFiles(); self.sortFiles();
} }
/** /**
...@@ -159,7 +174,7 @@ var cloud = (function(cloud) { ...@@ -159,7 +174,7 @@ var cloud = (function(cloud) {
function addFile(d) { function addFile(d) {
var viewData; var viewData;
if(d.TYPE === 'D') { if (d.TYPE === 'D') {
viewData = { viewData = {
originalName: d.NAME, originalName: d.NAME,
originalSize: 0, originalSize: 0,
...@@ -185,8 +200,8 @@ var cloud = (function(cloud) { ...@@ -185,8 +200,8 @@ var cloud = (function(cloud) {
ppt: /\.pptx?/, ppt: /\.pptx?/,
music: /\.(wav|mp3)$/ music: /\.(wav|mp3)$/
}; };
for(var i in ext) { for (var i in ext) {
if(d.NAME.match(ext[i])) { if (d.NAME.match(ext[i])) {
type = i; type = i;
break; break;
} }
...@@ -194,7 +209,7 @@ var cloud = (function(cloud) { ...@@ -194,7 +209,7 @@ var cloud = (function(cloud) {
var extension; var extension;
try { try {
extension = d.NAME.match(/\.\w+$/)[0].substr(1); extension = d.NAME.match(/\.\w+$/)[0].substr(1);
} catch(ex) { } catch (ex) {
extension = 'N/A'; extension = 'N/A';
} }
viewData = { viewData = {
...@@ -220,7 +235,7 @@ var cloud = (function(cloud) { ...@@ -220,7 +235,7 @@ var cloud = (function(cloud) {
//firefox sucks :S //firefox sucks :S
try { try {
$(e).hide().slideDown(500); $(e).hide().slideDown(500);
} catch(ex) { } catch (ex) {
} }
} }
...@@ -230,7 +245,7 @@ var cloud = (function(cloud) { ...@@ -230,7 +245,7 @@ var cloud = (function(cloud) {
$(e).slideUp(500, function() { $(e).slideUp(500, function() {
e.parentNode.removeChild(e); e.parentNode.removeChild(e);
}); });
} catch(ex) { } catch (ex) {
e.parentNode.removeChild(e); e.parentNode.removeChild(e);
} }
} }
...@@ -241,7 +256,7 @@ var cloud = (function(cloud) { ...@@ -241,7 +256,7 @@ var cloud = (function(cloud) {
self.download = function(item, ev) { self.download = function(item, ev) {
ev.stopPropagation(); ev.stopPropagation();
ev.preventDefault(); ev.preventDefault();
if(window.navigator.userAgent.indexOf('cloud-gui') > -1) { if (window.navigator.userAgent.indexOf('cloud-gui') > -1) {
window.location.href = 'cloudfile:' + self.currentPath() + item.originalName; window.location.href = 'cloudfile:' + self.currentPath() + item.originalName;
return; return;
} }
...@@ -253,7 +268,7 @@ var cloud = (function(cloud) { ...@@ -253,7 +268,7 @@ var cloud = (function(cloud) {
success: function(data) { success: function(data) {
window.location.href = data.url; window.location.href = data.url;
} }
}) });
} }
/** /**
...@@ -264,7 +279,7 @@ var cloud = (function(cloud) { ...@@ -264,7 +279,7 @@ var cloud = (function(cloud) {
ev.preventDefault(); ev.preventDefault();
$('#modal').show(); $('#modal').show();
s = ""; s = "";
if(item.type == gettext('file')) { if (item.type == gettext('file')) {
s = gettext("You are removing the file <strong>%s</strong>."); s = gettext("You are removing the file <strong>%s</strong>.");
} else { } else {
s = gettext("You are removing the folder <strong>%s</strong> (and its content)."); s = gettext("You are removing the folder <strong>%s</strong> (and its content).");
...@@ -303,8 +318,7 @@ var cloud = (function(cloud) { ...@@ -303,8 +318,7 @@ var cloud = (function(cloud) {
g.stopPropagation(); g.stopPropagation();
self.rename(item, g); self.rename(item, g);
}); });
}) });
//$(e.target).parent().parent().parent().unbind('click');
$(e.target).parent().parent().parent().find('.name').html('<input type="text" value="' + item.originalName + '" />\ $(e.target).parent().parent().parent().find('.name').html('<input type="text" value="' + item.originalName + '" />\
<input type="submit" value="' + gettext('Rename') + '" />'); <input type="submit" value="' + gettext('Rename') + '" />');
$(e.target).parent().parent().parent().find('.name input').click(function(f) { $(e.target).parent().parent().parent().find('.name input').click(function(f) {
...@@ -372,9 +386,10 @@ var cloud = (function(cloud) { ...@@ -372,9 +386,10 @@ var cloud = (function(cloud) {
/** /**
* Uploads the specified file(s) * Uploads the specified file(s)
*/ */
var readfiles = cloud.delayUntil(function(file) { var readfiles = cloud.delayUntil(function(file, next) {
console.log('read', file, next)
//1 GB file limit //1 GB file limit
if(file.size > 1024 * 1024 * 1024) { if (file.size > 1024 * 1024 * 1024) {
$('#upload-zone').hide(); $('#upload-zone').hide();
$('#upload-error').show(); $('#upload-error').show();
$('#upload-error-size').show(); $('#upload-error-size').show();
...@@ -387,26 +402,30 @@ var cloud = (function(cloud) { ...@@ -387,26 +402,30 @@ var cloud = (function(cloud) {
} }
var formData = tests.formdata ? new FormData() : null; var formData = tests.formdata ? new FormData() : null;
formData.append('data', file); formData.append('data', file);
// now post a new XHR request if (tests.formdata) {
if(tests.formdata) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
var start = new Date().getTime(); var start = new Date().getTime();
xhr.open('POST', self.uploadURL()); xhr.open('POST', self.uploadURL());
xhr.onload = xhr.onerror = function() { xhr.onload = xhr.onerror = function() {
self.uploadProgress('0%');
self.uploadURL('/');
if (next) {
console.log('complete, next')
next();
} else {
$('.file-upload').removeClass('opened'); $('.file-upload').removeClass('opened');
$('.file-upload .details').slideUp(700); $('.file-upload .details').slideUp(700);
$('#upload-zone').show(); $('#upload-zone').show();
$('#upload-progress-text').hide(); $('#upload-progress-text').hide();
self.uploadProgress('0%');
self.uploadURL('/');
loadFolder(self.currentPath()); loadFolder(self.currentPath());
} }
if(tests.progress) { }
if (tests.progress) {
$('#upload-zone').hide(); $('#upload-zone').hide();
$('#upload-progress-text').show(); $('#upload-progress-text').show();
var originalUsedQuota = self.quota.rawUsed(); var originalUsedQuota = self.quota.rawUsed();
xhr.upload.onprogress = function(event) { xhr.upload.onprogress = function(event) {
if(event.lengthComputable) { if (event.lengthComputable) {
self.quota.rawUsed(originalUsedQuota + parseInt(event.loaded / 1024)); self.quota.rawUsed(originalUsedQuota + parseInt(event.loaded / 1024));
var complete = (event.loaded / event.total * 100 | 0); var complete = (event.loaded / event.total * 100 | 0);
//progress.value = progress.innerHTML = complete; //progress.value = progress.innerHTML = complete;
...@@ -414,16 +433,16 @@ var cloud = (function(cloud) { ...@@ -414,16 +433,16 @@ var cloud = (function(cloud) {
var suffix = 'B KB MB GB'.split(' '); var suffix = 'B KB MB GB'.split(' ');
var l = event.loaded; var l = event.loaded;
var t = event.total; var t = event.total;
for(var i = 0; l > 1024; i++) { for (var i = 0; l > 1024; i++) {
l /= 1024; l /= 1024;
} }
l = l.toFixed(1) + ' ' + suffix[i]; l = l.toFixed(1) + ' ' + suffix[i];
for(var i = 0; t > 1024; i++) { for (var i = 0; t > 1024; i++) {
t /= 1024; t /= 1024;
} }
t = t.toFixed(1) + ' ' + suffix[i]; t = t.toFixed(1) + ' ' + suffix[i];
var diff = new Date().getTime() - start; var diff = new Date().getTime() - start;
if(complete < 100) { if (complete < 100) {
$('#upload-progress-text').html(gettext('Upload') + ': ' + cloud.convert(event.loaded / diff * 1000) + '/s (' + (event.loaded / event.total * 100).toFixed(2) + '%)'); $('#upload-progress-text').html(gettext('Upload') + ': ' + cloud.convert(event.loaded / diff * 1000) + '/s (' + (event.loaded / event.total * 100).toFixed(2) + '%)');
} else { } else {
$('#upload-progress-text').html(gettext('Upload') + ': ' + gettext('done, processing...')); $('#upload-progress-text').html(gettext('Upload') + ': ' + gettext('done, processing...'));
...@@ -443,11 +462,30 @@ var cloud = (function(cloud) { ...@@ -443,11 +462,30 @@ var cloud = (function(cloud) {
document.addEventListener('drop', function(e) { document.addEventListener('drop', function(e) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
readfiles(e.dataTransfer.files[0]); var len = e.dataTransfer.files.length;
var files = e.dataTransfer.files;
console.log(files);
console.log(e.dataTransfer.files);
var i = 1;
readfiles(e.dataTransfer.files[0], function() {
console.log('next', i);
next = arguments.callee;
return function() {
console.log('readnext', i, len);
if (i >= len - 2) {
console.log('end', i, len);
self.getUploadURL();
readfiles(files[i++], null);
return;
}
self.getUploadURL();
readfiles(files[i++], next());
}
}());
return false; return false;
}); });
document.addEventListener('dragover', function(e) { document.addEventListener('dragover', function(e) {
if(!uploadURLRequestInProgress && self.uploadURL() == '/') { if (!uploadURLRequestInProgress && self.uploadURL() == '/') {
$('.file-upload .summary').click(); $('.file-upload .summary').click();
} }
e.stopPropagation(); e.stopPropagation();
...@@ -483,6 +521,10 @@ var cloud = (function(cloud) { ...@@ -483,6 +521,10 @@ var cloud = (function(cloud) {
$('.key').slideDown(700); $('.key').slideDown(700);
$('#keys').slideUp(700); $('#keys').slideUp(700);
}); });
$('#current-location select').on('change', function() {
model.sortBy($('#current-location select').val());
model.sortFiles();
})
}); });
document.addEventListener('dragenter', function(e) { document.addEventListener('dragenter', function(e) {
e.stopPropagation(); e.stopPropagation();
......
html
{
min-height: 100%;
position: relative;
}
body body
{ {
min-height:100%; min-height:100%;
...@@ -15,6 +20,7 @@ body ...@@ -15,6 +20,7 @@ body
width:970px; width:970px;
text-align:left; text-align:left;
margin:0 auto; margin:0 auto;
padding-bottom: 100px;
} }
.contentblock .contentblock
...@@ -198,6 +204,13 @@ input[type=submit], input[type=button], input[type=reset]{ ...@@ -198,6 +204,13 @@ input[type=submit], input[type=button], input[type=reset]{
background: rgba(0,0,0,0.2); background: rgba(0,0,0,0.2);
}; };
} }
input:disabled {
background-color: rgba(255,0,0,0.2);
color: #222;
&:hover {
background-color: rgba(255,0,0,0.5);
}
}
textarea { textarea {
border-radius: 2px; border-radius: 2px;
...@@ -263,3 +276,29 @@ textarea::-moz-placeholder{ ...@@ -263,3 +276,29 @@ textarea::-moz-placeholder{
textarea:-ms-input-placeholder{ textarea:-ms-input-placeholder{
color: @placeholderColor; color: @placeholderColor;
} }
body > footer {
z-index: 999;
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
border-top: 1px solid #888;
box-shadow:0 0 30px rgba(0,0,0,0.4);
margin:0;
background-color: white;
}
#http-error {
margin: 20px auto;
width: 500px;
border-radius: 4px;
border: 1px solid #888;
background: #FFFF66;
box-shadow: 0 0 20px rgba(0,0,0,0.2);
padding: 20px;
}
.irasmu p {
margin-top: 20px;
}
.boxes .boxes {
{
width:480px; width:480px;
float:left; float:left;
} }
.box .box {
{
background-color:#000; background-color:#000;
background-image:url(/static/image/hexa.png); background-image:url(/static/image/hexa.png);
background-position:center 30%; background-position:center 30%;
...@@ -18,43 +16,41 @@ ...@@ -18,43 +16,41 @@
border-top-width:30px; border-top-width:30px;
margin:10px 420px 10px 10px; margin:10px 420px 10px 10px;
padding:2px; padding:2px;
h3 h3 {
{
color:#fff; color:#fff;
text-align:center; text-align:center;
margin:0; margin:0;
padding:3px; padding:3px;
} }
.content .content {
{
min-height:100px; min-height:100px;
margin:0; margin:0;
padding:5px; padding:5px;
} }
} }
.tooltip{ .tooltip {
position: relative; position: relative;
z-index: 1; z-index: 1;
.container{ .container {
margin: 10px 10px 5px 150px; margin: 10px 10px 5px 150px;
border-radius: 4px; border-radius: 4px;
border: 1px solid #888; border: 1px solid #888;
background: #FFFF66; background: #FFFF66;
box-shadow: 0 0 20px rgba(0,0,0,0.2); box-shadow: 0 0 20px rgba(0,0,0,0.2);
p{ p {
text-align: left; text-align: left;
font-size: 0.8em; font-size: 0.8em;
word-spacing: 2px; word-spacing: 2px;
padding: 5px; padding: 5px;
} }
.tail{ .tail {
position: absolute; position: absolute;
left: 350px; left: 350px;
border-width: 17px; border-width: 17px;
border-style: solid; border-style: solid;
border-color: #888 transparent transparent transparent; border-color: #888 transparent transparent transparent;
&:after{ &:after {
content: ""; content: "";
position: absolute; position: absolute;
left: -17px; left: -17px;
...@@ -70,9 +66,9 @@ ...@@ -70,9 +66,9 @@
.entry-list { .entry-list {
list-style-type: none; list-style-type: none;
} }
.entry{ .entry {
&.opened { &.opened {
.actions{ .actions {
display: block !important; display: block !important;
} }
.summary .name .details { .summary .name .details {
...@@ -80,13 +76,13 @@ ...@@ -80,13 +76,13 @@
border: none; border: none;
} }
} }
&.small .summary{ &.small .summary {
padding: 5px; padding: 5px;
cursor: default; cursor: default;
&:hover{ &:hover {
background-color: #c1c1c1; background-color: #c1c1c1;
} }
.name{ .name {
background: none !important; background: none !important;
text-align: center; text-align: center;
float: none; float: none;
...@@ -116,24 +112,24 @@ ...@@ -116,24 +112,24 @@
background-image: url(/static/icons/key--exclamation.png); background-image: url(/static/icons/key--exclamation.png);
} }
} }
.quota{ .quota {
left: 0; left: 0;
top: 0; top: 0;
z-index: 0; z-index: 0;
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
.used{ .used {
height: 100%; height: 100%;
position: absolute; position: absolute;
} }
.softLimit{ .softLimit {
height: 100%; height: 100%;
position: absolute; position: absolute;
border-left: 1px solid red; border-left: 1px solid red;
} }
} }
.summary{ .summary {
padding: 15px 5px; padding: 15px 5px;
line-height: 1.7em; line-height: 1.7em;
border-top: 1px solid #888; border-top: 1px solid #888;
...@@ -144,32 +140,32 @@ ...@@ -144,32 +140,32 @@
-moz-transition: background-color 0.3s; -moz-transition: background-color 0.3s;
-o-transition: background-color 0.3s; -o-transition: background-color 0.3s;
transition: background-color 0.3s; transition: background-color 0.3s;
&.unfinished{ &.unfinished {
background-color: rgb(252, 252, 108); background-color: rgb(252, 252, 108);
background-image: url(/static/image/constr.png); background-image: url(/static/image/constr.png);
background-position: right top; background-position: right top;
background-repeat: no-repeat; background-repeat: no-repeat;
&:hover{ &:hover {
background-color: rgb(236, 236, 106); background-color: rgb(236, 236, 106);
background-image: url(/static/image/constr.png); background-image: url(/static/image/constr.png);
} }
} }
&.selected-summary{ &.selected-summary {
background-color: rgb(124, 236, 103); background-color: rgb(124, 236, 103);
&:hover{ &:hover {
background-color: rgb(135, 211, 120); background-color: rgb(135, 211, 120);
} }
} }
&.public-template{ &.public-template {
background-color: rgb(167, 179, 195); background-color: rgb(167, 179, 195);
&:hover{ &:hover {
background-color: rgb(157, 169, 185); background-color: rgb(157, 169, 185);
} }
} }
&:hover{ &:hover {
background-color: #b1b1b1; background-color: #b1b1b1;
background-image: none; background-image: none;
.actions{ .actions {
display: block; display: block;
} }
.name .details { .name .details {
...@@ -178,11 +174,11 @@ ...@@ -178,11 +174,11 @@
} }
} }
.id{ .id {
float: right; float: right;
width: 30px; width: 30px;
} }
.name{ .name {
float: left; float: left;
padding-left: 25px; padding-left: 25px;
background-repeat: no-repeat; background-repeat: no-repeat;
...@@ -197,27 +193,27 @@ ...@@ -197,27 +193,27 @@
display: none; display: none;
} }
} }
.status{ .status {
text-align: right; text-align: right;
float: right; float: right;
width: 60px; width: 60px;
z-index: 2; z-index: 2;
position: relative; position: relative;
} }
.actions{ .actions {
float: right; float: right;
margin-left: 5px; margin-left: 5px;
display: none; display: none;
z-index: 2; z-index: 2;
position: relative; position: relative;
a{ a {
margin: 2px 0; margin: 2px 0;
height: 16px; height: 16px;
width: 16px; width: 16px;
display: block; display: block;
float: left; float: left;
margin-left: 2px; margin-left: 2px;
&:hover{ &:hover {
box-shadow: 0 0 10px rgba(0,0,0,0.4); box-shadow: 0 0 10px rgba(0,0,0,0.4);
background-color: rgba(0,0,0,0.4); background-color: rgba(0,0,0,0.4);
} }
...@@ -234,12 +230,12 @@ ...@@ -234,12 +230,12 @@
&.opened #new-folder-form { &.opened #new-folder-form {
display: block; display: block;
} }
.details{ .details {
border-top: 1px solid #888; border-top: 1px solid #888;
display: none; display: none;
.container{ .container {
padding: 5px 5px; padding: 5px 5px;
.upload-zone{ .upload-zone {
margin: 10px; margin: 10px;
border-radius: 10px; border-radius: 10px;
border: 2px dashed #666; border: 2px dashed #666;
...@@ -251,70 +247,73 @@ ...@@ -251,70 +247,73 @@
} }
} }
} }
h3{ h3 {
font-weight: normal; font-weight: normal;
} }
ul{ ul {
list-style: none; list-style: none;
margin: 0px 5px; margin: 0px 5px;
} }
li{ li {
margin: 8px 0px; margin: 8px 0px;
padding: 3px 0px 3px 20px; padding: 3px 0px 3px 20px;
border-bottom: 1px dotted #aaa; border-bottom: 1px dotted #aaa;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 0px 4px; background-position: 0px 4px;
&:last-child{ &:last-child {
border-bottom: none; border-bottom: none;
}; };
} }
a{ a {
text-decoration: underline; text-decoration: underline;
} }
.name{ .name {
float: none; float: none;
background-image: url(/static/icons/computer.png); background-image: url(/static/icons/computer.png);
} }
.os-win{ .os-win {
background-image: url(/static/icons/windows.png) background-image: url(/static/icons/windows.png);
}
.os-linux {
background-image: url(/static/icons/animal-penguin.png);
} }
.os-linux{ .template {
background-image: url(/static/icons/animal-penguin.png) background-image: url(/static/icons/document-template.png);
} }
.template{ .type {
background-image: url(/static/icons/document-template.png) background-image: url(/static/icons/box-share.png);
} }
.type{ .date {
background-image: url(/static/icons/box-share.png) background-image: url(/static/icons/calendar-day.png);
} }
.date{ .cpu {
background-image: url(/static/icons/calendar-day.png) background-image: url(/static/icons/processor.png);
} }
.cpu{ .memory {
background-image: url(/static/icons/processor.png) background-image: url(/static/icons/memory.png);
} }
.memory{ .count {
background-image: url(/static/icons/memory.png) background-image: url(/static/icons/documents-stack.png);
} }
.count{ .share-type {
background-image: url(/static/icons/documents-stack.png) background-image: url(/static/icons/calendar-day.png);
} }
.value{ .value {
float: right; float: right;
width: 200px; width: 200px;
text-align: right; text-align: right;
} }
.description{ .description {
font-size: inherit; font-size: inherit;
background-image: url(/static/icons/document-snippet.png); background-image: url(/static/icons/document-snippet.png);
.value{ .value {
font-size: 0.8em; font-size: 0.8em;
word-spacing: 3px; word-spacing: 3px;
width: 350px; width: 350px;
} }
} }
} }
&.new .name{ &.new .name {
background-image: url(/static/icons/computer--plus.png); background-image: url(/static/icons/computer--plus.png);
} }
} }
...@@ -327,11 +326,11 @@ ...@@ -327,11 +326,11 @@
background-position: left center; background-position: left center;
background-repeat: no-repeat; background-repeat: no-repeat;
padding-left: 18px; padding-left: 18px;
&.suspend{ &.suspend {
background-image: url(/static/icons/control-pause.png) background-image: url(/static/icons/control-pause.png);
} }
&.delete{ &.delete {
background-image: url(/static/icons/minus-circle.png) background-image: url(/static/icons/minus-circle.png);
} }
} }
} }
...@@ -344,25 +343,25 @@ ...@@ -344,25 +343,25 @@
background-position: left center; background-position: left center;
background-repeat: no-repeat; background-repeat: no-repeat;
padding-left: 18px; padding-left: 18px;
&.cpu{ &.cpu {
background-image: url(/static/icons/processor.png) background-image: url(/static/icons/processor.png);
} }
&.memory{ &.memory {
background-image: url(/static/icons/memory.png) background-image: url(/static/icons/memory.png);
} }
&.credit{ &.credit {
background-image: url(/static/icons/point.png) background-image: url(/static/icons/point.png);
} }
} }
} }
.file-list{ .file-list {
list-style: none; list-style: none;
max-height: 400px; max-height: 400px;
.name{ .name {
float: left; float: left;
} }
.info{ .info {
float: right; float: right;
width: 65px; width: 65px;
text-align: right; text-align: right;
...@@ -377,19 +376,19 @@ ...@@ -377,19 +376,19 @@
} }
#file-list { #file-list {
overflow-y: scroll; overflow-y: scroll;
li:nth-child(3) .summary{ li:nth-child(3) .summary {
border-top: none; border-top: none;
} }
li:nth-child(2) .summary{ li:nth-child(2) .summary {
border-top: none; border-top: none;
} }
li:nth-child(1) .summary{ li:nth-child(1) .summary {
border-top: none; border-top: none;
border-bottom: 1px solid #888 border-bottom: 1px solid #888
} }
} }
#current-location{ #current-location {
.summary{ .summary {
border-bottom: 1px solid #888; border-bottom: 1px solid #888;
height: 25px; height: 25px;
.name { .name {
...@@ -453,55 +452,55 @@ ...@@ -453,55 +452,55 @@
.filetype-jump-out { .filetype-jump-out {
background-image: url(/static/icons/arrow-curve-090.png); background-image: url(/static/icons/arrow-curve-090.png);
} }
.vm-on{ .vm-on {
background-image: url(/static/icons/computer-cloud.png); background-image: url(/static/icons/computer-cloud.png);
} }
.vm-off{ .vm-off {
background-image: url(/static/icons/computer-off.png); background-image: url(/static/icons/computer-off.png);
} }
#template .entry .summary .name{ #template .entry .summary .name {
background-image: url(/static/icons/document-template.png) background-image: url(/static/icons/document-template.png);
} }
#template .entry .public-template .name{ #template .entry .public-template .name {
background-image: url(/static/icons/blue-document-share.png) background-image: url(/static/icons/blue-document-share.png);
} }
#new-template-button .name{ #new-template-button .name {
background-image: url(/static/icons/document--plus.png) !important background-image: url(/static/icons/document--plus.png) !important;
} }
.wm-list.modal{ .wm-list.modal {
border-radius: 4px; border-radius: 4px;
border: 1px solid #666; border: 1px solid #666;
} }
.wm-list.modal input{ .wm-list.modal input {
padding: 2px 10px; padding: 2px 10px;
} }
.wm-list.modal .wm:nth-child(1) .summary{ .wm-list.modal .wm:nth-child(1) .summary {
border-top: none; border-top: none;
} }
#template{ #template {
.entry { .entry {
.template-details{ .template-details {
margin: 0; margin: 0;
padding: 0; padding: 0;
border-top: 1px solid #888; border-top: 1px solid #888;
display: none; display: none;
ul{ ul {
list-style-type: none; list-style-type: none;
} }
li{ li {
padding-left: 10px; padding-left: 10px;
border-top: 1px solid #aaa; border-top: 1px solid #aaa;
position: relative; position: relative;
&:first-child{ &:first-child {
border-top: none; border-top: none;
}; };
.status{ .status {
float: right; float: right;
padding: 0 5px; padding: 0 5px;
} }
.group-name{ .group-name {
float: left; float: left;
line-height: 1.5em; line-height: 1.5em;
z-index: 2; z-index: 2;
...@@ -525,7 +524,7 @@ table { ...@@ -525,7 +524,7 @@ table {
&:hover { &:hover {
background-color: rgba(0,0,0,0.1); background-color: rgba(0,0,0,0.1);
}; };
td,th { td, th {
padding: 5px; padding: 5px;
} }
td { td {
...@@ -591,7 +590,7 @@ table { ...@@ -591,7 +590,7 @@ table {
-moz-transition: background-color 0.3s; -moz-transition: background-color 0.3s;
-o-transition: background-color 0.3s; -o-transition: background-color 0.3s;
transition: background-color 0.3s; transition: background-color 0.3s;
&:hover{ &:hover {
background-color: rgba(0,0,0,0.1); background-color: rgba(0,0,0,0.1);
border: 1px solid #666; border: 1px solid #666;
input { input {
...@@ -611,6 +610,19 @@ table { ...@@ -611,6 +610,19 @@ table {
height: 30px; height: 30px;
right: -5px; right: -5px;
} }
&.description {
display: none;
height: default;
font-size: 0.8em;
margin-left: 20px;
}
.edit {
margin: 0 2px;
img:hover {
box-shadow: 0 0 10px rgba(0,0,0,0.4);
background-color: rgba(0,0,0,0.4);
}
}
} }
} }
...@@ -632,13 +644,22 @@ table { ...@@ -632,13 +644,22 @@ table {
margin:20px; margin:20px;
display: none; display: none;
} }
&:hover .boxhelp-box { .help:hover .boxhelp-box {
display: block; display: block;
} }
.help {
img {
cursor: default;
}
}
.icon { .icon {
display: block; display: block;
float: right; float: right;
} }
img {
margin: 3px;
cursor: pointer;
}
} }
#new-owner-autocomplete { #new-owner-autocomplete {
......
body{min-height:100%;font-family:'Titillium Web',sans-serif;font-size:.9em;background:#dadada url(/static/image/site_bgr.png) repeat-x;background-position:80px 0;margin:0;padding:0;overflow:scroll}#content{width:970px;text-align:left;margin:0 auto}.contentblock{background-color:#ccc;border-radius:4px;border:1px solid #aaa;box-shadow:0 0 30px rgba(0,0,0,0.3);margin:20px}.contentblock p,.contentblock dl{margin:0;padding:5px}.contentblock h2{background-color:#000;background-image:url(/static/image/hexabar.png);background-position:right center;background-repeat:no-repeat;border-radius:4px;border-bottom-left-radius:0;border-bottom-right-radius:0;color:#eee;font-size:1.5em;margin-top:0;padding:10px;position:relative}.contentblock.wide{margin-right:30px}.contentblock.note{background-color:#ffc}.contentblock ol{margin-left:2em}.contentblock ol li.done{color:#aaa}.big{font-size:2em}ul.messagelist{text-align:left;margin:0;padding:0 0 5px}ul.messagelist li{font-size:12px;display:block;border-bottom:1px solid #ddd;color:#666;background:#ffc url(/static/admin/img/icon_success.gif) 5px .3em no-repeat;margin:0 0 3px;padding:4px 5px 4px 25px}ul.messagelist li.warning{background-image:url(/static/admin/img/icon_alert.gif)}ul.messagelist li.error{background-image:url(/static/admin/img/icon_error.gif)}input.validated{padding-right:15px;background-image:url(/static/admin/img/icon_success.gif);background-repeat:no-repeat;background-position:right center}input.validated.error{background:#fcc url(/static/admin/img/icon_error.gif) right center no-repeat;padding-right:15px}.errornote{font-size:12px!important;display:block;border:1px solid red;color:red;background:#ffc url(/static/admin/img/icon_error.gif) 5px .3em no-repeat;margin:0 0 3px;padding:4px 5px 4px 25px}.errorlist li{font-size:12px!important;display:block;border:1px solid red;color:#FFF;background:#f00 url(/static/admin/img/icon_alert.gif) 5px .3em no-repeat;margin:0 0 3px;padding:4px 5px 4px 25px}.errorlist li a{color:#FFF;text-decoration:underline}td ul.errorlist li{margin:0!important}.errors{background:#ffc}.errors input,.errors select,.errors textarea{border:1px solid red}div.system-message{background:#ffc;font-size:.8em;margin:10px;padding:6px 8px}div.system-message p.system-message-title{color:red;background:#ffc url(/static/admin/img/icon_error.gif) 5px .3em no-repeat;margin:0;padding:4px 5px 4px 25px}small{font-size:.8em}input{border-radius:2px;border:1px solid #777;padding:2px;margin:1px 5px;background:rgba(0,0,0,0.1);font-family:'Titillium Web',sans-serif;outline:0;box-shadow:inset 0 0 10px rgba(0,0,0,0.2),0 0 5px rgba(0,0,0,0.2);-webkit-transition:box-shadow .5s;-moz-transition:box-shadow .5s;-o-transition:box-shadow .5s;transition:box-shadow .5s}input:hover{border:1px solid #666;box-shadow:inset 0 0 10px rgba(0,0,0,0.2),0 0 5px rgba(255,255,0,0.5)}input:focus{border:1px solid #555;box-shadow:inset 0 0 10px rgba(0,0,0,0.2),0 0 10px rgba(255,255,0,0.8)}input[type=submit],input[type=button],input[type=reset]{border:1px solid #777;cursor:pointer;box-shadow:0 0 5px rgba(0,0,0,0.2);-webkit-transition:background .5s;-moz-transition:background .5s;-o-transition:background .5s;transition:background .5s}input[type=submit]:hover,input[type=button]:hover,input[type=reset]:hover{background:rgba(0,0,0,0.2)}textarea{border-radius:2px;border:1px solid #777;padding:5px;margin:10px 5px;width:300px;height:100px;background:rgba(0,0,0,0.1);font-family:'Titillium Web',sans-serif;outline:0;box-shadow:inset 0 0 10px rgba(0,0,0,0.2),0 0 5px rgba(0,0,0,0.2);-webkit-transition:box-shadow .5s;-moz-transition:box-shadow .5s;-o-transition:box-shadow .5s;transition:box-shadow .5s}textarea:hover{border:1px solid #666;box-shadow:inset 0 0 10px rgba(0,0,0,0.2),0 0 5px rgba(255,255,0,0.5)}textarea:focus{border:1px solid #555;box-shadow:inset 0 0 10px rgba(0,0,0,0.2),0 0 10px rgba(255,255,0,0.8)}.hilight{background-color:#ff6}.hidden-password{padding-right:25px;background-image:url(/static/icons/eye-half.png);background-repeat:no-repeat;background-position:right center;cursor:pointer}.hidden-password.shown{background-image:url(/static/icons/eye.png)}input::-webkit-input-placeholder{color:#444}input:-moz-placeholder{color:#444}input::-moz-placeholder{color:#444}input:-ms-input-placeholder{color:#444}textarea::-webkit-input-placeholder{color:#444}textarea:-moz-placeholder{color:#444}textarea::-moz-placeholder{color:#444}textarea:-ms-input-placeholder{color:#444}#header{height:80px;background-color:#072c61;background-image:url(/static/image/bme_feher2.png);background-repeat:no-repeat;background-position:20px 18px;border-bottom:3px solid #0b4599;box-shadow:0 0 30px rgba(0,0,0,0.4);margin:0;padding:0 0 0 200px}#header h1{font-size:2em;line-height:80px;float:left;margin:0;padding:0 1em}#header h1 a{color:#fff;text-decoration:none}#loginblock{position:absolute;right:0;top:0;background-color:#000;background-image:url(/static/image/hexabar.png);background-position:center center;border-radius:0 0 0 10px;color:#fff;font-weight:700;margin:0;padding:7px}#loginblock a{color:#fff;text-decoration:underline}#loginblock a:hover{color:#aaa}.boxes{width:480px;float:left}.box{background-color:#000;background-image:url(/static/image/hexa.png);background-position:center 30%;background-repeat:no-repeat;color:#fff;font-weight:700;line-height:1.5em;width:400px;border-radius:10px;border-top-width:30px;margin:10px 420px 10px 10px;padding:2px}.box h3{color:#fff;text-align:center;margin:0;padding:3px}.box .content{min-height:100px;margin:0;padding:5px}.tooltip{position:relative;z-index:1}.tooltip .container{margin:10px 10px 5px 150px;border-radius:4px;border:1px solid #888;background:#ff6;box-shadow:0 0 20px rgba(0,0,0,0.2)}.tooltip .container p{text-align:left;font-size:.8em;word-spacing:2px;padding:5px}.tooltip .container .tail{position:absolute;left:350px;border-width:17px;border-style:solid;border-color:#888 transparent transparent transparent}.tooltip .container .tail:after{content:"";position:absolute;left:-17px;top:-18px;border-width:17px;border-style:solid;border-color:#ff6 transparent transparent transparent}.entry-list{list-style-type:none}.entry.opened .actions{display:block!important}.entry.opened .summary .name .details{display:inline;border:0}.entry.small .summary{padding:5px;cursor:default}.entry.small .summary:hover{background-color:#c1c1c1}.entry.small .summary .name{background:none!important;text-align:center;float:none}.entry.small-row .summary{padding:5px}.entry.small-row .summary:hover{background-color:#b1b1b1}.entry.small-row .summary .name{float:none}.entry.key .name{background-image:url(/static/icons/key.png)}.entry.key textarea{margin:10px;width:93%}.entry.key #new-key .name{background-image:url(/static/icons/key--plus.png)}.entry.key #reset-key .name{background-image:url(/static/icons/key--exclamation.png)}.entry .quota{left:0;top:0;z-index:0;position:absolute;width:100%;height:100%}.entry .quota .used{height:100%;position:absolute}.entry .quota .softLimit{height:100%;position:absolute;border-left:1px solid red}.entry .summary{padding:15px 5px;line-height:1.7em;border-top:1px solid #888;cursor:pointer;background-color:#c1c1c1;position:relative;-webkit-transition:background-color .3s;-moz-transition:background-color .3s;-o-transition:background-color .3s;transition:background-color .3s}.entry .summary.unfinished{background-color:#fcfc6c;background-image:url(/static/image/constr.png);background-position:right top;background-repeat:no-repeat}.entry .summary.unfinished:hover{background-color:#ecec6a;background-image:url(/static/image/constr.png)}.entry .summary.selected-summary{background-color:#7cec67}.entry .summary.selected-summary:hover{background-color:#87d378}.entry .summary.public-template{background-color:#a7b3c3}.entry .summary.public-template:hover{background-color:#9da9b9}.entry .summary:hover{background-color:#b1b1b1;background-image:none}.entry .summary:hover .actions{display:block}.entry .summary:hover .name .details{display:inline;border:0}.entry .summary .id{float:right;width:30px}.entry .summary .name{float:left;padding-left:25px;background-repeat:no-repeat;background-position:left center;z-index:2;position:relative;height:24px}.entry .summary .name.filetype-new-folder{float:left}.entry .summary .name .details{display:none}.entry .summary .status{text-align:right;float:right;width:60px;z-index:2;position:relative}.entry .summary .actions{float:right;margin-left:5px;display:none;z-index:2;position:relative}.entry .summary .actions a{margin:2px 0;height:16px;width:16px;display:block;float:left;margin-left:2px}.entry .summary .actions a:hover{box-shadow:0 0 10px rgba(0,0,0,0.4);background-color:rgba(0,0,0,0.4)}.entry .summary #new-folder-form{float:right;margin-left:5px;display:none;z-index:2;position:relative}.entry.opened #new-folder-form{display:block}.entry .details{border-top:1px solid #888;display:none}.entry .details .container{padding:5px 5px}.entry .details .container .upload-zone{margin:10px;border-radius:10px;border:2px dashed #666;text-align:center;font-size:.8em;padding:10px}.entry .details .container .upload-zone p{padding:0}.entry .details h3{font-weight:normal}.entry .details ul{list-style:none;margin:0 5px}.entry .details li{margin:8px 0;padding:3px 0 3px 20px;border-bottom:1px dotted #aaa;background-repeat:no-repeat;background-position:0 4px}.entry .details li:last-child{border-bottom:0}.entry .details a{text-decoration:underline}.entry .details .name{float:none;background-image:url(/static/icons/computer.png)}.entry .details .os-win{background-image:url(/static/icons/windows.png)}.entry .details .os-linux{background-image:url(/static/icons/animal-penguin.png)}.entry .details .template{background-image:url(/static/icons/document-template.png)}.entry .details .type{background-image:url(/static/icons/box-share.png)}.entry .details .date{background-image:url(/static/icons/calendar-day.png)}.entry .details .cpu{background-image:url(/static/icons/processor.png)}.entry .details .memory{background-image:url(/static/icons/memory.png)}.entry .details .count{background-image:url(/static/icons/documents-stack.png)}.entry .details .value{float:right;width:200px;text-align:right}.entry .details .description{font-size:inherit;background-image:url(/static/icons/document-snippet.png)}.entry .details .description .value{font-size:.8em;word-spacing:3px;width:350px}.entry.new .name{background-image:url(/static/icons/computer--plus.png)}#new-share .type-summary.type-summary,.share-type .value.type-summary{font-size:.8em;text-align:right}#new-share .type-summary span,.share-type .value span{background-position:left center;background-repeat:no-repeat;padding-left:18px}#new-share .type-summary span.suspend,.share-type .value span.suspend{background-image:url(/static/icons/control-pause.png)}#new-share .type-summary span.delete,.share-type .value span.delete{background-image:url(/static/icons/minus-circle.png)}#template-wizard .size-summary.size-summary,.type .value.size-summary{font-size:.8em;text-align:right}#template-wizard .size-summary span,.type .value span{background-position:left center;background-repeat:no-repeat;padding-left:18px}#template-wizard .size-summary span.cpu,.type .value span.cpu{background-image:url(/static/icons/processor.png)}#template-wizard .size-summary span.memory,.type .value span.memory{background-image:url(/static/icons/memory.png)}#template-wizard .size-summary span.credit,.type .value span.credit{background-image:url(/static/icons/point.png)}.file-list{list-style:none;max-height:400px}.file-list .name{float:left}.file-list .info{float:right;width:65px;text-align:right;font-size:.8em}.file-list select{position:absolute;left:10px;top:5px;z-index:10}#file-list{overflow-y:scroll}#file-list li:nth-child(3) .summary{border-top:0}#file-list li:nth-child(2) .summary{border-top:0}#file-list li:nth-child(1) .summary{border-top:0;border-bottom:1px solid #888}#current-location .summary{border-bottom:1px solid #888;height:25px}#current-location .summary .name{position:absolute;left:100px;text-align:left}.filetype-c{background-image:url(/static/icons/document-visual-studio.png)}.filetype-text{background-image:url(/static/icons/document.png)}.filetype-image{background-image:url(/static/icons/document-image.png)}.filetype-zip{background-image:url(/static/icons/folder-zipper.png)}.filetype-pdf{background-image:url(/static/icons/document-pdf.png)}.filetype-doc{background-image:url(/static/icons/document-word.png)}.filetype-excel{background-image:url(/static/icons/document-excel.png)}.filetype-csv{background-image:url(/static/icons/document-excel-csv.png)}.filetype-php{background-image:url(/static/icons/document-php.png)}.filetype-tex{background-image:url(/static/icons/document-tex.png)}.filetype-ppt{background-image:url(/static/icons/document-powerpoint.png)}.filetype-music{background-image:url(/static/icons/document-music.png)}.filetype-movie{background-image:url(/static/icons/document-film.png)}.filetype-folder{background-image:url(/static/icons/folder.png)}.toplist{background-image:url(/static/icons/arrow-circle-double.png)}.filetype-up{background-image:url(/static/icons/upload-cloud.png)}.filetype-new-folder{background-image:url(/static/icons/folder--plus.png)}.filetype-jump-out{background-image:url(/static/icons/arrow-curve-090.png)}.vm-on{background-image:url(/static/icons/computer-cloud.png)}.vm-off{background-image:url(/static/icons/computer-off.png)}#template .wm .summary .name{background-image:url(/static/icons/document-template.png)}#template .wm .public-template .name{background-image:url(/static/icons/blue-document-share.png)}#new-template-button .name{background-image:url(/static/icons/document--plus.png)!important}.wm-list.modal{border-radius:4px;border:1px solid #666}.wm-list.modal input{padding:2px 10px}.wm-list.modal .wm:nth-child(1) .summary{border-top:0}#template .entry .template-details{margin:0;padding:0;border-top:1px solid #888;display:none}#template .entry .template-details ul{list-style-type:none}#template .entry .template-details li{padding-left:10px;border-top:1px solid #aaa;position:relative}#template .entry .template-details li:first-child{border-top:0}#template .entry .template-details li .status{float:right;padding:0 5px}#template .entry .template-details li .group-name{float:left;line-height:1.5em;z-index:2;position:relative}#vm-credentials .content,#ports .content{padding:15px}table{width:100%;border-collapse:collapse}table tr{width:100%}table tr:hover{background-color:rgba(0,0,0,0.1)}table tr td,table tr th{padding:5px}table tr td{width:150px}#groups .entry .summary .name{background-image:url(/static/icons/users.png)}#groups #new-group .summary .name{background-image:url(/static/icons/user--plus.png)}#groups #show-hidden-groups .summary .name{background-image:url(/static/icons/eye.png)}#group-members .summary .name,#group-owners .summary .name{background-image:url(/static/icons/user.png);float:left}#new-member .name,#new-owner .name{background-image:url(/static/icons/user--plus.png)!important;float:left}#new-member #new-member-form,#new-owner #new-member-form,#new-member #new-owner-form,#new-owner #new-owner-form{float:right;margin-left:5px;display:none;z-index:2;position:relative}.shares{margin:5px;list-style:none}.shares li{overflow:hidden;border-radius:2px;border:1px solid #888;height:30px;position:relative;margin:5px 0;line-height:30px;padding-left:10px;background-color:rgba(0,0,0,0.05);-webkit-transition:background-color .3s;-moz-transition:background-color .3s;-o-transition:background-color .3s;transition:background-color .3s}.shares li:hover{background-color:rgba(0,0,0,0.1);border:1px solid #666}.shares li:hover input{border-left:1px solid #666}.shares li form{position:relative}.shares li input{border:0;border-radius:0;border-left:1px solid #888;box-shadow:none;position:relative;top:-1px;height:30px;right:-5px}.boxhelp{position:relative}.boxhelp .boxhelp-box{color:#000;position:absolute;left:-100px;width:500px;z-index:1000000;font-size:.7em;background-color:#ffc;border-radius:4px;border:1px solid #aaa;box-shadow:0 0 30px rgba(0,0,0,0.3);margin:20px;display:none}.boxhelp:hover .boxhelp-box{display:block}.boxhelp .icon{display:block;float:right}#modal{top:0;position:absolute;width:100%;height:100%;z-index:999}#shadow{position:fixed;height:100%;width:100%;background-color:rgba(0,0,0,0.6)}#modal-container{min-width:500px;position:fixed;left:50%;top:100px;margin-left:-270px;margin-top:0;min-height:50px;background-color:#fff;border-radius:4px;padding:20px;box-shadow:0 0 30px rgba(0,0,0,0.4);border:1px solid #333;max-height:60%;overflow:auto}#modal-container .container{max-height:400px;overflow:auto;border-radius:2px;border:1px solid #888;background-color:#ccc}#modal-container ul{list-style:none}#modal-container ul li:first-child .summary{border:0}.wizard li{border-bottom:1px dotted #999}.wizard label{display:inline-block;padding:3px;margin:10px 5px}.wizard h2{margin:10px 0}.wizard .progress{text-align:center;position:relative;width:100%;height:15px}.wizard .progress .bar{height:20px;background-color:#66c400;border-right:1px solid #468600}.wizard .progress .bar-container{border:1px solid #666;box-shadow:0 0 20px rgba(0,0,0,0.2);border-radius:4px;height:20px;position:absolute;width:500px}.wizard .progress h3{width:100%;position:absolute}.wizard input[type=text],.wizard input[type=number],.wizard select{display:block;float:right;margin-top:8px}.wizard input[type=number]{width:4em}.wizard textarea{float:right;text-align:right}.wizard nav{margin-top:15px}.wizard nav a{text-decoration:underline;display:block}.wizard nav .prev{float:left}.wizard nav .next{float:right}.wizard ul.radio{float:right}.wizard ul.radio label{float:left;margin:0}.wizard .radio li{float:left;padding:5px;margin:5px 3px;border-bottom:none!important}.wizard .size-summary{margin:10px}#new-template-name input{margin:10px 5px}*{margin:0;padding:0}.clear{clear:both}abbr{border-bottom:1px dotted #666}a:link,a:visited{color:black}
\ No newline at end of file
from celery.task import Task, PeriodicTask
import logging
import celery
import os
import sys
import time
from django.core.mail import send_mail
logger = logging.getLogger(__name__)
class SendMailTask(Task):
def run(self, to, subject, msg, sender=u'noreply@cloud.ik.bme.hu'):
send_mail(subject, msg, sender, [ to ], fail_silently=False)
logger.info("[django][one][tasks.py] %s->%s [%s]" % (sender, to, subject) )
{% extends "base.html" %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<!doctype html>
<html lang="{{LANGUAGE_CODE}}">
<head> {% block content %}
<meta charset="UTF-8"> <div id="http-error">
<title>404 - {% trans ":(" %}</title>
</head>
<body>
<h1>404 - {% trans ":(" %}</h1> <h1>404 - {% trans ":(" %}</h1>
</body> <p>
</html> {% trans "The requested page does not exists... Please go away..." %}
</p>
</div>
{% endblock %}
{% extends "base.html" %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
{% block content %}
<div id="http-error">
<h1>500 - {% trans ":(" %}</h1>
<p>
{% trans "Internal Server Error... Please leave the server alone..." %}
</p>
</div>
{% endblock %}
<!DOCTYPE html> <!DOCTYPE html>
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as lang %} {% get_current_language as lang %}
<html lang="{{lang}}"> <html lang="{{lang}}">
<head> <head>
<title>{% block title %}IK Cloud{% endblock %}</title> <title>{% block title %}IK Cloud{% endblock %}</title>
<link href="https://fonts.googleapis.com/css?family=Titillium+Web&amp;subset=latin,latin-ext" rel="stylesheet" type="text/css"> <link href="https://fonts.googleapis.com/css?family=Titillium+Web&amp;subset=latin,latin-ext" rel="stylesheet" type="text/css" />
<link rel="icon" type="image/png" href="/static/favicon.png" /> <link rel="icon" type="image/png" href="{% static "favicon.png" %}" />
<link rel="stylesheet/less" href="/static/style/style.less" /> {% if DEBUG %}<link rel="stylesheet/less" href="{% static "style/style.less" %}" />{% else %}
<link href="{% static "style/style.css" %}" rel="stylesheet" type="text/css" />{% endif %}
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="/static/script/jquery.min.js"></script> <script src="{% static "script/jquery.min.js" %}"></script>
<script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script> <script type="text/javascript" src="{% url django.views.i18n.javascript_catalog %}"></script>
<script type="text/javascript"> <script type="text/javascript">
window.localStorage.removeItem('https://cloud.ik.bme.hu/static/style/style.less:timestamp'); {% if DEBUG %}window.localStorage.removeItem('https://cloud.ik.bme.hu/static/style/style.less:timestamp');{% endif %}
var current_user={{user.id}}; var current_user={{user.id}};
</script> </script>
<script src="/static/script/less.min.js"></script> {% if DEBUG %}<script src="{% static "script/less.min.js" %}"></script>{% endif %}
<script src="/static/script/knockout.min.js"></script> <script src="{% static "script/knockout.min.js" %}"></script>
<script type="text/javascript" src="/static/script/util.js"></script> {% if DEBUG %}<script type="text/javascript" src="{% static "script/util.js" %}"></script>
<script type="text/javascript" src="/static/script/cloud.js"></script> {% else %}<script type="text/javascript" src="{% static "script/util.min.js" %}"></script>
{% endif %}
{% if DEBUG %}<script type="text/javascript" src="{% static "script/cloud.js" %}"></script>
{% else %}<script type="text/javascript" src="{% static "script/cloud.min.js" %}"></script>
{% endif %}
{{ form.media }} {{ form.media }}
{% block js %}{% endblock %} {% block js %}{% endblock %}
</head> </head>
...@@ -26,25 +32,27 @@ ...@@ -26,25 +32,27 @@
{% block login %} {% block login %}
<div id="loginblock"><p> <div id="loginblock"><p>
{% if user.is_authenticated %} {% if user.is_authenticated %}
Bejelentkezve: {{ user.username }}. {% trans "Logged in:" %} {{ user.username }}.
<a href="/logout/">Kijelentkezés</a>. <a href="{% url logout %}">{% trans "Logout" %}</a>.
{% if user.is_staff %} {% if user.is_staff %}
<a href="/admin/">Admin</a>. <a href="{% url admin:index %}">{% trans "Admin" %}</a>.
{% endif %} {% endif %}
{% else %} {% else %}
<a href="/login/">Bejelentkezés</a>. <a href="{% url login %}">{% trans "Login" %}</a>.
{% endif %} {% endif %}
{% if user.is_authenticated %}
{% if lang == 'hu' %} {% if lang == 'hu' %}
<a href="/language/en/">In English</a>. <a href="{% url school.views.language "en" %}">In English</a>.
{% else %} {% else %}
<a href="/language/hu/">Magyarul</a>. <a href="{% url school.views.language "hu" %}">Magyarul</a>.
{% endif %}
{% endif %} {% endif %}
</p> </p>
</div> </div>
{% endblock %} {% endblock %}
{% block header %} {% block header %}
{% block header_title %} {% block header_title %}
<h1><a href="/">IK Cloud</a></h1> <h1><a href="{% url one.views.index %}">IK Cloud</a></h1>
{% endblock %} {% endblock %}
{% endblock %} {% endblock %}
</div> </div>
...@@ -61,11 +69,27 @@ ...@@ -61,11 +69,27 @@
{% block content %}{% endblock %} {% block content %}{% endblock %}
<div class="clear"></div> <div class="clear"></div>
</div> </div>
<footer>
<a href="/sites/legal/">{% trans "Legal notice" %}</a> |
<a href="/sites/policy/">{% trans "Policy" %}</a> |
<a href="/sites/help/">{% trans "Help" %}</a> |
<a href="/sites/support/">{% trans "Support" %}</a>
</footer>
<div id="modal" style="display: none"> <div id="modal" style="display: none">
<div id="shadow"></div> <div id="shadow"></div>
<div id="modal-container"> <div id="modal-container">
</div> </div>
</div> </div>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-39125666-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body> </body>
</html> </html>
{% extends "box/base/box.html" %} {% extends "box/base/box.html" %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block title %} {% block title %}
...@@ -8,8 +9,9 @@ ...@@ -8,8 +9,9 @@
{% endblock title %} {% endblock title %}
{% block boxhelp %} {% block boxhelp %}
<div class="boxhelp"> <div class="boxhelp">
<div class="help">
<div class="icon"> <div class="icon">
<img src="/static/icons/information-frame.png" alt="{% trans "Help" %}" /> <img src="{% static "icons/information-frame.png" %}" alt="{% trans "Help" %}" />
</div> </div>
<div class="boxhelp-box"> <div class="boxhelp-box">
<p>{% blocktrans %}This is your global data store.{% endblocktrans %}</p> <p>{% blocktrans %}This is your global data store.{% endblocktrans %}</p>
...@@ -24,6 +26,10 @@ ...@@ -24,6 +26,10 @@
WinSCP) to access your files at {{serv}}. You will need to register a WinSCP) to access your files at {{serv}}. You will need to register a
public key bellow.{% endblocktrans %}</p> public key bellow.{% endblocktrans %}</p>
</div> </div>
</div>
<div class="icon">
<img src="" alt="toggle" title="{% trans "Show/hide box" %}" class="toggle-box" data-id="files" id="toggle-box-files"/>
</div>
</div> </div>
{% endblock %} {% endblock %}
...@@ -80,7 +86,7 @@ ...@@ -80,7 +86,7 @@
</li> </li>
<li class="entry small-row"> <li class="entry small-row">
<div class="summary" id="new-folder"> <div class="summary" id="new-folder">
<div class="name toplist" data-bind="click: loadTopList">{% trans "Toplist" %}</div> <div class="name toplist" data-bind="click: toggleToplist, text: getToplistText"></div>
<div class="clear"></div> <div class="clear"></div>
</div> </div>
</li> </li>
...@@ -100,7 +106,7 @@ ...@@ -100,7 +106,7 @@
</div> </div>
<div class="details"> <div class="details">
<div class="container"> <div class="container">
<form style="padding-bottom: 10px" action="/key/add/" method="POST"> <form style="padding-bottom: 10px" action="{% url one.views.key_add %}" method="POST">
{% csrf_token %} {% csrf_token %}
<textarea style="margin-bottom: 5px" name="key" placeholder="{% trans "Public key in OpenSSH format" %}"></textarea><br /> <textarea style="margin-bottom: 5px" name="key" placeholder="{% trans "Public key in OpenSSH format" %}"></textarea><br />
<input type="submit" style="margin-left: 10px;" value="{% trans "Save" %}" /> <input type="submit" style="margin-left: 10px;" value="{% trans "Save" %}" />
...@@ -139,7 +145,7 @@ ...@@ -139,7 +145,7 @@
<p id="upload-error-unknown" style="display: none"></p> <p id="upload-error-unknown" style="display: none"></p>
</div> </div>
<div style="display: none" class="upload-zone" id="old-upload-form"> <div style="display: none" class="upload-zone" id="old-upload-form">
<form action="/" method="POST" data-bind="attr: {action: uploadURL}" enctype="multipart/form-data"> <form action="{% url one.views.home %}" method="POST" data-bind="attr: {action: uploadURL}" enctype="multipart/form-data">
<input type="file" name="data" /> <input type="file" name="data" />
<input type="submit" value="Feltöltés" /> <input type="submit" value="Feltöltés" />
</form> </form>
......
{% extends "box/base/entry.html" %} {% extends "box/base/entry.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block summary %} {% block summary %}
...@@ -8,13 +9,13 @@ ...@@ -8,13 +9,13 @@
<div class="info" data-bind="text: size"></div> <div class="info" data-bind="text: size"></div>
<div class="actions"> <div class="actions">
<a href="#" data-bind="click: $parent.rename, clickBubble: false"> <a href="#" data-bind="click: $parent.rename, clickBubble: false">
<img src="/static/icons/pencil.png" alt="{% trans "rename" %}" /> <img src="{% static "icons/pencil.png" %}" alt="{% trans "rename" %}" />
</a> </a>
<a href="#" data-bind="click: $parent.delete, clickBubble: false"> <a href="#" data-bind="click: $parent.delete, clickBubble: false">
<img src="/static/icons/minus-circle.png" alt="{% trans "remove" %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans "remove" %}" />
</a> </a>
<a href="#" data-bind="click: $parent.download, clickBubble: false"> <a href="#" data-bind="click: $parent.download, clickBubble: false">
<img src="/static/icons/download-cloud.png" alt="{% trans "download" %}" /> <img src="{% static "icons/download-cloud.png" %}" alt="{% trans "download" %}" />
</a> </a>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
......
{% extends "box/base/entry.html" %} {% extends "box/base/entry.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block content %} {% block content %}
...@@ -15,7 +16,7 @@ ...@@ -15,7 +16,7 @@
</div> </div>
<div class="actions"> <div class="actions">
<a href="#" class="remove delete-key" data-id="{{key.id}}"> <a href="#" class="remove delete-key" data-id="{{key.id}}">
<img src="/static/icons/minus-circle.png" alt="{% trans 'Remove' %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans 'Remove' %}" />
</a> </a>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
......
{% extends "box/base/box.html" %} {% extends "box/base/box.html" %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block title %} {% block title %}
...@@ -9,8 +10,9 @@ ...@@ -9,8 +10,9 @@
{% block boxhelp %} {% block boxhelp %}
<div class="boxhelp"> <div class="boxhelp">
<div class="help">
<div class="icon"> <div class="icon">
<img src="/static/icons/information-frame.png" alt="{% trans "Help" %}" /> <img src="{% static "icons/information-frame.png" %}" alt="{% trans "Help" %}" />
</div> </div>
<div class="boxhelp-box"> <div class="boxhelp-box">
<p>{% blocktrans %}This is the list of your own templates.{% endblocktrans %}</p> <p>{% blocktrans %}This is the list of your own templates.{% endblocktrans %}</p>
...@@ -19,6 +21,10 @@ ...@@ -19,6 +21,10 @@
machine, and it will be ready to run by your students in minutes. machine, and it will be ready to run by your students in minutes.
{% endblocktrans %}</p> {% endblocktrans %}</p>
</div> </div>
</div>
<div class="icon">
<img src="" alt="toggle" title="{% trans "Show/hide box" %}" class="toggle-box" data-id="templates" id="toggle-box-templates"/>
</div>
</div> </div>
{% endblock %} {% endblock %}
...@@ -53,17 +59,17 @@ ...@@ -53,17 +59,17 @@
<div class="summary public-template"> <div class="summary public-template">
<div class="name"> <div class="name">
{{t.name}} {{t.name}}
<img src="/static/icons/lock-small.png" alt="{% trans "locked" %}" <img src="{% static "icons/lock-small.png" %}" alt="{% trans "locked" %}"
title="{% trans "This is a shared template." %}" /> title="{% trans "This is a shared template." %}" />
</div> </div>
<div class="status">{{t.state}}</div> <div class="status">{{t.state}}</div>
<div class="actions"> <div class="actions">
{% if t.state == 'READY' %} {% if t.state == 'READY' %}
<a href="#" class="try-template-button" data-id="{{t.id}}" title="{% trans "Try" %}"> <a href="#" class="try-template-button" data-id="{{t.id}}" title="{% trans "Try" %}">
<img src="/static/icons/control.png" alt="{% trans "Start" %}"/> <img src="{% static "icons/control.png" %}" alt="{% trans "Start" %}"/>
</a> </a>
<a href="#" class="template-share" data-id="{{t.id}}" data-gid="{{group.id}}" title="{% trans "Share" %}"> <a href="#" class="template-share" data-id="{{t.id}}" data-gid="{{group.id}}" title="{% trans "Share" %}">
<img src="/static/icons/user-share.png" alt="{% trans "Share" %}" /> <img src="{% static "icons/user-share.png" %}" alt="{% trans "Share" %}" />
</a> </a>
{% endif %} {% endif %}
</div> </div>
...@@ -75,14 +81,24 @@ ...@@ -75,14 +81,24 @@
<div class="quota"> <div class="quota">
<div class="used" style="width: {{ i.get_instance_pc|unlocalize }}%"></div> <div class="used" style="width: {{ i.get_instance_pc|unlocalize }}%"></div>
</div> </div>
<form action="/vm/unshare/{{i.id}}/" method="post"> <form action="{% url one.views.vm_unshare i.id %}" method="post">
<span title="{{i.name}}">{{i.name|truncatechars:20}}</span> <span title="{{i.name}}">{{i.name|truncatechars:20}}</span>
({{i.get_running}}/{{i.instance_limit}}) ({{i.get_running}}/{{i.instance_limit}}) {{i.type}}
<a href="#" class="edit" data-id="{{i.id}}">
<img src="{% static "icons/pencil.png" %}" alt="{% trans "Edit" %}" title="{% trans "Edit" %}" />
</a>
{% csrf_token %} {% csrf_token %}
<input type="submit" class="template-unshare" value="{% trans "Delete" %}" style="float: right"/> <input type="submit" class="template-unshare" value="{% trans "Delete" %}" style="float: right"/>
</form> </form>
<div class="clear"></div> <div class="clear"></div>
</li> </li>
<li class="description{% if not i.description %} empty{% endif %}">
{% if i.description %}
{{i.description}}
{% else %}
{% trans "No description available" %}
{% endif %}
</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
......
{% extends "box/base/summary.html" %} {% extends "box/base/summary.html" %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block content %} {% block content %}
...@@ -13,14 +14,24 @@ ...@@ -13,14 +14,24 @@
<div class="quota"> <div class="quota">
<div class="used" style="width: {{ i.get_instance_pc|unlocalize }}%"></div> <div class="used" style="width: {{ i.get_instance_pc|unlocalize }}%"></div>
</div> </div>
<form action="/vm/unshare/{{i.id}}/" method="post"> <form action="{% url one.views.vm_unshare i.id %}" method="post">
<span title="{{i.name}}">{{i.name|truncatechars:20}}</span> <span title="{{i.name}}">{{i.name|truncatechars:20}}</span>
({{i.get_running}}/{{i.instance_limit}}) ({{i.get_running}}/{{i.instance_limit}}) {{i.type}}
<a href="#" class="edit" data-id="{{i.id}}">
<img src="{% static "icons/pencil.png" %}" alt="{% trans "Edit" %}" title="{% trans "Edit" %}" />
</a>
{% csrf_token %} {% csrf_token %}
<input class="template-unshare" type="submit" value="{% trans "Delete" %}" style="float: right"/> <input class="template-unshare" type="submit" value="{% trans "Delete" %}" style="float: right"/>
</form> </form>
<div class="clear"></div> <div class="clear"></div>
</li> </li>
<li class="description{% if not i.description %} empty{% endif %}">
{% if i.description %}
{{i.description}}
{% else %}
{% trans "No description available" %}
{% endif %}
</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
...@@ -32,25 +43,25 @@ ...@@ -32,25 +43,25 @@
{% endblock %} {% endblock %}
{% block status %} {% block status %}
{{vm.state}} {{t.state}}
{% endblock status %} {% endblock status %}
{% block actions %} {% block actions %}
<a href="#" class="edit-template" data-id="{{ t.id }}" title="{% trans "Edit" %}">
<img src="{% static "icons/pencil.png" %}" alt="{% trans "Edit" %}" />
</a>
{% if t.state == 'READY' %} {% if t.state == 'READY' %}
<a href="#" class="try-template" data-id="{{t.id}}" title="{% trans "Try" %}"> <a href="#" class="try-template" data-id="{{t.id}}" title="{% trans "Try" %}">
<img src="/static/icons/control.png" alt="{% trans "Start" %}"/> <img src="{% static "icons/control.png" %}" alt="{% trans "Start" %}"/>
</a> </a>
<!--<a href="#" title="{% trans "Edit" %}"> <!--<a href="#" title="{% trans "Edit" %}">
<img src="/static/icons/pencil.png" alt="{% trans "Edit" %}" /> <img src="{% static "icons/pencil.png" %}" alt="{% trans "Edit" %}" />
</a>--> </a>-->
<a href="#" class="template-share" data-id="{{t.id}}" data-gid="{{group.id}}" title="{% trans "Share" %}"> <a href="#" class="template-share" data-id="{{t.id}}" data-gid="{{group.id}}" title="{% trans "Share" %}">
<img src="/static/icons/user-share.png" alt="{% trans "Share" %}" /> <img src="{% static "icons/user-share.png" %}" alt="{% trans "Share" %}" />
</a> </a>
{% endif %} {% endif %}
<a href="#" class="delete-template" data-id="{{ t.id }}" data-name="{{ t.name }}" title="{% trans "Remove" %}"> <a href="#" class="delete-template" data-id="{{ t.id }}" data-name="{{ t.name }}" title="{% trans "Remove" %}">
<img src="/static/icons/minus-circle.png" alt="{% trans "Remove" %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans "Remove" %}" />
</a> </a>
<!--<a href="#" class="edit-template" data-id="{{ t.id }}" title="{% trans "Edit" %}">
<img src="/static/icons/pencil.png" alt="{% trans "Edit" %}" />
</a>-->
{% endblock actions %} {% endblock actions %}
{% extends "box/base/box.html" %} {% extends "box/base/box.html" %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block title %} {% block title %}
...@@ -9,8 +10,9 @@ ...@@ -9,8 +10,9 @@
{% block boxhelp %} {% block boxhelp %}
<div class="boxhelp"> <div class="boxhelp">
<div class="help">
<div class="icon"> <div class="icon">
<img src="/static/icons/information-frame.png" alt="{% trans "Help" %}" /> <img class="help" src="{% static "icons/information-frame.png" %}" alt="{% trans "Help" %}" />
</div> </div>
<div class="boxhelp-box"> <div class="boxhelp-box">
<p>{% blocktrans %}This is the list of your running virtual machines.{% endblocktrans %}</p> <p>{% blocktrans %}This is the list of your running virtual machines.{% endblocktrans %}</p>
...@@ -19,6 +21,10 @@ ...@@ -19,6 +21,10 @@
<p>{% blocktrans %}Please note, that users and shares both have a limit <p>{% blocktrans %}Please note, that users and shares both have a limit
of launchable instances.{% endblocktrans %}</p> of launchable instances.{% endblocktrans %}</p>
</div> </div>
</div>
<div class="icon">
<img src="" alt="{% trans "Show/hide box" %}" class="toggle-box" data-id="vms" id="toggle-box-vms"/>
</div>
</div> </div>
{% endblock %} {% endblock %}
...@@ -103,7 +109,7 @@ ...@@ -103,7 +109,7 @@
<li> <li>
&nbsp; &nbsp;
<span class="value"> <span class="value">
<form method="POST" action="/vm/new/s{{s.pk}}/"> <form method="POST" action="{% url one.views.vm_new share=s.id %}">
{% csrf_token %} {% csrf_token %}
<input {% if s.running_shared >= s.per_user_limit or s.get_running >= s.instance_limit%}disabled="disabled" value="{% trans "Quota reached" %}" {%else%}value="{% trans "Launch" %}"{% endif %} type="submit" /> <input {% if s.running_shared >= s.per_user_limit or s.get_running >= s.instance_limit%}disabled="disabled" value="{% trans "Quota reached" %}" {%else%}value="{% trans "Launch" %}"{% endif %} type="submit" />
</form> </form>
......
{% extends "box/base/entry.html" %} {% extends "box/base/entry.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block content %} {% block content %}
...@@ -26,7 +27,7 @@ ...@@ -26,7 +27,7 @@
</li> </li>
<li class="template"> <li class="template">
{% trans "Type" %}: {% trans "Type" %}:
<span class="value">{{vm.share.type}}</span> <span class="value">{% if vm.share %}{{vm.share.type}}{% else %}{% trans "Try" %}{% endif %}</span>
<div class="clear"></div> <div class="clear"></div>
</li> </li>
<li class="template"> <li class="template">
...@@ -56,9 +57,9 @@ ...@@ -56,9 +57,9 @@
<li class="date"> <li class="date">
{% trans "time of suspend"|capfirst %}: {% trans "time of suspend"|capfirst %}:
<span class="value"> <abbr title="{{vm.time_of_suspend}}">{{vm.time_of_suspend|timeuntil}}</abbr> <span class="value"> <abbr title="{{vm.time_of_suspend}}">{{vm.time_of_suspend|timeuntil}}</abbr>
<a href="#" class="renew-vm-button renew-suspend-vm-button" data-id="{{ vm.id }}" title="{% trans "Renew suspend time" %}"> {% if vm.share %}<a href="#" class="renew-vm renew-suspend-vm" data-id="{{ vm.id }}" title="{% trans "Renew suspend time" %}">
<img src="/static/icons/control-double.png" alt="{% trans "Renew suspend time" %}" /> <img src="{% static "icons/control-double.png" %}" alt="{% trans "Renew suspend time" %}" />
</a> </a>{% endif %}
</span> </span>
</li> </li>
{% endif %} {% endif %}
...@@ -66,16 +67,16 @@ ...@@ -66,16 +67,16 @@
<li class="date"> <li class="date">
{% trans "time of delete"|capfirst %}: {% trans "time of delete"|capfirst %}:
<span class="value"> <abbr title="{{vm.time_of_delete}}">{{vm.time_of_delete|timeuntil}}</abbr> <span class="value"> <abbr title="{{vm.time_of_delete}}">{{vm.time_of_delete|timeuntil}}</abbr>
<a href="#" class="renew-vm-button renew-delete-vm-button" data-id="{{ vm.id }}" title="{% trans "Renew deletion time" %}"> {% if vm.share %}<a href="#" class="renew-vm renew-delete-vm" data-id="{{ vm.id }}" title="{% trans "Renew deletion time" %}">
<img src="/static/icons/control-double.png" alt="{% trans "Renew deletion time" %}" /> <img src="{% static "icons/control-double.png" %}" alt="{% trans "Renew deletion time" %}" />
</a> </a>{% endif %}
</span> </span>
</li> </li>
{% endif %} {% endif %}
<li> <li>
&nbsp; &nbsp;
<span class="value"> <span class="value">
<a href="/vm/show/{{vm.id}}/" title="{{vm.name}}">{% trans "More details" %}</a> <a href="{{ vm.get_absolute_url }}" title="{{vm.name}}">{% trans "More details" %}</a>
</span> </span>
</li> </li>
</ul> </ul>
......
{% extends "box/base/summary.html" %} {% extends "box/base/summary.html" %}
{% load staticfiles %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
...@@ -12,53 +13,53 @@ ...@@ -12,53 +13,53 @@
<div class="name {% if vm.state == 'ACTIVE' %}vm-on{% else %}vm-off{% endif %}"> <div class="name {% if vm.state == 'ACTIVE' %}vm-on{% else %}vm-off{% endif %}">
<span id="vm-{{vm.id}}-name">{{vm.name|truncatechars:20}}</span> <span id="vm-{{vm.id}}-name">{{vm.name|truncatechars:20}}</span>
<small id="vm-{{vm.id}}-name-details" class="details"> <small id="vm-{{vm.id}}-name-details" class="details">
(<a href="/vm/show/{{vm.id}}/" title="{{vm.name}}">{% trans "More details" %}</a>) (<a href="{{ vm.get_absolute_url }}" title="{{vm.name}}">{% trans "More details" %}</a>)
</small> </small>
</div> </div>
{% endblock %} {% endblock %}
{% block status %} {% block status %}
{{vm.state}} {% if vm.template.state != "READY" %} {{vm.template.state}} {% else %} {{vm.state}} {% endif %}
{% endblock status %} {% endblock status %}
{% block actions %} {% block actions %}
<a href="#" class="rename-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Edit name" %}"> <a href="#" class="rename-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Edit name" %}">
<img src="/static/icons/pencil.png" alt="{% trans "Edit name" %}" /> <img src="{% static "icons/pencil.png" %}" alt="{% trans "Edit name" %}" />
</a> </a>
{% if vm.waiting %} {% if vm.waiting %}
<a href="#"> <a href="#">
<img src="/static/image/load.gif" /> <img src="{% static "image/load.gif" %}" />
</a> </a>
{% elif vm.state == 'ACTIVE' %} {% elif vm.state == 'ACTIVE' %}
<a href="{{vm.get_connect_uri}}" data-id="{{ vm.id }}" class="connect-vm" title="{% trans "Connect" %}"> <a href="{{vm.get_connect_uri}}" data-id="{{ vm.id }}" class="connect-vm" title="{% trans "Connect" %}">
<img src="/static/icons/plug.png" alt="{% trans "Connect" %}" /> <img src="{% static "icons/plug.png" %}" alt="{% trans "Connect" %}" />
</a> </a>
<a href="#" class="stop-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Pause" %}"> <a href="#" class="stop-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Pause" %}">
<img src="/static/icons/control-pause.png" alt="{% trans "Pause" %}" /> <img src="{% static "icons/control-pause.png" %}" alt="{% trans "Pause" %}" />
</a> </a>
<a href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}"> <a href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}">
<img src="/static/icons/minus-circle.png" alt="{% trans "Delete" %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans "Delete" %}" />
</a> </a>
<a href="#" class="restart-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Restart" %}"> <a href="#" class="restart-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Restart" %}">
<img src="/static/icons/arrow-circle-double.png" alt="↺" /> <img src="{% static "icons/arrow-circle-double.png" %}" alt="↺" />
</a> </a>
{% elif vm.state == 'PENDING' %} {% elif vm.state == 'PENDING' %}
<a href="#"> <a href="#">
<img src="/static/image/load.gif" /> <img src="{% static "image/load.gif" %}" />
</a> </a>
<a style="float: right" href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}"> <a style="float: right" href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}">
<img src="/static/icons/minus-circle.png" alt="{% trans "Delete" %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans "Delete" %}" />
</a> </a>
{% elif vm.state == 'STOPPED' %} {% elif vm.state == 'STOPPED' %}
<a href="#" class="resume-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Resume" %}"> <a href="#" class="resume-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Resume" %}">
<img src="/static/icons/control.png" alt="{% trans "Resume" %}" /> <img src="{% static "icons/control.png" %}" alt="{% trans "Resume" %}" />
</a> </a>
<a href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}"> <a href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}">
<img src="/static/icons/minus-circle.png" alt="{% trans "Delete" %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans "Delete" %}" />
</a> </a>
{% elif vm.state == 'FAILED' %} {% elif vm.state == 'FAILED' %}
<a href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}"> <a href="#" class="delete-vm" data-name="{{ vm.name }}" data-id="{{ vm.id }}" title="{% trans "Delete" %}">
<img src="/static/icons/minus-circle.png" alt="{% trans "Delete" %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans "Delete" %}" />
</a> </a>
{% endif %} {% endif %}
{% endblock actions %} {% endblock actions %}
{% load i18n %}
{% get_current_language as LANGUAGE_CODE %}
<form action="{% url one.views.ajax_share_edit_wizard share.id %}" method="post" id="template-wizard">
{% csrf_token %}
<div id="new-share" class="wizard">
<h2>
{% blocktrans with t=share.name%}Editing share: {{t}}{% endblocktrans %}
</h2>
<p>{% trans "Change the parameters as needed." %}</p>
<ul>
<li>
<label for="share-name">{% trans "Name of share" %}</label>
<input type="text" name="name" id="share-name" value="{{share.name}}" />
<div class="clear"></div>
</li>
<li class="li-share-type">
<label for="share-type">{% trans "Type" %}</label>
<ul class="radio">
{% for s in types %}
<li>
<label>
<input type="radio" name="type" value="{{s.id}}" id="share-type-{{s.id}}"
{% if s.id == share.type %}checked="checked"{% endif %} />{{s.verbose_name}}
</label>
</li>
{% endfor %}
</ul>
{% for s in types %}
<p id="share-type-summary-{{s.id}}" class="type-summary clear"
{% if not s.id == share.type %}style="display:none"{% endif %}>
{{s.help_text}}
({% if s.suspend %}
<span class="suspend"
title="{% blocktrans with time=s.suspend %}Suspend after {{time}}.{%endblocktrans%}">{{s.suspendx|timeuntil}}</span>
{%endif%}{% if s.delete %}
<span class="delete"
title="{% blocktrans with time=s.delete %}Delete after {{time}}.{%endblocktrans%}">{{s.deletex|timeuntil}}</span>
{%endif%})
</p>
{% endfor %}
<div class="clear"></div>
</li>
<li>
<label for="share-instance-limit">{% trans "Maximal count of instances" %}</label>
<input type="number" name="instance_limit" id="share-instance-limit" value="{{share.instance_limit}}" />
<div class="clear"></div>
</li>
<li>
<label for="share-per-user-limit">{% trans "Maximal count of instaces/user" %}</label>
<input type="number" name="per_user_limit" id="share-per-user-limit" value="{{share.per_user_limit}}" />
<div class="clear"></div>
</li>
<li style="border: none" class="clear">
<label for="share-description">{% trans "Description" %}</label>
<textarea name="description" id="share-description" style="text-align: left">{{share.description}}</textarea>
<div class="clear"></div>
</li>
</ul>
<nav>
<input type="reset" class="prev" value="{% trans "Cancel" %}" />
<input type="submit" value="{% trans "Save" %}"/>
<div class="clear"></div>
</nav>
<script type="text/javascript">
$(function(){
$('#new-share nav .prev').click(function(){
$('#modal').hide();
})
$("#new-share input[name='type']").click(function(e){ /* TODO */
var v = $("#new-share input[name='type']:checked").val();
$("p.type-summary").hide();
$("#share-type-summary-" + v).show();
});
})
</script>
</div>
</form>
{% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %}
<form action="{% url one.views.ajax_template_edit_wizard template.id %}" method="post" id="template-wizard">
{% csrf_token %}
<div id="new-template-step-2" class="wizard">
<h2>{% trans "Edit template" %}</h2>
<p>{% trans "Change the parameters as needed." %}</p>
<ul>
<li>
<label for="new-template-name">{% trans "Name" %}</label>
<input type="text" name="name" id="new-template-name" value="{{template.name}}"
class="validated" />
<div class="clear"></div>
</li>
<li class="new-tpl-size">
<label for="new-template-size">{% trans "Size" %}</label>
<ul class="radio">
{% for s in sizes %}
<li>
<label>
<input type="radio" name="size" value="{{s.id}}" id="new-template-size-{{s.id}}"
{% if s == template.instance_type %}checked="checked"{% endif %} />
{{s.name}}
</label>
</li>
{% endfor %}
</ul>
{% for s in sizes %}
<p id="new-template-size-summary-{{s.id}}" class="size-summary clear"
{% if s != template.instance_type %}style="display:none"{% endif %}>
<span class="cpu">
{% blocktrans count n=s.CPU %}{{n}} core{% plural %}{{n}} cores{% endblocktrans %}
</span>
<span class="memory">{{s.RAM}} MiB</span>
<span class="credit">{{s.credit}}</span>
</p>
{% endfor %}
<div class="clear"></div>
</li>
<li style="border: none">
<label for="new-template-description">{% trans "Description" %}</label>
<textarea name="description" id="new-template-description" style="text-align: left">{{template.description}}</textarea>
<div class="clear"></div>
</li>
</ul>
<nav>
<input type="reset" class="prev" value="{% trans "Cancel" %}" />
<input type="submit" class="next" value="{% trans "Save" %}" />
<div class="clear"></div>
</nav>
<script type="text/javascript">
$(function(){
var original = '{{template.name}}';
$('#new-template-step-2 nav .prev').click(function(){
$('#modal').hide();
})
$(".new-tpl-size input[name='size']").click(function(e){
var v = $(".new-tpl-size input[name='size']:checked").val();
$("p.size-summary").hide();
$("#new-template-size-summary-" + v).show();
});
$("#new-template-name").keyup(function(){
var timer;
return function(e){
var self = this;
clearTimeout(timer);
timer=setTimeout(function(){
var s = $(self).val();
$.ajax({
'type': 'GET',
'url': '{% url one.views.ajax_template_name_unique %}?name=' + s,
'success': function(data, b, c) {
if (s != $("#new-template-name").val()) {
return true;
}
if (data == "True" || s == original) {
$('#new-template-name').removeClass("error");
$('#new-template-step-2 nav .next').removeAttr("disabled");
$('#new-template-name').removeProp("title");
}
else {
$('#new-template-name').addClass("error");
$('#new-template-step-2 nav .next').attr("disabled", "disabled");
$('#new-template-name').prop("title", gettext('Please choose a different name.'));
}
}
});
}, 1000)
}
}());
$("#template-wizard").submit(function(e){
e.preventDefault();
$.ajax({
'type': 'GET',
'url': '{% url one.views.ajax_template_name_unique %}?name=' + $("#new-template-name").val(),
'success': function(data, b, c) {
if (data == "True" || s == original) {
$("#template-wizard").unbind('submit').submit()
}
else {
$('#new-template-name').addClass("error");
$('#new-template-step-2 nav .next').attr("disabled", "disabled");
$('#new-template-name').prop("title", gettext('Please choose a different name.'));
}
}
});
});
})
</script>
</div>
</form>
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block js %} {% block js %}
<script type="text/javascript" src="/static/script/store.js"></script> {% if DEBUG %}<script type="text/javascript" src="{% static "script/store.js" %}"></script>
{% else %}<script type="text/javascript" src="{% static "script/store.min.js" %}"></script>
{% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<div class="boxes"> <div class="boxes">
......
{% load i18n %}
{% blocktrans with name=user.get_full_name %}
Dear {{name}},
{% endblocktrans %}
{% block body %}
{% endblock %}
--
{{site}}
{% extends "mails/base.txt" %}
{% load i18n %}
{% block body %}
{% blocktrans with reason=bl.reason snort_message=bl.snort_message vm=instance.name %}
Our network intrusion detection system showed that your machine
"{{vm}}" pursues the following forbidden network activity: {{reason}}.
"{{vm}}" has been BANNED from all network activity
including remote desktop and shell connection.
Details:
{{snort_message}}
{% endblocktrans %}
{% blocktrans with url=url %}
Please, reply to this notification, or delete the instance on the
cloud portal: {{url}}
{% endblocktrans %}
{% endblock %}
{% extends "mails/base.txt" %}
{% load i18n %}
{% block body %}
{% blocktrans with vm=instance.name state=instance.state|lower date=instance.time_of_delete %}
Your {{state}} virtual machine "{{vm}}" has been DELETED
at {{date}}.
{% endblocktrans %}
{% blocktrans %}
The disk image is IRRECOVERABLY REMOVED.
{% endblocktrans %}
{% blocktrans with url=url %}
You can start a new instance of the template on the cloud portal:
{{url}}
{% endblocktrans %}
{% endblock %}
{% extends "mails/base.txt" %}
{% load i18n %}
{% block body %}
{% blocktrans with vm=instance.name state=instance.state|lower date=instance.time_of_delete time=exp|timeuntil %}
Your {{state}} virtual machine "{{vm}}" is going to be DELETED
at {{date}} (in {{time}}).
{% endblocktrans %}
{% blocktrans %}
The disk image will be IRRECOVERABLY REMOVED.
{% endblocktrans %}
{% blocktrans with url=url %}
You can renew or delete the instance on the cloud portal:
{{url}}
{% endblocktrans %}
{% endblock %}
{% extends "mails/base.txt" %}
{% load i18n %}
{% block body %}
{% blocktrans with vm=instance.name state=instance.state|lower date=instance.time_of_suspend %}
Your {{state}} virtual machine "{{vm}}" has been STOPPED
at {{date}}.
{% endblocktrans %}
{% blocktrans with deldate=instance.time_of_delete %}
The disk and memory image is stored, and you can resume it
until the final expiration time ({{deldate}}).
{% endblocktrans %}
{% blocktrans with url=url %}
You can also renew or delete the instance on the cloud portal:
{{url}}
{% endblocktrans %}
{% endblock %}
{% extends "mails/base.txt" %}
{% load i18n %}
{% block body %}
{% blocktrans with vm=instance.name state=instance.state|lower date=instance.time_of_suspend time=exp|timeuntil url=url %}
Your {{state}} virtual machine "{{vm}}" is going to be STOPPED
at {{date}} (in {{time}}).
{% endblocktrans %}
{% blocktrans with deldate=instance.time_of_delete %}
The disk and memory image will be stored, and you can resume it
until the final expiration time ({{deldate}}).
{% endblocktrans %}
{% blocktrans with url=url %}
You can also renew or delete the instance on the cloud portal:
{{url}}
{% endblocktrans %}
{% endblock %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<form action="/ajax/share/{{base.id}}/" method="post" id="template-wizard"> <form action="{% url one.views.ajax_share_wizard id=base.id %}" method="post" id="template-wizard">
{% csrf_token %} {% csrf_token %}
<div id="new-share" class="wizard"> <div id="new-share" class="wizard">
<h2> <h2>
......
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<form action="/ajax/templateWizard" method="post" id="template-wizard"> <form action="{% url one.views.ajax_template_wizard %}" method="post" id="template-wizard">
{% csrf_token %} {% csrf_token %}
<div id="new-template-step-1" class="wizard"> <div id="new-template-step-1" class="wizard">
<div class="progress"> <div class="progress">
...@@ -28,7 +29,7 @@ ...@@ -28,7 +29,7 @@
<input type="radio" name="base" value="{{m.id}}" /> <input type="radio" name="base" value="{{m.id}}" />
{{m.name}} {{m.name}}
{% if m.public %} {% if m.public %}
<img src="/static/icons/lock-small.png" alt="{% trans "locked" %}" <img src="{% static "icons/lock-small.png" %}" alt="{% trans "locked" %}"
title="{% trans "This is a shared template." %}" /> title="{% trans "This is a shared template." %}" />
{% endif %} {% endif %}
</label> </label>
...@@ -56,7 +57,7 @@ ...@@ -56,7 +57,7 @@
else { else {
$.ajax({ $.ajax({
'type': 'POST', 'type': 'POST',
'url': '/ajax/templateWizard', 'url': '{% url one.views.ajax_template_wizard %}',
'data': $('#template-wizard').serialize(), 'data': $('#template-wizard').serialize(),
'success': function(data) { 'success': function(data) {
$('#modal-container').html(data); $('#modal-container').html(data);
......
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<form action="/vm/new/{{base.id}}/" method="post" id="template-wizard"> <form action="{% url new_vm_from_template base.id %}" method="post" id="template-wizard">
{% csrf_token %} {% csrf_token %}
<div id="new-template-step-2" class="wizard"> <div id="new-template-step-2" class="wizard">
<div class="progress"> <div class="progress">
...@@ -75,7 +76,7 @@ ...@@ -75,7 +76,7 @@
var s = $(self).val(); var s = $(self).val();
$.ajax({ $.ajax({
'type': 'GET', 'type': 'GET',
'url': '/ajax/template_name_unique/' + s, 'url': '{% url one.views.ajax_template_name_unique %}?name=' + s,
'success': function(data, b, c) { 'success': function(data, b, c) {
if (s != $("#new-template-name").val()) { if (s != $("#new-template-name").val()) {
return true; return true;
...@@ -99,7 +100,7 @@ ...@@ -99,7 +100,7 @@
e.preventDefault(); e.preventDefault();
$.ajax({ $.ajax({
'type': 'GET', 'type': 'GET',
'url': '/ajax/template_name_unique/' + $("#new-template-name").val(), 'url': '{% url one.views.ajax_template_name_unique %}?name=' + $("#new-template-name").val(),
'success': function(data, b, c) { 'success': function(data, b, c) {
if (data == "True") { if (data == "True") {
$("#template-wizard").unbind('submit').submit() $("#template-wizard").unbind('submit').submit()
......
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% block js %} {% block js %}
<script type="text/javascript"> <script type="text/javascript">
...@@ -8,14 +9,28 @@ ...@@ -8,14 +9,28 @@
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
dataType: 'json', dataType: 'json',
url: '/ajax/vm/status/{{ id }}', url: '{% url one.views.vm_ajax_instance_status id %}',
success: function(data){ success: function(data){
if( !data.booting && data.state == 'ACTIVE'){ if (!data.booting && data.state == 'ACTIVE'){
window.location.reload(); window.location.reload();
} }
} }
}) });
},2000); }, 5000);
{% endif %}
{% if i.template.state == 'SAVING' %}
var savingTimer=setInterval(function(){
$.ajax({
type: 'GET',
dataType: 'json',
url: '{% url one.views.vm_ajax_instance_status id %}',
success: function(data){
if(data.template.state == 'READY'){
window.location.href='{% url one.views.home %}';
}
}
});
}, 10000);
{% endif %} {% endif %}
</script> </script>
{% endblock %} {% endblock %}
...@@ -61,13 +76,18 @@ ...@@ -61,13 +76,18 @@
<div class="content"> <div class="content">
{% if state == "PENDING" or state == "ACTIVE" and booting %} {% if state == "PENDING" or state == "ACTIVE" and booting %}
<p style="font-size:25px; line-height:2em;text-align:center;"> <p style="font-size:25px; line-height:2em;text-align:center;">
<img src="/static/image/load.gif" /> <img src="{% static "image/load.gif" %}" />
{% trans "Starting..." %} {% trans "Starting..." %}
</p> </p>
{% elif i.template.state == "SAVING" %}
<p style="font-size:25px; line-height:2em;text-align:center;">
<img src="{% static "image/load.gif" %}" />
{% trans "Saving..." %}
</p>
{% elif state == "ACTIVE" and not booting %} {% elif state == "ACTIVE" and not booting %}
<p id="connect" style="display:block; font-size:25px; line-height:2em;text-align:center;"> <p id="connect" style="display:block; font-size:25px; line-height:2em;text-align:center;">
<a href="{{uri}}" class="button" onclick="return connectbutton();"> <a href="{{uri}}" class="button" onclick="return connectbutton();">
<img src="/static/image/load.gif" id="connecting" style="display:none;" /> <img src="{% static "image/load.gif" %}" id="connecting" style="display:none;" />
{% trans "Running" %} {% trans "Running" %}
</a> </a>
</p> </p>
...@@ -90,8 +110,9 @@ ...@@ -90,8 +110,9 @@
<div class="contentblock" id="ports"> <div class="contentblock" id="ports">
<h2> <h2>
<div class="boxhelp"> <div class="boxhelp">
<div class="help">
<div class="icon"> <div class="icon">
<img src="/static/icons/information-frame.png" alt="{% trans "Help" %}" /> <img src="{% static "icons/information-frame.png" %}" alt="{% trans "Help" %}" />
</div> </div>
<div class="boxhelp-box"> <div class="boxhelp-box">
<p>{% blocktrans %}This is a list about the network ports <p>{% blocktrans %}This is a list about the network ports
...@@ -105,23 +126,24 @@ ...@@ -105,23 +126,24 @@
{% endblocktrans %}</p> {% endblocktrans %}</p>
</div> </div>
</div> </div>
</div>
{% trans "Port administration" %}</h2> {% trans "Port administration" %}</h2>
<div class="content"> <div class="content">
<form action="{% url vm_port_add i.id %}" method="post"> <form action="{% url one.views.vm_port_add i.id %}" method="post">
{% csrf_token %} {% csrf_token %}
<table> <table>
<tr> <tr>
<th>{% trans "Protocol" %}</th> <th>{% trans "Protocol" %}</th>
<th>{% trans "Public port" %}</th> <th>{% trans "Public port" %}</th>
<th colspan="2">{% trans "Private port" %}</th> {% if i.template.network.nat %}<th colspan="2">{% trans "Private port" %}</th>{%endif%}
</tr> </tr>
{% for port in ports %} {% for port in ports %}
<tr> <tr>
<td>{{port.proto}}</td> <td>{{port.proto}}</td>
<td>{{port.public}}</td> <td>{{port.public}}</td>
<td>{{port.private}}</td> {% if i.template.network.nat %}<td>{{port.private}}</td>{%endif%}
<td> <td>
<a href="/vm/port_del/{{i.id}}/{{port.proto}}/{{port.public}}/">{% trans "Delete" %}</a> <a href="{% url one.views.vm_port_del i.id port.proto port.public %}">{% trans "Delete" %}</a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
...@@ -135,9 +157,11 @@ ...@@ -135,9 +157,11 @@
<td> <td>
<input style="min-width:70px;width:70px;" type="text" name="public"/> <input style="min-width:70px;width:70px;" type="text" name="public"/>
</td> </td>
{% if i.template.network.nat %}
<td> <td>
<input style="min-width:70px;width:70px;" type="text" name="private"/> <input style="min-width:70px;width:70px;" type="text" name="private"/>
</td> </td>
{% endif %}
<td> <td>
<input type="submit" style="min-width:3em" value="{% trans "Add" %}" /> <input type="submit" style="min-width:3em" value="{% trans "Add" %}" />
</td> </td>
......
{% load l10n %}
<html>
<head>
<!--Load the AJAX API-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
// Create the data table.
var data_cpu = new google.visualization.DataTable();
data_cpu.addColumn('string', 'Topping');
data_cpu.addColumn('number', 'Slices');
data_cpu.addRows([
['Free CPU', {{STAT.CPU.FREE_CPU}}],
['Allocated CPU', {{STAT.CPU.ALLOC_CPU}}],
['Used CPU', {{STAT.CPU.USED_CPU}}],
]);
// Set chart options
var cpu_options = {'title':'Cloud CPU usage percent (100/CPU)',
'width':400,
'height':300,
slices: {0: {color: 'blue'}, 1:{color: 'orange'},
2:{color: 'red'}}
};
var data_mem = new google.visualization.DataTable();
data_mem.addColumn('string', 'Topping');
data_mem.addColumn('number', 'Slices');
data_mem.addRows([
['Free Memory', {{STAT.MEM.FREE_MEM|unlocalize}}],
['Allocated Memory', {{STAT.MEM.ALLOC_MEM|unlocalize}}],
['Used Memory', {{STAT.MEM.USED_MEM|unlocalize}}],
]);
// Set chart options
var mem_options = {'title':'Cloud Memory usage in {{STAT.DIMENSION}}',
'width':400,
'height':300,
slices: {0: {color: 'blue'}, 1:{color: 'orange'},
2:{color: 'red'}}
};
// Instantiate and draw our chart, passing in some options.
var chart = new
google.visualization.PieChart(document.getElementById('chart_cpu_div'));
chart.draw(data_cpu, cpu_options);
var chart = new
google.visualization.PieChart(document.getElementById('chart_mem_div'));
chart.draw(data_mem, mem_options);
}
</script>
</head>
<body>
<!--Div that will hold the pie chart-->
<div>Running VMs: {{STAT.VMS}}</div>
<div id="chart_cpu_div"></div>
<div id="chart_mem_div"></div>
</body>
</html>
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
<div class="content"> <div class="content">
<table> <table>
...@@ -7,8 +8,9 @@ ...@@ -7,8 +8,9 @@
<td> <td>
<div class="boxhelp"> <div class="boxhelp">
<div class="help">
<div class="icon"> <div class="icon">
<img src="/static/icons/information-frame.png" alt="{% trans "Help" %}" /> <img src="{% static "icons/information-frame.png" %}" alt="{% trans "Help" %}" />
</div> </div>
<div class="boxhelp-box"> <div class="boxhelp-box">
{% if i.template.os_type == 'linux' %} {% if i.template.os_type == 'linux' %}
...@@ -30,16 +32,17 @@ ...@@ -30,16 +32,17 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div>
{{i.template.access_type|upper}} {{i.template.access_type|upper}}
</td> </td>
</tr> </tr>
<tr> <tr>
<th>{% trans "IP" %}:</th> <th>{% trans "IP" %}:</th>
<td>{{ i.firewall_host.pub_ipv4 }}</td> <td>{{ i.hostname }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Port" %}:</th> <th>{% trans "Port" %}:</th>
<td>{{ i.get_port}}</td> <td>{{ i.port}}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Username" %}:</th> <th>{% trans "Username" %}:</th>
......
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase from django.test import TestCase
class ViewsTestCase(TestCase):
class SimpleTest(TestCase): def test_index(self):
def test_basic_addition(self): '''Test whether index is reachable.'''
""" resp = self.client.get('/', follow=True)
Tests that 1 + 1 always equals 2. self.assertEqual(resp.status_code, 200)
"""
self.assertEqual(1 + 1, 2)
...@@ -26,6 +26,7 @@ from school.models import * ...@@ -26,6 +26,7 @@ from school.models import *
import django.contrib.auth as auth import django.contrib.auth as auth
import json import json
import logging import logging
import subprocess
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -33,11 +34,23 @@ def _list_instances(request): ...@@ -33,11 +34,23 @@ def _list_instances(request):
instances = Instance.objects.exclude(state='DONE').filter(owner=request.user) instances = Instance.objects.exclude(state='DONE').filter(owner=request.user)
for i in instances: for i in instances:
i.update_state() i.update_state()
instances = instances.exclude(state='DONE')
return instances return instances
def info(request):
return render_to_response("info.html", RequestContext(request, {}))
def index(request):
if request.user.is_authenticated():
return redirect(home)
else:
return redirect(info)
@require_GET @require_GET
@login_required @login_required
def home(request): def home(request):
instances = _list_instances(request)
shares = [s for s in request.user.person_set.all()[0].get_shares()] shares = [s for s in request.user.person_set.all()[0].get_shares()]
for i, s in enumerate(shares): for i, s in enumerate(shares):
s.running_shared = s.instance_set.all().exclude(state="DONE").filter(owner=request.user).count() s.running_shared = s.instance_set.all().exclude(state="DONE").filter(owner=request.user).count()
...@@ -52,10 +65,10 @@ def home(request): ...@@ -52,10 +65,10 @@ def home(request):
except: except:
generated_public_key = -1 generated_public_key = -1
return render_to_response("home.html", RequestContext(request, { return render_to_response("home.html", RequestContext(request, {
'instances': instances,
'shares': shares, 'shares': shares,
'templates': Template.objects.filter(state='READY'), 'templates': Template.objects.filter(state='READY'),
'mytemplates': Template.objects.filter(owner=request.user), 'mytemplates': Template.objects.filter(owner=request.user),
'instances': _list_instances(request),
'groups': request.user.person_set.all()[0].owned_groups.all(), 'groups': request.user.person_set.all()[0].owned_groups.all(),
'semesters': Semester.objects.all(), 'semesters': Semester.objects.all(),
'userdetails': details, 'userdetails': details,
...@@ -82,7 +95,8 @@ def ajax_template_delete(request): ...@@ -82,7 +95,8 @@ def ajax_template_delete(request):
else: else:
return HttpResponse(unicode(_("Unexpected error happened.")), status=404) return HttpResponse(unicode(_("Unexpected error happened.")), status=404)
def ajax_template_name_unique(request, name): def ajax_template_name_unique(request):
name = request.GET['name']
s = "True" s = "True"
if Template.objects.filter(name=name).exists(): if Template.objects.filter(name=name).exists():
s = "False" s = "False"
...@@ -92,6 +106,9 @@ def ajax_template_name_unique(request, name): ...@@ -92,6 +106,9 @@ def ajax_template_name_unique(request, name):
def vm_credentials(request, iid): def vm_credentials(request, iid):
try: try:
vm = get_object_or_404(Instance, pk=iid, owner=request.user) vm = get_object_or_404(Instance, pk=iid, owner=request.user)
proto = len(request.META["REMOTE_ADDR"].split('.')) == 1
vm.hostname = vm.get_connect_host(use_ipv6=proto)
vm.port = vm.get_port(use_ipv6=proto)
return render_to_response('vm-credentials.html', RequestContext(request, { 'i' : vm })) return render_to_response('vm-credentials.html', RequestContext(request, { 'i' : vm }))
except: except:
return HttpResponse(_("Could not get Virtual Machine credentials."), status=404) return HttpResponse(_("Could not get Virtual Machine credentials."), status=404)
...@@ -118,6 +135,27 @@ class AjaxTemplateWizard(View): ...@@ -118,6 +135,27 @@ class AjaxTemplateWizard(View):
})) }))
ajax_template_wizard = login_required(AjaxTemplateWizard.as_view()) ajax_template_wizard = login_required(AjaxTemplateWizard.as_view())
class AjaxTemplateEditWizard(View):
def get(self, request, id, *args, **kwargs):
template = get_object_or_404(Template, id=id)
if template.owner != request.user and not template.public and not request.user.is_superuser:
raise PermissionDenied()
return render_to_response('edit-template-flow.html', RequestContext(request, {
'sizes': InstanceType.objects.all(),
'template': template,
}))
def post(self, request, id, *args, **kwargs):
template = get_object_or_404(Template, id=id)
if template.owner != request.user and not template.public and not request.user.is_superuser:
raise PermissionDenied()
template.instance_type_id = request.POST['size']
template.description = request.POST['description']
template.name = request.POST['name']
template.save()
return redirect(home)
ajax_template_edit_wizard = login_required(AjaxTemplateEditWizard.as_view())
class AjaxShareWizard(View): class AjaxShareWizard(View):
def get(self, request, id, gid=None, *args, **kwargs): def get(self, request, id, gid=None, *args, **kwargs):
...@@ -166,7 +204,43 @@ class AjaxShareWizard(View): ...@@ -166,7 +204,43 @@ class AjaxShareWizard(View):
return redirect(group) return redirect(group)
ajax_share_wizard = login_required(AjaxShareWizard.as_view()) ajax_share_wizard = login_required(AjaxShareWizard.as_view())
class AjaxShareEditWizard(View):
def get(self, request, id, *args, **kwargs):
det = UserCloudDetails.objects.get(user=request.user)
if det.get_weighted_share_count() >= det.share_quota:
return HttpResponse(unicode(_('You do not have any free share quota.')))
types = TYPES_L
for i, t in enumerate(types):
t['deletex'] = datetime.now() + td(seconds=1) + t['delete'] if t['delete'] else None
t['suspendx'] = datetime.now() + td(seconds=1) + t['suspend'] if t['suspend'] else None
types[i] = t
share = get_object_or_404(Share, id=id)
return render_to_response('edit-share.html', RequestContext(request, {
'share': share,
'types': types,
}))
def post(self, request, id, *args, **kwargs):
det = UserCloudDetails.objects.get(user=request.user)
share = get_object_or_404(Share, id=id)
if share.owner != request.user and not request.user.is_superuser:
raise PermissionDenied()
stype = request.POST['type']
if not stype in TYPES.keys():
raise PermissionDenied()
il = request.POST['instance_limit']
if det.get_weighted_share_count() + int(il)*share.template.instance_type.credit > det.share_quota:
messages.error(request, _('You do not have enough free share quota.'))
return redirect('/')
share.name=request.POST['name']
share.description=request.POST['description']
share.type=stype
share.instance_limit=il
share.per_user_limit=request.POST['per_user_limit']
share.owner=request.user
share.save()
messages.success(request, _('Successfully edited share %s.') % share)
return redirect(share.group)
ajax_share_edit_wizard = login_required(AjaxShareEditWizard.as_view())
@require_POST @require_POST
...@@ -289,6 +363,14 @@ def vm_show(request, iid): ...@@ -289,6 +363,14 @@ def vm_show(request, iid):
ports = inst.firewall_host.list_ports() ports = inst.firewall_host.list_ports()
except: except:
ports = None ports = None
try:
details = UserCloudDetails.objects.get(user=request.user)
except UserCloudDetails.DoesNotExist:
details = UserCloudDetails(user=request.user)
details.save()
proto = len(request.META["REMOTE_ADDR"].split('.')) == 1
inst.hostname = inst.get_connect_host(use_ipv6=proto)
inst.port = inst.get_port(use_ipv6=proto)
return render_to_response("show.html", RequestContext(request,{ return render_to_response("show.html", RequestContext(request,{
'uri': inst.get_connect_uri(), 'uri': inst.get_connect_uri(),
'state': inst.state, 'state': inst.state,
...@@ -299,6 +381,7 @@ def vm_show(request, iid): ...@@ -299,6 +381,7 @@ def vm_show(request, iid):
'i': inst, 'i': inst,
'booting' : not inst.active_since, 'booting' : not inst.active_since,
'ports': ports, 'ports': ports,
'userdetails': details
})) }))
@require_safe @require_safe
...@@ -306,7 +389,12 @@ def vm_show(request, iid): ...@@ -306,7 +389,12 @@ def vm_show(request, iid):
def vm_ajax_instance_status(request, iid): def vm_ajax_instance_status(request, iid):
inst = get_object_or_404(Instance, id=iid, owner=request.user) inst = get_object_or_404(Instance, id=iid, owner=request.user)
inst.update_state() inst.update_state()
return HttpResponse(json.dumps({'booting': not inst.active_since, 'state': inst.state})) return HttpResponse(json.dumps({
'booting': not inst.active_since,
'state': inst.state,
'template': {
'state': inst.template.state
}}))
@login_required @login_required
def vm_ajax_rename(request, iid): def vm_ajax_rename(request, iid):
...@@ -336,7 +424,11 @@ class VmPortAddView(View): ...@@ -336,7 +424,11 @@ class VmPortAddView(View):
if public >= 22000 and public < 24000: if public >= 22000 and public < 24000:
raise ValidationError(_("Port number is in a restricted domain (22000 to 24000).")) raise ValidationError(_("Port number is in a restricted domain (22000 to 24000)."))
inst = get_object_or_404(Instance, id=iid, owner=request.user) inst = get_object_or_404(Instance, id=iid, owner=request.user)
inst.firewall_host.add_port(proto=request.POST['proto'], public=public, private=int(request.POST['private'])) if inst.template.network.nat:
private = private=int(request.POST['private'])
else:
private = 0
inst.firewall_host.add_port(proto=request.POST['proto'], public=public, private=private)
messages.success(request, _(u"Port %d successfully added.") % public) messages.success(request, _(u"Port %d successfully added.") % public)
except: except:
messages.error(request, _(u"Adding port failed.")) messages.error(request, _(u"Adding port failed."))
...@@ -355,7 +447,7 @@ def vm_port_del(request, iid, proto, public): ...@@ -355,7 +447,7 @@ def vm_port_del(request, iid, proto, public):
inst = get_object_or_404(Instance, id=iid, owner=request.user) inst = get_object_or_404(Instance, id=iid, owner=request.user)
try: try:
inst.firewall_host.del_port(proto=proto, public=public) inst.firewall_host.del_port(proto=proto, public=public)
messages.success(request, _(u"Port %d successfully removed.") % public) messages.success(request, _(u"Port %s successfully removed.") % public)
except: except:
messages.error(request, _(u"Removing port failed.")) messages.error(request, _(u"Removing port failed."))
return redirect('/vm/show/%d/' % int(iid)) return redirect('/vm/show/%d/' % int(iid))
...@@ -413,17 +505,22 @@ def vm_stop(request, iid, *args, **kwargs): ...@@ -413,17 +505,22 @@ def vm_stop(request, iid, *args, **kwargs):
@require_POST @require_POST
def vm_resume(request, iid, *args, **kwargs): def vm_resume(request, iid, *args, **kwargs):
try: try:
get_object_or_404(Instance, id=iid, owner=request.user).resume() obj = get_object_or_404(Instance, id=iid, owner=request.user)
obj.resume()
messages.success(request, _('Virtual machine is successfully resumed.')) messages.success(request, _('Virtual machine is successfully resumed.'))
except: except:
messages.error(request, _('Failed to resume virtual machine.')) messages.error(request, _('Failed to resume virtual machine.'))
try:
obj.renew()
except:
pass
return redirect('/') return redirect('/')
@login_required @login_required
@require_POST @require_POST
def vm_renew(request, which, iid, *args, **kwargs): def vm_renew(request, which, iid, *args, **kwargs):
try: try:
get_object_or_404(Instance, id=iid, owner=request.user).renew(which) get_object_or_404(Instance, id=iid, owner=request.user).renew()
messages.success(request, _('Virtual machine is successfully renewed.')) messages.success(request, _('Virtual machine is successfully renewed.'))
except: except:
messages.error(request, _('Failed to renew virtual machine.')) messages.error(request, _('Failed to renew virtual machine.'))
...@@ -460,9 +557,13 @@ def key_add(request): ...@@ -460,9 +557,13 @@ def key_add(request):
key.save() key.save()
_update_keys(request.user) _update_keys(request.user)
except ValidationError as e: except ValidationError as e:
messages.error(request, ''.join(e.messages)) for m in e.messages:
messages.error(request, m)
except: except:
messages.error(request, _('Failed to add public key')) messages.error(request, _('Failed to add public key.'))
else:
messages.success(request, _('Public key successfully added.'))
return redirect('/') return redirect('/')
@login_required @login_required
...@@ -497,5 +598,23 @@ def _update_keys(user): ...@@ -497,5 +598,23 @@ def _update_keys(user):
user = user.username user = user.username
StoreApi.updateauthorizationinfo(user, password, key_list) StoreApi.updateauthorizationinfo(user, password, key_list)
def stat(request):
values = subprocess.check_output(['/opt/webadmin/cloud/miscellaneous/stat/stat_wrap.sh'])
# values = '''
# {"CPU": {"USED_CPU": 2, "ALLOC_CPU": 0,
# "FREE_CPU": 98}, "MEM": {"FREE_MEM": 1685432, "ALLOC_MEM":0,
# "USED_MEM": 366284}}'''
stat_dict = json.loads(values)
return HttpResponse(render_to_response("stat.html", RequestContext(
request, {
'STAT' : stat_dict,
}
)))
def sites(request, site):
if site in [ "legal", "policy", "help", "support" ]:
return render_to_response("sites/%s.html" % site, RequestContext(request, {}))
else:
return redirect(home)
# vim: et sw=4 ai fenc=utf8 smarttab : # vim: et sw=4 ai fenc=utf8 smarttab :
...@@ -6,10 +6,10 @@ msgid "" ...@@ -6,10 +6,10 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-02-21 18:06+0100\n" "POT-Creation-Date: 2013-03-07 18:16+0100\n"
"PO-Revision-Date: 2013-02-19 18:47+0100\n" "PO-Revision-Date: 2013-03-07 17:48+0100\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: American English <kde-l10n-hu@kde.org>\n" "Language-Team: American English <cloud@ik.bme.hu>\n"
"Language: en_US\n" "Language: en_US\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
...@@ -159,127 +159,179 @@ msgstr "Érvénytelen Neptun-kód." ...@@ -159,127 +159,179 @@ msgstr "Érvénytelen Neptun-kód."
msgid "Invalid NEPTUN code" msgid "Invalid NEPTUN code"
msgstr "Érvénytelen Neptun-kód" msgstr "Érvénytelen Neptun-kód"
#: templates/show-group.html:8 #: templates/show-group.html:9
msgid "Owners of" msgid "Owners of"
msgstr "Tulajdonosok" msgstr "Tulajdonosok"
#: templates/show-group.html:22 templates/box/person/entry.html:22 #: templates/show-group.html:23 templates/box/person/entry.html:23
msgid "Remove" msgid "Remove"
msgstr "Eltávolítás" msgstr "Eltávolítás"
#: templates/show-group.html:30 templates/box/person/entry.html:31 #: templates/show-group.html:31 templates/box/person/entry.html:32
msgid "This user never logged in, no data available" msgid "This user never logged in, no data available"
msgstr "Ez a felhasználó még nem lépett be, nincs adat róla" msgstr "Ez a felhasználó még nem lépett be, nincs adat róla"
#: templates/show-group.html:34 templates/box/person/entry.html:35 #: templates/show-group.html:35 templates/box/person/entry.html:36
msgid "Name" msgid "Name"
msgstr "Név" msgstr "Név"
#: templates/show-group.html:37 templates/box/person/entry.html:38 #: templates/show-group.html:38 templates/box/person/entry.html:39
msgid "NEPTUN" msgid "NEPTUN"
msgstr "NEPTUN" msgstr "NEPTUN"
#: templates/show-group.html:50 #: templates/show-group.html:51
msgid "Add owner" msgid "Add owner"
msgstr "Tulajdonos hozzáadása" msgstr "Tulajdonos hozzáadása"
#: templates/show-group.html:55 #: templates/show-group.html:56
msgid "Owner name/NEPTUN" msgid "Owner name/NEPTUN"
msgstr "Tulajdonos neve/NEPTUN-kódja" msgstr "Tulajdonos neve/NEPTUN-kódja"
#: templates/show-group.html:68 #: templates/show-group.html:69
msgid "This group has no shared templates." msgid "This group has no shared templates."
msgstr "Ennek a csoportnak egy sablon sincs megosztva." msgstr "Ennek a csoportnak egy sablon sincs megosztva."
#: templates/show-group.html:71 #: templates/show-group.html:72
msgid "Share one, and the group members can start their own virtual machine." msgid "Share one, and the group members can start their own virtual machine."
msgstr "" msgstr ""
"Osszon meg egyet, hogy a csoport tagjai is elindíthassák egy példányát." "Osszon meg egyet, hogy a csoport tagjai is elindíthassák egy példányát."
#: templates/box/group/box.html:7 #: templates/box/group/box.html:11 templates/box/person/box.html:11
msgid "Help"
msgstr "Segítség"
#: templates/box/group/box.html:14
msgid "This is the list of groups you own."
msgstr "Ez az ön csoportjainak felsorolása."
#: templates/box/group/box.html:15
msgid "Groups are collections of users."
msgstr "A csoportok felhasználók halmazai."
#: templates/box/group/box.html:16
msgid ""
"You can share templates with your groups, so\n"
" that they can run instances of those templates.\n"
" "
msgstr ""
"Megoszthatja a sablonokat csoportjaival, \n"
" így a tagok elindíthatják a sablonokból saját példányaikat.\n"
" "
#: templates/box/group/box.html:22 templates/box/person/box.html:21
msgid "Show/hide box"
msgstr "Doboz megjelenítése/rejtése"
#: templates/box/group/box.html:28
msgid "My Groups" msgid "My Groups"
msgstr "Saját csoportok" msgstr "Saját csoportok"
#: templates/box/group/box.html:19 #: templates/box/group/box.html:40
msgid "You have no groups." msgid "You have no groups."
msgstr "Nincs még csoportja." msgstr "Nincs még csoportja."
#: templates/box/group/box.html:21 #: templates/box/group/box.html:42
msgid "Create a new one, and add your students to the new group." msgid "Create a new one, and add your students to the new group."
msgstr "Hozzon létre egyet, és vegy fel hallgatóit." msgstr "Hozzon létre egyet, és vegy fel hallgatóit."
#: templates/box/group/box.html:29 #: templates/box/group/box.html:50
msgid "Show hidden groups" msgid "Show hidden groups"
msgstr "Elrejtett csoportok megjelenítése" msgstr "Elrejtett csoportok megjelenítése"
#: templates/box/group/box.html:35 templates/box/group/box.html.py:41 #: templates/box/group/box.html:56 templates/box/group/box.html.py:62
msgid "Create new group" msgid "Create new group"
msgstr "Új csoport létrehozása" msgstr "Új csoport létrehozása"
#: templates/box/group/box.html:44 #: templates/box/group/box.html:65
msgid "Group name" msgid "Group name"
msgstr "Csoport neve" msgstr "Csoport neve"
#: templates/box/group/box.html:48 templates/box/group/entry.html:42 #: templates/box/group/box.html:69 templates/box/group/entry.html:43
msgid "Semester" msgid "Semester"
msgstr "Félév" msgstr "Félév"
#: templates/box/group/box.html:56 #: templates/box/group/box.html:77
msgid "Members" msgid "Members"
msgstr "Tagok" msgstr "Tagok"
#: templates/box/group/box.html:57 #: templates/box/group/box.html:78
msgid "Student NEPTUN codes, one per line" msgid "Student NEPTUN codes, one per line"
msgstr "Hallgatók NEPTUN-kódja, soronként egy" msgstr "Hallgatók NEPTUN-kódja, soronként egy"
#: templates/box/group/box.html:62 #: templates/box/group/box.html:83
msgid "Cancel" msgid "Cancel"
msgstr "Mégsem" msgstr "Mégsem"
#: templates/box/group/box.html:63 #: templates/box/group/box.html:84
msgid "Done" msgid "Done"
msgstr "Kész" msgstr "Kész"
#: templates/box/group/entry.html:15 templates/box/group/entry.html.py:56 #: templates/box/group/entry.html:16 templates/box/group/entry.html.py:57
msgid "More details" msgid "More details"
msgstr "Részletek" msgstr "Részletek"
#: templates/box/group/entry.html:19 #: templates/box/group/entry.html:20
msgid "Delete" msgid "Delete"
msgstr "Törlés" msgstr "Törlés"
#: templates/box/group/entry.html:22 #: templates/box/group/entry.html:23
msgid "Hide" msgid "Hide"
msgstr "Elrejtés" msgstr "Elrejtés"
#: templates/box/group/entry.html:32 #: templates/box/group/entry.html:33
msgid "Course" msgid "Course"
msgstr "Tárgy" msgstr "Tárgy"
#: templates/box/group/entry.html:37 #: templates/box/group/entry.html:38
msgid "Not assigned" msgid "Not assigned"
msgstr "Nincs hozzárendelve" msgstr "Nincs hozzárendelve"
#: templates/box/group/entry.html:46 #: templates/box/group/entry.html:47
msgid "Owner(s)" msgid "Owner(s)"
msgstr "Tulajdonosok" msgstr "Tulajdonosok"
#: templates/box/group/entry.html:50 #: templates/box/group/entry.html:51
msgid "Member count" msgid "Member count"
msgstr "Tagok száma" msgstr "Tagok száma"
#: templates/box/person/box.html:7 #: templates/box/person/box.html:14
msgid "This is the list of this group's members."
msgstr "Ez a csoport tagjainak felsorolása."
#: templates/box/person/box.html:15
msgid ""
"Members are the people who can start new\n"
" instances of templates shared with the group.\n"
" "
msgstr ""
"A tagok azok a személyek, akik jogosultak a csoportnak\n"
" megosztott sablonok példányainak indítására.\n"
" "
#: templates/box/person/box.html:27
msgid "Members of" msgid "Members of"
msgstr "Tagok" msgstr "Tagok"
#: templates/box/person/box.html:17 templates/box/person/box.html.py:20 #: templates/box/person/box.html:37 templates/box/person/box.html.py:40
msgid "Add user" msgid "Add user"
msgstr "Felhasználó hozzáadása" msgstr "Felhasználó hozzáadása"
#: templates/box/person/box.html:19 #: templates/box/person/box.html:39
msgid "User NEPTUN code" msgid "User NEPTUN code"
msgstr "Felhasználó Neptun-kódja" msgstr "Felhasználó Neptun-kódja"
#~ msgid "Templates are customized versions of the base images."
#~ msgstr "A sablonok alaprendszerek testre szabott változatai."
#~ msgid ""
#~ "You can install all the needed software on a master\n"
#~ " machine, and it will be ready to run by your students in "
#~ "minutes.\n"
#~ " "
#~ msgstr ""
#~ "Telepítheti az összes szükséges szoftvert egy mestergépen, és az "
#~ "ígykészült sablon pár perc múltán készen is állhat a hallgatók számára."
#~ msgid "Templates" #~ msgid "Templates"
#~ msgstr "Sablonok" #~ msgstr "Sablonok"
......
{% extends "box/base/box.html" %} {% extends "box/base/box.html" %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block boxhelp %}
<div class="boxhelp">
<div class="help">
<div class="icon">
<img src="{% static "icons/information-frame.png" %}" alt="{% trans "Help" %}" />
</div>
<div class="boxhelp-box">
<p>{% blocktrans %}This is the list of groups you own.{% endblocktrans %}</p>
<p>{% blocktrans %}Groups are collections of users.{% endblocktrans %}</p>
<p>{% blocktrans %}You can share templates with your groups, so
that they can run instances of those templates.
{% endblocktrans %}</p>
</div>
</div>
<div class="icon">
<img src="" alt="toggle" title="{% trans "Show/hide box" %}" class="toggle-box" data-id="groups" id="toggle-box-groups"/>
</div>
</div>
{% endblock %}
{% block title %} {% block title %}
{% trans "My Groups" %} {% trans "My Groups" %}
{% endblock title %} {% endblock title %}
...@@ -36,7 +57,7 @@ ...@@ -36,7 +57,7 @@
<div class="clear"></div> <div class="clear"></div>
</div> </div>
<div id="new-group-wizard" style="display: none"> <div id="new-group-wizard" style="display: none">
<form action="/group/new/" method="POST" class="wizard"> <form action="{% url school.views.group_new %}" method="POST" class="wizard">
{% csrf_token %} {% csrf_token %}
<h3>{% trans "Create new group" %}</h3> <h3>{% trans "Create new group" %}</h3>
<ul> <ul>
......
{% extends "box/base/entry.html" %} {% extends "box/base/entry.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block content %} {% block content %}
...@@ -12,14 +13,14 @@ ...@@ -12,14 +13,14 @@
<div class="summary"> <div class="summary">
<div class="name"> <div class="name">
{{ group.name }} {{ group.name }}
<small class="details">(<a href="/group/show/{{group.id}}">{% trans "More details" %}</a>)</small> <small class="details">(<a href="{{ group.get_absolute_url }}">{% trans "More details" %}</a>)</small>
</div> </div>
<div class="actions"> <div class="actions">
<a href="#" class="delete" data-id="{{group.id}}" data-name="{{group.name}}"> <a href="#" class="delete" data-id="{{group.id}}" data-name="{{group.name}}">
<img src="/static/icons/minus-circle.png" alt="{% trans "Delete" %}" title="{% trans "Delete" %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans "Delete" %}" title="{% trans "Delete" %}" />
</a> </a>
<a href="#" class="hide-group" data-id="{{group.id}}"> <a href="#" class="hide-group" data-id="{{group.id}}">
<img src="/static/icons/eye-half.png" alt="{% trans "Hide" %}" title="{% trans "Hide" %}" /> <img src="{% static "icons/eye-half.png" %}" alt="{% trans "Hide" %}" title="{% trans "Hide" %}" />
</a> </a>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
...@@ -53,7 +54,7 @@ ...@@ -53,7 +54,7 @@
<li> <li>
&nbsp; &nbsp;
<span class="value"> <span class="value">
<a href="/group/show/{{group.id}}">{% trans "More details" %}</a> <a href="{{group.get_absolute_url}}">{% trans "More details" %}</a>
</span> </span>
</li> </li>
</ul> </ul>
......
{% extends "box/base/box.html" %} {% extends "box/base/box.html" %}
{% load i18n %} {% load i18n %}
{% load l10n %} {% load l10n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block boxhelp %}
<div class="boxhelp">
<div class="help">
<div class="icon">
<img src="{% static "icons/information-frame.png" %}" alt="{% trans "Help" %}" />
</div>
<div class="boxhelp-box">
<p>{% blocktrans %}This is the list of this group's members.{% endblocktrans %}</p>
<p>{% blocktrans %}Members are the people who can start new
instances of templates shared with the group.
{% endblocktrans %}</p>
</div>
</div>
<div class="icon">
<img src="" alt="eye" title="{% trans "Show/hide box" %}" class="toggle-box" data-id="members" id="toggle-box-members"/>
</div>
</div>
{% endblock %}
{% block title %} {% block title %}
{% trans "Members of" %}: {{group.name}} {% trans "Members of" %}: {{group.name}}
{% endblock title %} {% endblock title %}
......
{% extends "box/base/entry.html" %} {% extends "box/base/entry.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block content %} {% block content %}
...@@ -19,7 +20,7 @@ ...@@ -19,7 +20,7 @@
</div> </div>
<div class="actions"> <div class="actions">
<a href="#" class="remove" data-gid="{{group.id}}" data-neptun="{{member.code}}"> <a href="#" class="remove" data-gid="{{group.id}}" data-neptun="{{member.code}}">
<img src="/static/icons/minus-circle.png" alt="{% trans 'Remove' %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans 'Remove' %}" />
</a> </a>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
......
{% extends "base.html" %} {% extends "base.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block content %} {% block content %}
<div class="boxes"> <div class="boxes">
...@@ -19,7 +20,7 @@ ...@@ -19,7 +20,7 @@
</div> </div>
<!--<div class="actions"> <!--<div class="actions">
<a href="#" class="remove" data-gid="{{group.id}}" data-neptun="{{owner.code}}"> <a href="#" class="remove" data-gid="{{group.id}}" data-neptun="{{owner.code}}">
<img src="/static/icons/minus-circle.png" alt="{% trans 'Remove' %}" /> <img src="{% static "icons/minus-circle.png" %}" alt="{% trans 'Remove' %}" />
</a> </a>
</div>--> </div>-->
<div class="clear"></div> <div class="clear"></div>
......
...@@ -98,8 +98,10 @@ def login(request): ...@@ -98,8 +98,10 @@ def login(request):
co.save() co.save()
g.save() g.save()
try:
affiliation = request.META['affiliation'] affiliation = request.META['affiliation']
except KeyError:
affiliation = ''
if affiliation == '': if affiliation == '':
affiliation = [] affiliation = []
else: else:
......
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