Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gelencsér Szabolcs
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
f2577fb3
authored
Apr 19, 2013
by
Őry Máté
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
one: enforce pep8 and others
parent
1b2fb7a6
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
408 additions
and
251 deletions
+408
-251
one/admin.py
+39
-18
one/models.py
+145
-95
one/tasks.py
+6
-1
one/util.py
+2
-1
one/views.py
+216
-136
No files found.
one/admin.py
View file @
f2577fb3
from
django.contrib
import
messages
from
django.core.exceptions
import
ValidationError
from
django
import
contrib
from
django.utils.translation
import
ugettext_lazy
as
_
from
one
import
models
import
string
import
school.models
def
owner_person
(
obj
):
p
=
obj
.
owner
return
"
%
s
%
s (
%
s)"
%
(
p
.
last_name
,
p
.
first_name
,
p
.
username
)
owner_person
.
short_description
=
_
(
'owner'
)
class
PersonInline
(
contrib
.
admin
.
StackedInline
):
model
=
models
.
Person
model
=
school
.
models
.
Person
max_num
=
1
can_delete
=
False
class
SshKeyInline
(
contrib
.
admin
.
TabularInline
):
model
=
models
.
SshKey
extra
=
2
class
DetailsInline
(
contrib
.
admin
.
StackedInline
):
model
=
models
.
UserCloudDetails
max_num
=
1
can_delete
=
False
class
MyUserAdmin
(
contrib
.
auth
.
admin
.
UserAdmin
):
list_display
=
(
'username'
,
'full_name'
,
'email'
,
'date_joined'
,
'instance_count'
,
'course_groups'
)
list_filter
=
(
'is_superuser'
,
'is_active'
,
'groups'
,
'person__course_groups'
,
)
class
MyUserAdmin
(
contrib
.
auth
.
admin
.
UserAdmin
):
list_display
=
(
'username'
,
'full_name'
,
'email'
,
'date_joined'
,
'instance_count'
,
'course_groups'
)
list_filter
=
(
'is_superuser'
,
'is_active'
,
'groups'
,
'person__course_groups'
,
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
MyUserAdmin
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
add
=
[
PersonInline
,
SshKeyInline
,
DetailsInline
,
]
try
:
inlines
=
inlines
+
(
PersonInline
,
SshKeyInline
,
DetailsInline
)
inlines
=
self
.
inlines
except
NameError
:
inlines
=
(
PersonInline
,
SshKeyInline
,
DetailsInline
)
inlines
=
list
()
self
.
inlines
=
inlines
+
add
def
instance_count
(
self
,
obj
):
return
_
(
"
%(sum)
d (
%(active)
d active)"
)
%
{
'sum'
:
obj
.
instance_set
.
count
(),
'active'
:
obj
.
instance_set
.
filter
(
state
=
'ACTIVE'
)
.
count
(),
}
return
_
(
"
%(sum)
d (
%(active)
d active)"
)
%
{
'sum'
:
obj
.
instance_set
.
count
(),
'active'
:
obj
.
instance_set
.
filter
(
state
=
'ACTIVE'
)
.
count
(),
}
def
course_groups
(
self
,
obj
):
try
:
...
...
@@ -48,31 +61,35 @@ class MyUserAdmin(contrib.auth.admin.UserAdmin):
ordering
=
[
"-date_joined"
]
contrib
.
admin
.
site
.
unregister
(
contrib
.
auth
.
models
.
User
)
contrib
.
admin
.
site
.
register
(
contrib
.
auth
.
models
.
User
,
MyUserAdmin
)
def
update_state
(
modeladmin
,
request
,
queryset
):
for
i
in
queryset
.
all
():
i
.
update_state
()
update_state
.
short_description
=
_
(
'Update status'
)
def
submit_vm
(
modeladmin
,
request
,
queryset
):
for
i
in
queryset
.
all
():
i
.
submit
(
request
.
user
)
i
.
update_state
()
submit_vm
.
short_description
=
_
(
'Submit VM'
)
def
delete_vm
(
modeladmin
,
request
,
queryset
):
for
i
in
queryset
.
exclude
(
state
=
'DONE'
)
.
all
():
i
.
one_delete
()
delete_vm
.
short_description
=
_
(
'Delete VM'
)
def
suspend_vm
(
modeladmin
,
request
,
queryset
):
for
i
in
queryset
.
filter
(
state
=
'ACTIVE'
)
.
all
():
i
.
stop
()
suspend_vm
.
short_description
=
_
(
'Suspend VM'
)
def
resume_vm
(
modeladmin
,
request
,
queryset
):
for
i
in
queryset
.
filter
(
state__in
=
(
'STOPPED'
,
'SUSPENDED'
))
.
all
():
i
.
resume
()
...
...
@@ -80,21 +97,24 @@ resume_vm.short_description = _('Resume VM')
class
TemplateAdmin
(
contrib
.
admin
.
ModelAdmin
):
model
=
models
.
Template
model
=
models
.
Template
list_display
=
(
'name'
,
'state'
,
owner_person
,
'system'
,
'public'
)
list_filter
=
(
'owner'
,
'public'
)
class
InstanceAdmin
(
contrib
.
admin
.
ModelAdmin
):
model
=
models
.
Instance
model
=
models
.
Instance
actions
=
[
update_state
,
submit_vm
,
delete_vm
,
suspend_vm
,
resume_vm
]
list_display
=
(
'id'
,
'name'
,
owner_person
,
'state'
)
readonly_fields
=
(
'ip'
,
'active_since'
,
'pw'
,
'template'
)
list_filter
=
(
'owner'
,
'template'
,
'state'
)
def
queryset
(
self
,
request
):
return
super
(
InstanceAdmin
,
self
)
.
queryset
(
request
)
class
DiskAdmin
(
contrib
.
admin
.
ModelAdmin
):
model
=
models
.
Disk
model
=
models
.
Disk
list_display
=
(
'name'
,
'used_by'
)
def
used_by
(
self
,
obj
):
...
...
@@ -104,12 +124,14 @@ class DiskAdmin(contrib.admin.ModelAdmin):
return
None
used_by
.
verbose_name
=
_
(
'used by'
)
class
NetworkAdmin
(
contrib
.
admin
.
ModelAdmin
):
model
=
models
.
Network
model
=
models
.
Network
list_display
=
(
'name'
,
'nat'
,
'public'
,
'get_vlan'
)
class
ShareAdmin
(
contrib
.
admin
.
ModelAdmin
):
model
=
models
.
Network
model
=
models
.
Network
list_filter
=
(
'group'
,
'template'
,
)
list_display
=
(
'name'
,
owner_person
,
'template'
,
'group'
,
)
...
...
@@ -119,4 +141,3 @@ contrib.admin.site.register(models.Network, NetworkAdmin)
contrib
.
admin
.
site
.
register
(
models
.
Disk
,
DiskAdmin
)
contrib
.
admin
.
site
.
register
(
models
.
Share
,
ShareAdmin
)
contrib
.
admin
.
site
.
register
(
models
.
InstanceType
)
one/models.py
View file @
f2577fb3
...
...
@@ -2,20 +2,21 @@
from
datetime
import
datetime
from
datetime
import
timedelta
as
td
import
subprocess
,
tempfile
,
os
,
stat
,
re
,
base64
,
struct
,
logging
import
base64
import
struct
import
logging
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
django.db.models.signals
import
post_delete
,
pre_delete
from
django.db.models.signals
import
post_save
from
django
import
forms
from
django.db.models.signals
import
post_save
,
pre_delete
from
django.template.defaultfilters
import
escape
from
django.utils.translation
import
ugettext_lazy
as
_
from
firewall.models
import
Host
,
Rule
,
Vlan
,
Record
from
school.models
import
Person
,
Group
from
firewall.models
import
Host
,
Vlan
from
school.models
import
Group
from
store.api
import
StoreApi
from
.util
import
keygen
import
django.conf
...
...
@@ -25,6 +26,7 @@ CLOUD_URL = django.conf.settings.CLOUD_URL
logger
=
logging
.
getLogger
(
__name__
)
pwgen
=
User
.
objects
.
make_random_password
def
create_user_profile
(
sender
,
instance
,
created
,
**
kwargs
):
"""User creation hook: create cloud details object"""
if
created
:
...
...
@@ -34,27 +36,33 @@ def create_user_profile(sender, instance, created, **kwargs):
post_save
.
connect
(
create_user_profile
,
sender
=
User
)
class
UserCloudDetails
(
models
.
Model
):
"""Cloud related details of a user."""
user
=
models
.
OneToOneField
(
User
,
verbose_name
=
_
(
'user'
),
related_name
=
'cloud_details'
)
smb_password
=
models
.
CharField
(
max_length
=
20
,
verbose_name
=
_
(
'Samba password'
),
help_text
=
_
(
'Generated password for accessing store from '
help_text
=
_
(
'Generated password for '
'accessing store from '
'Windows.'
))
ssh_key
=
models
.
ForeignKey
(
'SshKey'
,
verbose_name
=
_
(
'SSH key (public)'
),
null
=
True
,
blank
=
True
,
related_name
=
'userclouddetails_set'
,
help_text
=
_
(
'Generated SSH public key for accessing store from '
'Linux.'
))
ssh_private_key
=
models
.
TextField
(
verbose_name
=
_
(
'SSH key (private)'
),
blank
=
True
,
help_text
=
_
(
'Generated SSH private key for '
null
=
True
,
blank
=
True
,
related_name
=
'userclouddetails_set'
,
help_text
=
_
(
'Generated SSH public key for '
'accessing store from Linux.'
))
ssh_private_key
=
models
.
TextField
(
verbose_name
=
_
(
'SSH key (private)'
),
blank
=
True
,
help_text
=
_
(
'Generated SSH private key '
'for accessing store from '
'Linux.'
))
share_quota
=
models
.
IntegerField
(
verbose_name
=
_
(
'share quota'
),
default
=
0
)
instance_quota
=
models
.
IntegerField
(
verbose_name
=
_
(
'instance quota'
),
default
=
20
)
disk_quota
=
models
.
IntegerField
(
verbose_name
=
_
(
'disk quota'
),
default
=
2048
,
help_text
=
_
(
'Disk quota in mebibytes.'
))
default
=
2048
,
help_text
=
_
(
'Disk quota in mebibytes.'
))
def
reset_keys
(
self
):
"""Delete old SSH key pair and generate new one."""
...
...
@@ -79,16 +87,20 @@ class UserCloudDetails(models.Model):
if
i
.
state
in
(
'ACTIVE'
,
'PENDING'
,
):
c
=
c
+
i
.
template
.
instance_type
.
credit
return
c
def
get_instance_pc
(
self
):
return
100
*
self
.
get_weighted_instance_count
()
/
self
.
instance_quota
def
get_weighted_share_count
(
self
):
c
=
0
for
i
in
Share
.
objects
.
filter
(
owner
=
self
.
user
)
.
all
():
c
=
c
+
i
.
template
.
instance_type
.
credit
*
i
.
instance_limit
return
c
def
get_share_pc
(
self
):
return
100
*
self
.
get_weighted_share_count
()
/
self
.
share_quota
def
set_quota
(
sender
,
instance
,
created
,
**
kwargs
):
if
not
StoreApi
.
userexist
(
instance
.
user
.
username
):
try
:
...
...
@@ -108,6 +120,7 @@ def set_quota(sender, instance, created, **kwargs):
instance
.
disk_quota
*
1024
)
post_save
.
connect
(
set_quota
,
sender
=
UserCloudDetails
)
def
reset_keys
(
sender
,
instance
,
created
,
**
kwargs
):
if
created
:
instance
.
reset_smb
()
...
...
@@ -115,6 +128,7 @@ def reset_keys(sender, instance, created, **kwargs):
post_save
.
connect
(
reset_keys
,
sender
=
UserCloudDetails
)
class
OpenSshKeyValidator
(
object
):
"""Validate OpenSSH keys (length and type)."""
valid_types
=
[
'ssh-rsa'
,
'ssh-dsa'
]
...
...
@@ -133,21 +147,23 @@ class OpenSshKeyValidator(object):
data
=
base64
.
decodestring
(
key_string
)
int_len
=
4
str_len
=
struct
.
unpack
(
'>I'
,
data
[:
int_len
])[
0
]
if
not
data
[
int_len
:
int_len
+
str_len
]
==
type
:
if
not
data
[
int_len
:
(
int_len
+
str_len
)
]
==
type
:
raise
except
ValidationError
:
raise
except
:
raise
ValidationError
(
_
(
'Invalid OpenSSH public key.'
))
class
SshKey
(
models
.
Model
):
"""SSH public key (in OpenSSH format)."""
user
=
models
.
ForeignKey
(
User
,
related_name
=
'sshkey_set'
)
key
=
models
.
TextField
(
verbose_name
=
_
(
'SSH key'
),
help_text
=
_
(
'<a href="/info/ssh/">SSH public key in OpenSSH '
'format</a> used for shell and store login '
'(2048+ bit RSA preferred). Example: '
'<code>ssh-rsa AAAAB...QtQ== john</code>.'
),
help_text
=
_
(
'<a href="/info/ssh/">SSH public key '
'in OpenSSH format</a> used for shell '
'and store login (2048+ bit RSA '
'preferred). Example: <code>ssh-rsa '
'AAAAB...QtQ== john</code>.'
),
validators
=
[
OpenSshKeyValidator
()])
def
__unicode__
(
self
):
...
...
@@ -164,7 +180,7 @@ TYPES = {"LAB": {"verbose_name": _('lab'), "id": "LAB",
"suspend"
:
td
(
hours
=
5
),
"delete"
:
td
(
days
=
15
),
"help_text"
:
_
(
'For lab or homework with short lifetime.'
)},
"PROJECT"
:
{
"verbose_name"
:
_
(
'project'
),
"id"
:
"PROJECT"
,
"suspend"
:
td
(
weeks
=
5
),
"delete"
:
td
(
days
=
366
/
2
),
"suspend"
:
td
(
weeks
=
5
),
"delete"
:
td
(
days
=
366
/
2
),
"help_text"
:
_
(
'For project work.'
)},
"SERVER"
:
{
"verbose_name"
:
_
(
'server'
),
"id"
:
"SERVER"
,
"suspend"
:
td
(
days
=
365
),
"delete"
:
None
,
...
...
@@ -174,6 +190,7 @@ 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
()])
class
Share
(
models
.
Model
):
name
=
models
.
CharField
(
max_length
=
100
,
verbose_name
=
_
(
'name'
))
description
=
models
.
TextField
(
verbose_name
=
_
(
'description'
))
...
...
@@ -183,12 +200,15 @@ class Share(models.Model):
verbose_name
=
_
(
'created at'
))
type
=
models
.
CharField
(
choices
=
TYPES_C
,
max_length
=
10
)
instance_limit
=
models
.
IntegerField
(
verbose_name
=
_
(
'instance limit'
),
help_text
=
_
(
'Maximal count of instances launchable for this '
'share.'
))
help_text
=
_
(
'Maximal count of '
'instances launchable '
'for this share.'
))
per_user_limit
=
models
.
IntegerField
(
verbose_name
=
_
(
'per user limit'
),
help_text
=
_
(
'Maximal count of instances launchable by a single '
'user.'
))
owner
=
models
.
ForeignKey
(
User
,
null
=
True
,
blank
=
True
,
related_name
=
'share_set'
)
help_text
=
_
(
'Maximal count of '
'instances launchable by '
'a single user.'
))
owner
=
models
.
ForeignKey
(
User
,
null
=
True
,
blank
=
True
,
related_name
=
'share_set'
)
class
Meta
:
ordering
=
[
'group'
,
'template'
,
'owner'
,
]
...
...
@@ -233,6 +253,7 @@ class Share(models.Model):
def
get_used_quota
(
self
):
return
self
.
template
.
get_credits_per_instance
()
*
self
.
instance_limit
class
Disk
(
models
.
Model
):
"""Virtual disks automatically synchronized with OpenNebula."""
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
...
...
@@ -270,21 +291,23 @@ class Disk(models.Model):
if
delete
:
Disk
.
objects
.
exclude
(
id__in
=
l
)
.
delete
()
class
Network
(
models
.
Model
):
"""Virtual networks automatically synchronized with OpenNebula."""
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
nat
=
models
.
BooleanField
(
verbose_name
=
_
(
'NAT'
),
help_text
=
_
(
'If network address translation is done.'
))
help_text
=
_
(
'If network address translation is '
'done.'
))
public
=
models
.
BooleanField
(
verbose_name
=
_
(
'public'
),
help_text
=
_
(
'If internet gateway is available.'
))
help_text
=
_
(
'If internet gateway is '
'available.'
))
class
Meta
:
ordering
=
[
'name'
]
verbose_name
=
_
(
'network'
)
verbose_name_plural
=
_
(
'networks'
)
def
__unicode__
(
self
):
return
self
.
name
...
...
@@ -310,6 +333,7 @@ class Network(models.Model):
pass
l
.
append
(
id
)
Network
.
objects
.
exclude
(
id__in
=
l
)
.
delete
()
def
get_vlan
(
self
):
return
Vlan
.
objects
.
get
(
vid
=
self
.
id
)
...
...
@@ -333,15 +357,20 @@ class InstanceType(models.Model):
TEMPLATE_STATES
=
((
'NEW'
,
_
(
'new'
)),
(
'SAVING'
,
_
(
'saving'
)),
(
'READY'
,
_
(
'ready'
)),
)
class
Template
(
models
.
Model
):
"""Virtual machine template specifying OS, disk, type and network."""
name
=
models
.
CharField
(
max_length
=
100
,
unique
=
True
,
verbose_name
=
_
(
'name'
))
access_type
=
models
.
CharField
(
max_length
=
10
,
choices
=
[(
'rdp'
,
'rdp'
),
(
'nx'
,
'nx'
),
(
'ssh'
,
'ssh'
)],
choices
=
[(
'rdp'
,
'rdp'
),
(
'nx'
,
'nx'
),
(
'ssh'
,
'ssh'
)],
verbose_name
=
_
(
'access method'
))
disk
=
models
.
ForeignKey
(
Disk
,
verbose_name
=
_
(
'disk'
),
related_name
=
'template_set'
)
instance_type
=
models
.
ForeignKey
(
InstanceType
,
related_name
=
'template_set'
,
disk
=
models
.
ForeignKey
(
Disk
,
verbose_name
=
_
(
'disk'
),
related_name
=
'template_set'
)
instance_type
=
models
.
ForeignKey
(
InstanceType
,
related_name
=
'template_set'
,
verbose_name
=
_
(
'instance type'
))
network
=
models
.
ForeignKey
(
Network
,
verbose_name
=
_
(
'network'
),
related_name
=
'template_set'
)
...
...
@@ -352,10 +381,12 @@ class Template(models.Model):
state
=
models
.
CharField
(
max_length
=
10
,
choices
=
TEMPLATE_STATES
,
default
=
'NEW'
)
public
=
models
.
BooleanField
(
verbose_name
=
_
(
'public'
),
default
=
False
,
help_text
=
_
(
'If other users can derive templates of this one.'
))
help_text
=
_
(
'If other users can derive '
'templates of this one.'
))
description
=
models
.
TextField
(
verbose_name
=
_
(
'description'
),
blank
=
True
)
system
=
models
.
TextField
(
verbose_name
=
_
(
'operating system'
),
blank
=
True
,
help_text
=
(
_
(
'Name of operating system in format like "
%
s".'
)
%
help_text
=
(
_
(
'Name of operating system in '
'format like "
%
s".'
)
%
"Ubuntu 12.04 LTS Desktop amd64"
))
class
Meta
:
...
...
@@ -363,7 +394,6 @@ class Template(models.Model):
verbose_name_plural
=
_
(
'templates'
)
ordering
=
[
'name'
,
]
def
__unicode__
(
self
):
return
self
.
name
...
...
@@ -396,20 +426,19 @@ class Template(models.Model):
else
:
return
shares
def
get_share_quota_usage_for
(
self
,
user
=
None
):
shares
=
self
.
get_shares_for
(
user
)
usage
=
0
for
share
in
shares
:
usage
+=
share
.
instance_limit
*
self
.
get_credits_per_instance
()
return
usage
def
get_share_quota_usage_for
(
self
,
user
=
None
,
type
=
None
):
if
type
is
None
:
c
=
self
.
get_credits_per_instance
()
else
:
c
=
type
.
credit
def
get_share_quota_usage_for_user_with_type
(
self
,
type
,
user
=
None
):
shares
=
self
.
get_shares_for
(
user
)
usage
=
0
for
share
in
shares
:
usage
+=
share
.
instance_limit
*
type
.
credit
usage
+=
share
.
instance_limit
*
c
return
usage
class
Instance
(
models
.
Model
):
"""Virtual machine instance."""
name
=
models
.
CharField
(
max_length
=
100
,
...
...
@@ -433,19 +462,24 @@ class Instance(models.Model):
default
=
'DEPLOYABLE'
)
active_since
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'active since'
),
help_text
=
_
(
'Time stamp of successful boot report.'
))
help_text
=
_
(
'Time stamp of successful '
'boot report.'
))
firewall_host
=
models
.
ForeignKey
(
Host
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'host in firewall'
),
related_name
=
'instance_set'
)
verbose_name
=
_
(
'host in firewall'
),
related_name
=
'instance_set'
)
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'
))
share
=
models
.
ForeignKey
(
'Share'
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'share'
),
related_name
=
'instance_set'
)
verbose_name
=
_
(
'share'
),
related_name
=
'instance_set'
)
time_of_suspend
=
models
.
DateTimeField
(
default
=
None
,
verbose_name
=
_
(
'time of suspend'
),
null
=
True
,
blank
=
True
)
verbose_name
=
_
(
'time of suspend'
),
null
=
True
,
blank
=
True
)
time_of_delete
=
models
.
DateTimeField
(
default
=
None
,
verbose_name
=
_
(
'time of delete'
),
null
=
True
,
blank
=
True
)
verbose_name
=
_
(
'time of delete'
),
null
=
True
,
blank
=
True
)
waiting
=
models
.
BooleanField
(
default
=
False
)
class
Meta
:
...
...
@@ -458,13 +492,15 @@ class Instance(models.Model):
@models.permalink
def
get_absolute_url
(
self
):
return
(
'one.views.vm_show'
,
None
,
{
'iid'
:
self
.
id
})
return
(
'one.views.vm_show'
,
None
,
{
'iid'
:
self
.
id
})
def
get_port
(
self
,
use_ipv6
=
False
):
"""Get public port number for default access method."""
proto
=
self
.
template
.
access_type
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
])
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
]
...
...
@@ -510,21 +546,10 @@ class Instance(models.Model):
pass
return
age
@classmethod
def
submit
(
cls
,
template
,
owner
,
extra
=
""
,
share
=
None
):
"""Submit a new instance to OpenNebula."""
from
django.template.defaultfilters
import
escape
inst
=
Instance
(
pw
=
pwgen
(),
template
=
template
,
owner
=
owner
,
share
=
share
,
state
=
'PENDING'
)
inst
.
save
()
hostname
=
u"
%
d"
%
(
inst
.
id
,
)
token
=
signing
.
dumps
(
inst
.
id
,
salt
=
'activate'
)
try
:
details
=
owner
.
cloud_details
except
:
details
=
UserCloudDetails
(
user
=
owner
)
details
.
save
()
@staticmethod
def
_create_context
(
pw
,
hostname
,
smb_password
,
ssh_private_key
,
owner
,
token
,
extra
):
"""Return XML context configuration with given parameters."""
ctx
=
u'''
<SOURCE>web</SOURCE>
<HOSTNAME>
%(hostname)
s</HOSTNAME>
...
...
@@ -536,14 +561,64 @@ class Instance(models.Model):
<SERVER>store.cloud.ik.bme.hu</SERVER>
%(extra)
s
'''
%
{
"pw"
:
escape
(
inst
.
pw
),
"pw"
:
escape
(
pw
),
"hostname"
:
escape
(
hostname
),
"smbpw"
:
escape
(
details
.
smb_password
),
"sshkey"
:
escape
(
details
.
ssh_private_key
),
"neptun"
:
escape
(
owner
.
username
),
"booturl"
:
"
%
sb/
%
s/"
%
(
CLOUD_URL
,
token
),
"smbpw"
:
escape
(
smb_password
),
"sshkey"
:
escape
(
ssh_private_key
),
"neptun"
:
escape
(
owner
),
"booturl"
:
"
%
sb/
%
s/"
%
(
CLOUD_URL
,
token
),
"extra"
:
extra
}
return
ctx
def
_create_host
(
self
,
hostname
,
occi_result
):
"""Create firewall host for recently submitted Instance."""
host
=
Host
(
vlan
=
Vlan
.
objects
.
get
(
name
=
self
.
template
.
network
.
name
),
owner
=
self
.
owner
,
hostname
=
hostname
,
mac
=
occi_result
[
'interfaces'
][
0
][
'mac'
],
ipv4
=
occi_result
[
'interfaces'
][
0
][
'ip'
],
ipv6
=
'auto'
,
)
if
self
.
template
.
network
.
nat
:
host
.
pub_ipv4
=
Vlan
.
objects
.
get
(
name
=
self
.
template
.
network
.
name
)
.
snat_ip
host
.
shared_ip
=
True
try
:
host
.
save
()
except
:
for
i
in
Host
.
objects
.
filter
(
ipv4
=
host
.
ipv4
)
.
all
():
logger
.
warning
(
'Delete orphan fw host (
%
s) of
%
s.'
%
(
i
,
self
))
i
.
delete
()
for
i
in
Host
.
objects
.
filter
(
mac
=
host
.
mac
)
.
all
():
logger
.
warning
(
'Delete orphan fw host (
%
s) of
%
s.'
%
(
i
,
self
))
i
.
delete
()
host
.
save
()
host
.
enable_net
()
port
=
{
"rdp"
:
3389
,
"nx"
:
22
,
"ssh"
:
22
}[
self
.
template
.
access_type
]
host
.
add_port
(
"tcp"
,
self
.
get_port
(),
port
)
self
.
firewall_host
=
host
self
.
save
()
@classmethod
def
submit
(
cls
,
template
,
owner
,
extra
=
""
,
share
=
None
):
"""Submit a new instance to OpenNebula."""
inst
=
Instance
(
pw
=
pwgen
(),
template
=
template
,
owner
=
owner
,
share
=
share
,
state
=
'PENDING'
,
waiting
=
True
)
inst
.
save
()
hostname
=
u"
%
d"
%
(
inst
.
id
,
)
token
=
signing
.
dumps
(
inst
.
id
,
salt
=
'activate'
)
try
:
details
=
owner
.
cloud_details
except
:
details
=
UserCloudDetails
(
user
=
owner
)
details
.
save
()
ctx
=
cls
.
_create_context
(
inst
.
pw
,
hostname
,
details
.
smb_password
,
details
.
ssh_private_key
,
owner
.
username
,
token
,
extra
)
try
:
from
.tasks
import
CreateInstanceTask
x
=
CreateInstanceTask
.
delay
(
...
...
@@ -566,33 +641,7 @@ class Instance(models.Model):
'id'
:
inst
.
one_id
})
inst
.
save
()
host
=
Host
(
vlan
=
Vlan
.
objects
.
get
(
name
=
template
.
network
.
name
),
owner
=
owner
,
hostname
=
hostname
,
mac
=
res
[
'interfaces'
][
0
][
'mac'
],
ipv4
=
res
[
'interfaces'
][
0
][
'ip'
],
ipv6
=
'auto'
,
)
if
inst
.
template
.
network
.
nat
:
host
.
pub_ipv4
=
Vlan
.
objects
.
get
(
name
=
template
.
network
.
name
)
.
snat_ip
host
.
shared_ip
=
True
try
:
host
.
save
()
except
:
for
i
in
Host
.
objects
.
filter
(
ipv4
=
host
.
ipv4
)
.
all
():
logger
.
warning
(
'Delete orphan fw host (
%
s) of
%
s.'
%
(
i
,
inst
))
i
.
delete
()
for
i
in
Host
.
objects
.
filter
(
mac
=
host
.
mac
)
.
all
():
logger
.
warning
(
'Delete orphan fw host (
%
s) of
%
s.'
%
(
i
,
inst
))
i
.
delete
()
host
.
save
()
host
.
enable_net
()
host
.
add_port
(
"tcp"
,
inst
.
get_port
(),
{
"rdp"
:
3389
,
"nx"
:
22
,
"ssh"
:
22
}[
inst
.
template
.
access_type
])
inst
.
firewall_host
=
host
inst
.
save
()
inst
.
_create_host
(
hostname
)
return
inst
def
one_delete
(
self
):
...
...
@@ -678,6 +727,7 @@ class Instance(models.Model):
self
.
firewall_host_delete
()
return
True
def
delete_instance_pre
(
sender
,
instance
,
using
,
**
kwargs
):
if
instance
.
state
!=
'DONE'
:
instance
.
one_delete
()
...
...
one/tasks.py
View file @
f2577fb3
...
...
@@ -37,27 +37,32 @@ class UpdateInstanceStateTask(Task):
# ezek csak azert vannak felveve, hogy szepen meg lehessen hivni oket
# ezeket a fejgepen futo celery futtatja
class
CreateInstanceTask
(
Task
):
def
run
(
self
,
name
,
instance_type
,
disk_id
,
network_id
,
ctx
):
pass
class
DeleteInstanceTask
(
Task
):
def
run
(
self
,
one_id
):
pass
class
ChangeInstanceStateTask
(
Task
):
def
run
(
self
,
one_id
,
new_state
):
pass
class
SaveAsTask
(
Task
):
def
run
(
self
,
one_id
,
new_img
):
pass
class
UpdateDiskTask
(
Task
):
def
run
(
self
):
pass
class
UpdateNetworkTask
(
Task
):
def
run
(
self
):
pass
one/util.py
View file @
f2577fb3
def
keygen
(
length
=
1024
):
import
os
,
base64
import
os
import
base64
from
datetime
import
date
from
Crypto.PublicKey
import
RSA
...
...
one/views.py
View file @
f2577fb3
...
...
@@ -3,26 +3,21 @@ from datetime import datetime
from
django.conf
import
settings
from
datetime
import
timedelta
as
td
from
django.contrib.auth.decorators
import
login_required
from
django.contrib.auth.models
import
User
from
django.contrib
import
messages
from
django.core.exceptions
import
PermissionDenied
from
django.core
import
signing
,
urlresolvers
from
django.core.mail
import
mail_managers
,
send_mail
from
django.db
import
transaction
from
django.forms
import
ModelForm
,
Textarea
from
django.http
import
Http404
from
django.shortcuts
import
render
,
render_to_response
,
get_object_or_404
,
redirect
from
django.core.exceptions
import
PermissionDenied
,
ValidationError
from
django.core
import
signing
from
django.shortcuts
import
render_to_response
,
get_object_or_404
,
redirect
from
django.template
import
RequestContext
from
django.
template.loader
import
render_to_string
from
django.
utils.decorators
import
method_decorator
from
django.
utils.translation
import
get_language
as
lang
from
django.
utils.translation
import
ugettext_lazy
as
_
from
django.views.
decorators.http
import
*
from
django.views.generic
import
*
from
firewall.tasks
import
*
from
one.models
import
*
from
school.models
import
*
import
django.contrib.auth
as
auth
from
django.
utils.translation
import
ugettext_lazy
as
_
,
ugettext
from
django.
views.decorators.http
import
require_GET
,
require_POST
from
django.
views.decorators.http
import
require_safe
from
django.
http
import
HttpResponse
from
django.views.
generic
import
View
# from firewall.tasks
import *
from
one.models
import
Instance
,
UserCloudDetails
,
Template
,
Share
from
one.models
import
InstanceType
,
TYPES_L
,
TYPES
,
SshKey
from
school.models
import
Semester
,
Group
from
store.api
import
StoreApi
import
json
import
logging
import
subprocess
...
...
@@ -30,14 +25,18 @@ import subprocess
store_settings
=
settings
.
STORE_SETTINGS
logger
=
logging
.
getLogger
(
__name__
)
def
_list_instances
(
request
):
instances
=
Instance
.
objects
.
exclude
(
state
=
'DONE'
)
.
filter
(
owner
=
request
.
user
)
instances
=
Instance
.
objects
.
exclude
(
state
=
'DONE'
)
.
filter
(
owner
=
request
.
user
)
instances
=
instances
.
exclude
(
state
=
'DONE'
)
return
instances
def
info
(
request
):
return
render_to_response
(
"info.html"
,
RequestContext
(
request
,
{}))
def
index
(
request
):
if
request
.
user
.
is_authenticated
():
return
redirect
(
home
)
...
...
@@ -51,7 +50,8 @@ def home(request):
instances
=
_list_instances
(
request
)
shares
=
[
s
for
s
in
request
.
user
.
person_set
.
all
()[
0
]
.
get_shares
()]
for
i
,
s
in
enumerate
(
shares
):
s
.
running_shared
=
s
.
instance_set
.
all
()
.
exclude
(
state
=
"DONE"
)
.
filter
(
owner
=
request
.
user
)
.
count
()
s
.
running_shared
=
s
.
instance_set
.
all
()
.
exclude
(
state
=
"DONE"
)
.
filter
(
owner
=
request
.
user
)
.
count
()
shares
[
i
]
=
s
try
:
details
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
...
...
@@ -74,6 +74,7 @@ def home(request):
'storeserv'
:
store_settings
[
'store_public'
],
}))
@login_required
def
ajax_template_delete
(
request
):
try
:
...
...
@@ -82,16 +83,21 @@ def ajax_template_delete(request):
return
HttpResponse
(
unicode
(
_
(
"Invalid template ID."
)),
status
=
404
)
template
=
get_object_or_404
(
Template
,
id
=
template_id
)
if
template
.
running_instances
()
>
0
:
return
HttpResponse
(
unicode
(
_
(
"There are running instances of this template."
)),
status
=
404
)
return
HttpResponse
(
unicode
(
_
(
'There are running instances of '
'this template.'
)),
status
=
404
)
elif
template
.
share_set
.
exists
():
return
HttpResponse
(
unicode
(
_
(
"Template is still shared."
)),
status
=
404
)
return
HttpResponse
(
unicode
(
_
(
"Template is still shared."
)),
status
=
404
)
elif
template
.
owner
!=
request
.
user
:
return
HttpResponse
(
unicode
(
_
(
"You don't have permission to delete this template."
)),
status
=
404
)
return
HttpResponse
(
unicode
(
_
(
"You don't have permission to delete "
"this template."
)),
status
=
404
)
else
:
if
template
.
safe_delete
():
return
HttpResponse
(
unicode
(
_
(
"Template successfully deleted."
)))
else
:
return
HttpResponse
(
unicode
(
_
(
"Unexpected error happened."
)),
status
=
404
)
return
HttpResponse
(
unicode
(
_
(
"Unexpected error happened."
)),
status
=
404
)
def
ajax_template_name_unique
(
request
):
name
=
request
.
GET
[
'name'
]
...
...
@@ -100,6 +106,7 @@ def ajax_template_name_unique(request):
s
=
"False"
return
HttpResponse
(
s
)
@login_required
def
vm_credentials
(
request
,
iid
):
try
:
...
...
@@ -110,54 +117,70 @@ def vm_credentials(request, iid):
vm
.
is_ipv6
=
is_ipv6
vm
.
port_v4
=
vm
.
get_port
(
use_ipv6
=
False
)
vm
.
port_v6
=
vm
.
get_port
(
use_ipv6
=
True
)
return
render_to_response
(
'vm-credentials.html'
,
RequestContext
(
request
,
{
'i'
:
vm
}))
return
render_to_response
(
'vm-credentials.html'
,
RequestContext
(
request
,
{
'i'
:
vm
}))
except
:
return
HttpResponse
(
_
(
"Could not get Virtual Machine credentials."
),
status
=
404
)
return
HttpResponse
(
_
(
"Could not get Virtual Machine credentials."
),
status
=
404
)
messages
.
error
(
request
,
_
(
'Failed to power off virtual machine.'
))
class
AjaxTemplateWizard
(
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
return
render_to_response
(
'new-template-flow-1.html'
,
RequestContext
(
request
,
{
'templates'
:
[
t
for
t
in
Template
.
objects
.
filter
(
public
=
True
)
.
all
()]
+
[
t
for
t
in
Template
.
objects
.
filter
(
owner
=
request
.
user
)
.
all
()],
}))
templates
=
([
t
for
t
in
Template
.
objects
.
filter
(
public
=
True
)
.
all
()]
+
[
t
for
t
in
Template
.
objects
.
filter
(
owner
=
request
.
user
)
.
all
()])
ctx
=
RequestContext
(
request
,
{
'templates'
:
templates
})
return
render_to_response
(
'new-template-flow-1.html'
,
ctx
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
base
=
get_object_or_404
(
Template
,
id
=
request
.
POST
[
'base'
])
if
base
.
owner
!=
request
.
user
and
not
base
.
public
and
not
request
.
user
.
is_superuser
:
if
base
.
owner
!=
request
.
user
and
(
not
base
.
public
and
not
request
.
user
.
is_superuser
):
raise
PermissionDenied
()
try
:
maxshare
=
Template
.
objects
.
order_by
(
'-pk'
)[
0
]
.
pk
+
1
except
:
maxshare
=
1
return
render_to_response
(
'new-template-flow.html'
,
RequestContext
(
request
,
{
'sizes'
:
InstanceType
.
objects
.
all
(),
ctx
=
{
'sizes'
:
InstanceType
.
objects
.
all
(),
'base'
:
base
,
'maxshare'
:
maxshare
,
}))
}
return
render_to_response
(
'new-template-flow.html'
,
RequestContext
(
request
,
ctx
))
ajax_template_wizard
=
login_required
(
AjaxTemplateWizard
.
as_view
())
class
AjaxTemplateEditWizard
(
View
):
def
get
(
self
,
request
,
id
,
*
args
,
**
kwargs
):
template
=
get_object_or_404
(
Template
,
id
=
id
)
if
template
.
owner
!=
request
.
user
and
not
template
.
public
and
not
request
.
user
.
is_superuser
:
if
template
.
owner
!=
request
.
user
and
(
not
template
.
public
and
not
request
.
user
.
is_superuser
):
raise
PermissionDenied
()
return
render_to_response
(
'edit-template-flow.html'
,
RequestContext
(
request
,
{
'sizes'
:
InstanceType
.
objects
.
all
(),
ctx
=
{
'sizes'
:
InstanceType
.
objects
.
all
(),
'template'
:
template
,
}))
}
return
render_to_response
(
'edit-template-flow.html'
,
RequestContext
(
request
,
ctx
))
def
post
(
self
,
request
,
id
,
*
args
,
**
kwargs
):
template
=
get_object_or_404
(
Template
,
id
=
id
)
user_details
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
if
template
.
owner
!=
request
.
user
and
not
template
.
public
and
not
request
.
user
.
is_superuser
:
if
template
.
owner
!=
request
.
user
and
(
not
template
.
public
and
not
request
.
user
.
is_superuser
):
raise
PermissionDenied
()
instance_type
=
get_object_or_404
(
InstanceType
,
id
=
request
.
POST
[
'size'
])
current_used_share_quota
=
user_details
.
get_weighted_share_count
()
current_used_share_quota_without_template
=
current_used_share_quota
-
template
.
get_share_quota_usage_for
(
request
.
user
)
new_quota_for_current_template
=
template
.
get_share_quota_usage_for_user_with_type
(
instance_type
,
request
.
user
)
new_used_share_quota
=
current_used_share_quota_without_template
+
new_quota_for_current_template
allow_type_modify
=
True
if
new_used_share_quota
<=
user_details
.
share_quota
else
False
if
not
allow_type_modify
:
messages
.
error
(
request
,
_
(
'You do not have enough free share quota.'
))
instance_type
=
get_object_or_404
(
InstanceType
,
id
=
request
.
POST
[
'size'
])
# calculate quota need with changed template type
q
=
user_details
.
get_weighted_share_count
()
q
-=
template
.
get_share_quota_usage_for
(
request
.
user
)
q
+=
template
.
get_share_quota_usage_for
(
request
.
user
,
type
=
instance_type
)
if
q
>
user_details
.
share_quota
:
messages
.
error
(
request
,
_
(
'You do not have enough free share quota.'
))
return
redirect
(
home
)
template
.
instance_type
=
instance_type
template
.
description
=
request
.
POST
[
'description'
]
...
...
@@ -172,12 +195,15 @@ class AjaxShareWizard(View):
def
get
(
self
,
request
,
id
,
gid
=
None
,
*
args
,
**
kwargs
):
det
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
if
det
.
get_weighted_share_count
()
>=
det
.
share_quota
:
return
HttpResponse
(
unicode
(
_
(
'You do not have any free share quota.'
)))
msg
=
ugettext
(
'You do not have any free share quota.'
)
return
HttpResponse
(
msg
)
types
=
TYPES_L
types
[
0
][
'default'
]
=
True
for
i
,
t
in
enumerate
(
types
):
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
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
types
[
i
]
=
t
if
gid
:
gid
=
get_object_or_404
(
Group
,
id
=
gid
)
...
...
@@ -188,10 +214,12 @@ class AjaxShareWizard(View):
'types'
:
types
,
'group'
:
gid
,
}))
def
post
(
self
,
request
,
id
,
gid
=
None
,
*
args
,
**
kwargs
):
det
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
base
=
get_object_or_404
(
Template
,
id
=
id
)
if
base
.
owner
!=
request
.
user
and
not
base
.
public
and
not
request
.
user
.
is_superuser
:
if
base
.
owner
!=
request
.
user
and
(
not
base
.
public
and
not
request
.
user
.
is_superuser
):
raise
PermissionDenied
()
group
=
None
if
gid
:
...
...
@@ -205,35 +233,45 @@ class AjaxShareWizard(View):
if
not
stype
in
TYPES
.
keys
():
raise
PermissionDenied
()
il
=
request
.
POST
[
'instance_limit'
]
if
det
.
get_weighted_share_count
()
+
int
(
il
)
*
base
.
instance_type
.
credit
>
det
.
share_quota
:
messages
.
error
(
request
,
_
(
'You do not have enough free share quota.'
))
if
det
.
share_quota
<
(
det
.
get_weighted_share_count
()
+
int
(
il
)
*
base
.
instance_type
.
credit
):
messages
.
error
(
request
,
_
(
'You do not have enough free share quota.'
))
return
redirect
(
'/'
)
s
=
Share
.
objects
.
create
(
name
=
request
.
POST
[
'name'
],
description
=
request
.
POST
[
'description'
],
type
=
stype
,
instance_limit
=
il
,
per_user_limit
=
request
.
POST
[
'per_user_limit'
],
Share
.
objects
.
create
(
name
=
request
.
POST
[
'name'
],
description
=
request
.
POST
[
'description'
],
type
=
stype
,
instance_limit
=
il
,
per_user_limit
=
request
.
POST
[
'per_user_limit'
],
group
=
group
,
template
=
base
,
owner
=
request
.
user
)
messages
.
success
(
request
,
_
(
'Successfully shared
%
s.'
)
%
base
)
return
redirect
(
group
)
ajax_share_wizard
=
login_required
(
AjaxShareWizard
.
as_view
())
class
AjaxShareEditWizard
(
View
):
def
get
(
self
,
request
,
id
,
*
args
,
**
kwargs
):
det
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
if
det
.
get_weighted_share_count
()
>
det
.
share_quota
:
logger
.
warning
(
'[one] User
%
s ha more used share quota, than its limit, how is that possible? (
%
d >
%
d)'
,
str
(
request
.
user
),
logger
.
warning
(
'[one] User
%
s ha more used share quota, than its limit, how '
'is that possible? (
%
d >
%
d)'
,
str
(
request
.
user
),
det
.
get_weighted_share_count
(),
det
.
share_quota
)
return
HttpResponse
(
unicode
(
_
(
'You do not have any free share quota.'
)))
msg
=
ugettext
(
'You do not have any free share quota.'
)
return
HttpResponse
(
msg
)
types
=
TYPES_L
for
i
,
t
in
enumerate
(
types
):
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
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
types
[
i
]
=
t
share
=
get_object_or_404
(
Share
,
id
=
id
)
return
render_to_response
(
'edit-share.html'
,
RequestContext
(
request
,
{
'share'
:
share
,
'types'
:
types
,
}))
def
post
(
self
,
request
,
id
,
*
args
,
**
kwargs
):
det
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
share
=
get_object_or_404
(
Share
,
id
=
id
)
...
...
@@ -243,13 +281,15 @@ class AjaxShareEditWizard(View):
if
not
stype
in
TYPES
.
keys
():
raise
PermissionDenied
()
instance_limit
=
int
(
request
.
POST
[
'instance_limit'
])
current_used_share_quota
=
det
.
get_weighted_share_count
()
current_used_share_quota_without_current_share
=
current_used_share_quota
-
share
.
get_used_quota
()
new_quota_for_current_share
=
instance_limit
*
share
.
template
.
get_credits_per_instance
()
new_used_share_quota
=
current_used_share_quota_without_current_share
+
new_quota_for_current_share
allow_stype_modify
=
True
if
new_used_share_quota
<=
det
.
share_quota
else
False
if
not
allow_stype_modify
:
messages
.
error
(
request
,
_
(
'You do not have enough free share quota.'
))
# calculate quota need with changed share
q
=
det
.
get_weighted_share_count
()
q
-=
share
.
get_used_quota
()
q
+=
instance_limit
*
share
.
template
.
get_credits_per_instance
()
if
det
.
share_quota
<
q
:
messages
.
error
(
request
,
_
(
'You do not have enough free share quota.'
))
return
redirect
(
share
.
group
)
share
.
name
=
request
.
POST
[
'name'
]
share
.
description
=
request
.
POST
[
'description'
]
...
...
@@ -273,9 +313,11 @@ def vm_saveas(request, vmid):
messages
.
success
(
request
,
_
(
"Template is being saved..."
))
return
redirect
(
inst
)
def
vm_new_ajax
(
request
,
template
):
return
vm_new
(
request
,
template
,
redir
=
False
)
def
_redirect_or_201
(
path
,
redir
):
if
redir
:
return
redirect
(
path
)
...
...
@@ -284,38 +326,80 @@ def _redirect_or_201(path, redir):
response
[
'Location'
]
=
path
return
response
def
_template_for_save
(
base
,
request
):
if
base
.
owner
!=
request
.
user
and
not
base
.
public
and
not
request
.
user
.
is_superuser
:
if
base
.
owner
!=
request
.
user
and
(
not
base
.
public
and
not
request
.
user
.
is_superuser
):
raise
PermissionDenied
()
name
=
request
.
POST
[
'name'
]
t
=
Template
.
objects
.
create
(
name
=
name
,
disk
=
base
.
disk
,
instance_type_id
=
request
.
POST
[
'size'
],
network
=
base
.
network
,
owner
=
request
.
user
)
t
=
Template
.
objects
.
create
(
name
=
name
,
disk
=
base
.
disk
,
instance_type_id
=
request
.
POST
[
'size'
],
network
=
base
.
network
,
owner
=
request
.
user
)
t
.
access_type
=
base
.
access_type
t
.
description
=
request
.
POST
[
'description'
]
t
.
system
=
base
.
system
t
.
save
()
return
t
def
_check_quota
(
request
,
template
,
share
):
"""
Returns if the given request is permitted to run the new vm.
"""
det
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
if
det
.
get_weighted_instance_count
()
+
template
.
instance_type
.
credit
>
det
.
instance_quota
:
messages
.
error
(
request
,
_
(
'You do not have any free quota. You can not launch this until you stop an other instance.'
))
user
=
request
.
user
det
=
UserCloudDetails
.
objects
.
get
(
user
=
user
)
q
=
det
.
get_weighted_instance_count
()
+
template
.
instance_type
.
credit
if
q
>
det
.
instance_quota
:
messages
.
error
(
request
,
_
(
'You do not have any free quota. You can not launch '
'this until you stop an other instance.'
))
return
False
if
share
:
if
share
.
get_running
()
+
1
>
share
.
instance_limit
:
messages
.
error
(
request
,
_
(
'The share does not have any free quota. You can not launch this until someone stops an instance.'
))
if
share
.
instance_limit
<
share
.
get_running
()
+
1
:
msg
=
_
(
'The share does not have any free quota. You can '
'not launch this until someone stops an instance.'
)
messages
.
error
(
request
,
msg
)
return
False
elif
share
.
get_running_or_stopped
(
request
.
user
)
+
1
>
share
.
per_user_limit
:
messages
.
error
(
request
,
_
(
'You do not have any free quota for this share. You can not launch this until you stop an other instance.'
))
if
share
.
per_user_limit
<
share
.
get_running_or_stopped
(
user
)
+
1
:
msg
=
_
(
'You do not have any free quota for this share. You can '
'not launch this until you stop an other instance.'
)
messages
.
error
(
request
,
msg
)
return
False
if
not
share
.
group
.
members
.
filter
(
user
=
request
.
user
)
and
not
share
.
group
.
owners
.
filter
(
user
=
request
.
user
):
messages
.
error
(
request
,
_
(
'You are not a member of the share group.'
))
if
not
share
.
group
.
members
.
filter
(
user
=
request
.
user
)
and
\
not
share
.
group
.
owners
.
filter
(
user
=
request
.
user
):
msg
=
_
(
'You are not a member of the share group.'
)
messages
.
error
(
request
,
msg
)
return
False
return
True
@require_POST
def
_check_permission
(
request
,
template
,
share
):
"""
Returns if the given request is permitted to try the new vm.
"""
if
not
share
and
not
template
.
public
and
template
.
owner
!=
request
.
user
:
msg
=
_
(
'You have no permission to try this instance without a share. '
'Launch a new instance through a share.'
)
messages
.
error
(
request
,
msg
)
return
False
else
:
return
True
def
_try_submit
(
base
,
request
,
extra
,
share
):
try
:
inst
=
Instance
.
submit
(
base
,
request
.
user
,
extra
=
extra
,
share
=
share
)
except
Exception
as
e
:
logger
.
error
(
'Failed to create virtual machine.'
+
unicode
(
e
))
messages
.
error
(
request
,
_
(
'Failed to create virtual machine.'
))
else
:
inst
.
renew
()
return
inst
@login_required
def
vm_new
(
request
,
template
=
None
,
share
=
None
,
redir
=
True
):
base
=
None
...
...
@@ -334,44 +418,14 @@ def vm_new(request, template=None, share=None, redir=True):
except
:
messages
.
error
(
request
,
_
(
'Can not create template.'
))
go
=
False
go
=
go
and
_check_quota
(
request
,
base
,
share
)
if
not
share
and
not
base
.
public
and
base
.
owner
!=
request
.
user
:
messages
.
error
(
request
,
_
(
'You have no permission to try this instance without a share. Launch a new instance through a share.'
))
go
=
False
type
=
share
.
type
if
share
else
'LAB'
TYPES
[
type
][
'suspend'
]
time_of_suspend
=
TYPES
[
type
][
'suspend'
]
+
datetime
.
now
()
if
TYPES
[
type
][
'delete'
]:
time_of_delete
=
TYPES
[
type
][
'delete'
]
+
datetime
.
now
()
else
:
time_of_delete
=
None
inst
=
None
go
=
go
and
(
_check_quota
(
request
,
base
,
share
)
and
_check_permission
(
request
,
base
,
share
))
if
go
:
try
:
inst
=
Instance
.
submit
(
base
,
request
.
user
,
extra
=
extra
,
share
=
share
)
except
Exception
as
e
:
logger
.
error
(
'Failed to create virtual machine.'
+
unicode
(
e
))
messages
.
error
(
request
,
_
(
'Failed to create virtual machine.'
))
inst
=
None
if
inst
:
inst
.
waiting
=
True
inst
.
time_of_suspend
=
time_of_suspend
inst
.
time_of_delete
=
time_of_delete
inst
.
save
()
elif
extra
and
base
:
inst
=
_try_submit
(
base
,
request
,
extra
,
share
)
elif
extra
and
base
:
# clean up new template object
base
.
delete
()
return
_redirect_or_201
(
inst
.
get_absolute_url
()
if
inst
else
'/'
,
redir
)
class
VmListView
(
ListView
):
context_object_name
=
'instances'
template_name
=
'list.html'
def
get_queryset
(
self
):
self
.
profile
=
request
.
user
return
Instance
.
objects
.
filter
(
owner
=
self
.
profile
)
vm_list
=
login_required
(
VmListView
.
as_view
())
@require_safe
@login_required
...
...
@@ -392,7 +446,7 @@ def vm_show(request, iid):
inst
.
hostname_v6
=
inst
.
get_connect_host
(
use_ipv6
=
True
)
inst
.
port_v4
=
inst
.
get_port
(
use_ipv6
=
False
)
inst
.
port_v6
=
inst
.
get_port
(
use_ipv6
=
True
)
return
render_to_response
(
"show.html"
,
RequestContext
(
request
,{
return
render_to_response
(
"show.html"
,
RequestContext
(
request
,
{
'uri'
:
inst
.
get_connect_uri
(),
'state'
:
inst
.
state
,
'name'
:
inst
.
name
,
...
...
@@ -400,11 +454,12 @@ def vm_show(request, iid):
'age'
:
inst
.
get_age
(),
'instances'
:
_list_instances
(
request
),
'i'
:
inst
,
'booting'
:
not
inst
.
active_since
,
'booting'
:
not
inst
.
active_since
,
'ports'
:
ports
,
'userdetails'
:
details
}))
@require_safe
@login_required
def
vm_ajax_instance_status
(
request
,
iid
):
...
...
@@ -417,6 +472,7 @@ def vm_ajax_instance_status(request, iid):
'state'
:
inst
.
template
.
state
}}))
@login_required
def
vm_ajax_rename
(
request
,
iid
):
inst
=
get_object_or_404
(
Instance
,
id
=
iid
,
owner
=
request
.
user
)
...
...
@@ -424,6 +480,7 @@ def vm_ajax_rename(request, iid):
inst
.
save
()
return
HttpResponse
(
json
.
dumps
({
'name'
:
inst
.
name
}))
def
boot_token
(
request
,
token
):
try
:
id
=
signing
.
loads
(
token
,
salt
=
'activate'
)
...
...
@@ -437,6 +494,7 @@ def boot_token(request, token):
inst
.
save
()
return
HttpResponse
(
"KTHXBYE"
)
class
VmPortAddView
(
View
):
def
post
(
self
,
request
,
iid
,
*
args
,
**
kwargs
):
try
:
...
...
@@ -460,6 +518,7 @@ class VmPortAddView(View):
vm_port_add
=
login_required
(
VmPortAddView
.
as_view
())
@require_safe
@login_required
@require_GET
...
...
@@ -473,14 +532,17 @@ def vm_port_del(request, iid, proto, private):
messages
.
error
(
request
,
_
(
u"Removing port failed."
))
return
redirect
(
'/vm/show/
%
d/'
%
int
(
iid
))
class
VmDeleteView
(
View
):
def
post
(
self
,
request
,
iid
,
*
args
,
**
kwargs
):
try
:
inst
=
get_object_or_404
(
Instance
,
id
=
iid
,
owner
=
request
.
user
)
if
inst
.
template
.
state
!=
'READY'
and
inst
.
template
.
owner
==
request
.
user
:
if
inst
.
template
.
state
!=
'READY'
and
\
inst
.
template
.
owner
==
request
.
user
:
inst
.
template
.
delete
()
inst
.
one_delete
()
messages
.
success
(
request
,
_
(
'Virtual machine is successfully deleted.'
))
messages
.
success
(
request
,
_
(
'Virtual machine is successfully deleted.'
))
except
:
messages
.
error
(
request
,
_
(
'Failed to delete virtual machine.'
))
if
request
.
is_ajax
():
...
...
@@ -490,13 +552,14 @@ class VmDeleteView(View):
def
get
(
self
,
request
,
iid
,
*
args
,
**
kwargs
):
i
=
get_object_or_404
(
Instance
,
id
=
iid
,
owner
=
request
.
user
)
return
render_to_response
(
"confirm_delete.html"
,
RequestContext
(
request
,
{
'i'
:
i
})
)
ctx
=
RequestContext
(
request
,
{
'i'
:
i
,
})
return
render_to_response
(
"confirm_delete.html"
,
ctx
)
vm_delete
=
login_required
(
VmDeleteView
.
as_view
())
@login_required
#@require_POST
#
@require_POST
def
vm_unshare
(
request
,
id
,
*
args
,
**
kwargs
):
s
=
get_object_or_404
(
Share
,
id
=
id
)
g
=
s
.
group
...
...
@@ -504,7 +567,8 @@ def vm_unshare(request, id, *args, **kwargs):
raise
PermissionDenied
()
try
:
if
s
.
get_running_or_stopped
()
>
0
:
messages
.
error
(
request
,
_
(
'There are machines running of this share.'
))
messages
.
error
(
request
,
_
(
'There are machines running of this share.'
))
else
:
s
.
delete
()
messages
.
success
(
request
,
_
(
'Share is successfully removed.'
))
...
...
@@ -512,23 +576,27 @@ def vm_unshare(request, id, *args, **kwargs):
messages
.
error
(
request
,
_
(
'Failed to remove share.'
))
return
redirect
(
g
)
@login_required
@require_POST
def
vm_stop
(
request
,
iid
,
*
args
,
**
kwargs
):
try
:
get_object_or_404
(
Instance
,
id
=
iid
,
owner
=
request
.
user
)
.
stop
()
messages
.
success
(
request
,
_
(
'Virtual machine is successfully stopped.'
))
messages
.
success
(
request
,
_
(
'Virtual machine is successfully stopped.'
))
except
:
messages
.
error
(
request
,
_
(
'Failed to stop virtual machine.'
))
return
redirect
(
'/'
)
@login_required
@require_POST
def
vm_resume
(
request
,
iid
,
*
args
,
**
kwargs
):
try
:
obj
=
get_object_or_404
(
Instance
,
id
=
iid
,
owner
=
request
.
user
)
obj
.
resume
()
messages
.
success
(
request
,
_
(
'Virtual machine is successfully resumed.'
))
messages
.
success
(
request
,
_
(
'Virtual machine is successfully resumed.'
))
except
:
messages
.
error
(
request
,
_
(
'Failed to resume virtual machine.'
))
try
:
...
...
@@ -537,6 +605,7 @@ def vm_resume(request, iid, *args, **kwargs):
pass
return
redirect
(
'/'
)
@login_required
@require_POST
def
vm_renew
(
request
,
which
,
iid
,
*
args
,
**
kwargs
):
...
...
@@ -550,33 +619,38 @@ def vm_renew(request, which, iid, *args, **kwargs):
'vm'
:
vm
}))
@login_required
@require_POST
def
vm_power_off
(
request
,
iid
,
*
args
,
**
kwargs
):
try
:
get_object_or_404
(
Instance
,
id
=
iid
,
owner
=
request
.
user
)
.
poweroff
()
messages
.
success
(
request
,
_
(
'Virtual machine is successfully powered off.'
))
messages
.
success
(
request
,
_
(
'Virtual machine is successfully powered off.'
))
except
:
messages
.
error
(
request
,
_
(
'Failed to power off virtual machine.'
))
return
redirect
(
'/'
)
@login_required
@require_POST
def
vm_restart
(
request
,
iid
,
*
args
,
**
kwargs
):
try
:
get_object_or_404
(
Instance
,
id
=
iid
,
owner
=
request
.
user
)
.
restart
()
messages
.
success
(
request
,
_
(
'Virtual machine is successfully restarted.'
))
messages
.
success
(
request
,
_
(
'Virtual machine is successfully restarted.'
))
except
:
messages
.
error
(
request
,
_
(
'Failed to restart virtual machine.'
))
return
redirect
(
'/'
)
@login_required
@require_POST
def
key_add
(
request
):
try
:
key
=
SshKey
()
key
.
key
=
request
.
POST
[
'key'
]
key
.
user
=
request
.
user
key
=
SshKey
()
key
.
key
=
request
.
POST
[
'key'
]
key
.
user
=
request
.
user
key
.
full_clean
()
key
.
save
()
_update_keys
(
request
.
user
)
...
...
@@ -590,22 +664,25 @@ def key_add(request):
messages
.
success
(
request
,
_
(
'Public key successfully added.'
))
return
redirect
(
'/'
)
@login_required
@require_POST
def
key_ajax_delete
(
request
):
try
:
key
=
get_object_or_404
(
SshKey
,
id
=
request
.
POST
[
'id'
],
user
=
request
.
user
)
key
=
get_object_or_404
(
SshKey
,
id
=
request
.
POST
[
'id'
],
user
=
request
.
user
)
key
.
delete
()
_update_keys
(
request
.
user
)
except
:
messages
.
error
(
request
,
_
(
'Failed to delete public key'
))
return
HttpResponse
(
'OK'
)
@login_required
@require_POST
def
key_ajax_reset
(
request
):
try
:
det
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
det
=
UserCloudDetails
.
objects
.
get
(
user
=
request
.
user
)
det
.
reset_smb
()
det
.
reset_keys
()
_update_keys
(
request
.
user
)
...
...
@@ -613,6 +690,7 @@ def key_ajax_reset(request):
messages
.
error
(
request
,
_
(
'Failed to reset keys'
))
return
HttpResponse
(
'OK'
)
def
_update_keys
(
user
):
details
=
user
.
cloud_details
password
=
details
.
smb_password
...
...
@@ -622,22 +700,24 @@ def _update_keys(user):
user
=
user
.
username
StoreApi
.
updateauthorizationinfo
(
user
,
password
,
key_list
)
def
stat
(
request
):
values
=
subprocess
.
check_output
([
'/opt/webadmin/cloud/miscellaneous/stat/stat_wrap.sh'
])
values
=
subprocess
.
check_output
(
[
'/opt/webadmin/cloud/miscellaneous/stat/stat_wrap.sh'
])
# values = '''
# {"CPU": {"USED_CPU": 2, "ALLOC_CPU": 0,
# "FREE_CPU": 98}, "MEM": {"FREE_MEM": 1685432, "ALLOC_MEM":0,
# "USED_MEM": 366284}}'''
stat_dict
=
json
.
loads
(
values
)
return
HttpResponse
(
render_to_response
(
"stat.html"
,
RequestContext
(
request
,
{
'STAT'
:
stat_dict
,
}
request
,
{
'STAT'
:
stat_dict
,
}
)))
def
sites
(
request
,
site
):
if
site
in
[
"legal"
,
"policy"
,
"help"
,
"support"
,
"changelog"
,
]:
return
render_to_response
(
"sites/
%
s.html"
%
site
,
RequestContext
(
request
,
{}))
if
site
in
[
"legal"
,
"policy"
,
"help"
,
"support"
,
"changelog"
,
]:
ctx
=
RequestContext
(
request
,
{})
return
render_to_response
(
"sites/
%
s.html"
%
site
,
ctx
)
else
:
return
redirect
(
home
)
...
...
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