Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
825f8c1e
authored
Nov 15, 2012
by
Őry Máté
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of vm-92.ik.bme.hu:cloud
parents
71672b2a
b096549f
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
122 additions
and
70 deletions
+122
-70
cloud/settings.py
+1
-0
one/admin.py
+14
-1
one/models.py
+64
-29
one/static/style.css
+3
-1
one/templates/box-vmlist.html
+1
-1
one/templates/confirm_delete.html
+14
-0
one/templates/home.html
+10
-9
one/templates/show.html
+5
-20
one/util.py
+6
-5
one/views.py
+3
-3
school/models.py
+1
-1
No files found.
cloud/settings.py
View file @
825f8c1e
...
...
@@ -124,6 +124,7 @@ INSTALLED_APPS = (
'school'
,
'cloud'
,
'south'
,
#'django_bfm',
)
# A sample logging configuration. The only tangible logging
...
...
one/admin.py
View file @
825f8c1e
...
...
@@ -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
)
one/models.py
View file @
825f8c1e
# 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
%03
d)"
%
(
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>
%(n
eptun)
s
%(n
ame)
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
:
...
...
one/static/style.css
View file @
825f8c1e
...
...
@@ -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
;
}
one/templates/box-vmlist.html
View file @
825f8c1e
...
...
@@ -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>
...
...
one/templates/confirm_delete.html
0 → 100644
View file @
825f8c1e
{% 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 %}
one/templates/home.html
View file @
825f8c1e
...
...
@@ -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"
>
...
...
one/templates/show.html
View file @
825f8c1e
...
...
@@ -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=
"<-"
/></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>
...
...
one/util.py
View file @
825f8c1e
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
(
len
gth
,
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
())
one/views.py
View file @
825f8c1e
...
...
@@ -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
=
i
d
,
owner
=
request
.
user
)
.
one_
delete
()
get_object_or_404
(
Instance
,
id
=
i
id
,
owner
=
request
.
user
)
.
delete
()
messages
.
success
(
request
,
_
(
'Virtual machine is successfully deleted.'
))
except
:
messages
.
error
(
request
,
_
(
'Failed to delete virtual machine.'
))
...
...
school/models.py
View file @
825f8c1e
...
...
@@ -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
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment