Commit 825f8c1e by Őry Máté

Merge branch 'master' of vm-92.ik.bme.hu:cloud

parents 71672b2a b096549f
......@@ -124,6 +124,7 @@ INSTALLED_APPS = (
'school',
'cloud',
'south',
#'django_bfm',
)
# A sample logging configuration. The only tangible logging
......
......@@ -18,11 +18,16 @@ class DetailsInline(contrib.admin.StackedInline):
can_delete = False
class MyUserAdmin(contrib.auth.admin.UserAdmin):
list_display = ('username', 'email', 'is_staff', 'date_joined', 'get_profile')
list_display = ('username', 'full_name', 'email', 'date_joined', 'instance_count')
try:
inlines = inlines + (PersonInline, SshKeyInline, DetailsInline)
except NameError:
inlines = (PersonInline, SshKeyInline, DetailsInline)
def instance_count(self, obj):
return obj.instance_set.count()
def full_name(self, obj):
return u"%s %s" % (obj.last_name, obj.first_name)
full_name.admin_order_field = 'last_name'
......@@ -49,6 +54,14 @@ class InstanceAdmin(contrib.admin.ModelAdmin):
list_display = ['id', 'name', 'owner', 'state']
readonly_fields = ['ip', 'active_since', 'pw', 'template']
list_filter = ['owner', 'template', 'state']
class DiskAdmin(contrib.admin.ModelAdmin):
model=models.Disk
class NetworkAdmin(contrib.admin.ModelAdmin):
model=models.Network
contrib.admin.site.register(models.Template, TemplateAdmin)
contrib.admin.site.register(models.Instance, InstanceAdmin)
contrib.admin.site.register(models.Network, NetworkAdmin)
contrib.admin.site.register(models.Disk, DiskAdmin)
# coding=utf-8
from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core import signing
from django.db import models
from django.db import transaction
from school.models import Person
from django.core.exceptions import ValidationError
import subprocess, tempfile, os, stat
from django.db.models.signals import post_save
from django import forms
from django.utils.translation import ugettext_lazy as _
from one.util import keygen
from django.db.models.signals import post_save
from school.models import Person
import subprocess, tempfile, os, stat
pwgen = User.objects.make_random_password
......@@ -23,7 +25,7 @@ class UserCloudDetails(models.Model):
user = models.ForeignKey(User, null=False, blank=False, unique=True)
smb_password = models.CharField(max_length=20)
ssh_key = models.ForeignKey('SshKey', null=True)
ssh_private_key = models.CharField(max_length=1024)
ssh_private_key = models.TextField()
def reset_keys(self):
......@@ -43,8 +45,8 @@ class UserCloudDetails(models.Model):
super(UserCloudDetails, self).clean()
if not self.ssh_key:
self.reset_keys()
if not self.smb_password or len(self.smb_password) == 0:
self.reset_smb()
if not self.smb_password or len(self.smb_password) == 0:
self.reset_smb()
class OpenSshKeyValidator(object):
valid_types = ['ssh-rsa', 'ssh-dsa']
......@@ -76,6 +78,13 @@ class SshKey(models.Model):
help_text=_('<a href="/info/ssh/">SSH public key in OpenSSH format</a> used for shell login '
'(2048+ bit RSA preferred). Example: <code>ssh-rsa AAAAB...QtQ== '
'john</code>.'), validators=[OpenSshKeyValidator()])
def __unicode__(self):
try:
keycomment = self.key.split(None, 2)[2]
except:
keycomment = _("unnamed")
return u"%s (%s)" % (keycomment, self.user)
class Disk(models.Model):
......@@ -90,10 +99,18 @@ class Disk(models.Model):
from xml.dom.minidom import parse, parseString
x = parseString(out)
with transaction.commit_on_success():
Disk.objects.all().delete()
l = []
for d in x.getElementsByTagName("STORAGE"):
Disk(id=int(d.getAttributeNode('href').nodeValue.split('/')[-1]),
name=d.getAttributeNode('name').nodeValue).save()
id = int(d.getAttributeNode('href').nodeValue.split('/')[-1])
name=d.getAttributeNode('name').nodeValue
try:
d = Disk.objects.get(id=id)
d.name=name
d.save()
except:
Disk(id=id, name=name).save
l.append(id)
Disk.objects.exclude(id__in=l).delete()
def __unicode__(self):
return u"%s (#%d)" % (self.name, self.id)
......@@ -116,22 +133,39 @@ class Network(models.Model):
from xml.dom.minidom import parse, parseString
x = parseString(out)
with transaction.commit_on_success():
cls.objects.all().delete()
l = []
for d in x.getElementsByTagName("NETWORK"):
Network(id=int(d.getAttributeNode('href').nodeValue.split('/')[-1]),
name=d.getAttributeNode('name').nodeValue).save()
id = int(d.getAttributeNode('href').nodeValue.split('/')[-1])
name=d.getAttributeNode('name').nodeValue
try:
n = Network.objects.get(id=id)
n.name = name
n.save()
except:
Network(id=id, name=name).save()
l.append(id)
cls.objects.exclude(id__in=l).delete()
def __unicode__(self):
return u"%s (vlan%03d)" % (self.name, self.id)
class Meta:
ordering = ['name']
class InstanceType(models.Model):
name = models.CharField(max_length=100, unique=True,
verbose_name=_('name'))
CPU = models.IntegerField()
RAM = models.IntegerField()
def __unicode__(self):
return u"%s" % self.name
class Template(models.Model):
name = models.CharField(max_length=100, unique=True,
verbose_name=_('név'))
access_type = models.CharField(max_length=10, choices=[('rdp', 'rdp'), ('nx', 'nx'), ('ssh', 'ssh')])
disk = models.ForeignKey(Disk)
instance_type = models.CharField(max_length=20, choices=[('small', 'small'), ('medium', 'medium'), ('large', 'large')])
instance_type = models.ForeignKey(InstanceType)
network = models.ForeignKey(Network)
owner = models.ForeignKey(User)
created_at = models.DateTimeField(auto_now_add=True)
......@@ -157,15 +191,15 @@ class Instance(models.Model):
one_id = models.IntegerField(unique=True, blank=True, null=True)
def get_port(self):
proto = self.template.access_type
if self.template.network.name == 'bmenet':
return {"rdp": 3389, "nx": 22, "ssh": 22}[proto]
if self.template.network.name == 'vmnet':
if self.template.network.nat:
return {"rdp": 23000, "nx": 22000, "ssh": 22000}[proto] + int(self.ip.split('.')[3])
else:
return {"rdp": 3389, "nx": 22, "ssh": 22}[proto]
def get_connect_host(self):
if self.template.network.name == 'bmenet':
return self.ip
elif self.template.network.name == 'vmnet':
if self.template.network.nat:
return 'cloud'
else:
return self.ip
def get_connect_uri(self):
try:
proto = self.template.access_type
......@@ -234,7 +268,7 @@ class Instance(models.Model):
tpl = u"""
<COMPUTE>
<NAME>%(neptun)s %(name)s</NAME>
<NAME>%(name)s</NAME>
<INSTANCE_TYPE href="http://www.opennebula.org/instance_type/%(instance)s"/>
<DISK>
<STORAGE href="http://www.opennebula.org/storage/%(disk)d"/>
......@@ -244,10 +278,12 @@ class Instance(models.Model):
</NIC>
<CONTEXT>
<HOSTNAME>cloud-$VMID</HOSTNAME>
<USERNAME>%(neptun)s</USERNAME>
<NEPTUN>%(neptun)s</NEPTUN>
<USERPW>%(pw)s</USERPW>
<SMBPW>%(smbpw)s</SMBPW>
<SSHPRIV>%(sshkey)s</SSHPRIV>
<BOOTURL>%(booturl)s</BOOTURL>
<SERVER>152.66.243.73</SERVER>
</CONTEXT>
</COMPUTE>""" % {"name": u"%s %d" % (owner.username, inst.id),
"instance": template.instance_type,
......@@ -255,10 +291,10 @@ class Instance(models.Model):
"net": template.network.id,
"pw": escape(inst.pw),
"smbpw": escape(details.smb_password),
"sshkey": escape(details.ssh_private_key),
"neptun": escape(owner.username),
"booturl": "http://cloud.ik.bme.hu/b/%s/" % token,
}
"sshkey": escape(details.ssh_private_key),
"neptun": escape(owner.username),
"booturl": "http://cloud.ik.bme.hu/b/%s/" % token,
}
f.write(tpl)
f.close()
import subprocess
......@@ -280,9 +316,8 @@ class Instance(models.Model):
return inst
def delete(self):
get_object_or_404(Instance, id=id, owner=request.user.get_profile())
proc = subprocess.Popen(["/var/lib/opennebula/bin/occi.sh", "compute",
"delete", id], stdout=subprocess.PIPE)
"delete", "%d"%self.one_id], stdout=subprocess.PIPE)
(out, err) = proc.communicate()
class Meta:
......
......@@ -306,7 +306,9 @@ width:400px;
display:block;
cursor:pointer;
}
.icon-delete {
background-image: url(/static/icons/Edit-delete-2.png);
background-repeat: no-repeat;
padding-left: 26px!important;
}
......@@ -4,7 +4,7 @@
<div class="content">
{% if instances %}
<table style="width:388px">
<tr><th>#</th><th>Megnevezés</th><th>Állapot</th><th style="width: 96px">Műveletek</th></tr>
<!--<tr><th>#</th><th>Megnevezés</th><th>Állapot</th><th style="width: 96px">Műveletek</th></tr>-->
{% for i in instances %}
<tr style="line-height: 22px;">
<td>{{i.id}}</td>
......
{% extends "base.html" %}
{% block content %}
<div class="boxes">
<div class="contentblock" id="state">
<h2>Törlés</h2>
<div class="content">
<form action="{% url vm_delete i.id %}" method="post">
{% csrf_token %}
<p>Biztosan törli a gépet? <input type="submit" value="Törlés" /></p>
</form>
</div>
</div>
</div>
{% endblock %}
......@@ -26,16 +26,17 @@
{% endfor %}
</div>
<div class="boxes">
{% for box in boxes %}
{% if forloop.counter|divisibleby:2 %}
<div class="contentblock">
<h2>{{ box.title }}</h2>
<div class="content">
{{ box.text|safe }}
</div>
<div class="contentblock">
<h2>Adattár</h2>
<div class="content">
<ul>
<li>a.out <span class="file-size">4K</span> <span class="file-age">(5 perce)</span> <a href="" class="file-download">Letöltés</a></li>
<li>a.out <span class="file-size">4K</span> <span class="file-age">(5 perce)</span> <a href="" class="file-download">Letöltés</a></li>
<li class="file-details">Tovább</li>
<li class="file-upload">Fájl feltöltése</li>
</ul>
</div>
{% endif %}
{% endfor %}
</div>
<div class="contentblock" id="state">
<h2>A cluster állapota</h2>
<div class="content">
......
......@@ -3,23 +3,8 @@
{% block js %}
<script type="text/javascript">
{% if state == "PENDING" %}
setTimeout("location.reload(true);", 1500)
{% endif %}
{% if state == "ACTIVE" %}
{% if age < 15 %}
setTimeout("document.getElementById('wait').style.display='none';document.getElementById('connect').style.display='block';", 15000-{{age}}000);
{% endif %}
var meloading = false;
function connectbutton() {
if (meloading) {
return false;
}
meloading = true;
setTimeout("document.getElementById('connecting').style.display='none';meloading=false;", 15000);
document.getElementById('connecting').style.display='inline';
return true;
}
{% if booting %}
setTimeout("location.reload(true);", 2000);
{% endif %}
</script>
{% endblock %}
......@@ -29,14 +14,14 @@
<div class="contentblock" id="state">
<h2>{{name}}</h2>
<div class="content">
{% if state == "PENDING" %}
{% if state == "PENDING" or state == "ACTIVE" and booting %}
<p style="font-size:25px; line-height:2em;text-align:center;"><img src="/static/load-2.gif" /> Gép indítása..</p>
<p style="font-size:25px; line-height:2em;text-align:center;">
<form action="{% url vm_delete id %}" method="post" onsubmit="return confirm('Biztosan törli a gépet?')">{% csrf_token %}<input type="submit" class="icon-delete" value="Törlés" /></form>
<a href="/"><img src="/static/icons/Go-home.png" alt="&lt;-" /></a>
</p>
{% endif %}
{% if state == "ACTIVE" %}
{% if state == "ACTIVE" and not booting %}
{% if age < 15 %}
<p id="wait" style="font-size:25px; line-height:2em;text-align:center;"><img src="/static/load-2.gif" /> Gép indítása...</p>
<p id="connect" style="display:none; font-size:25px; line-height:2em;text-align:center;">
......@@ -89,7 +74,7 @@
<tr><th>Port:</th><td>{{ i.get_port}}
</td></tr>
<tr><th>Felhasználónév:</th><td>cloud</td></tr>
<tr><th>Jelszó:</th><td>ezmiez</td></tr>
<tr><th>Jelszó:</th><td>{{ i.pw }}</td></tr>
</table>
</div>
</div>
......
def keygen(len=1024):
import os
def keygen(length=1024):
import os, base64
from datetime import date
from Crypto.PublicKey import RSA
key = RSA.generate(len, os.urandom)
key = RSA.generate(length, os.urandom)
try:
pub = key.exportKey('OpenSSH')
if not pub.startswith("ssh-"):
raise ValueError(pub)
except ValueError:
except:
ssh_rsa = '00000007' + base64.b16encode('ssh-rsa')
exponent = '%x' % (key.e, )
if len(exponent) % 2:
......@@ -28,6 +29,6 @@ def keygen(len=1024):
pub = 'ssh-rsa %s' % (
base64.b64encode(base64.b16decode(ssh_rsa.upper())), )
return key.exportKey(), pub
return key.exportKey(), "%s %s" % (pub, "cloud-%s" % date.today())
......@@ -105,14 +105,14 @@ def vm_show(request, iid):
'id': iid,
'age': inst.get_age(),
'instances': _list_instances(request),
'i': inst
'i': inst,
'booting' : not inst.active_since,
}))
class VmDeleteView(View):
def post(self, request, iid, *args, **kwargs):
try:
get_object_or_404(Instance, id=id, owner=request.user).one_delete()
get_object_or_404(Instance, id=iid, owner=request.user).delete()
messages.success(request, _('Virtual machine is successfully deleted.'))
except:
messages.error(request, _('Failed to delete virtual machine.'))
......
......@@ -12,7 +12,7 @@ post_save.connect(create_user_profile, sender=User)
LANGS = [('hu', _('Hungarian')), ('en_US', _('US English'))]
class Person(models.Model):
user = models.ForeignKey(User, null=False, blank=False, unique=True)
language = models.CharField(max_length=6, choices=LANGS,
language = models.CharField(max_length=6, choices=LANGS, default='hu',
verbose_name=_('Preferred language'))
def __unicode__(self):
......
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