Commit e84c01cf by Őry Máté

Merge branch 'release-13.04.1' into releases

Conflicts:
	one/locale/hu/LC_MESSAGES/django.po
	one/locale/hu/LC_MESSAGES/djangojs.po
	school/locale/hu/LC_MESSAGES/django.po
parents f6fdeffe 3c786fcb
......@@ -14,7 +14,15 @@
<a id="master"></a>
<section>
<h3 id="release-13.03.2"><a href="#13.03.2">13.03.2 (2013. március 21.)</a></h3>
<h3 id="release-13.04.1"><a href="#release-13.04.1">13.04.1 (2013. április 4.)</a></h3>
<ul>
<li>Hálózati beállítások új felületen.</li>
<li>Rövidebb IPv6-os gépnév.</li>
<li>Hibajavítások.</li>
</ul>
</section>
<section>
<h3 id="release-13.03.2"><a href="#release-13.03.2">13.03.2 (2013. március 21.)</a></h3>
<ul>
<li>Súgó.</li>
<li>Változáslista.</li>
......@@ -26,7 +34,7 @@
</section>
<section>
<h3 id="release-13.03.1"><a href="#13.03.1">13.03.1 (2013. március 7.)</a></h3>
<h3 id="release-13.03.1"><a href="#release-13.03.1">13.03.1 (2013. március 7.)</a></h3>
<ul>
<li>Határidős felfüggesztés élesítve.</li>
<li>Csatlakozási adatoknál IP cím helyett DNS név jelenik meg.</li>
......@@ -50,7 +58,7 @@
</section>
<section>
<h3 id="release-13.02.2"><a href="#13.02.2">13.02.2 (2013. február 21.)</a></h3>
<h3 id="release-13.02.2"><a href="#release-13.02.2">13.02.2 (2013. február 21.)</a></h3>
<ul>
<li>Felhasználói kvóták megvalósítása.</li>
<li>Publikus kulcsok kezelése.</li>
......
......@@ -37,7 +37,7 @@ urlpatterns = patterns('',
url(r'^vm/renew/(?P<which>(suspend|delete))/(?P<iid>\d+)/$',
'one.views.vm_renew', ),
url(r'^vm/port_add/(?P<iid>\d+)/$', 'one.views.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<private>\d+)/$',
'one.views.vm_port_del', ),
url(r'^ajax/shareEdit/(?P<id>\d+)/$', 'one.views.ajax_share_edit_wizard',
name='ajax_share_edit_wizard'),
......
......@@ -10,6 +10,7 @@ from django.core.validators import MinValueValidator, MaxValueValidator
from cloud.settings import firewall_settings as settings
from django.db.models.signals import post_save
import re
import random
class Rule(models.Model):
CHOICES_type = (('host', 'host'), ('firewall', 'firewall'),
......@@ -174,15 +175,30 @@ class Host(models.Model):
def enable_net(self):
self.groups.add(Group.objects.get(name="netezhet"))
def add_port(self, proto, public, private = 0):
def add_port(self, proto, public=None, private=None):
proto = "tcp" if proto == "tcp" else "udp"
if self.shared_ip:
if public < 1024:
raise ValidationError(_("Only ports above 1024 can be used."))
for host in Host.objects.filter(pub_ipv4=self.pub_ipv4):
if host.rules.filter(nat=True, proto=proto, dport=public):
used_ports = Rule.objects.filter(host__pub_ipv4=self.pub_ipv4,
nat=True, proto=proto).values_list('dport', flat=True)
if public is None:
public = random.randint(1024, 21000)
if public in used_ports:
for i in range(1024, 21000) + range(24000, 65535):
if i not in used_ports:
public = i
break
else:
raise ValidationError(_("Port %s %s is already in use.") %
(proto, public))
else:
if public < 1024:
raise ValidationError(_("Only ports above 1024 can be used."))
if public in used_ports:
raise ValidationError(_("Port %s %s is already in use.") %
(proto, public))
rule = Rule(direction='1', owner=self.owner, dport=public,
proto=proto, nat=True, accept=True, r_type="host",
nat_dport=private, host=self, foreign_network=VlanGroup.
......@@ -199,15 +215,58 @@ class Host(models.Model):
rule.full_clean()
rule.save()
def del_port(self, proto, public):
self.rules.filter(owner=self.owner, proto=proto, host=self,
dport=public).delete()
def del_port(self, proto, private):
if self.shared_ip:
self.rules.filter(owner=self.owner, proto=proto, host=self,
nat_dport=private).delete()
else:
self.rules.filter(owner=self.owner, proto=proto, host=self,
dport=private).delete()
def get_hostname(self, proto):
try:
if proto == 'ipv6':
res = self.record_set.filter(type='AAAA')
elif proto == 'ipv4':
if self.shared_ip:
res = Record.objects.filter(type='A',
address=self.pub_ipv4)
else:
res = self.record_set.filter(type='A')
return unicode(res[0].get_data()['name'])
except:
raise
if self.shared_ip:
return self.pub_ipv4
else:
return self.ipv4
def list_ports(self):
return [{'proto': rule.proto,
'public': rule.dport,
'private': rule.nat_dport} for rule in
self.rules.filter(owner=self.owner)]
retval = []
for rule in self.rules.filter(owner=self.owner):
private = rule.nat_dport if self.shared_ip else rule.dport
forward = {
'proto': rule.proto,
'private': private,
}
if self.shared_ip:
public4 = rule.dport
public6 = rule.nat_dport
else:
public4 = public6 = rule.dport
if True: # ipv4
forward['ipv4'] = {
'host': self.get_hostname(proto='ipv4'),
'port': public4,
}
if self.ipv6: # ipv6
forward['ipv6'] = {
'host': self.get_hostname(proto='ipv6'),
'port': public6,
}
retval.append(forward)
return retval
def get_fqdn(self):
return self.hostname + u'.' + unicode(self.vlan.domain)
......
description "IK Cloud Django Development Server"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
respawn limit 30 30
exec sudo -u cloud /opt/webadmin/cloud/manage.py celery worker --loglevel=info -c 1 -Q local
......@@ -183,6 +183,7 @@ class Browser:
def load_committed_cb(self,web_view, frame):
uri = frame.get_uri()
print uri
try:
self.webview.execute_script('document.getElementsByTagName("a")[0].target="";')
except:
......@@ -193,7 +194,7 @@ class Browser:
### JS
self.post_key(self.public_key_b64)
### Parse values and do mounting ###
elif uri.startswith("https://cloud.ik.bme.hu/?"):
elif uri.startswith("https://cloud.ik.bme.hu/home/?"):
if self.mounted != True:
try:
uri, params = uri.split('?', 1)
......
@inproceedings{younge2011analysis,
title={Analysis of virtualization technologies for high performance computing environments},
author={Younge, Andrew J and Henschel, Robert and Brown, James T and von Laszewski, Gregor and Qiu, Judy and Fox, Geoffrey C},
booktitle={Cloud Computing (CLOUD), 2011 IEEE International Conference on},
pages={9--16},
year={2011},
organization={IEEE}
}
@article{creasy1981origin,
title={The origin of the VM/370 time-sharing system},
author={Creasy, Robert J.},
journal={IBM Journal of Research and Development},
volume={25},
number={5},
pages={483--490},
year={1981},
publisher={IBM}
}
@article{duatonew,
title={A New Approach to rCUDA},
author={Duato, Jos{\'e} and Pena, Antonio J and Silla, Federico and Fern{\'a}ndez, Juan C and Mayo, Rafael and Quintana-Ort{\i}, Enrique S}
}
@book{holovaty2009definitive,
title={The Definitive Guide to Django: Web Development Done Right},
author={Holovaty, Adrian and Kaplan-Moss, Jacob},
year={2009},
publisher={Apress}
}
@techreport{pinzari2003introduction,
title={Introduction to NX technology},
author={Pinzari, Gian Filippo},
year={2003},
institution={NoMachine Technical Report 309}
}
@article{victoria2009creating,
title={Creating and Controlling KVM Guests using libvirt},
author={Victoria, B},
journal={University of Victoria},
year={2009}
}
@inproceedings{bolte2010non,
title={Non-intrusive virtualization management using libvirt},
author={Bolte, Matthias and Sievers, Michael and Birkenheuer, Georg and Nieh{\"o}rster, Oliver and Brinkmann, Andr{\'e}},
booktitle={Proceedings of the Conference on Design, Automation and Test in Europe},
pages={574--579},
year={2010},
organization={European Design and Automation Association}
}
@article{pfaff2009extending,
title={Extending networking into the virtualization layer},
author={Pfaff, Ben and Pettit, Justin and Koponen, Teemu and Amidon, Keith and Casado, Martin and Shenker, Scott},
journal={Proc. HotNets (October 2009)},
year={2009}
}
@article{hoskins2006sshfs,
title={Sshfs: super easy file access over ssh},
author={Hoskins, Matthew E},
journal={Linux Journal},
volume={2006},
number={146},
pages={4},
year={2006},
publisher={Belltown Media}
}
@article{szeredi2010fuse,
title={FUSE: Filesystem in userspace},
author={M. Szeredi},
journal={Accessed on},
year={2010}
}
@inproceedings{yang2012implementation,
title={On implementation of GPU virtualization using PCI pass-through},
author={Yang, Chao-Tung and Wang, Hsien-Yi and Ou, Wei-Shen and Liu, Yu-Tso and Hsu, Ching-Hsien},
booktitle={Cloud Computing Technology and Science (CloudCom), 2012 IEEE 4th International Conference on},
pages={711--716},
year={2012},
organization={IEEE}
}
@inproceedings{duato2011enabling,
title={Enabling CUDA acceleration within virtual machines using rCUDA},
author={Duato, Jos{\'e} and Pena, Antonio J and Silla, Federico and Fern{\'a}ndez, Juan C and Mayo, Rafael and Quintana-Orti, ES},
booktitle={High Performance Computing (HiPC), 2011 18th International Conference on},
pages={1--10},
year={2011},
organization={IEEE}
}
@inproceedings{callaghan2002nfs,
title={Nfs over rdma},
author={Callaghan, Brent and Lingutla-Raj, Theresa and Chiu, Alex and Staubach, Peter and Asad, Omer},
booktitle={Proceedings of ACM SIGCOMM Summer 2003 NICELI Workshop},
year={2002}
}
@article{vinoski2006advanced,
title={Advanced message queuing protocol},
author={Vinoski, Steve},
journal={Internet Computing, IEEE},
volume={10},
number={6},
pages={87--89},
year={2006},
publisher={IEEE}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
#!/usr/bin/python
import xmltodict
import xml.dom.minidom as minidom
import sys
import json
......@@ -23,14 +22,15 @@ mem_max = 0
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 host.getElementsByTagName("STATE")[0].childNodes[0].data == "2":
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
......
......@@ -98,8 +98,19 @@ class InstanceAdmin(contrib.admin.ModelAdmin):
class DiskAdmin(contrib.admin.ModelAdmin):
model=models.Disk
list_display = ('name', 'used_by')
def used_by(self, obj):
try:
return ", ".join(obj.template_set.all())
except:
return None
used_by.verbose_name = _('used by')
class NetworkAdmin(contrib.admin.ModelAdmin):
model=models.Network
list_display = ('name', 'nat', 'public', 'get_vlan')
class ShareAdmin(contrib.admin.ModelAdmin):
model=models.Network
list_filter = ('group', 'template', )
......
......@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-22 10:43+0100\n"
"PO-Revision-Date: 2013-03-07 17:02+0100\n"
"POT-Creation-Date: 2013-04-04 18:33+0200\n"
"PO-Revision-Date: 2013-04-04 18:03+0200\n"
"Last-Translator: \n"
"Language-Team: Hungarian <cloud@ik.bme.hu>\n"
"Language: hu\n"
......@@ -17,17 +17,18 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Lokalize 1.4\n"
#: static/script/cloud.js:24
#: static/script/cloud.js:41 static/script/cloud.min.js:1
msgid "Are you sure deleting key?"
msgstr "Biztosan törli a kulcsot?"
#: static/script/cloud.js:24 static/script/cloud.js.c:301
#: static/script/cloud.js:373 static/script/cloud.js.c:600
#: static/script/store.js:288
#: static/script/cloud.js:41 static/script/cloud.js.c:338
#: static/script/cloud.js:416 static/script/cloud.js.c:644
#: static/script/cloud.min.js:1 static/script/store.js:288
#: static/script/store.min.js:1
msgid "Delete"
msgstr "Törlés"
#: static/script/cloud.js:36
#: static/script/cloud.js:53 static/script/cloud.min.js:1
msgid ""
"Are you sure about reseting store credentials?<br /> You will lose your "
"access to your store account on your existing virtual machines!"
......@@ -35,92 +36,114 @@ msgstr ""
"Biztosan újragenerálja az adattár-kulcsait?<br /> El fogja veszteni az "
"adattár-hozzáférést a már futó virtuális gépekből!"
#: static/script/cloud.js:36
#: static/script/cloud.js:53 static/script/cloud.min.js:1
msgid "Reset"
msgstr "Újragenerálás"
#: static/script/cloud.js:76 static/script/store.js:323
#: static/script/cloud.js:95 static/script/cloud.min.js:1
#: static/script/store.js:323 static/script/store.min.js:1
msgid "Rename"
msgstr "Átnevezés"
#: static/script/cloud.js:276 static/script/store.js:288
#: static/script/cloud.js:311 static/script/cloud.min.js:1
#: static/script/store.js:288 static/script/store.min.js:1
msgid "Cancel"
msgstr "Mégsem"
#: static/script/cloud.js:290
#: static/script/cloud.js:327 static/script/cloud.min.js:1
#, c-format
msgid "Are you sure stopping %s?"
msgstr "Biztosan felfüggeszti a következőt: %s?"
#: static/script/cloud.js:291
#: static/script/cloud.js:328 static/script/cloud.min.js:1
msgid "Stop"
msgstr "Felfüggesztés"
#: static/script/cloud.js:300
#: static/script/cloud.js:337 static/script/cloud.min.js:1
#, c-format
msgid "Are you sure deleting %s?"
msgstr "Biztosan törli a következőt: %s?"
#: static/script/cloud.js:310
#: static/script/cloud.js:347 static/script/cloud.min.js:1
#, c-format
msgid "Are you sure restarting %s?"
msgstr "Biztosan újraindítja a következőt: %s?"
#: static/script/cloud.js:311
#: static/script/cloud.js:348 static/script/cloud.min.js:1
msgid "Restart"
msgstr "Újraindítás"
#: static/script/cloud.js:372
#: static/script/cloud.js:415 static/script/cloud.min.js:1
#, c-format
msgid "Are you sure deleting this %s template?"
msgstr "Biztosan törli a következő sablont: %s?"
#: static/script/cloud.js:551 static/script/cloud.js.c:554
#: static/script/cloud.js:436 static/script/cloud.min.js:1
msgid "Template deletion successful!"
msgstr "Sablon törlése sikeres."
#: static/script/cloud.js:595 static/script/cloud.js.c:598
#: static/script/cloud.min.js:1
msgid "Add owner"
msgstr "Tulajdonos hozzáadása"
#: static/script/cloud.js:554
#: static/script/cloud.js:598 static/script/cloud.min.js:1
msgid "Unknown"
msgstr "Ismeretlen"
#: static/script/cloud.js:600
#: static/script/cloud.js:644 static/script/cloud.min.js:1
#, c-format
msgid "Are you sure deleting <strong>%s</strong>"
msgstr "Törli a következő fájlt: <strong>%s</strong>"
#: static/script/store.js:52 static/script/store.js.c:61
#: static/script/store.js:70 static/script/store.js.c:220
#: static/script/store.js:282
#: static/script/store.js:282 static/script/store.min.js:1
msgid "file"
msgstr "fájl"
#: static/script/store.js:125
#: 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.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.js:283 static/script/store.min.js:1
#, c-format
msgid "You are removing the file <strong>%s</strong>."
msgstr "Törli a következő fájlt: <strong>%s</strong>."
#: static/script/store.js:285
#: static/script/store.js:285 static/script/store.min.js:1
#, c-format
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>."
#: static/script/store.js:288
#: static/script/store.js:288 static/script/store.min.js:1
msgid "Are you sure?"
msgstr "Biztos benne?"
#: static/script/store.js:446 static/script/store.js.c:448
#: static/script/store.js:396 static/script/store.min.js:1
#, c-format
msgid "File %s is already present! Click OK to override it."
msgstr "%s már létezik. Felülírja?"
#: static/script/store.js:408 static/script/store.min.js:1
#, c-format
msgid ""
"%s seems to be a directory. Uploading directories is currently not "
"supported. If you're sure that %s is a file, click OK to upload it."
msgstr ""
"%s egy mappának tűnik. Mappák feltöltésére nincs lehetőség. Ha biztos benne, "
"hogy %s egy fájl, kattintson az OK-ra a feltöltéshez."
#: static/script/store.js:463 static/script/store.js.c:465
#: static/script/store.min.js:1
msgid "Upload"
msgstr "Feltöltés"
#: static/script/store.js:448
#: static/script/store.js:465 static/script/store.min.js:1
msgid "done, processing..."
msgstr "kész, feldolgozás..."
......
......@@ -158,7 +158,6 @@ class SshKey(models.Model):
TEMPLATE_STATES = (("INIT", _('init')), ("PREP", _('perparing')),
("SAVE", _('saving')), ("READY", _('ready')))
TYPES = {"LAB": {"verbose_name": _('lab'), "id": "LAB",
"suspend": td(hours=5), "delete": td(days=15),
"help_text": _('For lab or homework with short lifetime.')},
......@@ -169,6 +168,7 @@ TYPES = {"LAB": {"verbose_name": _('lab'), "id": "LAB",
"suspend": td(days=365), "delete": None,
"help_text": _('For long-term server use.')},
}
DEFAULT_TYPE = TYPES['LAB']
TYPES_L = sorted(TYPES.values(), key=lambda m: m["suspend"])
TYPES_C = tuple([(i[0], i[1]["verbose_name"]) for i in TYPES.items()])
......@@ -188,13 +188,23 @@ class Share(models.Model):
'user.'))
owner = models.ForeignKey(User, null=True, blank=True, related_name='share_set')
def get_type(self):
t = TYPES[self.type]
class Meta:
ordering = ['group', 'template', 'owner', ]
verbose_name = _('share')
verbose_name_plural = _('shares')
@classmethod
def extend_type(cls, t):
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)
return t
def get_type(self):
t = TYPES[self.type]
return self.extend_type(t)
def get_running_or_stopped(self, user=None):
running = (Instance.objects.all().exclude(state='DONE')
.filter(share=self))
......@@ -210,9 +220,14 @@ class Share(models.Model):
return running.filter(owner=user).count()
else:
return running.count()
def get_instance_pc(self):
return float(self.get_running()) / self.instance_limit * 100
def __unicode__(self):
return u"%(group)s: %(tpl)s %(owner)s" % {
'group': self.group, 'tpl': self.template, 'owner': self.owner}
class Disk(models.Model):
"""Virtual disks automatically synchronized with OpenNebula."""
name = models.CharField(max_length=100, unique=True,
......@@ -220,6 +235,8 @@ class Disk(models.Model):
class Meta:
ordering = ['name']
verbose_name = _('disk')
verbose_name_plural = _('disks')
def __unicode__(self):
return u"%s (#%d)" % (self.name, self.id)
......@@ -259,6 +276,9 @@ class Network(models.Model):
class Meta:
ordering = ['name']
verbose_name = _('network')
verbose_name_plural = _('networks')
def __unicode__(self):
return self.name
......@@ -285,6 +305,8 @@ class Network(models.Model):
Network(id=id, name=name).save()
l.append(id)
Network.objects.exclude(id__in=l).delete()
def get_vlan(self):
return Vlan.objects.get(vid=self.id)
class InstanceType(models.Model):
......@@ -298,6 +320,8 @@ class InstanceType(models.Model):
class Meta:
ordering = ['credit']
verbose_name = _('instance type')
verbose_name_plural = _('instance types')
def __unicode__(self):
return u"%s" % self.name
......@@ -332,6 +356,8 @@ class Template(models.Model):
class Meta:
verbose_name = _('template')
verbose_name_plural = _('templates')
ordering = ['name', ]
def __unicode__(self):
return self.name
......@@ -357,7 +383,7 @@ class Template(models.Model):
class Instance(models.Model):
"""Virtual machine instance."""
name = models.CharField(max_length=100, unique=True,
name = models.CharField(max_length=100,
verbose_name=_('name'), blank=True)
ip = models.IPAddressField(blank=True, null=True,
verbose_name=_('IP address'))
......@@ -396,6 +422,7 @@ class Instance(models.Model):
class Meta:
verbose_name = _('instance')
verbose_name_plural = _('instances')
ordering = ['pk', ]
def __unicode__(self):
return self.name
......@@ -407,28 +434,17 @@ class Instance(models.Model):
def get_port(self, use_ipv6=False):
"""Get public port number for default access method."""
proto = self.template.access_type
if self.template.network.nat and not use_ipv6:
if self.nat and not use_ipv6:
return {"rdp": 23000, "nx": 22000, "ssh": 22000}[proto] + int(self.ip.split('.')[2]) * 256 + int(self.ip.split('.')[3])
else:
return {"rdp": 3389, "nx": 22, "ssh": 22}[proto]
def get_connect_host(self, use_ipv6=False):
"""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:
ip = self.firewall_host.pub_ipv4
return Record.objects.filter(type='A', address=ip)[0].get_data()['name']
else:
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
proto = 'ipv6' if use_ipv6 else 'ipv4'
return self.firewall_host.get_hostname(proto=proto)
def get_connect_uri(self, use_ipv6=False):
"""Get access parameters in URI format."""
......@@ -472,6 +488,15 @@ class Instance(models.Model):
self.check_if_is_save_as_done()
return x
@property
def nat(self):
if self.firewall_host is not None:
return self.firewall_host.shared_ip
elif self.template is not None:
return self.template.network.nat
else:
return False
def get_age(self):
"""Get age of VM in seconds."""
from datetime import datetime
......@@ -491,7 +516,7 @@ class Instance(models.Model):
inst = Instance(pw=pwgen(), template=template, owner=owner,
share=share, state='PENDING')
inst.save()
hostname = u"cloud-%d" % (inst.id, )
hostname = u"%d" % (inst.id, )
with tempfile.NamedTemporaryFile(delete=False) as f:
os.chmod(f.name, stat.S_IRUSR|stat.S_IWUSR|stat.S_IRGRP|stat.S_IROTH)
token = signing.dumps(inst.id, salt='activate')
......@@ -638,13 +663,20 @@ class Instance(models.Model):
def renew(self, which='both'):
if which in ['suspend', 'both']:
self.time_of_suspend = self.share.get_type()['suspendx']
self.time_of_suspend = self.share_type['suspendx']
if which in ['delete', 'both']:
self.time_of_delete = self.share.get_type()['deletex']
self.time_of_delete = self.share_type['deletex']
if not (which in ['suspend', 'delete', 'both']):
raise ValueError('No such expiration type.')
self.save()
@property
def share_type(self):
if self.share:
return self.share.get_type()
else:
return Share.extend_type(DEFAULT_TYPE)
def save_as(self):
"""Save image and shut down."""
imgname = "template-%d-%d" % (self.template.id, self.id)
......
......@@ -9,7 +9,24 @@ $(function() {
$(this).next('.details').slideDown(700);
}
})
$('a').click(function(e) {
$('a[href=#]').click(function(e) {
e.preventDefault();
});
$('.host-toggle').click(function(e){
e.preventDefault();
if($(this).find('.v4').is(':hidden')){
$(this).find('.v4').show();
$(this).find('.v6').hide();
$(this).parent().next().find('.host').show();
$(this).parent().next().find('.ipv4host').hide();
} else {
$(this).find('.v6').show();
$(this).find('.v4').hide();
$(this).parent().next().find('.host').hide();
$(this).parent().next().find('.ipv4host').show();
}
});
$('a[href!=#]').click(function(e) {
e.stopPropagation();
});