Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Fukász Rómeó Ervin
/
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
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
4684a0a9
authored
Jul 27, 2014
by
Bach Dániel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature-add-interface-fixes' into 'master'
Interface Fixes
parents
a4b51d64
0261e9b2
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
94 additions
and
71 deletions
+94
-71
circle/dashboard/forms.py
+19
-0
circle/dashboard/static/dashboard/vm-common.js
+4
-1
circle/dashboard/templates/dashboard/vm-detail/network.html
+7
-37
circle/dashboard/tests/test_views.py
+23
-10
circle/dashboard/views.py
+25
-21
circle/vm/operations.py
+16
-2
No files found.
circle/dashboard/forms.py
View file @
4684a0a9
...
@@ -952,6 +952,25 @@ class VmDownloadDiskForm(forms.Form):
...
@@ -952,6 +952,25 @@ class VmDownloadDiskForm(forms.Form):
return
helper
return
helper
class
VmAddInterfaceForm
(
forms
.
Form
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
choices
=
kwargs
.
pop
(
'choices'
)
super
(
VmAddInterfaceForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
field
=
forms
.
ModelChoiceField
(
queryset
=
choices
,
required
=
True
,
label
=
_
(
'Vlan'
))
if
not
choices
:
field
.
widget
.
attrs
[
'disabled'
]
=
'disabled'
field
.
empty_label
=
_
(
'No more networks.'
)
self
.
fields
[
'vlan'
]
=
field
@property
def
helper
(
self
):
helper
=
FormHelper
(
self
)
helper
.
form_tag
=
False
return
helper
class
CircleAuthenticationForm
(
AuthenticationForm
):
class
CircleAuthenticationForm
(
AuthenticationForm
):
# fields: username, password
# fields: username, password
...
...
circle/dashboard/static/dashboard/vm-common.js
View file @
4684a0a9
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
$
(
function
()
{
$
(
function
()
{
/* vm operations */
/* vm operations */
$
(
'#ops, #vm-details-resources-disk, #vm-details-renew-op'
).
on
(
'click'
,
'.operation.btn'
,
function
(
e
)
{
$
(
'#ops, #vm-details-resources-disk, #vm-details-renew-op
, #vm-details-pw-reset, #vm-details-add-interface
'
).
on
(
'click'
,
'.operation.btn'
,
function
(
e
)
{
var
icon
=
$
(
this
).
children
(
"i"
).
addClass
(
'fa-spinner fa-spin'
);
var
icon
=
$
(
this
).
children
(
"i"
).
addClass
(
'fa-spinner fa-spin'
);
$
.
ajax
({
$
.
ajax
({
...
@@ -50,6 +50,9 @@ $(function() {
...
@@ -50,6 +50,9 @@ $(function() {
*/
*/
if
(
data
.
success
)
{
if
(
data
.
success
)
{
$
(
'a[href="#activity"]'
).
trigger
(
"click"
);
$
(
'a[href="#activity"]'
).
trigger
(
"click"
);
if
(
data
.
with_reload
)
{
location
.
reload
();
}
/* if there are messages display them */
/* if there are messages display them */
if
(
data
.
messages
&&
data
.
messages
.
length
>
0
)
{
if
(
data
.
messages
&&
data
.
messages
.
length
>
0
)
{
...
...
circle/dashboard/templates/dashboard/vm-detail/network.html
View file @
4684a0a9
{% load i18n %}
{% load i18n %}
{% load network_tags %}
{% load network_tags %}
<h2>
<h2>
<a
href=
"#"
id=
"vm-details-network-add"
class=
"btn btn-success pull-right no-js-hidden"
>
<div
id=
"vm-details-add-interface"
>
<i
class=
"fa fa-plus"
></i>
{% trans "add interface" %}
{% with op=op.add_interface %}{% if op %}
</a>
<a
href=
"{{op.get_url}}"
class=
"btn btn-{{op.effect}} operation pull-right"
{%
if
op
.
disabled
%}
disabled
{%
endif
%}
>
<i
class=
"fa fa-{{op.icon}}"
></i>
{% trans "add interface" %}
</a>
{% endif %}{% endwith %}
</div>
{% trans "Interfaces" %}
{% trans "Interfaces" %}
</h2>
</h2>
<div
class=
"js-hidden row"
id=
"vm-details-network-add-form"
>
<div
class=
"col-md-12"
>
<div>
<hr
/>
<h3>
{% trans "Add new network interface!" %}
</h3>
<form
method=
"POST"
action=
""
>
{% csrf_token %}
<div
class=
"input-group"
style=
"max-width: 330px;"
>
<select
name=
"new_network_vlan"
class=
"form-control font-awesome-font"
>
{% for v in vlans %}
<option
value=
"{{ v.pk }}"
>
{% if v.managed %}

{% else %}

{% endif %}
{{ v.name }}
</option>
{% empty %}
<option
value=
"-1"
>
No more networks!
</option>
{% endfor %}
</select>
<div
class=
"input-group-btn"
>
<button
{%
if
vlans
|
length =
=
0
%}
disabled
{%
endif
%}
type=
"submit"
class=
"btn btn-success"
><i
class=
"fa fa-plus-circle"
></i></button>
</div>
</div>
</form>
<hr
/>
</div>
</div>
</div>
{% for i in instance.interface_set.all %}
{% for i in instance.interface_set.all %}
<div>
<div>
...
...
circle/dashboard/tests/test_views.py
View file @
4684a0a9
...
@@ -24,8 +24,9 @@ from django.contrib.auth.models import User, Group
...
@@ -24,8 +24,9 @@ from django.contrib.auth.models import User, Group
from
django.contrib.auth.models
import
Permission
from
django.contrib.auth.models
import
Permission
from
django.contrib.auth
import
authenticate
from
django.contrib.auth
import
authenticate
from
dashboard.views
import
VmAddInterfaceView
from
vm.models
import
Instance
,
InstanceTemplate
,
Lease
,
Node
,
Trait
from
vm.models
import
Instance
,
InstanceTemplate
,
Lease
,
Node
,
Trait
from
vm.operations
import
WakeUpOperation
from
vm.operations
import
WakeUpOperation
,
AddInterfaceOperation
from
..models
import
Profile
from
..models
import
Profile
from
firewall.models
import
Vlan
,
Host
,
VlanGroup
from
firewall.models
import
Vlan
,
Host
,
VlanGroup
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
...
@@ -168,7 +169,8 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -168,7 +169,8 @@ class VmDetailTest(LoginMixin, TestCase):
def
test_unpermitted_network_add_wo_perm
(
self
):
def
test_unpermitted_network_add_wo_perm
(
self
):
c
=
Client
()
c
=
Client
()
self
.
login
(
c
,
"user2"
)
self
.
login
(
c
,
"user2"
)
response
=
c
.
post
(
"/dashboard/vm/1/"
,
{
'new_network_vlan'
:
1
})
response
=
c
.
post
(
"/dashboard/vm/1/op/add_interface/"
,
{
'vlan'
:
1
})
self
.
assertEqual
(
response
.
status_code
,
403
)
self
.
assertEqual
(
response
.
status_code
,
403
)
def
test_unpermitted_network_add_wo_vlan_perm
(
self
):
def
test_unpermitted_network_add_wo_vlan_perm
(
self
):
...
@@ -176,8 +178,18 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -176,8 +178,18 @@ class VmDetailTest(LoginMixin, TestCase):
self
.
login
(
c
,
"user2"
)
self
.
login
(
c
,
"user2"
)
inst
=
Instance
.
objects
.
get
(
pk
=
1
)
inst
=
Instance
.
objects
.
get
(
pk
=
1
)
inst
.
set_level
(
self
.
u2
,
'owner'
)
inst
.
set_level
(
self
.
u2
,
'owner'
)
response
=
c
.
post
(
"/dashboard/vm/1/"
,
{
'new_network_vlan'
:
1
})
interface_count
=
inst
.
interface_set
.
count
()
self
.
assertEqual
(
response
.
status_code
,
403
)
with
patch
.
object
(
AddInterfaceOperation
,
'async'
)
as
async
:
async
.
side_effect
=
inst
.
add_interface
.
call
with
patch
.
object
(
VmAddInterfaceView
,
'get_form_kwargs'
,
autospec
=
True
)
as
get_form_kwargs
:
get_form_kwargs
.
return_value
=
{
'choices'
:
Vlan
.
objects
.
all
()}
response
=
c
.
post
(
"/dashboard/vm/1/op/add_interface/"
,
{
'vlan'
:
1
})
self
.
assertEqual
(
response
.
status_code
,
302
)
assert
async
.
called
self
.
assertEqual
(
inst
.
interface_set
.
count
(),
interface_count
)
def
test_permitted_network_add
(
self
):
def
test_permitted_network_add
(
self
):
c
=
Client
()
c
=
Client
()
...
@@ -187,9 +199,12 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -187,9 +199,12 @@ class VmDetailTest(LoginMixin, TestCase):
vlan
=
Vlan
.
objects
.
get
(
id
=
1
)
vlan
=
Vlan
.
objects
.
get
(
id
=
1
)
vlan
.
set_level
(
self
.
u1
,
'user'
)
vlan
.
set_level
(
self
.
u1
,
'user'
)
interface_count
=
inst
.
interface_set
.
count
()
interface_count
=
inst
.
interface_set
.
count
()
response
=
c
.
post
(
"/dashboard/vm/1/"
,
with
patch
.
object
(
AddInterfaceOperation
,
'async'
)
as
mock_method
:
{
'new_network_vlan'
:
1
})
mock_method
.
side_effect
=
inst
.
add_interface
response
=
c
.
post
(
"/dashboard/vm/1/op/add_interface/"
,
{
'vlan'
:
1
})
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
assert
mock_method
.
called
self
.
assertEqual
(
inst
.
interface_set
.
count
(),
interface_count
+
1
)
self
.
assertEqual
(
inst
.
interface_set
.
count
(),
interface_count
+
1
)
def
test_permitted_network_delete
(
self
):
def
test_permitted_network_delete
(
self
):
...
@@ -401,8 +416,7 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -401,8 +416,7 @@ class VmDetailTest(LoginMixin, TestCase):
inst
.
set_level
(
self
.
u2
,
'owner'
)
inst
.
set_level
(
self
.
u2
,
'owner'
)
vlan
=
Vlan
.
objects
.
get
(
id
=
1
)
vlan
=
Vlan
.
objects
.
get
(
id
=
1
)
vlan
.
set_level
(
self
.
u2
,
'user'
)
vlan
.
set_level
(
self
.
u2
,
'user'
)
response
=
c
.
post
(
"/dashboard/vm/1/"
,
inst
.
add_interface
(
user
=
self
.
u2
,
vlan
=
vlan
)
{
'new_network_vlan'
:
1
})
host
=
Host
.
objects
.
get
(
host
=
Host
.
objects
.
get
(
interface__in
=
inst
.
interface_set
.
all
())
interface__in
=
inst
.
interface_set
.
all
())
self
.
u2
.
user_permissions
.
add
(
Permission
.
objects
.
get
(
self
.
u2
.
user_permissions
.
add
(
Permission
.
objects
.
get
(
...
@@ -421,8 +435,7 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -421,8 +435,7 @@ class VmDetailTest(LoginMixin, TestCase):
inst
.
set_level
(
self
.
u2
,
'owner'
)
inst
.
set_level
(
self
.
u2
,
'owner'
)
vlan
=
Vlan
.
objects
.
get
(
id
=
1
)
vlan
=
Vlan
.
objects
.
get
(
id
=
1
)
vlan
.
set_level
(
self
.
u2
,
'user'
)
vlan
.
set_level
(
self
.
u2
,
'user'
)
response
=
c
.
post
(
"/dashboard/vm/1/"
,
inst
.
add_interface
(
user
=
self
.
u2
,
vlan
=
vlan
)
{
'new_network_vlan'
:
1
})
host
=
Host
.
objects
.
get
(
host
=
Host
.
objects
.
get
(
interface__in
=
inst
.
interface_set
.
all
())
interface__in
=
inst
.
interface_set
.
all
())
self
.
u2
.
user_permissions
.
add
(
Permission
.
objects
.
get
(
self
.
u2
.
user_permissions
.
add
(
Permission
.
objects
.
get
(
...
...
circle/dashboard/views.py
View file @
4684a0a9
...
@@ -61,7 +61,8 @@ from .forms import (
...
@@ -61,7 +61,8 @@ from .forms import (
UserCreationForm
,
GroupProfileUpdateForm
,
UnsubscribeForm
,
UserCreationForm
,
GroupProfileUpdateForm
,
UnsubscribeForm
,
VmSaveForm
,
UserKeyForm
,
VmRenewForm
,
VmSaveForm
,
UserKeyForm
,
VmRenewForm
,
CirclePasswordChangeForm
,
VmCreateDiskForm
,
VmDownloadDiskForm
,
CirclePasswordChangeForm
,
VmCreateDiskForm
,
VmDownloadDiskForm
,
TraitsForm
,
RawDataForm
,
GroupPermissionForm
,
AclUserAddForm
TraitsForm
,
RawDataForm
,
GroupPermissionForm
,
AclUserAddForm
,
VmAddInterfaceForm
,
)
)
from
.tables
import
(
from
.tables
import
(
...
@@ -309,7 +310,6 @@ class VmDetailView(CheckedDetailView):
...
@@ -309,7 +310,6 @@ class VmDetailView(CheckedDetailView):
'new_tag'
:
self
.
__add_tag
,
'new_tag'
:
self
.
__add_tag
,
'to_remove'
:
self
.
__remove_tag
,
'to_remove'
:
self
.
__remove_tag
,
'port'
:
self
.
__add_port
,
'port'
:
self
.
__add_port
,
'new_network_vlan'
:
self
.
__new_network
,
'abort_operation'
:
self
.
__abort_operation
,
'abort_operation'
:
self
.
__abort_operation
,
}
}
for
k
,
v
in
options
.
iteritems
():
for
k
,
v
in
options
.
iteritems
():
...
@@ -454,24 +454,6 @@ class VmDetailView(CheckedDetailView):
...
@@ -454,24 +454,6 @@ class VmDetailView(CheckedDetailView):
return
redirect
(
reverse_lazy
(
"dashboard.views.detail"
,
return
redirect
(
reverse_lazy
(
"dashboard.views.detail"
,
kwargs
=
{
'pk'
:
self
.
get_object
()
.
pk
}))
kwargs
=
{
'pk'
:
self
.
get_object
()
.
pk
}))
def
__new_network
(
self
,
request
):
self
.
object
=
self
.
get_object
()
if
not
self
.
object
.
has_level
(
request
.
user
,
'owner'
):
raise
PermissionDenied
()
vlan
=
get_object_or_404
(
Vlan
,
pk
=
request
.
POST
.
get
(
"new_network_vlan"
))
if
not
vlan
.
has_level
(
request
.
user
,
'user'
):
raise
PermissionDenied
()
try
:
self
.
object
.
add_interface
(
vlan
=
vlan
,
user
=
request
.
user
)
messages
.
success
(
request
,
_
(
"Successfully added new interface."
))
except
Exception
,
e
:
error
=
u' '
.
join
(
e
.
messages
)
messages
.
error
(
request
,
error
)
return
redirect
(
"
%
s#network"
%
reverse_lazy
(
"dashboard.views.detail"
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
}))
def
__abort_operation
(
self
,
request
):
def
__abort_operation
(
self
,
request
):
self
.
object
=
self
.
get_object
()
self
.
object
=
self
.
get_object
()
...
@@ -643,7 +625,9 @@ class FormOperationMixin(object):
...
@@ -643,7 +625,9 @@ class FormOperationMixin(object):
request
,
extra
,
*
args
,
**
kwargs
)
request
,
extra
,
*
args
,
**
kwargs
)
if
request
.
is_ajax
():
if
request
.
is_ajax
():
return
HttpResponse
(
return
HttpResponse
(
json
.
dumps
({
'success'
:
True
}),
json
.
dumps
({
'success'
:
True
,
'with_reload'
:
getattr
(
self
,
'with_reload'
,
False
)}),
content_type
=
"application=json"
content_type
=
"application=json"
)
)
else
:
else
:
...
@@ -660,6 +644,25 @@ class RequestFormOperationMixin(FormOperationMixin):
...
@@ -660,6 +644,25 @@ class RequestFormOperationMixin(FormOperationMixin):
return
val
return
val
class
VmAddInterfaceView
(
FormOperationMixin
,
VmOperationView
):
op
=
'add_interface'
form_class
=
VmAddInterfaceForm
show_in_toolbar
=
False
icon
=
'globe'
effect
=
'success'
with_reload
=
True
def
get_form_kwargs
(
self
):
inst
=
self
.
get_op
()
.
instance
choices
=
Vlan
.
get_objects_with_level
(
"user"
,
self
.
request
.
user
)
.
exclude
(
vm_interface__instance__in
=
[
inst
])
val
=
super
(
VmAddInterfaceView
,
self
)
.
get_form_kwargs
()
val
.
update
({
'choices'
:
choices
})
return
val
class
VmCreateDiskView
(
FormOperationMixin
,
VmOperationView
):
class
VmCreateDiskView
(
FormOperationMixin
,
VmOperationView
):
op
=
'create_disk'
op
=
'create_disk'
...
@@ -854,6 +857,7 @@ vm_ops = OrderedDict([
...
@@ -854,6 +857,7 @@ vm_ops = OrderedDict([
op
=
'destroy'
,
icon
=
'times'
,
effect
=
'danger'
)),
op
=
'destroy'
,
icon
=
'times'
,
effect
=
'danger'
)),
(
'create_disk'
,
VmCreateDiskView
),
(
'create_disk'
,
VmCreateDiskView
),
(
'download_disk'
,
VmDownloadDiskView
),
(
'download_disk'
,
VmDownloadDiskView
),
(
'add_interface'
,
VmAddInterfaceView
),
(
'renew'
,
VmRenewView
),
(
'renew'
,
VmRenewView
),
(
'resources_change'
,
VmResourcesChangeView
),
(
'resources_change'
,
VmResourcesChangeView
),
])
])
...
...
circle/vm/operations.py
View file @
4684a0a9
...
@@ -94,12 +94,21 @@ class AddInterfaceOperation(InstanceOperation):
...
@@ -94,12 +94,21 @@ class AddInterfaceOperation(InstanceOperation):
"the VM."
)
"the VM."
)
required_perms
=
()
required_perms
=
()
def
rollback
(
self
,
net
,
activity
):
with
activity
.
sub_activity
(
'destroying_net'
,
readable_name
=
ugettext_noop
(
"destroy network (rollback)"
)):
net
.
destroy
()
net
.
delete
()
def
check_precond
(
self
):
def
check_precond
(
self
):
super
(
AddInterfaceOperation
,
self
)
.
check_precond
()
super
(
AddInterfaceOperation
,
self
)
.
check_precond
()
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
,
'RUNNING'
]:
if
self
.
instance
.
status
not
in
[
'STOPPED'
,
'PENDING'
,
'RUNNING'
]:
raise
self
.
instance
.
WrongStateError
(
self
.
instance
)
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
not
vlan
.
has_level
(
user
,
'user'
):
raise
PermissionDenied
()
if
managed
is
None
:
if
managed
is
None
:
managed
=
vlan
.
managed
managed
=
vlan
.
managed
...
@@ -107,8 +116,13 @@ class AddInterfaceOperation(InstanceOperation):
...
@@ -107,8 +116,13 @@ 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'
):
try
:
self
.
instance
.
attach_network
(
net
)
with
activity
.
sub_activity
(
'attach_network'
):
self
.
instance
.
attach_network
(
net
)
except
Exception
as
e
:
if
hasattr
(
e
,
'libvirtError'
):
self
.
rollback
(
net
,
activity
)
raise
net
.
deploy
()
net
.
deploy
()
return
net
return
net
...
...
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