Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gyuricska Milán
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
156fc6bc
authored
Jan 25, 2013
by
x
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
ssh://giccero.cloud.ik.bme.hu/cloud
parents
8dc2613b
81cd77d5
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
483 additions
and
49 deletions
+483
-49
miscellaneous/store-server/CloudStore.py
+278
-0
miscellaneous/store-server/UserManager.sh
+88
-0
one/models.py
+117
-49
No files found.
miscellaneous/store-server/CloudStore.py
0 → 100755
View file @
156fc6bc
#!/usr/bin/python
#TODO File permission checks
from
bottle
import
route
,
run
,
request
,
static_file
,
abort
,
redirect
,
app
import
json
,
os
,
shutil
import
uuid
import
subprocess
from
pwd
import
getpwnam
ROOT_WWW_FOLDER
=
'/var/www'
ROOT_BIN_FOLDER
=
'/opt/store-server'
SITE_URL
=
'https://store.cloud.ik.bme.hu'
USER_MANAGER
=
'UserManager.sh'
@route
(
'/'
)
def
index
():
return
"It works!"
#@route('/<neptun:re:[a-zA-Z0-9]{6}>', method='GET')
@route
(
'/<neptun>'
,
method
=
'GET'
)
def
neptun_GET
(
neptun
):
home_path
=
'/home/'
+
neptun
+
'/home'
if
os
.
path
.
exists
(
home_path
)
!=
True
:
abort
(
401
,
'The requested user does not exist!'
)
else
:
statistics
=
getQuotaStatus
(
neptun
)
return
{
'Used'
:
statistics
[
0
],
'Soft'
:
statistics
[
1
],
'Hard'
:
statistics
[
2
]}
@route
(
'/<neptun>'
,
method
=
'POST'
)
def
neptun_POST
(
neptun
):
#Check if user avaiable (home folder ready)
home_path
=
'/home/'
+
neptun
+
'/home'
if
os
.
path
.
exists
(
home_path
)
!=
True
:
abort
(
401
,
'The requested user does not exist!'
)
else
:
#Parse post
#LISTING
if
request
.
json
[
'CMD'
]
==
'LIST'
:
list_path
=
home_path
+
request
.
json
[
'PATH'
]
if
os
.
path
.
exists
(
list_path
)
!=
True
:
abort
(
404
,
"Path not found!"
)
else
:
return
list_directory
(
home_path
,
list_path
)
#DOWNLOAD LINK GENERATOR
elif
request
.
json
[
'CMD'
]
==
'DOWNLOAD'
:
dl_path
=
home_path
+
'/'
+
request
.
json
[
'PATH'
]
dl_path
=
os
.
path
.
normpath
(
dl_path
)
if
not
dl_path
.
startswith
(
home_path
):
abort
(
400
,
'Invalid download path.'
)
if
(
os
.
path
.
isfile
(
dl_path
)
):
dl_hash
=
str
(
uuid
.
uuid4
())
os
.
symlink
(
dl_path
,
ROOT_WWW_FOLDER
+
'/'
+
dl_hash
)
#Debug
#redirect('http://store.cloud.ik.bme.hu:8080/dl/'+dl_hash)
return
json
.
dumps
({
'LINK'
:
SITE_URL
+
'/dl/'
+
dl_hash
})
else
:
abort
(
400
,
'Can
\'
t download folder'
)
#UPLOAD
elif
request
.
json
[
'CMD'
]
==
'UPLOAD'
:
up_path
=
home_path
+
'/'
+
request
.
json
[
'PATH'
]
up_path
=
os
.
path
.
normpath
(
up_path
)
if
not
up_path
.
startswith
(
home_path
):
abort
(
400
,
'Invalid upload path.'
)
if
os
.
path
.
exists
(
up_path
)
==
True
and
os
.
path
.
isdir
(
up_path
):
up_hash
=
str
(
uuid
.
uuid4
())
os
.
symlink
(
up_path
,
ROOT_WWW_FOLDER
+
'/'
+
up_hash
)
return
json
.
dumps
({
'LINK'
:
SITE_URL
+
'/ul/'
+
up_hash
})
else
:
abort
(
400
,
'Upload directory not exists!'
)
#MOVE
elif
request
.
json
[
'CMD'
]
==
'MOVE'
:
src_path
=
home_path
+
'/'
+
request
.
json
[
'SOURCE'
]
dst_path
=
home_path
+
'/'
+
request
.
json
[
'DESTINATION'
]
if
not
os
.
path
.
normpath
(
src_path
)
.
startswith
(
home_path
):
abort
(
400
,
'Invalid source path.'
)
if
not
os
.
path
.
normpath
(
dst_path
)
.
startswith
(
home_path
):
abort
(
400
,
'Invalid destination path.'
)
if
os
.
path
.
exists
(
src_path
)
==
True
and
os
.
path
.
exists
(
dst_path
)
==
True
and
os
.
path
.
isdir
(
dst_path
)
==
True
:
shutil
.
move
(
src_path
,
dst_path
)
return
else
:
#TODO
abort
(
400
,
"Can not move the file."
)
#RENAME
elif
request
.
json
[
'CMD'
]
==
'RENAME'
:
src_path
=
home_path
+
'/'
+
request
.
json
[
'PATH'
]
if
not
os
.
path
.
normpath
(
src_path
)
.
startswith
(
home_path
):
abort
(
400
,
'Invalid source path.'
)
dst_path
=
os
.
path
.
dirname
(
src_path
)
+
'/'
+
request
.
json
[
'NEW_NAME'
]
if
os
.
path
.
exists
(
src_path
)
==
True
:
os
.
rename
(
src_path
,
dst_path
)
else
:
abort
(
404
,
"File or Folder not found!"
)
return
#NEW FOLDER
elif
request
.
json
[
'CMD'
]
==
'NEW_FOLDER'
:
dir_path
=
home_path
+
'/'
+
request
.
json
[
'PATH'
]
if
not
os
.
path
.
normpath
(
dir_path
)
.
startswith
(
home_path
):
abort
(
400
,
'Invalid directory path.'
)
if
os
.
path
.
exists
(
dir_path
)
==
True
:
abort
(
400
,
"Directory already exist!"
)
else
:
os
.
mkdir
(
dir_path
,
0755
)
return
#REMOVE
elif
request
.
json
[
'CMD'
]
==
'REMOVE'
:
remove_path
=
home_path
+
'/'
+
request
.
json
[
'PATH'
]
if
not
os
.
path
.
normpath
(
remove_path
)
.
startswith
(
home_path
):
abort
(
400
,
'Invalid path.'
)
if
os
.
path
.
exists
(
remove_path
)
!=
True
:
abort
(
404
,
"Path not found!"
)
else
:
if
os
.
path
.
isdir
(
remove_path
)
==
True
:
shutil
.
rmtree
(
remove_path
)
return
else
:
os
.
remove
(
remove_path
)
return
else
:
abort
(
400
,
"Command not found!"
)
@route
(
'/set/<neptun>'
,
method
=
'POST'
)
def
set_keys
(
neptun
):
key_list
=
[]
smb_password
=
''
try
:
smbpasswd
=
request
.
json
[
'SMBPASSWD'
]
for
key
in
request
.
json
[
'KEYS'
]:
key_list
.
append
(
key
)
except
:
abort
(
400
,
'Wrong syntax!'
)
result
=
subprocess
.
call
([
ROOT_BIN_FOLDER
+
'/'
+
USER_MANAGER
,
'set'
,
neptun
,
smbpasswd
])
if
result
==
0
:
updateSSHAuthorizedKeys
(
neptun
,
key_list
)
return
elif
result
==
2
:
abort
(
403
,
'User does not exist!'
)
@route
(
'/new/<neptun>'
,
method
=
'POST'
)
def
new_user
(
neptun
):
key_list
=
[]
smbpasswd
=
''
try
:
smbpasswd
=
request
.
json
[
'SMBPASSWD'
]
except
:
abort
(
400
,
'Invalid syntax'
)
#Call user creator script
result
=
subprocess
.
call
([
ROOT_BIN_FOLDER
+
'/'
+
USER_MANAGER
,
'add'
,
neptun
,
smbpasswd
])
if
result
==
0
:
try
:
for
key
in
request
.
json
[
'KEYS'
]:
key_list
.
append
(
key
)
updateSSHAuthorizedKeys
(
neptun
,
key_list
)
except
:
abort
(
400
,
'SSH'
)
return
elif
result
==
2
:
abort
(
403
,
'User already exist!'
)
else
:
abort
(
400
,
'An error occured!'
)
#Static file
@route
(
'/dl/<hash_num>'
,
method
=
'GET'
)
def
dl_hash
(
hash_num
):
hash_path
=
ROOT_WWW_FOLDER
if
os
.
path
.
exists
(
hash_path
)
!=
True
:
abort
(
404
,
"File not found!"
)
else
:
filename
=
os
.
path
.
basename
(
os
.
path
.
realpath
(
hash_path
+
'/'
+
hash_num
))
return
static_file
(
hash_num
,
root
=
hash_path
,
download
=
filename
)
@route
(
'/ul/<hash_num>'
,
method
=
'POST'
)
def
upload
(
hash_num
):
if
not
os
.
path
.
exists
(
ROOT_WWW_FOLDER
+
'/'
+
hash_num
):
abort
(
404
,
'Token not found!'
)
try
:
file_data
=
request
.
files
.
data
file_name
=
file_data
.
filename
except
:
if
os
.
path
.
exists
(
ROOT_WWW_FOLDER
+
'/'
+
hash_num
):
os
.
remove
(
ROOT_WWW_FOLDER
+
'/'
+
hash_num
)
abort
(
400
,
'No file was specified!'
)
up_path
=
os
.
path
.
realpath
(
ROOT_WWW_FOLDER
+
'/'
+
hash_num
+
'/'
+
file_name
)
if
os
.
path
.
exists
(
up_path
):
abort
(
400
,
'File already exists'
)
#Check if upload path valid
if
not
os
.
path
.
normpath
(
up_path
)
.
startswith
(
'/home'
):
abort
(
400
,
'Invalid path.'
)
os
.
remove
(
ROOT_WWW_FOLDER
+
'/'
+
hash_num
)
#Get the real upload path
#Delete the hash link
#Get the username from path for proper ownership
username
=
up_path
.
split
(
'/'
,
3
)[
2
]
#os.setegid(getpwnam(username).pw_gid)
#os.seteuid(getpwnam(username).pw_uid)
#TODO setuid subcommand
#Check if file exist (root can overwrite anything not safe)
f
=
open
(
up_path
,
'wb'
)
datalength
=
0
for
chunk
in
fbuffer
(
file_data
.
file
):
f
.
write
(
chunk
)
datalength
+=
len
(
chunk
)
f
.
close
()
os
.
chown
(
up_path
,
getpwnam
(
username
)
.
pw_uid
,
getpwnam
(
username
)
.
pw_gid
)
os
.
chmod
(
up_path
,
0744
)
return
'Upload finished: '
+
file_name
+
' - '
+
str
(
datalength
)
+
' Byte'
#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
def
updateSSHAuthorizedKeys
(
username
,
key_list
):
user_home_ssh
=
'/home/'
+
username
+
'/home/.ssh'
user_uid
=
getpwnam
(
username
)
.
pw_uid
user_gid
=
getpwnam
(
username
)
.
pw_gid
if
not
os
.
path
.
exists
(
user_home_ssh
):
os
.
mkdir
(
user_home_ssh
,
0700
)
os
.
chown
(
user_home_ssh
,
user_uid
,
user_gid
)
auth_file_name
=
user_home_ssh
+
'/authorized_keys'
auth_file
=
open
(
auth_file_name
,
'w'
)
for
key
in
key_list
:
auth_file
.
write
(
key
+
'
\n
'
)
auth_file
.
close
()
os
.
chmod
(
auth_file_name
,
0600
)
os
.
chown
(
auth_file_name
,
user_uid
,
user_gid
)
return
#For debug purpose
#@route('/ul/<hash_num>', method='GET')
#def upload_get(hash_num):
# return """<form method="POST" action="/ul/{hash}" enctype="multipart/form-data">
# <input name="data" type="file" />
# <input type="submit" />
#</form>""".format(hash=hash_num)
def
list_directory
(
home
,
path
):
#Check for path breakout
if
not
os
.
path
.
normpath
(
path
)
.
startswith
(
home
):
abort
(
400
,
'Invalid path.'
)
#Check if path exist
if
os
.
path
.
exists
(
path
)
!=
True
:
abort
(
404
,
'No such file or directory'
)
else
:
#If it's a file return with list
if
os
.
path
.
isdir
(
path
)
!=
True
:
return
json
.
dumps
((
os
.
path
.
basename
(
path
),
'F'
,
os
.
path
.
getsize
(
path
),
os
.
path
.
getmtime
(
path
)))
#List directory and return list
else
:
tuplelist
=
[]
filelist
=
os
.
listdir
(
path
)
#Add type support
for
item
in
filelist
:
static_route
=
path
+
"/"
+
item
if
os
.
path
.
isdir
(
static_route
):
is_dir
=
'D'
else
:
is_dir
=
'F'
tuplelist
.
append
((
item
,
is_dir
,
os
.
path
.
getsize
(
static_route
)
/
1024
,
os
.
path
.
getmtime
(
static_route
)
))
return
json
.
dumps
(
tuplelist
)
def
getQuotaStatus
(
neptun
):
output
=
subprocess
.
check_output
([
ROOT_BIN_FOLDER
+
'/'
+
USER_MANAGER
,
'status'
,
neptun
],
stderr
=
subprocess
.
STDOUT
)
return
output
.
split
()
if
__name__
==
"__main__"
:
run
(
host
=
'0.0.0.0'
,
port
=
8080
)
else
:
application
=
app
()
miscellaneous/store-server/UserManager.sh
0 → 100755
View file @
156fc6bc
#!/bin/bash
#
# Return values:
# 0: succesfully created
# 1: invalid syntax
# 2: user already exist
#
GRP_NAME
=
"cloudusers"
COMMAND
=
"
$1
"
USER_NAME
=
"
$2
"
SMB_PASSWD
=
"
$3
"
umask
022
case
$COMMAND
in
'add'
)
if
[
"x
${
USER_NAME
}
"
==
"x"
]
;
then
exit
1
fi
if
[
"x
${
SMB_PASSWD
}
"
==
"x"
]
;
then
exit
1
fi
#Check if user already exist
id
${
USER_NAME
}
>
/dev/null 2>&1
if
[
$?
==
'0'
]
;
then
exit
2
fi
HOME_DIR
=
"/home/
${
USER_NAME
}
/home"
mkdir
-p
${
HOME_DIR
}
useradd
--no-user-group
--home
${
HOME_DIR
}
--gid
${
GRP_NAME
}
${
USER_NAME
}
>
/dev/null 2>&1
adduser
${
USER_NAME
}
${
GRP_NAME
}
>
/dev/null 2>&1
chown
${
USER_NAME
}
:cloudusers
${
HOME_DIR
}
>
/dev/null 2>&1
chmod 0755
${
HOME_DIR
}
>
/dev/null 2>&1
chmod 0755
"/home/
${
USER_NAME
}
"
2>&1
#Set password to SMB_PASSWD
echo
-e
"
${
SMB_PASSWD
}
\n
${
SMB_PASSWD
}
\n
"
| passwd
${
USER_NAME
}
>
/dev/null 2>&1
#Set SMBPASSWD
echo
-e
"
${
SMB_PASSWD
}
\n
${
SMB_PASSWD
}
"
|
(
smbpasswd
-a
-s
${
USER_NAME
}
)
>
/dev/null
echo
"User
${
USER_NAME
}
CREATED at
`
date
`
"
>>
/root/users.log
#Set quotas
# Username Soft Hard Inode Dev
setquota
${
USER_NAME
}
2097152 2621440 0 0 /home
;;
'set'
)
id
${
USER_NAME
}
>
/dev/null 2>&1
if
[
$?
==
'0'
]
;
then
echo
-e
"
${
SMB_PASSWD
}
\n
${
SMB_PASSWD
}
\n
"
| passwd
${
USER_NAME
}
>
/dev/null 2>&1
echo
-e
"
${
SMB_PASSWD
}
\n
${
SMB_PASSWD
}
"
|
(
smbpasswd
-a
-s
${
USER_NAME
}
)
>
/dev/null
else
exit
2
fi
;;
'del'
)
id
${
USER_NAME
}
>
/dev/null 2>&1
if
[
$?
!=
'0'
]
;
then
exit
2
fi
smbpasswd
-x
${
USER_NAME
}
>
/dev/null 2>&1
deluser
--remove-home
${
USER_NAME
}
>
/dev/null 2>&1
rmdir /home/
${
USER_NAME
}
>
/dev/null 2>&1
echo
"User
${
USER_NAME
}
DELETED at
`
date
`
"
>>
/root/users.log
;;
'stat'
)
stat
=(
$(
quota
-w
${
USER_NAME
}
2>/dev/null | tail
-1
| awk
'{ print $2" "$3" "$4 }'
)
)
USED_DISK
=
${
stat
[0]
}
SOFT_LIMIT
=
${
stat
[1]
}
HARD_LIMIT
=
${
stat
[3]
}
case
$3
in
'used'
)
echo
$USED_DISK
;;
'soft'
)
echo
$SOFT_LIMIT
;;
'hard'
)
echo
$HARD_LIMIT
;;
esac
;;
'status'
)
echo
$(
quota
-w
${
USER_NAME
}
2>/dev/null | tail
-1
| awk
'{ print $2" "$3" "$4 }'
)
;;
*
)
echo
"Usage: UserManager.sh COMMAND USER PASSWORD"
exit
1
;;
esac
one/models.py
View file @
156fc6bc
...
...
@@ -7,16 +7,18 @@ from django.db import transaction
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
school.models
import
Person
from
firewall.models
import
Host
,
Rule
,
Vlan
from
firewall.tasks
import
reload_firewall_lock
from
one.util
import
keygen
from
school.models
import
Person
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
):
if
created
:
d
=
UserCloudDetails
(
user
=
instance
)
...
...
@@ -24,13 +26,22 @@ def create_user_profile(sender, instance, created, **kwargs):
d
.
save
()
post_save
.
connect
(
create_user_profile
,
sender
=
User
)
"""
Cloud related details of a user
"""
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
.
TextField
()
user
=
models
.
ForeignKey
(
User
,
null
=
False
,
blank
=
False
,
unique
=
True
,
verbose_name
=
_
(
'user'
))
smb_password
=
models
.
CharField
(
max_length
=
20
,
verbose_name
=
_
(
'Samba password'
),
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
):
pri
,
pub
=
keygen
()
self
.
ssh_private_key
=
pri
...
...
@@ -41,9 +52,15 @@ class UserCloudDetails(models.Model):
self
.
ssh_key
=
SshKey
(
user
=
self
.
user
,
key
=
pub
)
self
.
ssh_key
.
save
()
"""
Generate new Samba password.
"""
def
reset_smb
(
self
):
self
.
smb_password
=
pwgen
()
"""
Generate key pair and Samba password if needed.
"""
def
clean
(
self
):
super
(
UserCloudDetails
,
self
)
.
clean
()
if
not
self
.
ssh_key
:
...
...
@@ -51,6 +68,9 @@ class UserCloudDetails(models.Model):
if
not
self
.
smb_password
or
len
(
self
.
smb_password
)
==
0
:
self
.
reset_smb
()
"""
Validate OpenSSH keys (length and type).
"""
class
OpenSshKeyValidator
(
object
):
valid_types
=
[
'ssh-rsa'
,
'ssh-dsa'
]
...
...
@@ -74,13 +94,16 @@ class OpenSshKeyValidator(object):
except
:
raise
ValidationError
(
_
(
'Invalid OpenSSH public key.'
))
"""
SSH public key (in OpenSSH format).
"""
class
SshKey
(
models
.
Model
):
user
=
models
.
ForeignKey
(
User
,
null
=
False
,
blank
=
False
)
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 '
'(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
]
...
...
@@ -89,10 +112,15 @@ class SshKey(models.Model):
return
u"
%
s (
%
s)"
%
(
keycomment
,
self
.
user
)
"""
Virtual disks automatically synchronized with OpenNebula.
"""
class
Disk
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
"""
Get and register virtual disks from OpenNebula.
"""
@classmethod
def
update
(
cls
):
import
subprocess
...
...
@@ -121,12 +149,17 @@ class Disk(models.Model):
class
Meta
:
ordering
=
[
'name'
]
"""
Virtual networks automatically synchronized with OpenNebula.
"""
class
Network
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
nat
=
models
.
BooleanField
()
public
=
models
.
BooleanField
()
nat
=
models
.
BooleanField
(
verbose_name
=
_
(
'NAT'
),
help_text
=
_
(
'If network address translation is done.'
))
public
=
models
.
BooleanField
(
verbose_name
=
_
(
'public'
),
help_text
=
_
(
'If internet gateway is available.'
))
"""
Get and register virtual networks from OpenNebula.
"""
@classmethod
def
update
(
cls
):
import
subprocess
...
...
@@ -154,56 +187,84 @@ class Network(models.Model):
class
Meta
:
ordering
=
[
'name'
]
"""
Instance types in OCCI configuration (manually synchronized).
"""
class
InstanceType
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
CPU
=
models
.
IntegerField
()
RAM
=
models
.
IntegerField
()
CPU
=
models
.
IntegerField
(
help_text
=
_
(
'CPU cores.'
)
)
RAM
=
models
.
IntegerField
(
help_text
=
_
(
'Mebibytes of memory.'
)
)
def
__unicode__
(
self
):
return
u"
%
s"
%
self
.
name
"""
Virtual machine template specifying OS, disk, type and network.
"""
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
.
ForeignKey
(
InstanceType
)
network
=
models
.
ForeignKey
(
Network
)
owner
=
models
.
ForeignKey
(
User
)
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
)
verbose_name
=
_
(
'name'
))
access_type
=
models
.
CharField
(
max_length
=
10
,
choices
=
[(
'rdp'
,
'rdp'
),
(
'nx'
,
'nx'
),
(
'ssh'
,
'ssh'
)],
verbose_name
=
_
(
'access method'
))
disk
=
models
.
ForeignKey
(
Disk
,
verbose_name
=
_
(
'disk'
))
instance_type
=
models
.
ForeignKey
(
InstanceType
,
verbose_name
=
_
(
'instance type'
))
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
):
return
self
.
name
class
Meta
:
verbose_name
=
_
(
'sablon'
)
verbose_name_plural
=
_
(
'sablonok'
)
verbose_name
=
_
(
'template'
)
verbose_name_plural
=
_
(
'templates'
)
"""
Virtual machine instance.
"""
class
Instance
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'név'
),
null
=
True
,
blank
=
True
)
ip
=
models
.
IPAddressField
(
blank
=
True
,
null
=
True
)
template
=
models
.
ForeignKey
(
Template
)
owner
=
models
.
ForeignKey
(
User
)
created_at
=
models
.
DateTimeField
(
auto_now_add
=
True
)
state
=
models
.
CharField
(
max_length
=
20
,
choices
=
[(
'DEPLOYABLE'
,
'DEPLOYABLE'
),
(
'PENDING'
,
'PENDING'
),
(
'DONE'
,
'DONE'
),
(
'ACTIVE'
,
'ACTIVE'
),(
'UNKNOWN'
,
'UNKNOWN'
),
(
'SUSPENDED'
,
'SUSPENDED'
),
(
'FAILED'
,
'FAILED'
)],
default
=
'DEPLOYABLE'
)
active_since
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
firewall_host
=
models
.
ForeignKey
(
Host
,
blank
=
True
,
null
=
True
)
pw
=
models
.
CharField
(
max_length
=
20
)
one_id
=
models
.
IntegerField
(
unique
=
True
,
blank
=
True
,
null
=
True
)
ip
=
models
.
IPAddressField
(
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'IP address'
))
template
=
models
.
ForeignKey
(
Template
,
verbose_name
=
_
(
'template'
))
owner
=
models
.
ForeignKey
(
User
,
verbose_name
=
_
(
'owner'
))
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'
)
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
):
proto
=
self
.
template
.
access_type
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
]
"""
Get public hostname.
"""
def
get_connect_host
(
self
):
if
self
.
template
.
network
.
nat
:
return
'cloud'
else
:
return
self
.
ip
"""
Get access parameters in URI format.
"""
def
get_connect_uri
(
self
):
try
:
proto
=
self
.
template
.
access_type
...
...
@@ -217,6 +278,10 @@ class Instance(models.Model):
def
__unicode__
(
self
):
return
self
.
name
"""
Get and update VM state from OpenNebula.
"""
def
update_state
(
self
):
import
subprocess
...
...
@@ -241,11 +306,14 @@ class Instance(models.Model):
self
.
save
()
return
x
"""
Get age of VM in seconds.
"""
def
get_age
(
self
):
from
datetime
import
datetime
age
=
0
try
:
age
=
(
datetime
.
now
()
.
replace
(
tzinfo
=
None
)
age
=
(
datetime
.
now
()
.
replace
(
tzinfo
=
None
)
-
self
.
active_since
.
replace
(
tzinfo
=
None
))
.
seconds
except
:
pass
...
...
@@ -253,8 +321,11 @@ class Instance(models.Model):
@models.permalink
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
def
submit
(
cls
,
template
,
owner
):
from
django.template.defaultfilters
import
escape
...
...
@@ -296,10 +367,9 @@ 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
...
...
@@ -332,6 +402,9 @@ class Instance(models.Model):
reload_firewall_lock
()
return
inst
"""
Delete host in OpenNebula.
"""
def
delete
(
self
):
proc
=
subprocess
.
Popen
([
"/opt/occi.sh"
,
"compute"
,
"delete"
,
"
%
d"
%
self
.
one_id
],
stdout
=
subprocess
.
PIPE
)
...
...
@@ -343,8 +416,3 @@ class Instance(models.Model):
class
Meta
:
verbose_name
=
_
(
'instance'
)
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