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
81cd77d5
authored
Jan 25, 2013
by
Őry Máté
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
one: code formatting, documentation
parent
418e464e
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
117 additions
and
49 deletions
+117
-49
one/models.py
+117
-49
No files found.
one/models.py
View file @
81cd77d5
...
@@ -7,16 +7,18 @@ from django.db import transaction
...
@@ -7,16 +7,18 @@ from django.db import transaction
from
django.db.models.signals
import
post_save
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
one.util
import
keygen
from
school.models
import
Person
from
firewall.models
import
Host
,
Rule
,
Vlan
from
firewall.models
import
Host
,
Rule
,
Vlan
from
firewall.tasks
import
reload_firewall_lock
from
firewall.tasks
import
reload_firewall_lock
from
one.util
import
keygen
from
school.models
import
Person
import
subprocess
,
tempfile
,
os
,
stat
,
re
import
subprocess
,
tempfile
,
os
,
stat
,
re
pwgen
=
User
.
objects
.
make_random_password
pwgen
=
User
.
objects
.
make_random_password
"""
User creation hook: create cloud details object
"""
def
create_user_profile
(
sender
,
instance
,
created
,
**
kwargs
):
def
create_user_profile
(
sender
,
instance
,
created
,
**
kwargs
):
if
created
:
if
created
:
d
=
UserCloudDetails
(
user
=
instance
)
d
=
UserCloudDetails
(
user
=
instance
)
...
@@ -24,13 +26,22 @@ def create_user_profile(sender, instance, created, **kwargs):
...
@@ -24,13 +26,22 @@ def create_user_profile(sender, instance, created, **kwargs):
d
.
save
()
d
.
save
()
post_save
.
connect
(
create_user_profile
,
sender
=
User
)
post_save
.
connect
(
create_user_profile
,
sender
=
User
)
"""
Cloud related details of a user
"""
class
UserCloudDetails
(
models
.
Model
):
class
UserCloudDetails
(
models
.
Model
):
user
=
models
.
ForeignKey
(
User
,
null
=
False
,
blank
=
False
,
unique
=
True
)
user
=
models
.
ForeignKey
(
User
,
null
=
False
,
blank
=
False
,
unique
=
True
,
verbose_name
=
_
(
'user'
))
smb_password
=
models
.
CharField
(
max_length
=
20
)
smb_password
=
models
.
CharField
(
max_length
=
20
,
ssh_key
=
models
.
ForeignKey
(
'SshKey'
,
null
=
True
)
verbose_name
=
_
(
'Samba password'
),
ssh_private_key
=
models
.
TextField
()
help_text
=
_
(
'Generated password for accessing store from Windows.'
))
ssh_key
=
models
.
ForeignKey
(
'SshKey'
,
null
=
True
,
verbose_name
=
_
(
'SSH key (public)'
),
help_text
=
_
(
'Generated SSH public key for accessing store from Linux.'
))
ssh_private_key
=
models
.
TextField
(
verbose_name
=
_
(
'SSH key (private)'
),
help_text
=
_
(
'Generated SSH private key for accessing store from Linux.'
))
"""
Delete old SSH key pair and generate new one.
"""
def
reset_keys
(
self
):
def
reset_keys
(
self
):
pri
,
pub
=
keygen
()
pri
,
pub
=
keygen
()
self
.
ssh_private_key
=
pri
self
.
ssh_private_key
=
pri
...
@@ -41,9 +52,15 @@ class UserCloudDetails(models.Model):
...
@@ -41,9 +52,15 @@ class UserCloudDetails(models.Model):
self
.
ssh_key
=
SshKey
(
user
=
self
.
user
,
key
=
pub
)
self
.
ssh_key
=
SshKey
(
user
=
self
.
user
,
key
=
pub
)
self
.
ssh_key
.
save
()
self
.
ssh_key
.
save
()
"""
Generate new Samba password.
"""
def
reset_smb
(
self
):
def
reset_smb
(
self
):
self
.
smb_password
=
pwgen
()
self
.
smb_password
=
pwgen
()
"""
Generate key pair and Samba password if needed.
"""
def
clean
(
self
):
def
clean
(
self
):
super
(
UserCloudDetails
,
self
)
.
clean
()
super
(
UserCloudDetails
,
self
)
.
clean
()
if
not
self
.
ssh_key
:
if
not
self
.
ssh_key
:
...
@@ -51,6 +68,9 @@ class UserCloudDetails(models.Model):
...
@@ -51,6 +68,9 @@ class UserCloudDetails(models.Model):
if
not
self
.
smb_password
or
len
(
self
.
smb_password
)
==
0
:
if
not
self
.
smb_password
or
len
(
self
.
smb_password
)
==
0
:
self
.
reset_smb
()
self
.
reset_smb
()
"""
Validate OpenSSH keys (length and type).
"""
class
OpenSshKeyValidator
(
object
):
class
OpenSshKeyValidator
(
object
):
valid_types
=
[
'ssh-rsa'
,
'ssh-dsa'
]
valid_types
=
[
'ssh-rsa'
,
'ssh-dsa'
]
...
@@ -74,13 +94,16 @@ class OpenSshKeyValidator(object):
...
@@ -74,13 +94,16 @@ class OpenSshKeyValidator(object):
except
:
except
:
raise
ValidationError
(
_
(
'Invalid OpenSSH public key.'
))
raise
ValidationError
(
_
(
'Invalid OpenSSH public key.'
))
"""
SSH public key (in OpenSSH format).
"""
class
SshKey
(
models
.
Model
):
class
SshKey
(
models
.
Model
):
user
=
models
.
ForeignKey
(
User
,
null
=
False
,
blank
=
False
)
user
=
models
.
ForeignKey
(
User
,
null
=
False
,
blank
=
False
)
key
=
models
.
CharField
(
max_length
=
2000
,
verbose_name
=
_
(
'SSH key'
),
key
=
models
.
CharField
(
max_length
=
2000
,
verbose_name
=
_
(
'SSH key'
),
help_text
=
_
(
'<a href="/info/ssh/">SSH public key in OpenSSH format</a> used for shell login '
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== '
'(2048+ bit RSA preferred). Example: <code>ssh-rsa AAAAB...QtQ== '
'john</code>.'
),
validators
=
[
OpenSshKeyValidator
()])
'john</code>.'
),
validators
=
[
OpenSshKeyValidator
()])
def
__unicode__
(
self
):
def
__unicode__
(
self
):
try
:
try
:
keycomment
=
self
.
key
.
split
(
None
,
2
)[
2
]
keycomment
=
self
.
key
.
split
(
None
,
2
)[
2
]
...
@@ -89,10 +112,15 @@ class SshKey(models.Model):
...
@@ -89,10 +112,15 @@ class SshKey(models.Model):
return
u"
%
s (
%
s)"
%
(
keycomment
,
self
.
user
)
return
u"
%
s (
%
s)"
%
(
keycomment
,
self
.
user
)
"""
Virtual disks automatically synchronized with OpenNebula.
"""
class
Disk
(
models
.
Model
):
class
Disk
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
"""
Get and register virtual disks from OpenNebula.
"""
@classmethod
@classmethod
def
update
(
cls
):
def
update
(
cls
):
import
subprocess
import
subprocess
...
@@ -121,12 +149,17 @@ class Disk(models.Model):
...
@@ -121,12 +149,17 @@ class Disk(models.Model):
class
Meta
:
class
Meta
:
ordering
=
[
'name'
]
ordering
=
[
'name'
]
"""
Virtual networks automatically synchronized with OpenNebula.
"""
class
Network
(
models
.
Model
):
class
Network
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
nat
=
models
.
BooleanField
()
nat
=
models
.
BooleanField
(
verbose_name
=
_
(
'NAT'
),
help_text
=
_
(
'If network address translation is done.'
))
public
=
models
.
BooleanField
()
public
=
models
.
BooleanField
(
verbose_name
=
_
(
'public'
),
help_text
=
_
(
'If internet gateway is available.'
))
"""
Get and register virtual networks from OpenNebula.
"""
@classmethod
@classmethod
def
update
(
cls
):
def
update
(
cls
):
import
subprocess
import
subprocess
...
@@ -154,56 +187,84 @@ class Network(models.Model):
...
@@ -154,56 +187,84 @@ class Network(models.Model):
class
Meta
:
class
Meta
:
ordering
=
[
'name'
]
ordering
=
[
'name'
]
"""
Instance types in OCCI configuration (manually synchronized).
"""
class
InstanceType
(
models
.
Model
):
class
InstanceType
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
verbose_name
=
_
(
'name'
))
CPU
=
models
.
IntegerField
()
CPU
=
models
.
IntegerField
(
help_text
=
_
(
'CPU cores.'
)
)
RAM
=
models
.
IntegerField
()
RAM
=
models
.
IntegerField
(
help_text
=
_
(
'Mebibytes of memory.'
)
)
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
u"
%
s"
%
self
.
name
return
u"
%
s"
%
self
.
name
"""
Virtual machine template specifying OS, disk, type and network.
"""
class
Template
(
models
.
Model
):
class
Template
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'név'
))
verbose_name
=
_
(
'name'
))
access_type
=
models
.
CharField
(
max_length
=
10
,
choices
=
[(
'rdp'
,
'rdp'
),
(
'nx'
,
'nx'
),
(
'ssh'
,
'ssh'
)])
access_type
=
models
.
CharField
(
max_length
=
10
,
disk
=
models
.
ForeignKey
(
Disk
)
choices
=
[(
'rdp'
,
'rdp'
),
(
'nx'
,
'nx'
),
(
'ssh'
,
'ssh'
)],
instance_type
=
models
.
ForeignKey
(
InstanceType
)
verbose_name
=
_
(
'access method'
))
network
=
models
.
ForeignKey
(
Network
)
disk
=
models
.
ForeignKey
(
Disk
,
verbose_name
=
_
(
'disk'
))
owner
=
models
.
ForeignKey
(
User
)
instance_type
=
models
.
ForeignKey
(
InstanceType
,
verbose_name
=
_
(
'instance type'
))
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
)
network
=
models
.
ForeignKey
(
Network
,
verbose_name
=
_
(
'network'
))
owner
=
models
.
ForeignKey
(
User
,
verbose_name
=
_
(
'owner'
))
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'created at'
))
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
self
.
name
return
self
.
name
class
Meta
:
class
Meta
:
verbose_name
=
_
(
'sablon'
)
verbose_name
=
_
(
'template'
)
verbose_name_plural
=
_
(
'sablonok'
)
verbose_name_plural
=
_
(
'templates'
)
"""
Virtual machine instance.
"""
class
Instance
(
models
.
Model
):
class
Instance
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'név'
),
null
=
True
,
blank
=
True
)
verbose_name
=
_
(
'név'
),
null
=
True
,
blank
=
True
)
ip
=
models
.
IPAddressField
(
blank
=
True
,
null
=
True
)
ip
=
models
.
IPAddressField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'IP address'
))
template
=
models
.
ForeignKey
(
Template
)
template
=
models
.
ForeignKey
(
Template
,
verbose_name
=
_
(
'template'
))
owner
=
models
.
ForeignKey
(
User
)
owner
=
models
.
ForeignKey
(
User
,
verbose_name
=
_
(
'owner'
))
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
)
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
,
verbose_name
=
_
(
'created_at'
))
state
=
models
.
CharField
(
max_length
=
20
,
choices
=
[(
'DEPLOYABLE'
,
'DEPLOYABLE'
),
(
'PENDING'
,
'PENDING'
),
(
'DONE'
,
'DONE'
),
(
'ACTIVE'
,
'ACTIVE'
),(
'UNKNOWN'
,
'UNKNOWN'
),
(
'SUSPENDED'
,
'SUSPENDED'
),
(
'FAILED'
,
'FAILED'
)],
default
=
'DEPLOYABLE'
)
state
=
models
.
CharField
(
max_length
=
20
,
active_since
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
choices
=
[(
'DEPLOYABLE'
,
_
(
'deployable'
)),
firewall_host
=
models
.
ForeignKey
(
Host
,
blank
=
True
,
null
=
True
)
(
'PENDING'
,
_
(
'pending'
)),
pw
=
models
.
CharField
(
max_length
=
20
)
(
'DONE'
,
_
(
'done'
)),
one_id
=
models
.
IntegerField
(
unique
=
True
,
blank
=
True
,
null
=
True
)
(
'ACTIVE'
,
_
(
'active'
)),
(
'UNKNOWN'
,
_
(
'unknown'
)),
(
'SUSPENDED'
,
_
(
'suspended'
)),
(
'FAILED'
,
_
(
'failed'
))],
default
=
'DEPLOYABLE'
)
active_since
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'active since'
),
help_text
=
_
(
'Time stamp of successful boot report.'
))
firewall_host
=
models
.
ForeignKey
(
Host
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'host in firewall'
))
pw
=
models
.
CharField
(
max_length
=
20
,
verbose_name
=
_
(
'password'
),
help_text
=
_
(
'Original password of instance'
))
one_id
=
models
.
IntegerField
(
unique
=
True
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'OpenNebula ID'
))
"""
Get public port number for default access method.
"""
def
get_port
(
self
):
def
get_port
(
self
):
proto
=
self
.
template
.
access_type
proto
=
self
.
template
.
access_type
if
self
.
template
.
network
.
nat
:
if
self
.
template
.
network
.
nat
:
return
{
"rdp"
:
23000
,
"nx"
:
22000
,
"ssh"
:
22000
}[
proto
]
+
int
(
self
.
ip
.
split
(
'.'
)[
3
])
return
{
"rdp"
:
23000
,
"nx"
:
22000
,
"ssh"
:
22000
}[
proto
]
+
int
(
self
.
ip
.
split
(
'.'
)[
3
])
else
:
else
:
return
{
"rdp"
:
3389
,
"nx"
:
22
,
"ssh"
:
22
}[
proto
]
return
{
"rdp"
:
3389
,
"nx"
:
22
,
"ssh"
:
22
}[
proto
]
"""
Get public hostname.
"""
def
get_connect_host
(
self
):
def
get_connect_host
(
self
):
if
self
.
template
.
network
.
nat
:
if
self
.
template
.
network
.
nat
:
return
'cloud'
return
'cloud'
else
:
else
:
return
self
.
ip
return
self
.
ip
"""
Get access parameters in URI format.
"""
def
get_connect_uri
(
self
):
def
get_connect_uri
(
self
):
try
:
try
:
proto
=
self
.
template
.
access_type
proto
=
self
.
template
.
access_type
...
@@ -217,6 +278,10 @@ class Instance(models.Model):
...
@@ -217,6 +278,10 @@ class Instance(models.Model):
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
self
.
name
return
self
.
name
"""
Get and update VM state from OpenNebula.
"""
def
update_state
(
self
):
def
update_state
(
self
):
import
subprocess
import
subprocess
...
@@ -241,11 +306,14 @@ class Instance(models.Model):
...
@@ -241,11 +306,14 @@ class Instance(models.Model):
self
.
save
()
self
.
save
()
return
x
return
x
"""
Get age of VM in seconds.
"""
def
get_age
(
self
):
def
get_age
(
self
):
from
datetime
import
datetime
from
datetime
import
datetime
age
=
0
age
=
0
try
:
try
:
age
=
(
datetime
.
now
()
.
replace
(
tzinfo
=
None
)
age
=
(
datetime
.
now
()
.
replace
(
tzinfo
=
None
)
-
self
.
active_since
.
replace
(
tzinfo
=
None
))
.
seconds
-
self
.
active_since
.
replace
(
tzinfo
=
None
))
.
seconds
except
:
except
:
pass
pass
...
@@ -253,8 +321,11 @@ class Instance(models.Model):
...
@@ -253,8 +321,11 @@ 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
(
'vm_show'
,
None
,
{
'iid'
:
self
.
id
})
"""
Submit a new instance to OpenNebula.
"""
@classmethod
@classmethod
def
submit
(
cls
,
template
,
owner
):
def
submit
(
cls
,
template
,
owner
):
from
django.template.defaultfilters
import
escape
from
django.template.defaultfilters
import
escape
...
@@ -296,10 +367,9 @@ class Instance(models.Model):
...
@@ -296,10 +367,9 @@ class Instance(models.Model):
"net"
:
template
.
network
.
id
,
"net"
:
template
.
network
.
id
,
"pw"
:
escape
(
inst
.
pw
),
"pw"
:
escape
(
inst
.
pw
),
"smbpw"
:
escape
(
details
.
smb_password
),
"smbpw"
:
escape
(
details
.
smb_password
),
"sshkey"
:
escape
(
details
.
ssh_private_key
),
"sshkey"
:
escape
(
details
.
ssh_private_key
),
"neptun"
:
escape
(
owner
.
username
),
"neptun"
:
escape
(
owner
.
username
),
"booturl"
:
"http://cloud.ik.bme.hu/b/
%
s/"
%
token
,
"booturl"
:
"http://cloud.ik.bme.hu/b/
%
s/"
%
token
,
}
}
f
.
write
(
tpl
)
f
.
write
(
tpl
)
f
.
close
()
f
.
close
()
import
subprocess
import
subprocess
...
@@ -332,6 +402,9 @@ class Instance(models.Model):
...
@@ -332,6 +402,9 @@ class Instance(models.Model):
reload_firewall_lock
()
reload_firewall_lock
()
return
inst
return
inst
"""
Delete host in OpenNebula.
"""
def
delete
(
self
):
def
delete
(
self
):
proc
=
subprocess
.
Popen
([
"/opt/occi.sh"
,
"compute"
,
proc
=
subprocess
.
Popen
([
"/opt/occi.sh"
,
"compute"
,
"delete"
,
"
%
d"
%
self
.
one_id
],
stdout
=
subprocess
.
PIPE
)
"delete"
,
"
%
d"
%
self
.
one_id
],
stdout
=
subprocess
.
PIPE
)
...
@@ -343,8 +416,3 @@ class Instance(models.Model):
...
@@ -343,8 +416,3 @@ class Instance(models.Model):
class
Meta
:
class
Meta
:
verbose_name
=
_
(
'instance'
)
verbose_name
=
_
(
'instance'
)
verbose_name_plural
=
_
(
'instances'
)
verbose_name_plural
=
_
(
'instances'
)
# vim: et sw=4 ai fenc=utf8 smarttab :
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