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
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
eabb2f53
authored
Jul 21, 2014
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into feature-store
parents
4816e34a
d0891d38
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
153 additions
and
23 deletions
+153
-23
circle/dashboard/fixtures/test-vm-fixture.json
+1
-0
circle/dashboard/tests/test_views.py
+4
-0
circle/storage/models.py
+14
-1
circle/vm/migrations/0023_auto__del_unique_instancetemplate_n.py
+5
-3
circle/vm/migrations/0024_auto__del_field_instanceactivity_result__add_field_instanceactivity_re.py
+19
-8
circle/vm/models/instance.py
+46
-0
circle/vm/operations.py
+44
-11
circle/vm/tasks/vm_tasks.py
+20
-0
No files found.
circle/dashboard/fixtures/test-vm-fixture.json
View file @
eabb2f53
...
@@ -1395,6 +1395,7 @@
...
@@ -1395,6 +1395,7 @@
"raw_data"
:
""
,
"raw_data"
:
""
,
"vnc_port"
:
1234
,
"vnc_port"
:
1234
,
"num_cores"
:
2
,
"num_cores"
:
2
,
"status"
:
"RUNNING"
,
"modified"
:
"2013-10-14T07:27:38.192Z"
"modified"
:
"2013-10-14T07:27:38.192Z"
}
}
},
},
...
...
circle/dashboard/tests/test_views.py
View file @
eabb2f53
...
@@ -199,6 +199,8 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -199,6 +199,8 @@ class VmDetailTest(LoginMixin, TestCase):
inst
=
Instance
.
objects
.
get
(
pk
=
1
)
inst
=
Instance
.
objects
.
get
(
pk
=
1
)
inst
.
set_level
(
self
.
u1
,
'owner'
)
inst
.
set_level
(
self
.
u1
,
'owner'
)
inst
.
add_interface
(
vlan
=
Vlan
.
objects
.
get
(
pk
=
1
),
user
=
self
.
us
)
inst
.
add_interface
(
vlan
=
Vlan
.
objects
.
get
(
pk
=
1
),
user
=
self
.
us
)
inst
.
status
=
'RUNNING'
inst
.
save
()
iface_count
=
inst
.
interface_set
.
count
()
iface_count
=
inst
.
interface_set
.
count
()
c
.
post
(
"/dashboard/interface/1/delete/"
)
c
.
post
(
"/dashboard/interface/1/delete/"
)
...
@@ -211,6 +213,8 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -211,6 +213,8 @@ class VmDetailTest(LoginMixin, TestCase):
inst
.
set_level
(
self
.
u1
,
'owner'
)
inst
.
set_level
(
self
.
u1
,
'owner'
)
vlan
=
Vlan
.
objects
.
get
(
pk
=
1
)
vlan
=
Vlan
.
objects
.
get
(
pk
=
1
)
inst
.
add_interface
(
vlan
=
vlan
,
user
=
self
.
us
)
inst
.
add_interface
(
vlan
=
vlan
,
user
=
self
.
us
)
inst
.
status
=
'RUNNING'
inst
.
save
()
iface_count
=
inst
.
interface_set
.
count
()
iface_count
=
inst
.
interface_set
.
count
()
response
=
c
.
post
(
"/dashboard/interface/1/delete/"
,
response
=
c
.
post
(
"/dashboard/interface/1/delete/"
,
...
...
circle/storage/models.py
View file @
eabb2f53
...
@@ -185,12 +185,24 @@ class Disk(AclBase, TimeStampedModel):
...
@@ -185,12 +185,24 @@ class Disk(AclBase, TimeStampedModel):
return
{
return
{
'qcow2-norm'
:
'vd'
,
'qcow2-norm'
:
'vd'
,
'qcow2-snap'
:
'vd'
,
'qcow2-snap'
:
'vd'
,
'iso'
:
'
h
d'
,
'iso'
:
'
s
d'
,
'raw-ro'
:
'vd'
,
'raw-ro'
:
'vd'
,
'raw-rw'
:
'vd'
,
'raw-rw'
:
'vd'
,
}[
self
.
type
]
}[
self
.
type
]
@property
@property
def
device_bus
(
self
):
"""Returns the proper device prefix for different types of images.
"""
return
{
'qcow2-norm'
:
'virtio'
,
'qcow2-snap'
:
'virtio'
,
'iso'
:
'scsi'
,
'raw-ro'
:
'virtio'
,
'raw-rw'
:
'virtio'
,
}[
self
.
type
]
@property
def
is_deletable
(
self
):
def
is_deletable
(
self
):
"""True if the associated file can be deleted.
"""True if the associated file can be deleted.
"""
"""
...
@@ -251,6 +263,7 @@ class Disk(AclBase, TimeStampedModel):
...
@@ -251,6 +263,7 @@ class Disk(AclBase, TimeStampedModel):
'driver_type'
:
self
.
vm_format
,
'driver_type'
:
self
.
vm_format
,
'driver_cache'
:
'none'
,
'driver_cache'
:
'none'
,
'target_device'
:
self
.
device_type
+
self
.
dev_num
,
'target_device'
:
self
.
device_type
+
self
.
dev_num
,
'target_bus'
:
self
.
device_bus
,
'disk_device'
:
'cdrom'
if
self
.
type
==
'iso'
else
'disk'
'disk_device'
:
'cdrom'
if
self
.
type
==
'iso'
else
'disk'
}
}
...
...
circle/vm/migrations/0023_auto__del_unique_instancetemplate_n.py
View file @
eabb2f53
...
@@ -9,7 +9,10 @@ class Migration(SchemaMigration):
...
@@ -9,7 +9,10 @@ class Migration(SchemaMigration):
def
forwards
(
self
,
orm
):
def
forwards
(
self
,
orm
):
# Removing unique constraint on 'InstanceTemplate', fields ['name']
# Removing unique constraint on 'InstanceTemplate', fields ['name']
db
.
delete_unique
(
u'vm_instancetemplate'
,
[
'name'
])
try
:
db
.
delete_unique
(
u'vm_instancetemplate'
,
[
'name'
])
except
Exception
as
e
:
print
unicode
(
e
)
# Changing field 'InstanceTemplate.parent'
# Changing field 'InstanceTemplate.parent'
...
@@ -281,4 +284,4 @@ class Migration(SchemaMigration):
...
@@ -281,4 +284,4 @@ class Migration(SchemaMigration):
}
}
}
}
complete_apps
=
[
'vm'
]
complete_apps
=
[
'vm'
]
\ No newline at end of file
circle/vm/migrations/0024_auto__del_field_instanceactivity_result__add_field_instanceactivity_re.py
View file @
eabb2f53
...
@@ -7,34 +7,45 @@ class Migration(SchemaMigration):
...
@@ -7,34 +7,45 @@ class Migration(SchemaMigration):
def
forwards
(
self
,
orm
):
def
forwards
(
self
,
orm
):
db
.
start_transaction
()
# Adding field 'InstanceActivity.result_data'
# Adding field 'InstanceActivity.result_data'
db
.
add_column
(
u'vm_instanceactivity'
,
'result_data'
,
db
.
add_column
(
u'vm_instanceactivity'
,
'result_data'
,
self
.
gf
(
'jsonfield.fields.JSONField'
)(
null
=
True
,
blank
=
True
),
self
.
gf
(
'jsonfield.fields.JSONField'
)(
null
=
True
,
blank
=
True
),
keep_default
=
False
)
keep_default
=
False
)
# Adding field 'NodeActivity.result_data'
db
.
add_column
(
u'vm_nodeactivity'
,
'result_data'
,
self
.
gf
(
'jsonfield.fields.JSONField'
)(
null
=
True
,
blank
=
True
),
keep_default
=
False
)
db
.
commit_transaction
()
db
.
start_transaction
()
for
i
in
orm
.
InstanceActivity
.
objects
.
all
():
for
i
in
orm
.
InstanceActivity
.
objects
.
all
():
result
=
i
.
result
.
replace
(
"
%
"
,
"
%%
"
)
if
i
.
result
else
""
result
=
i
.
result
.
replace
(
"
%
"
,
"
%%
"
)
if
i
.
result
else
""
i
.
result_data
=
{
"user_text_template"
:
""
,
i
.
result_data
=
{
"user_text_template"
:
""
,
"admin_text_template"
:
result
,
"params"
:
{}}
"admin_text_template"
:
result
,
"params"
:
{}}
i
.
save
()
i
.
save
()
# Deleting field 'InstanceActivity.result'
db
.
delete_column
(
u'vm_instanceactivity'
,
'result'
)
# Adding field 'NodeActivity.result_data'
db
.
add_column
(
u'vm_nodeactivity'
,
'result_data'
,
self
.
gf
(
'jsonfield.fields.JSONField'
)(
null
=
True
,
blank
=
True
),
keep_default
=
False
)
for
i
in
orm
.
NodeActivity
.
objects
.
all
():
for
i
in
orm
.
NodeActivity
.
objects
.
all
():
result
=
i
.
result
.
replace
(
"
%
"
,
"
%%
"
)
if
i
.
result
else
""
result
=
i
.
result
.
replace
(
"
%
"
,
"
%%
"
)
if
i
.
result
else
""
i
.
result_data
=
{
"user_text_template"
:
""
,
i
.
result_data
=
{
"user_text_template"
:
""
,
"admin_text_template"
:
result
,
"params"
:
{}}
"admin_text_template"
:
result
,
"params"
:
{}}
i
.
save
()
i
.
save
()
db
.
commit_transaction
()
db
.
start_transaction
()
# Deleting field 'InstanceActivity.result'
db
.
delete_column
(
u'vm_instanceactivity'
,
'result'
)
# Deleting field 'NodeActivity.result'
# Deleting field 'NodeActivity.result'
db
.
delete_column
(
u'vm_nodeactivity'
,
'result'
)
db
.
delete_column
(
u'vm_nodeactivity'
,
'result'
)
db
.
commit_transaction
()
def
backwards
(
self
,
orm
):
def
backwards
(
self
,
orm
):
# Adding field 'InstanceActivity.result'
# Adding field 'InstanceActivity.result'
...
...
circle/vm/models/instance.py
View file @
eabb2f53
...
@@ -763,6 +763,52 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
...
@@ -763,6 +763,52 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
"""
"""
return
scheduler
.
select_node
(
self
,
Node
.
objects
.
all
())
return
scheduler
.
select_node
(
self
,
Node
.
objects
.
all
())
def
attach_disk
(
self
,
disk
,
timeout
=
15
):
queue_name
=
self
.
get_remote_queue_name
(
'vm'
,
'fast'
)
return
vm_tasks
.
attach_disk
.
apply_async
(
args
=
[
self
.
vm_name
,
disk
.
get_vmdisk_desc
()],
queue
=
queue_name
)
.
get
(
timeout
=
timeout
)
def
detach_disk
(
self
,
disk
,
timeout
=
15
):
try
:
queue_name
=
self
.
get_remote_queue_name
(
'vm'
,
'fast'
)
return
vm_tasks
.
detach_disk
.
apply_async
(
args
=
[
self
.
vm_name
,
disk
.
get_vmdisk_desc
()],
queue
=
queue_name
)
.
get
(
timeout
=
timeout
)
except
Exception
as
e
:
if
e
.
libvirtError
and
"not found"
in
str
(
e
):
logger
.
debug
(
"Disk
%
s was not found."
%
disk
.
name
)
else
:
raise
def
attach_network
(
self
,
network
,
timeout
=
15
):
queue_name
=
self
.
get_remote_queue_name
(
'vm'
,
'fast'
)
return
vm_tasks
.
attach_network
.
apply_async
(
args
=
[
self
.
vm_name
,
network
.
get_vmnetwork_desc
()],
queue
=
queue_name
)
.
get
(
timeout
=
timeout
)
def
detach_network
(
self
,
network
,
timeout
=
15
):
try
:
queue_name
=
self
.
get_remote_queue_name
(
'vm'
,
'fast'
)
return
vm_tasks
.
detach_network
.
apply_async
(
args
=
[
self
.
vm_name
,
network
.
get_vmnetwork_desc
()],
queue
=
queue_name
)
.
get
(
timeout
=
timeout
)
except
Exception
as
e
:
if
e
.
libvirtError
and
"not found"
in
str
(
e
):
logger
.
debug
(
"Interface
%
s was not found."
%
(
network
.
__unicode__
()))
else
:
raise
def
deploy_disks
(
self
):
def
deploy_disks
(
self
):
"""Deploy all associated disks.
"""Deploy all associated disks.
"""
"""
...
...
circle/vm/operations.py
View file @
eabb2f53
...
@@ -18,6 +18,7 @@
...
@@ -18,6 +18,7 @@
from
__future__
import
absolute_import
,
unicode_literals
from
__future__
import
absolute_import
,
unicode_literals
from
logging
import
getLogger
from
logging
import
getLogger
from
re
import
search
from
re
import
search
from
string
import
ascii_lowercase
from
django.core.exceptions
import
PermissionDenied
from
django.core.exceptions
import
PermissionDenied
from
django.utils
import
timezone
from
django.utils
import
timezone
...
@@ -35,7 +36,6 @@ from .models import (
...
@@ -35,7 +36,6 @@ from .models import (
NodeActivity
,
NodeActivity
,
)
)
logger
=
getLogger
(
__name__
)
logger
=
getLogger
(
__name__
)
...
@@ -94,6 +94,11 @@ class AddInterfaceOperation(InstanceOperation):
...
@@ -94,6 +94,11 @@ class AddInterfaceOperation(InstanceOperation):
"the VM."
)
"the VM."
)
required_perms
=
()
required_perms
=
()
def
check_precond
(
self
):
super
(
AddInterfaceOperation
,
self
)
.
check_precond
()
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
,
'RUNNING'
]:
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
def
_operation
(
self
,
activity
,
user
,
system
,
vlan
,
managed
=
None
):
def
_operation
(
self
,
activity
,
user
,
system
,
vlan
,
managed
=
None
):
if
managed
is
None
:
if
managed
is
None
:
managed
=
vlan
.
managed
managed
=
vlan
.
managed
...
@@ -102,6 +107,8 @@ class AddInterfaceOperation(InstanceOperation):
...
@@ -102,6 +107,8 @@ class AddInterfaceOperation(InstanceOperation):
managed
=
managed
,
owner
=
user
,
vlan
=
vlan
)
managed
=
managed
,
owner
=
user
,
vlan
=
vlan
)
if
self
.
instance
.
is_running
:
if
self
.
instance
.
is_running
:
with
activity
.
sub_activity
(
'attach_network'
):
self
.
instance
.
attach_network
(
net
)
net
.
deploy
()
net
.
deploy
()
return
net
return
net
...
@@ -115,6 +122,7 @@ register_operation(AddInterfaceOperation)
...
@@ -115,6 +122,7 @@ register_operation(AddInterfaceOperation)
class
CreateDiskOperation
(
InstanceOperation
):
class
CreateDiskOperation
(
InstanceOperation
):
activity_code_suffix
=
'create_disk'
activity_code_suffix
=
'create_disk'
id
=
'create_disk'
id
=
'create_disk'
name
=
_
(
"create disk"
)
name
=
_
(
"create disk"
)
...
@@ -123,20 +131,29 @@ class CreateDiskOperation(InstanceOperation):
...
@@ -123,20 +131,29 @@ class CreateDiskOperation(InstanceOperation):
def
check_precond
(
self
):
def
check_precond
(
self
):
super
(
CreateDiskOperation
,
self
)
.
check_precond
()
super
(
CreateDiskOperation
,
self
)
.
check_precond
()
# TODO remove check when hot-attach is implemented
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
,
'RUNNING'
]:
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
]:
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
def
_operation
(
self
,
user
,
size
,
name
=
None
):
def
_operation
(
self
,
user
,
size
,
activity
,
name
=
None
):
# TODO implement with hot-attach when it'll be available
from
storage.models
import
Disk
from
storage.models
import
Disk
if
not
name
:
if
not
name
:
name
=
"new disk"
name
=
"new disk"
disk
=
Disk
.
create
(
size
=
size
,
name
=
name
,
type
=
"qcow2-norm"
)
disk
=
Disk
.
create
(
size
=
size
,
name
=
name
,
type
=
"qcow2-norm"
)
disk
.
full_clean
()
disk
.
full_clean
()
devnums
=
list
(
ascii_lowercase
)
for
d
in
self
.
instance
.
disks
.
all
():
devnums
.
remove
(
d
.
dev_num
)
disk
.
dev_num
=
devnums
.
pop
(
0
)
disk
.
save
()
self
.
instance
.
disks
.
add
(
disk
)
self
.
instance
.
disks
.
add
(
disk
)
if
self
.
instance
.
is_running
:
with
activity
.
sub_activity
(
'deploying_disk'
):
disk
.
deploy
()
with
activity
.
sub_activity
(
'attach_disk'
):
self
.
instance
.
attach_disk
(
disk
)
def
get_activity_name
(
self
,
kwargs
):
def
get_activity_name
(
self
,
kwargs
):
return
create_readable
(
ugettext_noop
(
"create
%(size)
s disk"
),
return
create_readable
(
ugettext_noop
(
"create
%(size)
s disk"
),
size
=
kwargs
[
'size'
])
size
=
kwargs
[
'size'
])
...
@@ -156,21 +173,29 @@ class DownloadDiskOperation(InstanceOperation):
...
@@ -156,21 +173,29 @@ class DownloadDiskOperation(InstanceOperation):
def
check_precond
(
self
):
def
check_precond
(
self
):
super
(
DownloadDiskOperation
,
self
)
.
check_precond
()
super
(
DownloadDiskOperation
,
self
)
.
check_precond
()
# TODO remove check when hot-attach is implemented
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
,
'RUNNING'
]:
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
]:
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
def
_operation
(
self
,
user
,
url
,
task
,
activity
,
name
=
None
):
def
_operation
(
self
,
user
,
url
,
task
,
activity
,
name
=
None
):
activity
.
result
=
url
activity
.
result
=
url
# TODO implement with hot-attach when it'll be available
from
storage.models
import
Disk
from
storage.models
import
Disk
disk
=
Disk
.
download
(
url
=
url
,
name
=
name
,
task
=
task
)
disk
=
Disk
.
download
(
url
=
url
,
name
=
name
,
task
=
task
)
devnums
=
list
(
ascii_lowercase
)
for
d
in
self
.
instance
.
disks
.
all
():
devnums
.
remove
(
d
.
dev_num
)
disk
.
dev_num
=
devnums
.
pop
(
0
)
disk
.
full_clean
()
disk
.
full_clean
()
disk
.
save
()
self
.
instance
.
disks
.
add
(
disk
)
self
.
instance
.
disks
.
add
(
disk
)
activity
.
readable_name
=
create_readable
(
activity
.
readable_name
=
create_readable
(
ugettext_noop
(
"download
%(name)
s"
),
name
=
disk
.
name
)
ugettext_noop
(
"download
%(name)
s"
),
name
=
disk
.
name
)
# TODO iso (cd) hot-plug is not supported by kvm/guests
if
self
.
instance
.
is_running
and
disk
.
type
not
in
[
"iso"
]:
with
activity
.
sub_activity
(
'attach_disk'
):
self
.
instance
.
attach_disk
(
disk
)
register_operation
(
DownloadDiskOperation
)
register_operation
(
DownloadDiskOperation
)
...
@@ -366,8 +391,15 @@ class RemoveInterfaceOperation(InstanceOperation):
...
@@ -366,8 +391,15 @@ class RemoveInterfaceOperation(InstanceOperation):
description
=
_
(
"Remove the specified network interface from the VM."
)
description
=
_
(
"Remove the specified network interface from the VM."
)
required_perms
=
()
required_perms
=
()
def
check_precond
(
self
):
super
(
RemoveInterfaceOperation
,
self
)
.
check_precond
()
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
,
'RUNNING'
]:
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
def
_operation
(
self
,
activity
,
user
,
system
,
interface
):
def
_operation
(
self
,
activity
,
user
,
system
,
interface
):
if
self
.
instance
.
is_running
:
if
self
.
instance
.
is_running
:
with
activity
.
sub_activity
(
'detach_network'
):
self
.
instance
.
detach_network
(
interface
)
interface
.
shutdown
()
interface
.
shutdown
()
interface
.
destroy
()
interface
.
destroy
()
...
@@ -386,12 +418,13 @@ class RemoveDiskOperation(InstanceOperation):
...
@@ -386,12 +418,13 @@ class RemoveDiskOperation(InstanceOperation):
def
check_precond
(
self
):
def
check_precond
(
self
):
super
(
RemoveDiskOperation
,
self
)
.
check_precond
()
super
(
RemoveDiskOperation
,
self
)
.
check_precond
()
# TODO remove check when hot-detach is implemented
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
,
'RUNNING'
]:
if
self
.
instance
.
status
not
in
[
'STOPPED'
]:
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
def
_operation
(
self
,
activity
,
user
,
system
,
disk
):
def
_operation
(
self
,
activity
,
user
,
system
,
disk
):
# TODO implement with hot-detach when it'll be available
if
self
.
instance
.
is_running
and
disk
.
type
not
in
[
"iso"
]:
with
activity
.
sub_activity
(
'detach_disk'
):
self
.
instance
.
detach_disk
(
disk
)
return
self
.
instance
.
disks
.
remove
(
disk
)
return
self
.
instance
.
disks
.
remove
(
disk
)
...
...
circle/vm/tasks/vm_tasks.py
View file @
eabb2f53
...
@@ -62,6 +62,26 @@ def get_queues():
...
@@ -62,6 +62,26 @@ def get_queues():
return
result
return
result
@celery.task
(
name
=
'vmdriver.attach_disk'
)
def
attach_disk
(
vm
,
disk
):
pass
@celery.task
(
name
=
'vmdriver.detach_disk'
)
def
detach_disk
(
vm
,
disk
):
pass
@celery.task
(
name
=
'vmdriver.attach_network'
)
def
attach_network
(
vm
,
net
):
pass
@celery.task
(
name
=
'vmdriver.detach_network'
)
def
detach_network
(
vm
,
net
):
pass
@celery.task
(
name
=
'vmdriver.create'
)
@celery.task
(
name
=
'vmdriver.create'
)
def
deploy
(
params
):
def
deploy
(
params
):
pass
pass
...
...
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