Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gelencsér Szabolcs
/
circlestack
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
7fed7d2c
authored
Jan 01, 2015
by
Bach Dániel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature-remove-garbage'
parents
32e83265
f876f926
Hide whitespace changes
Inline
Side-by-side
Showing
39 changed files
with
477 additions
and
1369 deletions
+477
-1369
circle/circle/settings/base.py
+1
-0
circle/common/operations.py
+2
-0
circle/dashboard/forms.py
+31
-1
circle/dashboard/static/dashboard/activity.js
+116
-4
circle/dashboard/static/dashboard/dashboard.js
+27
-171
circle/dashboard/static/dashboard/group-details.js
+0
-36
circle/dashboard/static/dashboard/group-list.js
+3
-3
circle/dashboard/static/dashboard/node-create.js
+0
-10
circle/dashboard/static/dashboard/node-details.js
+0
-33
circle/dashboard/static/dashboard/node-list.js
+0
-45
circle/dashboard/static/dashboard/template-list.js
+0
-86
circle/dashboard/static/dashboard/vm-create.js
+16
-18
circle/dashboard/static/dashboard/vm-details.js
+1
-219
circle/dashboard/templates/dashboard/confirm/ajax-delete.html
+14
-8
circle/dashboard/templates/dashboard/confirm/ajax-node-status.html
+0
-27
circle/dashboard/templates/dashboard/confirm/ajax-remove.html
+0
-22
circle/dashboard/templates/dashboard/confirm/base-delete.html
+10
-4
circle/dashboard/templates/dashboard/confirm/base-remove.html
+0
-14
circle/dashboard/templates/dashboard/confirm/base-renew.html
+0
-32
circle/dashboard/templates/dashboard/confirm/mass-delete.html
+0
-18
circle/dashboard/templates/dashboard/confirm/node-flush.html
+0
-33
circle/dashboard/templates/dashboard/confirm/node-status.html
+0
-35
circle/dashboard/templates/dashboard/group-list/column-name.html
+1
-1
circle/dashboard/templates/dashboard/index-templates.html
+1
-1
circle/dashboard/templates/dashboard/modal-wrapper.html
+0
-19
circle/dashboard/templates/dashboard/node-detail.html
+2
-1
circle/dashboard/templates/dashboard/node-detail/_activity-timeline.html
+30
-29
circle/dashboard/templates/dashboard/node-detail/activity.html
+1
-1
circle/dashboard/templates/dashboard/vm-detail.html
+2
-1
circle/dashboard/templates/dashboard/vm-detail/network.html
+14
-7
circle/dashboard/tests/test_views.py
+22
-96
circle/dashboard/urls.py
+7
-8
circle/dashboard/views/group.py
+20
-78
circle/dashboard/views/node.py
+28
-87
circle/dashboard/views/template.py
+19
-95
circle/dashboard/views/user.py
+10
-48
circle/dashboard/views/util.py
+43
-1
circle/dashboard/views/vm.py
+50
-73
circle/vm/models/instance.py
+6
-4
No files found.
circle/circle/settings/base.py
View file @
7fed7d2c
...
@@ -198,6 +198,7 @@ PIPELINE_JS = {
...
@@ -198,6 +198,7 @@ PIPELINE_JS = {
"jquery-knob/dist/jquery.knob.min.js"
,
"jquery-knob/dist/jquery.knob.min.js"
,
"jquery-simple-slider/js/simple-slider.js"
,
"jquery-simple-slider/js/simple-slider.js"
,
"dashboard/dashboard.js"
,
"dashboard/dashboard.js"
,
"dashboard/activity.js"
,
"dashboard/group-details.js"
,
"dashboard/group-details.js"
,
"dashboard/group-list.js"
,
"dashboard/group-list.js"
,
"dashboard/js/stupidtable.min.js"
,
# no bower file
"dashboard/js/stupidtable.min.js"
,
# no bower file
...
...
circle/common/operations.py
View file @
7fed7d2c
...
@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None):
...
@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None):
"in the 'target_cls' parameter to this "
"in the 'target_cls' parameter to this "
"call."
)
"call."
)
assert
not
hasattr
(
target_cls
,
op_id
),
(
"target class already has an attribute with this id"
)
if
not
issubclass
(
target_cls
,
OperatedMixin
):
if
not
issubclass
(
target_cls
,
OperatedMixin
):
raise
TypeError
(
"
%
r is not a subclass of
%
r"
%
raise
TypeError
(
"
%
r is not a subclass of
%
r"
%
(
target_cls
.
__name__
,
OperatedMixin
.
__name__
))
(
target_cls
.
__name__
,
OperatedMixin
.
__name__
))
...
...
circle/dashboard/forms.py
View file @
7fed7d2c
...
@@ -898,7 +898,7 @@ class VmDownloadDiskForm(OperationForm):
...
@@ -898,7 +898,7 @@ class VmDownloadDiskForm(OperationForm):
def
clean
(
self
):
def
clean
(
self
):
cleaned_data
=
super
(
VmDownloadDiskForm
,
self
)
.
clean
()
cleaned_data
=
super
(
VmDownloadDiskForm
,
self
)
.
clean
()
if
not
cleaned_data
[
'name'
]:
if
not
cleaned_data
[
'name'
]:
if
cleaned_data
[
'url'
]
:
if
cleaned_data
.
get
(
'url'
)
:
cleaned_data
[
'name'
]
=
urlparse
(
cleaned_data
[
'name'
]
=
urlparse
(
cleaned_data
[
'url'
])
.
path
.
split
(
'/'
)[
-
1
]
cleaned_data
[
'url'
])
.
path
.
split
(
'/'
)[
-
1
]
if
not
cleaned_data
[
'name'
]:
if
not
cleaned_data
[
'name'
]:
...
@@ -908,6 +908,36 @@ class VmDownloadDiskForm(OperationForm):
...
@@ -908,6 +908,36 @@ class VmDownloadDiskForm(OperationForm):
return
cleaned_data
return
cleaned_data
class
VmRemoveInterfaceForm
(
OperationForm
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
choices
=
kwargs
.
pop
(
'choices'
)
self
.
interface
=
kwargs
.
pop
(
'default'
)
super
(
VmRemoveInterfaceForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
fields
.
insert
(
0
,
'interface'
,
forms
.
ModelChoiceField
(
queryset
=
choices
,
initial
=
self
.
interface
,
required
=
True
,
empty_label
=
None
,
label
=
_
(
'Interface'
)))
if
self
.
interface
:
self
.
fields
[
'interface'
]
.
widget
=
HiddenInput
()
@property
def
helper
(
self
):
helper
=
super
(
VmRemoveInterfaceForm
,
self
)
.
helper
if
self
.
interface
:
helper
.
layout
=
Layout
(
AnyTag
(
"div"
,
HTML
(
format_html
(
_
(
"<label>Vlan:</label> {0}"
),
self
.
interface
.
vlan
)),
css_class
=
"form-group"
,
),
Field
(
"interface"
),
)
return
helper
class
VmAddInterfaceForm
(
OperationForm
):
class
VmAddInterfaceForm
(
OperationForm
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
choices
=
kwargs
.
pop
(
'choices'
)
choices
=
kwargs
.
pop
(
'choices'
)
...
...
circle/dashboard/static/dashboard/
vm-common
.js
→
circle/dashboard/static/dashboard/
activity
.js
View file @
7fed7d2c
/* for functions in both vm list and vm detail */
$
(
function
()
{
$
(
function
()
{
var
in_progress
=
false
;
var
activity_hash
=
5
;
var
show_all
=
false
;
var
reload_vm_detail
=
false
;
/* do we need to check for new activities */
if
(
decideActivityRefresh
())
{
if
(
!
in_progress
)
{
checkNewActivity
(
1
);
in_progress
=
true
;
}
}
/* vm operations */
$
(
'a[href="#activity"]'
).
click
(
function
(){
$
(
'a[href="#activity"] i'
).
addClass
(
'fa-spin'
);
if
(
!
in_progress
)
{
checkNewActivity
(
1
);
in_progress
=
true
;
}
});
$
(
"#activity-refresh"
).
on
(
"click"
,
"#show-all-activities"
,
function
()
{
$
(
this
).
find
(
"i"
).
addClass
(
"fa-spinner fa-spin"
);
show_all
=
!
show_all
;
$
(
'a[href="#activity"]'
).
trigger
(
"click"
);
return
false
;
});
/* operations */
$
(
'#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper'
).
on
(
'click'
,
'.operation'
,
function
(
e
)
{
$
(
'#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper'
).
on
(
'click'
,
'.operation'
,
function
(
e
)
{
var
icon
=
$
(
this
).
children
(
"i"
).
addClass
(
'fa-spinner fa-spin'
);
var
icon
=
$
(
this
).
children
(
"i"
).
addClass
(
'fa-spinner fa-spin'
);
...
@@ -23,7 +48,7 @@ $(function() {
...
@@ -23,7 +48,7 @@ $(function() {
});
});
/* if the operation fails show the modal again */
/* if the operation fails show the modal again */
$
(
"body"
).
on
(
"click"
,
"#op-form-send"
,
function
()
{
$
(
"body"
).
on
(
"click"
,
"#
confirmation-modal #
op-form-send"
,
function
()
{
var
url
=
$
(
this
).
closest
(
"form"
).
prop
(
"action"
);
var
url
=
$
(
this
).
closest
(
"form"
).
prop
(
"action"
);
$
.
ajax
({
$
.
ajax
({
...
@@ -77,4 +102,91 @@ $(function() {
...
@@ -77,4 +102,91 @@ $(function() {
return
false
;
return
false
;
});
});
function
decideActivityRefresh
()
{
var
check
=
false
;
/* if something is still spinning */
if
(
$
(
'.timeline .activity i'
).
hasClass
(
'fa-spin'
))
check
=
true
;
return
check
;
}
function
checkNewActivity
(
runs
)
{
$
.
ajax
({
type
:
'GET'
,
url
:
$
(
'a[href="#activity"]'
).
attr
(
'data-activity-url'
),
data
:
{
'show_all'
:
show_all
},
success
:
function
(
data
)
{
var
new_activity_hash
=
(
data
.
activities
+
""
).
hashCode
();
if
(
new_activity_hash
!=
activity_hash
)
{
$
(
"#activity-refresh"
).
html
(
data
.
activities
);
}
activity_hash
=
new_activity_hash
;
$
(
"#ops"
).
html
(
data
.
ops
);
$
(
"#disk-ops"
).
html
(
data
.
disk_ops
);
$
(
"[title]"
).
tooltip
();
/* changing the status text */
var
icon
=
$
(
"#vm-details-state i"
);
if
(
data
.
is_new_state
)
{
if
(
!
icon
.
hasClass
(
"fa-spin"
))
icon
.
prop
(
"class"
,
"fa fa-spinner fa-spin"
);
}
else
{
icon
.
prop
(
"class"
,
"fa "
+
data
.
icon
);
}
var
vm_state
=
$
(
"#vm-details-state"
);
if
(
vm_state
.
length
)
{
vm_state
.
data
(
"status"
,
data
[
'status'
]);
$
(
"#vm-details-state span"
).
html
(
data
[
'human_readable_status'
].
toUpperCase
());
}
if
(
data
[
'status'
]
==
"RUNNING"
)
{
if
(
data
[
'connect_uri'
])
{
$
(
"#dashboard-vm-details-connect-button"
).
removeClass
(
'disabled'
);
}
$
(
"[data-target=#_console]"
).
attr
(
"data-toggle"
,
"pill"
).
attr
(
"href"
,
"#console"
).
parent
(
"li"
).
removeClass
(
"disabled"
);
}
else
{
if
(
data
[
'connect_uri'
])
{
$
(
"#dashboard-vm-details-connect-button"
).
addClass
(
'disabled'
);
}
$
(
"[data-target=#_console]"
).
attr
(
"data-toggle"
,
"_pill"
).
attr
(
"href"
,
"#"
).
parent
(
"li"
).
addClass
(
"disabled"
);
}
if
(
data
.
status
==
"STOPPED"
||
data
.
status
==
"PENDING"
)
{
$
(
".change-resources-button"
).
prop
(
"disabled"
,
false
);
$
(
".change-resources-help"
).
hide
();
}
else
{
$
(
".change-resources-button"
).
prop
(
"disabled"
,
true
);
$
(
".change-resources-help"
).
show
();
}
if
(
runs
>
0
&&
decideActivityRefresh
())
{
setTimeout
(
function
()
{
checkNewActivity
(
runs
+
1
);},
1000
+
Math
.
exp
(
runs
*
0.05
)
);
}
else
{
in_progress
=
false
;
if
(
reload_vm_detail
)
location
.
reload
();
}
$
(
'a[href="#activity"] i'
).
removeClass
(
'fa-spin'
);
},
error
:
function
()
{
in_progress
=
false
;
}
});
}
});
});
String
.
prototype
.
hashCode
=
function
()
{
var
hash
=
0
,
i
,
chr
,
len
;
if
(
this
.
length
==
0
)
return
hash
;
for
(
i
=
0
,
len
=
this
.
length
;
i
<
len
;
i
++
)
{
chr
=
this
.
charCodeAt
(
i
);
hash
=
((
hash
<<
5
)
-
hash
)
+
chr
;
hash
|=
0
;
// Convert to 32bit integer
}
return
hash
;
};
circle/dashboard/static/dashboard/dashboard.js
View file @
7fed7d2c
...
@@ -5,63 +5,39 @@ $(function () {
...
@@ -5,63 +5,39 @@ $(function () {
var
template
=
$
(
this
).
data
(
"template"
);
var
template
=
$
(
this
).
data
(
"template"
);
$
.
ajax
({
$
.
ajax
({
type
:
'GET'
,
type
:
'GET'
,
url
:
'/dashboard/vm/create/'
+
(
typeof
template
===
"undefined"
?
''
:
'?template='
+
template
),
url
:
$
(
this
).
attr
(
'href'
),
success
:
function
(
data
)
{
success
:
function
(
data
)
{
$
(
'body'
).
append
(
data
);
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
vmCreateLoaded
();
addSliderMiscs
();
addSliderMiscs
();
$
(
'#create-modal'
).
modal
(
'show'
);
var
modal
=
$
(
'#confirmation-modal'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
modal
.
modal
(
'show'
);
$
(
'#create-modal'
).
remove
();
modal
.
on
(
'hidden.bs.modal'
,
function
()
{
modal
.
remove
();
});
});
}
}
});
});
return
false
;
return
false
;
});
});
$
(
'.
node-create
'
).
click
(
function
(
e
)
{
$
(
'.
group-create, .node-create, .tx-tpl-ownership, .group-delete, .node-delete, .disk-remove, .template-delete, .delete-from-group
'
).
click
(
function
(
e
)
{
$
.
ajax
({
$
.
ajax
({
type
:
'GET'
,
type
:
'GET'
,
url
:
'/dashboard/node/create/'
,
url
:
$
(
this
).
prop
(
'href'
)
,
success
:
function
(
data
)
{
success
:
function
(
data
)
{
$
(
'body'
).
append
(
data
);
$
(
'body'
).
append
(
data
);
nodeCreateLoaded
();
var
modal
=
$
(
'#confirmation-modal'
);
addSliderMiscs
();
modal
.
modal
(
'show'
);
$
(
'#create-modal'
).
modal
(
'show'
);
modal
.
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
modal
.
remove
();
$
(
'#create-modal'
).
remove
();
});
}
});
return
false
;
});
$
(
'.group-create'
).
click
(
function
(
e
)
{
$
.
ajax
({
type
:
'GET'
,
url
:
'/dashboard/group/create/'
,
success
:
function
(
data
)
{
$
(
'body'
).
append
(
data
);
addSliderMiscs
();
$
(
'#create-modal'
).
modal
(
'show'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
remove
();
});
}
});
return
false
;
});
$
(
'.tx-tpl-ownership'
).
click
(
function
(
e
)
{
$
.
ajax
({
type
:
'GET'
,
url
:
$
(
'.tx-tpl-ownership'
).
attr
(
'href'
),
success
:
function
(
data
)
{
$
(
'body'
).
append
(
data
);
$
(
'#confirmation-modal'
).
modal
(
'show'
);
$
(
'#confirmation-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#confirmation-modal'
).
remove
();
});
});
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
if
(
xhr
.
status
===
403
)
{
addMessage
(
gettext
(
"Only the owners can delete the selected object."
),
"warning"
);
}
else
{
addMessage
(
gettext
(
"An error occurred. ("
)
+
xhr
.
status
+
")"
,
'danger'
)
}
}
}
});
});
return
false
;
return
false
;
...
@@ -70,12 +46,13 @@ $(function () {
...
@@ -70,12 +46,13 @@ $(function () {
$
(
'.template-choose'
).
click
(
function
(
e
)
{
$
(
'.template-choose'
).
click
(
function
(
e
)
{
$
.
ajax
({
$
.
ajax
({
type
:
'GET'
,
type
:
'GET'
,
url
:
'/dashboard/template/choose/'
,
url
:
$
(
this
).
prop
(
'href'
)
,
success
:
function
(
data
)
{
success
:
function
(
data
)
{
$
(
'body'
).
append
(
data
);
$
(
'body'
).
append
(
data
);
$
(
'#create-modal'
).
modal
(
'show'
);
var
modal
=
$
(
'#confirmation-modal'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
modal
.
modal
(
'show'
);
$
(
'#create-modal'
).
remove
();
modal
.
on
(
'hidden.bs.modal'
,
function
()
{
modal
.
remove
();
});
});
// check if user selected anything
// check if user selected anything
$
(
"#template-choose-next-button"
).
click
(
function
()
{
$
(
"#template-choose-next-button"
).
click
(
function
()
{
...
@@ -101,6 +78,7 @@ $(function () {
...
@@ -101,6 +78,7 @@ $(function () {
e
.
stopImmediatePropagation
();
e
.
stopImmediatePropagation
();
return
false
;
return
false
;
});
});
$
(
'[href=#index-list-view]'
).
click
(
function
(
e
)
{
$
(
'[href=#index-list-view]'
).
click
(
function
(
e
)
{
var
box
=
$
(
this
).
data
(
'index-box'
);
var
box
=
$
(
this
).
data
(
'index-box'
);
$
(
'#'
+
box
+
'-graph-view'
).
hide
();
$
(
'#'
+
box
+
'-graph-view'
).
hide
();
...
@@ -110,9 +88,10 @@ $(function () {
...
@@ -110,9 +88,10 @@ $(function () {
e
.
stopImmediatePropagation
();
e
.
stopImmediatePropagation
();
return
false
;
return
false
;
});
});
$
(
'body [title]:not(.title-favourite)'
).
tooltip
();
$
(
'body .title-favourite'
).
tooltip
({
'placement'
:
'right'
});
$
(
'body .title-favourite'
).
tooltip
({
'placement'
:
'right'
});
$
(
'body :input[title]'
).
tooltip
({
trigger
:
'focus'
,
placement
:
'auto right'
});
$
(
'body :input[title]'
).
tooltip
({
trigger
:
'focus'
,
placement
:
'auto right'
});
$
(
'body [title]'
).
tooltip
();
$
(
".knob"
).
knob
();
$
(
".knob"
).
knob
();
$
(
'[data-toggle="pill"]'
).
click
(
function
()
{
$
(
'[data-toggle="pill"]'
).
click
(
function
()
{
...
@@ -167,74 +146,6 @@ $(function () {
...
@@ -167,74 +146,6 @@ $(function () {
addSliderMiscs
();
addSliderMiscs
();
/* for VM removes buttons */
$
(
'.vm-delete'
).
click
(
function
()
{
var
vm_pk
=
$
(
this
).
data
(
'vm-pk'
);
var
dir
=
window
.
location
.
pathname
.
indexOf
(
'list'
)
==
-
1
;
addModalConfirmation
(
deleteObject
,
{
'url'
:
'/dashboard/vm/delete/'
+
vm_pk
+
'/'
,
'data'
:
[],
'pk'
:
vm_pk
,
'type'
:
"vm"
,
'redirect'
:
dir
});
return
false
;
});
/* for disk remove buttons */
$
(
'.disk-remove'
).
click
(
function
()
{
var
disk_pk
=
$
(
this
).
data
(
'disk-pk'
);
addModalConfirmation
(
deleteObject
,
{
'url'
:
'/dashboard/disk/'
+
disk_pk
+
'/remove/'
,
'data'
:
[],
'pk'
:
disk_pk
,
'type'
:
"disk"
,
});
return
false
;
});
/* for Node removes buttons */
$
(
'.node-delete'
).
click
(
function
()
{
var
node_pk
=
$
(
this
).
data
(
'node-pk'
);
var
dir
=
window
.
location
.
pathname
.
indexOf
(
'list'
)
==
-
1
;
addModalConfirmation
(
deleteObject
,
{
'url'
:
'/dashboard/node/delete/'
+
node_pk
+
'/'
,
'data'
:
[],
'pk'
:
node_pk
,
'type'
:
"node"
,
'redirect'
:
dir
});
return
false
;
});
/* for Node flush buttons */
$
(
'.node-flush'
).
click
(
function
()
{
var
node_pk
=
$
(
this
).
data
(
'node-pk'
);
var
postto
=
$
(
this
).
attr
(
'href'
);
var
dir
=
window
.
location
.
pathname
.
indexOf
(
'list'
)
==
-
1
;
addModalConfirmation
(
function
(){},
{
'url'
:
postto
,
'data'
:
[],
'pk'
:
node_pk
,
'type'
:
"node"
,
'redirect'
:
dir
});
return
false
;
});
/* for Group removes buttons */
$
(
'.group-delete'
).
click
(
function
()
{
var
group_pk
=
$
(
this
).
data
(
'group-pk'
);
var
dir
=
window
.
location
.
pathname
.
indexOf
(
'list'
)
==
-
1
;
addModalConfirmation
(
deleteObject
,
{
'url'
:
'/dashboard/group/delete/'
+
group_pk
+
'/'
,
'data'
:
[],
'type'
:
"group"
,
'pk'
:
group_pk
,
'redirect'
:
dir
});
return
false
;
});
/* search for vms */
/* search for vms */
var
my_vms
=
[];
var
my_vms
=
[];
$
(
"#dashboard-vm-search-input"
).
keyup
(
function
(
e
)
{
$
(
"#dashboard-vm-search-input"
).
keyup
(
function
(
e
)
{
...
@@ -558,62 +469,6 @@ function setDefaultSliderValues() {
...
@@ -558,62 +469,6 @@ function setDefaultSliderValues() {
}
}
/* deletes the VM with the pk
* if dir is true, then redirect to the dashboard landing page
* else it adds a success message */
function
deleteObject
(
data
)
{
$
.
ajax
({
type
:
'POST'
,
data
:
{
'redirect'
:
data
.
redirect
},
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
if
(
!
data
.
redirect
)
{
selected
=
[];
addMessage
(
re
.
message
,
'success'
);
if
(
data
.
type
===
"disk"
)
{
// no need to remove them from DOM
$
(
'a[data-disk-pk="'
+
data
.
pk
+
'"]'
).
parent
(
"li"
).
fadeOut
();
$
(
'a[data-disk-pk="'
+
data
.
pk
+
'"]'
).
parent
(
"h4"
).
fadeOut
();
}
else
{
$
(
'a[data-'
+
data
.
type
+
'-pk="'
+
data
.
pk
+
'"]'
).
closest
(
'tr'
).
fadeOut
(
function
()
{
$
(
this
).
remove
();
});
}
}
else
{
window
.
location
.
replace
(
'/dashboard'
);
}
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
'Uh oh :('
,
'danger'
);
}
});
}
function
massDeleteVm
(
data
)
{
f
=
function
()
{
selected
=
[];
// reset group buttons
$
(
'.vm-list-group-control a'
).
attr
(
'disabled'
,
true
);
$
(
this
).
remove
();
};
$
.
ajax
({
traditional
:
true
,
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
type
:
'POST'
,
data
:
{
'vms'
:
data
.
data
.
v
},
success
:
function
(
re
,
textStatus
,
xhr
)
{
for
(
var
i
=
0
;
i
<
data
.
data
.
v
.
length
;
i
++
)
$
(
'.vm-list-table tbody tr[data-vm-pk="'
+
data
.
data
.
v
[
i
]
+
'"]'
).
fadeOut
(
500
,
f
);
addMessage
(
re
.
message
,
'success'
);
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
// TODO this
}
});
}
function
addMessage
(
text
,
type
)
{
function
addMessage
(
text
,
type
)
{
...
@@ -701,6 +556,7 @@ function csrfSafeMethod(method) {
...
@@ -701,6 +556,7 @@ function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
// these HTTP methods do not require CSRF protection
return
(
/^
(
GET|HEAD|OPTIONS|TRACE
)
$/
.
test
(
method
));
return
(
/^
(
GET|HEAD|OPTIONS|TRACE
)
$/
.
test
(
method
));
}
}
$
.
ajaxSetup
({
$
.
ajaxSetup
({
beforeSend
:
function
(
xhr
,
settings
)
{
beforeSend
:
function
(
xhr
,
settings
)
{
if
(
!
csrfSafeMethod
(
settings
.
type
)
&&
!
this
.
crossDomain
)
{
if
(
!
csrfSafeMethod
(
settings
.
type
)
&&
!
this
.
crossDomain
)
{
...
...
circle/dashboard/static/dashboard/group-details.js
View file @
7fed7d2c
...
@@ -28,39 +28,3 @@
...
@@ -28,39 +28,3 @@
$
(
".group-details-help-button"
).
click
(
function
()
{
$
(
".group-details-help-button"
).
click
(
function
()
{
$
(
".group-details-help"
).
stop
().
slideToggle
();
$
(
".group-details-help"
).
stop
().
slideToggle
();
});
});
/* for Node removes buttons */
$
(
'.delete-from-group'
).
click
(
function
()
{
var
href
=
$
(
this
).
attr
(
'href'
);
var
tr
=
$
(
this
).
closest
(
'tr'
);
var
group
=
$
(
this
).
data
(
'group_pk'
);
var
member
=
$
(
this
).
data
(
'member_pk'
);
var
dir
=
window
.
location
.
pathname
.
indexOf
(
'list'
)
==
-
1
;
addModalConfirmation
(
removeMember
,
{
'url'
:
href
,
'data'
:
[],
'tr'
:
tr
,
'group_pk'
:
group
,
'member_pk'
:
member
,
'type'
:
"user"
,
'redirect'
:
dir
});
return
false
;
});
function
removeMember
(
data
)
{
$
.
ajax
({
type
:
'POST'
,
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
data
.
tr
.
fadeOut
(
function
()
{
$
(
this
).
remove
();});
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
'Uh oh :('
,
'danger'
);
}
});
}
circle/dashboard/static/dashboard/group-list.js
View file @
7fed7d2c
$
(
function
()
{
$
(
function
()
{
/* rename */
/* rename */
$
(
"#group-list-rename-button, .group-details-rename-button"
).
click
(
function
()
{
$
(
"#group-list-rename-button, .group-details-rename-button"
).
click
(
function
()
{
$
(
"
#
group-list-column-name"
,
$
(
this
).
closest
(
"tr"
)).
hide
();
$
(
"
.
group-list-column-name"
,
$
(
this
).
closest
(
"tr"
)).
hide
();
$
(
"#group-list-rename"
,
$
(
this
).
closest
(
"tr"
)).
css
(
'display'
,
'inline'
);
$
(
"#group-list-rename"
,
$
(
this
).
closest
(
"tr"
)).
css
(
'display'
,
'inline'
);
$
(
"#group-list-rename"
).
find
(
"input"
).
select
();
$
(
"#group-list-rename"
).
find
(
"input"
).
select
();
});
});
...
@@ -10,7 +10,7 @@ $(function() {
...
@@ -10,7 +10,7 @@ $(function() {
$
(
'.group-list-rename-submit'
).
click
(
function
()
{
$
(
'.group-list-rename-submit'
).
click
(
function
()
{
var
row
=
$
(
this
).
closest
(
"tr"
);
var
row
=
$
(
this
).
closest
(
"tr"
);
var
name
=
$
(
'#group-list-rename-name'
,
row
).
val
();
var
name
=
$
(
'#group-list-rename-name'
,
row
).
val
();
var
url
=
'/dashboard/group/'
+
row
.
children
(
"td:first-child"
).
text
().
replace
(
" "
,
""
)
+
'/'
;
var
url
=
row
.
find
(
".group-list-column-name a"
).
prop
(
"href"
)
;
$
.
ajax
({
$
.
ajax
({
method
:
'POST'
,
method
:
'POST'
,
url
:
url
,
url
:
url
,
...
@@ -18,7 +18,7 @@ $(function() {
...
@@ -18,7 +18,7 @@ $(function() {
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
data
,
textStatus
,
xhr
)
{
success
:
function
(
data
,
textStatus
,
xhr
)
{
$
(
"
#
group-list-column-name"
,
row
).
html
(
$
(
"
.
group-list-column-name"
,
row
).
html
(
$
(
"<a/>"
,
{
$
(
"<a/>"
,
{
'class'
:
"real-link"
,
'class'
:
"real-link"
,
href
:
"/dashboard/group/"
+
data
.
group_pk
+
"/"
,
href
:
"/dashboard/group/"
+
data
.
group_pk
+
"/"
,
...
...
circle/dashboard/static/dashboard/node-create.js
deleted
100644 → 0
View file @
32e83265
$
(
function
()
{
nodeCreateLoaded
();
});
function
nodeCreateLoaded
()
{
/* no js compatibility */
$
(
'.no-js-hidden'
).
show
();
$
(
'.js-hidden'
).
hide
();
}
circle/dashboard/static/dashboard/node-details.js
View file @
7fed7d2c
...
@@ -30,20 +30,6 @@ $(function() {
...
@@ -30,20 +30,6 @@ $(function() {
$
(
".node-details-help"
).
stop
().
slideToggle
();
$
(
".node-details-help"
).
stop
().
slideToggle
();
});
});
/* for Node removes buttons */
$
(
'.node-enable'
).
click
(
function
()
{
var
node_pk
=
$
(
this
).
data
(
'node-pk'
);
var
dir
=
window
.
location
.
pathname
.
indexOf
(
'list'
)
==
-
1
;
addModalConfirmation
(
changeNodeStatus
,
{
'url'
:
'/dashboard/node/status/'
+
node_pk
+
'/'
,
'data'
:
[],
'pk'
:
node_pk
,
'type'
:
"node"
,
'redirect'
:
dir
});
return
false
;
});
// remove trait
// remove trait
$
(
'.node-details-remove-trait'
).
click
(
function
()
{
$
(
'.node-details-remove-trait'
).
click
(
function
()
{
var
to_remove
=
$
(
this
).
data
(
"trait-pk"
);
var
to_remove
=
$
(
this
).
data
(
"trait-pk"
);
...
@@ -69,22 +55,3 @@ $(function() {
...
@@ -69,22 +55,3 @@ $(function() {
});
});
});
});
function
changeNodeStatus
(
data
)
{
$
.
ajax
({
type
:
'POST'
,
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
if
(
!
data
.
redirect
)
{
selected
=
[];
addMessage
(
re
.
message
,
'success'
);
}
else
{
window
.
location
.
replace
(
'/dashboard'
);
}
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
'Uh oh :('
,
'danger'
);
}
});
}
circle/dashboard/static/dashboard/node-list.js
View file @
7fed7d2c
...
@@ -9,49 +9,4 @@ $(function() {
...
@@ -9,49 +9,4 @@ $(function() {
$
(
'.false'
).
closest
(
"tr"
).
addClass
(
'danger'
);
$
(
'.false'
).
closest
(
"tr"
).
addClass
(
'danger'
);
$
(
'.true'
).
closest
(
"tr"
).
removeClass
(
'danger'
);
$
(
'.true'
).
closest
(
"tr"
).
removeClass
(
'danger'
);
}
}
function
statuschangeSuccess
(
tr
){
var
tspan
=
tr
.
children
(
'.enabled'
).
children
();
var
buttons
=
tr
.
children
(
'.actions'
).
children
(
'.btn-group'
).
children
(
'.dropdown-menu'
).
children
(
'li'
).
children
(
'.node-enable'
);
buttons
.
each
(
function
(
index
){
if
(
$
(
this
).
css
(
"display"
)
==
"block"
){
$
(
this
).
css
(
"display"
,
"none"
);
}
else
{
$
(
this
).
css
(
"display"
,
"block"
);
}
});
if
(
tspan
.
hasClass
(
"false"
)){
tspan
.
removeClass
(
"false"
);
tspan
.
addClass
(
"true"
);
tspan
.
text
(
"✔"
);
}
else
{
tspan
.
removeClass
(
"true"
);
tspan
.
addClass
(
"false"
);
tspan
.
text
(
"✘"
);
}
colortable
();
}
$
(
'#table_container'
).
on
(
'click'
,
'.node-enable'
,
function
()
{
var
tr
=
$
(
this
).
closest
(
"tr"
);
var
pk
=
$
(
this
).
attr
(
'data-node-pk'
);
var
url
=
$
(
this
).
attr
(
'href'
);
$
.
ajax
({
method
:
'POST'
,
url
:
url
,
data
:
{
'change_status'
:
''
},
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
data
,
textStatus
,
xhr
)
{
statuschangeSuccess
(
tr
);
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
"Error!"
,
"danger"
);
}
});
return
false
;
});
});
});
circle/dashboard/static/dashboard/template-list.js
View file @
7fed7d2c
$
(
function
()
{
$
(
function
()
{
/* for template removes buttons */
$
(
'.template-delete'
).
click
(
function
()
{
var
template_pk
=
$
(
this
).
data
(
'template-pk'
);
addModalConfirmationOrDisplayMessage
(
deleteTemplate
,
{
'url'
:
'/dashboard/template/delete/'
+
template_pk
+
'/'
,
'data'
:
[],
'template_pk'
:
template_pk
,
});
return
false
;
});
/* for lease removes buttons */
$
(
'.lease-delete'
).
click
(
function
()
{
var
lease_pk
=
$
(
this
).
data
(
'lease-pk'
);
addModalConfirmationOrDisplayMessage
(
deleteLease
,
{
'url'
:
'/dashboard/lease/delete/'
+
lease_pk
+
'/'
,
'data'
:
[],
'lease_pk'
:
lease_pk
,
});
return
false
;
});
/* template table sort */
/* template table sort */
var
ttable
=
$
(
".template-list-table"
).
stupidtable
();
var
ttable
=
$
(
".template-list-table"
).
stupidtable
();
...
@@ -43,67 +21,3 @@ $(function() {
...
@@ -43,67 +21,3 @@ $(function() {
event
.
preventDefault
();
event
.
preventDefault
();
});
});
});
});
// send POST request then delete the row in table
function
deleteTemplate
(
data
)
{
$
.
ajax
({
type
:
'POST'
,
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
addMessage
(
re
.
message
,
'success'
);
$
(
'a[data-template-pk="'
+
data
.
template_pk
+
'"]'
).
closest
(
'tr'
).
fadeOut
(
function
()
{
$
(
this
).
remove
();
});
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
'Uh oh :('
,
'danger'
);
}
});
}
// send POST request then delete the row in table
function
deleteLease
(
data
)
{
$
.
ajax
({
type
:
'POST'
,
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
addMessage
(
re
.
message
,
'success'
);
$
(
'a[data-lease-pk="'
+
data
.
lease_pk
+
'"]'
).
closest
(
'tr'
).
fadeOut
(
function
()
{
$
(
this
).
remove
();
});
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
'Uh oh :('
,
'danger'
);
}
});
}
function
addModalConfirmationOrDisplayMessage
(
func
,
data
)
{
$
.
ajax
({
type
:
'GET'
,
url
:
data
[
'url'
],
data
:
jQuery
.
param
(
data
[
'data'
]),
success
:
function
(
result
)
{
$
(
'body'
).
append
(
result
);
$
(
'#confirmation-modal'
).
modal
(
'show'
);
$
(
'#confirmation-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#confirmation-modal'
).
remove
();
});
$
(
'#confirmation-modal-button'
).
click
(
function
()
{
func
(
data
);
$
(
'#confirmation-modal'
).
modal
(
'hide'
);
});
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
if
(
xhr
.
status
===
403
)
{
addMessage
(
gettext
(
"Only the owners can delete the selected object."
),
"warning"
);
}
else
{
addMessage
(
gettext
(
"An error occurred. ("
)
+
xhr
.
status
+
")"
,
'danger'
)
}
}
});
}
circle/dashboard/static/dashboard/vm-create.js
View file @
7fed7d2c
...
@@ -20,15 +20,15 @@ function vmCreateLoaded() {
...
@@ -20,15 +20,15 @@ function vmCreateLoaded() {
var
template
=
$
(
this
).
data
(
"template-pk"
);
var
template
=
$
(
this
).
data
(
"template-pk"
);
$
.
get
(
"/dashboard/vm/create/?template="
+
template
,
function
(
data
)
{
$
.
get
(
"/dashboard/vm/create/?template="
+
template
,
function
(
data
)
{
var
r
=
$
(
'#c
reate
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#c
onfirmation
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
$
(
'body'
).
append
(
data
);
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
vmCreateLoaded
();
addSliderMiscs
();
addSliderMiscs
();
$
(
'#c
reate
-modal'
).
modal
(
'show'
);
$
(
'#c
onfirmation
-modal'
).
modal
(
'show'
);
$
(
'#c
reate
-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#c
onfirmation
-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#c
reate
-modal'
).
remove
();
$
(
'#c
onfirmation
-modal'
).
remove
();
});
});
$
(
"#c
reate
-modal"
).
on
(
"shown.bs.modal"
,
function
()
{
$
(
"#c
onfirmation
-modal"
).
on
(
"shown.bs.modal"
,
function
()
{
setDefaultSliderValues
();
setDefaultSliderValues
();
});
});
});
});
...
@@ -48,18 +48,18 @@ function vmCreateLoaded() {
...
@@ -48,18 +48,18 @@ function vmCreateLoaded() {
window
.
location
.
replace
(
data
.
redirect
+
'#activity'
);
window
.
location
.
replace
(
data
.
redirect
+
'#activity'
);
}
}
else
{
else
{
var
r
=
$
(
'#c
reate
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#c
onfirmation
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
$
(
'body'
).
append
(
data
);
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
vmCreateLoaded
();
addSliderMiscs
();
addSliderMiscs
();
$
(
'#c
reate
-modal'
).
modal
(
'show'
);
$
(
'#c
onfirmation
-modal'
).
modal
(
'show'
);
$
(
'#c
reate
-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#c
onfirmation
-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#c
reate
-modal'
).
remove
();
$
(
'#c
onfirmation
-modal'
).
remove
();
});
});
}
}
},
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
error
:
function
(
xhr
,
textStatus
,
error
)
{
var
r
=
$
(
'#c
reate
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#c
onfirmation
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
if
(
xhr
.
status
==
500
)
{
if
(
xhr
.
status
==
500
)
{
addMessage
(
"500 Internal Server Error"
,
"danger"
);
addMessage
(
"500 Internal Server Error"
,
"danger"
);
...
@@ -211,7 +211,7 @@ function vmCustomizeLoaded() {
...
@@ -211,7 +211,7 @@ function vmCustomizeLoaded() {
});
});
/* start vm button clicks */
/* start vm button clicks */
$
(
'#vm-create-customized-start'
).
click
(
function
()
{
$
(
'#
confirmation-modal #
vm-create-customized-start'
).
click
(
function
()
{
var
error
=
false
;
var
error
=
false
;
$
(
".cpu-count-input, .ram-input, #id_name, #id_amount "
).
each
(
function
()
{
$
(
".cpu-count-input, .ram-input, #id_name, #id_amount "
).
each
(
function
()
{
if
(
!
$
(
this
)[
0
].
checkValidity
())
{
if
(
!
$
(
this
)[
0
].
checkValidity
())
{
...
@@ -222,8 +222,6 @@ function vmCustomizeLoaded() {
...
@@ -222,8 +222,6 @@ function vmCustomizeLoaded() {
$
(
this
).
find
(
"i"
).
prop
(
"class"
,
"fa fa-spinner fa-spin"
);
$
(
this
).
find
(
"i"
).
prop
(
"class"
,
"fa fa-spinner fa-spin"
);
if
(
$
(
"#create-modal"
))
return
true
;
$
.
ajax
({
$
.
ajax
({
url
:
'/dashboard/vm/create/'
,
url
:
'/dashboard/vm/create/'
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
...
@@ -238,18 +236,18 @@ function vmCustomizeLoaded() {
...
@@ -238,18 +236,18 @@ function vmCustomizeLoaded() {
window
.
location
.
href
=
data
.
redirect
+
'#activity'
;
window
.
location
.
href
=
data
.
redirect
+
'#activity'
;
}
}
else
{
else
{
var
r
=
$
(
'#c
reate
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#c
onfirmation
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
$
(
'body'
).
append
(
data
);
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
vmCreateLoaded
();
addSliderMiscs
();
addSliderMiscs
();
$
(
'#c
reate
-modal'
).
modal
(
'show'
);
$
(
'#c
onfirmation
-modal'
).
modal
(
'show'
);
$
(
'#c
reate
-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#c
onfirmation
-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#c
reate
-modal'
).
remove
();
$
(
'#c
onfirmation
-modal'
).
remove
();
});
});
}
}
},
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
error
:
function
(
xhr
,
textStatus
,
error
)
{
var
r
=
$
(
'#c
reate
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#c
onfirmation
-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
if
(
xhr
.
status
==
500
)
{
if
(
xhr
.
status
==
500
)
{
addMessage
(
"500 Internal Server Error"
,
"danger"
);
addMessage
(
"500 Internal Server Error"
,
"danger"
);
...
...
circle/dashboard/static/dashboard/vm-details.js
View file @
7fed7d2c
var
show_all
=
false
;
var
in_progress
=
false
;
var
activity_hash
=
5
;
var
Websock_native
;
// not sure
var
Websock_native
;
// not sure
var
reload_vm_detail
=
false
;
$
(
function
()
{
$
(
function
()
{
/* do we need to check for new activities */
if
(
decideActivityRefresh
())
{
if
(
!
in_progress
)
{
checkNewActivity
(
1
);
in_progress
=
true
;
}
}
$
(
'a[href="#activity"]'
).
click
(
function
(){
$
(
'a[href="#activity"] i'
).
addClass
(
'fa-spin'
);
if
(
!
in_progress
)
{
checkNewActivity
(
1
);
in_progress
=
true
;
}
});
$
(
"#activity-refresh"
).
on
(
"click"
,
"#show-all-activities"
,
function
()
{
$
(
this
).
find
(
"i"
).
addClass
(
"fa-spinner fa-spin"
);
show_all
=
!
show_all
;
$
(
'a[href="#activity"]'
).
trigger
(
"click"
);
return
false
;
});
/* save resources */
/* save resources */
$
(
'#vm-details-resources-save'
).
click
(
function
(
e
)
{
$
(
'#vm-details-resources-save'
).
click
(
function
(
e
)
{
var
error
=
false
;
var
error
=
false
;
...
@@ -43,7 +16,7 @@ $(function() {
...
@@ -43,7 +16,7 @@ $(function() {
var
vm
=
$
(
this
).
data
(
"vm"
);
var
vm
=
$
(
this
).
data
(
"vm"
);
$
.
ajax
({
$
.
ajax
({
type
:
'POST'
,
type
:
'POST'
,
url
:
"/dashboard/vm/"
+
vm
+
"/op/resources_change/"
,
url
:
$
(
this
).
parent
(
"form"
).
prop
(
'action'
)
,
data
:
$
(
'#vm-details-resources-form'
).
serialize
(),
data
:
$
(
'#vm-details-resources-form'
).
serialize
(),
success
:
function
(
data
,
textStatus
,
xhr
)
{
success
:
function
(
data
,
textStatus
,
xhr
)
{
if
(
data
.
success
)
{
if
(
data
.
success
)
{
...
@@ -89,17 +62,6 @@ $(function() {
...
@@ -89,17 +62,6 @@ $(function() {
return
false
;
return
false
;
});
});
/* remove port */
$
(
'.vm-details-remove-port'
).
click
(
function
()
{
addModalConfirmation
(
removePort
,
{
'url'
:
$
(
this
).
prop
(
"href"
),
'data'
:
[],
'rule'
:
$
(
this
).
data
(
"rule"
)
});
return
false
;
});
/* for js fallback */
/* for js fallback */
$
(
"#vm-details-pw-show"
).
parent
(
"div"
).
children
(
"input"
).
prop
(
"type"
,
"password"
);
$
(
"#vm-details-pw-show"
).
parent
(
"div"
).
children
(
"input"
).
prop
(
"type"
,
"password"
);
...
@@ -123,80 +85,6 @@ $(function() {
...
@@ -123,80 +85,6 @@ $(function() {
span
.
tooltip
();
span
.
tooltip
();
});
});
/* change password confirmation */
$
(
"#vm-details-pw-change"
).
click
(
function
()
{
$
(
"#vm-details-pw-confirm"
).
fadeIn
();
return
false
;
});
/* change password */
$
(
".vm-details-pw-confirm-choice"
).
click
(
function
()
{
choice
=
$
(
this
).
data
(
"choice"
);
if
(
choice
)
{
pk
=
$
(
this
).
data
(
"vm"
);
$
.
ajax
({
type
:
'POST'
,
url
:
"/dashboard/vm/"
+
pk
+
"/"
,
data
:
{
'change_password'
:
'true'
},
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
location
.
reload
();
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
if
(
xhr
.
status
==
500
)
{
addMessage
(
"Internal Server Error"
,
"danger"
);
}
else
{
addMessage
(
xhr
.
status
+
" Unknown Error"
,
"danger"
);
}
}
});
}
else
{
$
(
"#vm-details-pw-confirm"
).
fadeOut
();
}
return
false
;
});
/* add network button */
$
(
"#vm-details-network-add"
).
click
(
function
()
{
$
(
"#vm-details-network-add-form"
).
toggle
();
return
false
;
});
/* add disk button */
$
(
"#vm-details-disk-add"
).
click
(
function
()
{
$
(
"#vm-details-disk-add-for-form"
).
html
(
$
(
"#vm-details-disk-add-form"
).
html
());
return
false
;
});
/* for interface remove buttons */
$
(
'.interface-remove'
).
click
(
function
()
{
var
interface_pk
=
$
(
this
).
data
(
'interface-pk'
);
addModalConfirmation
(
removeInterface
,
{
'url'
:
'/dashboard/interface/'
+
interface_pk
+
'/delete/'
,
'data'
:
[],
'pk'
:
interface_pk
,
'type'
:
"interface"
,
});
return
false
;
});
/* removing interface post */
function
removeInterface
(
data
)
{
$
.
ajax
({
type
:
'POST'
,
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
/* remove the html element */
$
(
'a[data-interface-pk="'
+
data
.
pk
+
'"]'
).
closest
(
"div"
).
fadeOut
();
location
.
reload
();
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
'Uh oh :('
,
'danger'
);
}
});
}
/* rename */
/* rename */
$
(
"#vm-details-h1-name, .vm-details-rename-button"
).
click
(
function
()
{
$
(
"#vm-details-h1-name, .vm-details-rename-button"
).
click
(
function
()
{
$
(
"#vm-details-h1-name"
).
hide
();
$
(
"#vm-details-h1-name"
).
hide
();
...
@@ -336,109 +224,3 @@ $(function() {
...
@@ -336,109 +224,3 @@ $(function() {
});
});
});
});
function
removePort
(
data
)
{
$
.
ajax
({
type
:
'POST'
,
url
:
data
.
url
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
re
,
textStatus
,
xhr
)
{
$
(
"a[data-rule="
+
data
.
rule
+
"]"
).
each
(
function
()
{
$
(
this
).
closest
(
"tr"
).
fadeOut
(
500
,
function
()
{
$
(
this
).
remove
();
});
});
addMessage
(
re
.
message
,
"success"
);
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
}
});
}
function
decideActivityRefresh
()
{
var
check
=
false
;
/* if something is still spinning */
if
(
$
(
'.timeline .activity i'
).
hasClass
(
'fa-spin'
))
check
=
true
;
return
check
;
}
function
checkNewActivity
(
runs
)
{
var
instance
=
location
.
href
.
split
(
'/'
);
instance
=
instance
[
instance
.
length
-
2
];
$
.
ajax
({
type
:
'GET'
,
url
:
'/dashboard/vm/'
+
instance
+
'/activity/'
,
data
:
{
'show_all'
:
show_all
},
success
:
function
(
data
)
{
var
new_activity_hash
=
(
data
.
activities
+
""
).
hashCode
();
if
(
new_activity_hash
!=
activity_hash
)
{
$
(
"#activity-refresh"
).
html
(
data
.
activities
);
}
activity_hash
=
new_activity_hash
;
$
(
"#ops"
).
html
(
data
.
ops
);
$
(
"#disk-ops"
).
html
(
data
.
disk_ops
);
$
(
"[title]"
).
tooltip
();
/* changing the status text */
var
icon
=
$
(
"#vm-details-state i"
);
if
(
data
.
is_new_state
)
{
if
(
!
icon
.
hasClass
(
"fa-spin"
))
icon
.
prop
(
"class"
,
"fa fa-spinner fa-spin"
);
}
else
{
icon
.
prop
(
"class"
,
"fa "
+
data
.
icon
);
}
$
(
"#vm-details-state"
).
data
(
"status"
,
data
[
'status'
]);
$
(
"#vm-details-state span"
).
html
(
data
[
'human_readable_status'
].
toUpperCase
());
if
(
data
[
'status'
]
==
"RUNNING"
)
{
if
(
data
[
'connect_uri'
])
{
$
(
"#dashboard-vm-details-connect-button"
).
removeClass
(
'disabled'
);
}
$
(
"[data-target=#_console]"
).
attr
(
"data-toggle"
,
"pill"
).
attr
(
"href"
,
"#console"
).
parent
(
"li"
).
removeClass
(
"disabled"
);
}
else
{
if
(
data
[
'connect_uri'
])
{
$
(
"#dashboard-vm-details-connect-button"
).
addClass
(
'disabled'
);
}
$
(
"[data-target=#_console]"
).
attr
(
"data-toggle"
,
"_pill"
).
attr
(
"href"
,
"#"
).
parent
(
"li"
).
addClass
(
"disabled"
);
}
if
(
data
.
status
==
"STOPPED"
||
data
.
status
==
"PENDING"
)
{
$
(
".change-resources-button"
).
prop
(
"disabled"
,
false
);
$
(
".change-resources-help"
).
hide
();
}
else
{
$
(
".change-resources-button"
).
prop
(
"disabled"
,
true
);
$
(
".change-resources-help"
).
show
();
}
if
(
runs
>
0
&&
decideActivityRefresh
())
{
setTimeout
(
function
()
{
checkNewActivity
(
runs
+
1
);},
1000
+
Math
.
exp
(
runs
*
0.05
)
);
}
else
{
in_progress
=
false
;
if
(
reload_vm_detail
)
location
.
reload
();
}
$
(
'a[href="#activity"] i'
).
removeClass
(
'fa-spin'
);
},
error
:
function
()
{
in_progress
=
false
;
}
});
}
String
.
prototype
.
hashCode
=
function
()
{
var
hash
=
0
,
i
,
chr
,
len
;
if
(
this
.
length
===
0
)
return
hash
;
for
(
i
=
0
,
len
=
this
.
length
;
i
<
len
;
i
++
)
{
chr
=
this
.
charCodeAt
(
i
);
hash
=
((
hash
<<
5
)
-
hash
)
+
chr
;
hash
|=
0
;
// Convert to 32bit integer
}
return
hash
;
};
circle/dashboard/templates/dashboard/confirm/ajax-delete.html
View file @
7fed7d2c
...
@@ -3,19 +3,25 @@
...
@@ -3,19 +3,25 @@
<div
class=
"modal-dialog"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content"
>
<div
class=
"modal-content"
>
<div
class=
"modal-body"
>
<div
class=
"modal-body"
>
{% if text %}
{% if member %}
{{ text|safe }}
{% blocktrans with group=object member=member %}
Do you really want to remove
<strong>
{{ member }}
</strong>
from {{ group }}?
{% endblocktrans %}
{% else %}
{% else %}
{%
blocktrans with object=object
%}
{%
blocktrans with object=object
%}
Are you sure you want to delete
<strong>
{{ object }}
</strong>
?
Are you sure you want to delete
<strong>
{{ object }}
</strong>
?
{%
endblocktrans
%}
{%
endblocktrans
%}
{% endif %}
{% endif %}
<br
/>
<br
/>
<div
class=
"pull-right"
style=
"margin-top: 15px;"
>
<div
class=
"pull-right"
style=
"margin-top: 15px;"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
{% trans "Cancel" %}
</button>
<form
action=
"{{ request.path }}"
method=
"POST"
>
<button
id=
"confirmation-modal-button"
type=
"button"
class=
"btn btn-danger"
{% csrf_token %}
{%
if
disable_submit
%}
disabled
{%
endif
%}
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
{% trans "Cancel" %}
</button>
>
{% trans "Delete" %}
</button>
<input
type=
"hidden"
name=
"next"
value=
"{{ request.GET.next }}"
/>
<button
class=
"btn btn-danger"
{%
if
disable_submit
%}
disabled
{%
endif
%}
>
{% trans "Delete" %}
</button>
</form>
</div>
</div>
<div
class=
"clearfix"
></div>
<div
class=
"clearfix"
></div>
</div>
</div>
...
...
circle/dashboard/templates/dashboard/confirm/ajax-node-status.html
deleted
100644 → 0
View file @
32e83265
{% load i18n %}
<div
class=
"modal fade"
id=
"confirmation-modal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content"
>
<div
class=
"modal-body"
>
{% if text %}
{{ text }}
{% else %}
{%blocktrans with object=object%}
Are you sure you want to change
<strong>
{{ object }}
</strong>
status?
{%endblocktrans%}
{% endif %}
<div
class=
"pull-right"
>
<form
action=
"{% url "
dashboard
.
views
.
status-node
"
pk=
object.pk
%}"
method=
"POST"
>
{% csrf_token %}
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
{% trans "Cancel" %}
</button>
<input
type=
"hidden"
name=
"change_status"
value=
""
/>
<button
class=
"btn btn-warning"
>
{% blocktrans with status=status %}Yes, {{status}}{% endblocktrans %}
</button>
</form>
</div>
<div
class=
"clearfix"
></div>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
circle/dashboard/templates/dashboard/confirm/ajax-remove.html
deleted
100644 → 0
View file @
32e83265
{% load i18n %}
<div
class=
"modal fade"
id=
"confirmation-modal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content"
>
<div
class=
"modal-body"
>
{% if text %}
{{ text }}
{% else %}
{%blocktrans with object=object%}
Are you sure you want to remove
<strong>
{{ member }}
</strong>
from
<strong>
{{ object }}
</strong>
?
{%endblocktrans%}
{% endif %}
<br
/>
<div
class=
"pull-right"
style=
"margin-top: 15px;"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
Cancel
</button>
<button
id=
"confirmation-modal-button"
type=
"button"
class=
"btn btn-warning"
>
Remove
</button>
</div>
<div
class=
"clearfix"
></div>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
circle/dashboard/templates/dashboard/confirm/base-delete.html
View file @
7fed7d2c
...
@@ -17,12 +17,18 @@
...
@@ -17,12 +17,18 @@
{% if text %}
{% if text %}
{{ text|safe }}
{{ text|safe }}
{% else %}
{% else %}
{%blocktrans with object=object%}
{% if member %}
Are you sure you want to delete
<strong>
{{ object }}
</strong>
?
{% blocktrans with group=object member=member %}
{%endblocktrans%}
Do you really want to remove
<strong>
{{ member }}
</strong>
from {{ group }}?
{% endblocktrans %}
{% else %}
{% blocktrans with object=object %}
Are you sure you want to delete
<strong>
{{ object }}
</strong>
?
{% endblocktrans %}
{% endif %}
{% endif %}
{% endif %}
<div
class=
"pull-right"
>
<div
class=
"pull-right"
>
<form
action=
""
method=
"POST"
>
<form
action=
"
{{ request.path }}
"
method=
"POST"
>
{% csrf_token %}
{% csrf_token %}
<a
class=
"btn btn-default"
>
{% trans "Cancel" %}
</a>
<a
class=
"btn btn-default"
>
{% trans "Cancel" %}
</a>
<input
type=
"hidden"
name=
"next"
value=
"{{ request.GET.next }}"
/>
<input
type=
"hidden"
name=
"next"
value=
"{{ request.GET.next }}"
/>
...
...
circle/dashboard/templates/dashboard/confirm/base-remove.html
deleted
100644 → 0
View file @
32e83265
{% extends "base.html" %}
{% load i18n %}
{% block title-site %}Dashboard | CIRCLE{% endblock %}
{% block content %}
{% blocktrans with group=object member=member %}
Do you really want to remove {{member}} from {{group}}?
{% endblocktrans %}
<form
action=
""
method=
"POST"
>
{% csrf_token %}
<input
type=
"submit"
value=
"{% trans "
Remove
"
%}"
/>
</form>
{% endblock %}
circle/dashboard/templates/dashboard/confirm/base-renew.html
deleted
100644 → 0
View file @
32e83265
{% extends "dashboard/base.html" %}
{% load i18n %}
{% block content %}
<div
class=
"body-content"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<h3
class=
"no-margin"
>
{%blocktrans with instance=instance.name%}
Renewing
<em>
{{instance}}
</em>
{%endblocktrans%}
</h3>
</div>
<div
class=
"panel-body"
>
{%blocktrans with object=instance.name%}
Do you want to renew
<strong>
{{ object }}
</strong>
?
{%endblocktrans%}
{%blocktrans with suspend=time_of_suspend delete=time_of_delete|default:"n/a" %}
The instance will be suspended at
<em>
{{suspend}}
</em>
and removed at
<em>
{{delete}}
</em>
if you renew it now.
{%endblocktrans%}
<div
class=
"pull-right"
>
<form
action=
""
method=
"POST"
>
{% csrf_token %}
<a
class=
"btn btn-default"
href=
"{{instance.get_absolute_path}}"
>
{% trans "Back" %}
</a>
<button
class=
"btn btn-danger"
>
{% trans "Renew" %}
</button>
</form>
</div>
</div>
</div>
{% endblock %}
circle/dashboard/templates/dashboard/confirm/mass-delete.html
deleted
100644 → 0
View file @
32e83265
{% load i18n %}
<div
class=
"modal fade"
id=
"confirmation-modal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content"
>
<div
class=
"modal-body"
>
{% trans "Are you sure you want to delete the following objects?" %}
<br
/>
{% for o in objects %}
<strong>
{{ o }}
</strong>
{% if not forloop.last %},{% endif %}
{% endfor %}
<div
class=
"pull-right"
style=
"margin-top: 40px;"
>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
>
{% trans "Cancel" %}
</button>
<button
id=
"confirmation-modal-button"
type=
"button"
class=
"btn btn-danger"
>
{% trans "Delete" %}
</button>
</div>
<div
class=
"clearfix"
></div>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
circle/dashboard/templates/dashboard/confirm/node-flush.html
deleted
100644 → 0
View file @
32e83265
{% extends "dashboard/base.html" %}
{% load i18n %}
{% block content %}
<div
class=
"body-content"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<h3
class=
"no-margin"
>
{% if title %}
{{ title }}
{% else %}
Flush confirmation
{% endif %}
</h3>
</div>
<div
class=
"panel-body"
>
{% if text %}
{{ text }}
{% else %}
{%blocktrans with object=object%}
Are you sure you want to flush
<strong>
{{ object }}
</strong>
?
{%endblocktrans%}
{% endif %}
<div
class=
"pull-right"
>
<form
action=
""
method=
"POST"
>
{% csrf_token %}
<a
class=
"btn btn-default"
>
{% trans "Back" %}
</a>
<input
type=
"hidden"
name=
"flush"
value=
""
/>
<button
class=
"btn btn-warning"
>
{% trans "Yes" %}
</button>
</form>
</div>
</div>
</div>
{% endblock %}
circle/dashboard/templates/dashboard/confirm/node-status.html
deleted
100644 → 0
View file @
32e83265
{% extends "dashboard/base.html" %}
{% load i18n %}
{% block content %}
<div
class=
"body-content"
>
<div
class=
"panel panel-default"
>
<div
class=
"panel-heading"
>
<h3
class=
"no-margin"
>
{% if title %}
{{ title }}
{% else %}
{% trans "Status changing confirmation" %}
{% endif %}
</h3>
</div>
<div
class=
"panel-body"
>
{% if text %}
{{ text }}
{% else %}
{%blocktrans with object=object%}
Are you sure you want to change
<strong>
{{ object }}
</strong>
status?
{%endblocktrans%}
{% endif %}
<div
class=
"pull-right"
>
<form
action=
""
method=
"POST"
>
{% csrf_token %}
<a
class=
"btn btn-default"
>
{% trans "Cancel" %}
</a>
<button
type=
"button"
class=
"btn btn-default"
data-dismiss=
"modal"
></button>
<input
type=
"hidden"
name=
"change_status"
value=
""
/>
<button
class=
"btn btn-warning"
>
{% blocktrans with status=status %}Yes, {{status}}{% endblocktrans %}
</button>
</form>
</div>
</div>
</div>
{% endblock %}
circle/dashboard/templates/dashboard/group-list/column-name.html
View file @
7fed7d2c
...
@@ -7,6 +7,6 @@
...
@@ -7,6 +7,6 @@
<button
type=
"submit"
class=
"group-list-rename-submit btn btn-sm"
>
{% trans "Rename" %}
</button>
<button
type=
"submit"
class=
"group-list-rename-submit btn btn-sm"
>
{% trans "Rename" %}
</button>
</form>
</form>
</div>
</div>
<div
id
=
"group-list-column-name"
>
<div
class
=
"group-list-column-name"
>
<a
class=
"real-link"
href=
"{% url "
dashboard
.
views
.
group-detail
"
pk=
record.pk
%}"
>
{{ record.name }}
</a>
<a
class=
"real-link"
href=
"{% url "
dashboard
.
views
.
group-detail
"
pk=
record.pk
%}"
>
{{ record.name }}
</a>
</div>
</div>
circle/dashboard/templates/dashboard/index-templates.html
View file @
7fed7d2c
...
@@ -16,7 +16,7 @@
...
@@ -16,7 +16,7 @@
<i
class=
"fa fa-{{ t.os_type }}"
></i>
{{ t.name }}
<i
class=
"fa fa-{{ t.os_type }}"
></i>
{{ t.name }}
</span>
</span>
<small
class=
"text-muted index-template-list-system"
>
{{ t.system }}
</small>
<small
class=
"text-muted index-template-list-system"
>
{{ t.system }}
</small>
<div
class=
"pull-right vm-create"
data-template=
"{{ t.pk }}
"
>
<div
href=
"{% url "
dashboard
.
views
.
vm-create
"
%}?
template=
{{
t
.
pk
}}"
class=
"pull-right vm-create
"
>
<i
data-container=
"body"
title=
"{% trans "
Start
VM
instance
"
%}"
<i
data-container=
"body"
title=
"{% trans "
Start
VM
instance
"
%}"
class=
"fa fa-play"
></i>
class=
"fa fa-play"
></i>
</div>
</div>
...
...
circle/dashboard/templates/dashboard/modal-wrapper.html
deleted
100644 → 0
View file @
32e83265
<div
class=
"modal fade"
id=
"create-modal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content"
>
{% if box_title and ajax_title %}
<div
class=
"modal-header"
>
<button
type=
"button"
class=
"close"
data-dismiss=
"modal"
aria-hidden=
"true"
>
×
</button>
<h4
class=
"modal-title"
>
{{ box_title }}
</h4>
</div>
{% endif %}
<div
class=
"modal-body"
>
{% include template %}
</div>
<!--<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>-->
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
circle/dashboard/templates/dashboard/node-detail.html
View file @
7fed7d2c
...
@@ -80,7 +80,8 @@
...
@@ -80,7 +80,8 @@
</a>
</a>
</li>
</li>
<li>
<li>
<a
href=
"#activity"
data-toggle=
"pill"
class=
"text-center"
>
<a
href=
"#activity"
data-toggle=
"pill"
class=
"text-center"
data-activity-url=
"{% url "
dashboard
.
views
.
node-activity-list
"
node
.
pk
%}"
>
<i
class=
"fa fa-clock-o fa-2x"
></i><br>
<i
class=
"fa fa-clock-o fa-2x"
></i><br>
{% trans "Activity" %}
{% trans "Activity" %}
</a>
</a>
...
...
circle/dashboard/templates/dashboard/node-detail/_activity-timeline.html
View file @
7fed7d2c
{% load i18n %}
{% load i18n %}
{% load hro %}
{% load hro %}
<div
id=
"activity-timeline"
class=
"timeline"
>
<div
id=
"activity-timeline"
class=
"timeline"
>
{% for a in activities %}
{% for a in activities %}
<div
class=
"activity"
data-activity-id=
"{{ a.pk }}"
>
<div
class=
"activity"
data-activity-id=
"{{ a.pk }}"
>
<span
class=
"timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}"
>
<span
class=
"timeline-icon{% if a.has_failed %} timeline-icon-failed{% endif %}"
>
<i
class=
"fa {% if not a.finished %}fa-refresh fa-spin {% else %}fa-plus{% endif %}"
></i>
<i
class=
"fa {% if not a.finished %}fa-refresh fa-spin {% else %}fa-plus{% endif %}"
></i>
</span>
</span>
<strong
title=
"{{ a.result.get_admin_text }}"
>
<strong
title=
"{{ a.result.get_admin_text }}"
>
{{ a.readable_name.get_admin_text|capfirst }}
{{ a.readable_name.get_admin_text|capfirst }}
</strong>
</strong>
{{ a.started|date:"Y-m-d H:i" }}, {{ a.user }}
{{ a.started|date:"Y-m-d H:i" }}{% if a.user %}, {{ a.user }}{% endif %}
{% if a.children.count > 0 %}
{% if a.children.count > 0 %}
<div
class=
"sub-timeline"
>
<div
class=
"sub-timeline"
>
{% for s in a.children.all %}
{% for s in a.children.all %}
<div
data-activity-id=
"{{ s.pk }}"
<div
data-activity-id=
"{{ s.pk }}"
class=
"sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}"
class=
"sub-activity{% if s.has_failed %} sub-activity-failed{% endif %}"
>
>
<span
title=
"{{ s.result.get_admin_text }}"
>
{{ s.readable_name|get_text:user }}
{{ s.readable_name|get_text:user }}
–
</span>
{% if s.finished %}
–
{{ s.finished|time:"H:i:s" }}
{% if s.finished %}
{% else %}
{{ s.finished|time:"H:i:s" }}
<i
class=
"fa fa-refresh fa-spin"
class=
"sub-activity-loading-icon"
></i>
{% else %}
{% endif %}
<i
class=
"fa fa-refresh fa-spin"
class=
"sub-activity-loading-icon"
></i>
{% if s.has_failed %}
{% endif %}
<div
title=
"{{ s.result.get_admin_text }}"
class=
"label label-danger"
>
{% trans "failed" %}
</div>
{% if s.has_failed %}
{% endif %}
<div
class=
"label label-danger"
>
{% trans "failed" %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
{% endif %}
</div>
{% endif %}
</div>
</div>
{% endfor %}
{% endfor %}
</div>
</div>
circle/dashboard/templates/dashboard/node-detail/activity.html
View file @
7fed7d2c
...
@@ -2,6 +2,6 @@
...
@@ -2,6 +2,6 @@
<h3>
{% trans "Activity" %}
</h3>
<h3>
{% trans "Activity" %}
</h3>
<div
id=
"activity-
timeline-wrapper
"
>
<div
id=
"activity-
refresh
"
>
{% include "dashboard/node-detail/_activity-timeline.html" %}
{% include "dashboard/node-detail/_activity-timeline.html" %}
</div>
</div>
circle/dashboard/templates/dashboard/vm-detail.html
View file @
7fed7d2c
...
@@ -207,7 +207,8 @@
...
@@ -207,7 +207,8 @@
{% trans "Network" %}
</a>
{% trans "Network" %}
</a>
</li>
</li>
<li>
<li>
<a
href=
"#activity"
data-toggle=
"pill"
data-target=
"#_activity"
class=
"text-center"
>
<a
href=
"#activity"
data-toggle=
"pill"
data-target=
"#_activity"
class=
"text-center"
data-activity-url=
"{% url "
dashboard
.
views
.
vm-activity-list
"
instance
.
pk
%}"
>
<i
class=
"fa fa-clock-o fa-2x"
></i><br>
<i
class=
"fa fa-clock-o fa-2x"
></i><br>
{% trans "Activity" %}
</a>
{% trans "Activity" %}
</a>
</li>
</li>
...
...
circle/dashboard/templates/dashboard/vm-detail/network.html
View file @
7fed7d2c
...
@@ -21,13 +21,14 @@
...
@@ -21,13 +21,14 @@
<a
href=
"{{ i.host.get_absolute_url }}"
<a
href=
"{{ i.host.get_absolute_url }}"
class=
"btn btn-default btn-xs"
>
{% trans "edit" %}
</a>
class=
"btn btn-default btn-xs"
>
{% trans "edit" %}
</a>
{% endif %}
{% endif %}
{%
if is_owner
%}
{%
with op=op.remove_interface %}{% if op
%}
<a
href=
"{% url "
dashboard
.
views
.
interface-delete
"
pk=
i.pk
%}?
next=
{{
request
.
path
}}"
<span
class=
"operation-wrapper"
>
class=
"btn btn-danger btn-xs interface-remove
"
<a
href=
"{{op.get_url}}?interface={{ i.pk }}
"
data-interface-pk=
"{{ i.pk }}"
>
class=
"btn btn-{{op.effect}} btn-xs operation interface-remove"
{% trans "remove" %}
{%
if
op
.
disabled
%}
disabled
{%
endif
%}
>
{% trans "remove" %}
</a>
</a>
{% endif %}
</span>
{% endif %}{% endwith %}
</h3>
</h3>
{% if i.host %}
{% if i.host %}
<div
class=
"row"
>
<div
class=
"row"
>
...
@@ -78,7 +79,13 @@
...
@@ -78,7 +79,13 @@
{{ l.private }}/{{ l.proto }}
{{ l.private }}/{{ l.proto }}
</td>
</td>
<td>
<td>
<a
href=
"{{ op.remove_port.get_url }}?rule={{ l.ipv4.pk }}"
class=
"btn btn-link btn-xs vm-details-remove-port"
data-rule=
"{{ l.ipv4.pk }}"
title=
"{% trans "
Remove
"
%}"
><i
class=
"fa fa-times"
><span
class=
"sr-only"
>
{% trans "Remove" %}
</span></i></a>
<span
class=
"operation-wrapper"
>
<a
href=
"{{ op.remove_port.get_url }}?rule={{ l.ipv4.pk }}"
class=
"btn btn-link btn-xs operation"
title=
"{% trans "
Remove
"
%}"
>
<i
class=
"fa fa-times"
><span
class=
"sr-only"
>
{% trans "Remove" %}
</span></i>
</a>
</span>
</td>
</td>
</tr>
</tr>
{% endif %}
{% endif %}
...
...
circle/dashboard/tests/test_views.py
View file @
7fed7d2c
...
@@ -27,7 +27,7 @@ from django.contrib.auth import authenticate
...
@@ -27,7 +27,7 @@ from django.contrib.auth import authenticate
from
dashboard.views
import
VmAddInterfaceView
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
,
AddInterfaceOperation
,
from
vm.operations
import
(
WakeUpOperation
,
AddInterfaceOperation
,
AddPortOperation
)
AddPortOperation
,
RemoveInterfaceOperation
)
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
...
@@ -169,26 +169,12 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -169,26 +169,12 @@ class VmDetailTest(LoginMixin, TestCase):
inst
.
save
()
inst
.
save
()
iface_count
=
inst
.
interface_set
.
count
()
iface_count
=
inst
.
interface_set
.
count
()
c
.
post
(
"/dashboard/interface/1/delete/"
)
with
patch
.
object
(
RemoveInterfaceOperation
,
'async'
)
as
mock_method
:
self
.
assertEqual
(
inst
.
interface_set
.
count
(),
iface_count
-
1
)
mock_method
.
side_effect
=
inst
.
remove_interface
response
=
c
.
post
(
"/dashboard/vm/1/op/remove_interface/"
,
def
test_permitted_network_delete_w_ajax
(
self
):
{
'interface'
:
1
})
c
=
Client
()
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
login
(
c
,
"user1"
)
assert
mock_method
.
called
inst
=
Instance
.
objects
.
get
(
pk
=
1
)
inst
.
set_level
(
self
.
u1
,
'owner'
)
vlan
=
Vlan
.
objects
.
get
(
pk
=
1
)
inst
.
add_interface
(
vlan
=
vlan
,
user
=
self
.
us
)
inst
.
status
=
'RUNNING'
inst
.
save
()
iface_count
=
inst
.
interface_set
.
count
()
response
=
c
.
post
(
"/dashboard/interface/1/delete/"
,
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
)
removed_network
=
json
.
loads
(
response
.
content
)[
'removed_network'
]
self
.
assertEqual
(
removed_network
[
'vlan'
],
vlan
.
name
)
self
.
assertEqual
(
removed_network
[
'vlan_pk'
],
vlan
.
pk
)
self
.
assertEqual
(
removed_network
[
'managed'
],
vlan
.
managed
)
self
.
assertEqual
(
inst
.
interface_set
.
count
(),
iface_count
-
1
)
self
.
assertEqual
(
inst
.
interface_set
.
count
(),
iface_count
-
1
)
def
test_unpermitted_network_delete
(
self
):
def
test_unpermitted_network_delete
(
self
):
...
@@ -199,7 +185,10 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -199,7 +185,10 @@ class VmDetailTest(LoginMixin, TestCase):
inst
.
add_interface
(
vlan
=
Vlan
.
objects
.
get
(
pk
=
1
),
user
=
self
.
us
)
inst
.
add_interface
(
vlan
=
Vlan
.
objects
.
get
(
pk
=
1
),
user
=
self
.
us
)
iface_count
=
inst
.
interface_set
.
count
()
iface_count
=
inst
.
interface_set
.
count
()
response
=
c
.
post
(
"/dashboard/interface/1/delete/"
)
with
patch
.
object
(
RemoveInterfaceOperation
,
'async'
)
as
mock_method
:
mock_method
.
side_effect
=
inst
.
remove_interface
response
=
c
.
post
(
"/dashboard/vm/1/op/remove_interface/"
,
{
'interface'
:
1
})
self
.
assertEqual
(
iface_count
,
inst
.
interface_set
.
count
())
self
.
assertEqual
(
iface_count
,
inst
.
interface_set
.
count
())
self
.
assertEqual
(
response
.
status_code
,
403
)
self
.
assertEqual
(
response
.
status_code
,
403
)
...
@@ -766,42 +755,6 @@ class NodeDetailTest(LoginMixin, TestCase):
...
@@ -766,42 +755,6 @@ class NodeDetailTest(LoginMixin, TestCase):
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
len
(
Node
.
objects
.
get
(
pk
=
1
)
.
traits
.
all
()),
trait_count
)
self
.
assertEqual
(
len
(
Node
.
objects
.
get
(
pk
=
1
)
.
traits
.
all
()),
trait_count
)
def
test_anon_change_node_status
(
self
):
c
=
Client
()
node
=
Node
.
objects
.
get
(
pk
=
1
)
node_enabled
=
node
.
enabled
response
=
c
.
post
(
"/dashboard/node/1/"
,
{
'change_status'
:
''
})
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
node_enabled
,
Node
.
objects
.
get
(
pk
=
1
)
.
enabled
)
def
test_unpermitted_change_node_status
(
self
):
c
=
Client
()
self
.
login
(
c
,
"user2"
)
node
=
Node
.
objects
.
get
(
pk
=
1
)
node_enabled
=
node
.
enabled
response
=
c
.
post
(
"/dashboard/node/status/1/"
,
{
'change_status'
:
''
})
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
node_enabled
,
Node
.
objects
.
get
(
pk
=
1
)
.
enabled
)
def
test_permitted_change_node_status
(
self
):
c
=
Client
()
self
.
login
(
c
,
"superuser"
)
node
=
Node
.
objects
.
get
(
pk
=
1
)
node_enabled
=
node
.
enabled
response
=
c
.
post
(
"/dashboard/node/status/1/"
,
{
'change_status'
:
''
})
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
node_enabled
,
not
Node
.
objects
.
get
(
pk
=
1
)
.
enabled
)
def
test_permitted_change_node_status_w_ajax
(
self
):
c
=
Client
()
self
.
login
(
c
,
"superuser"
)
node
=
Node
.
objects
.
get
(
pk
=
1
)
node_enabled
=
node
.
enabled
response
=
c
.
post
(
"/dashboard/node/status/1/"
,
{
'change_status'
:
''
},
HTTP_X_REQUESTED_WITH
=
'XMLHttpRequest'
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
node_enabled
,
not
Node
.
objects
.
get
(
pk
=
1
)
.
enabled
)
class
GroupCreateTest
(
LoginMixin
,
TestCase
):
class
GroupCreateTest
(
LoginMixin
,
TestCase
):
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
...
@@ -949,21 +902,26 @@ class GroupDeleteTest(LoginMixin, TestCase):
...
@@ -949,21 +902,26 @@ class GroupDeleteTest(LoginMixin, TestCase):
def
test_permitted_group_page
(
self
):
def
test_permitted_group_page
(
self
):
c
=
Client
()
c
=
Client
()
self
.
login
(
c
,
'user0'
)
self
.
login
(
c
,
'user0'
)
response
=
c
.
get
(
'/dashboard/group/delete/'
+
str
(
self
.
g1
.
pk
)
+
'/'
)
with
patch
(
'dashboard.views.util.messages'
)
as
msg
:
response
=
c
.
get
(
'/dashboard/group/delete/
%
d/'
%
self
.
g1
.
pk
)
assert
not
msg
.
error
.
called
and
not
msg
.
warning
.
called
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
def
test_unpermitted_group_page
(
self
):
def
test_unpermitted_group_page
(
self
):
c
=
Client
()
c
=
Client
()
self
.
login
(
c
,
'user1'
)
self
.
login
(
c
,
'user1'
)
response
=
c
.
get
(
'/dashboard/group/delete/'
+
str
(
self
.
g1
.
pk
)
+
'/'
)
with
patch
(
'dashboard.views.util.messages'
)
as
msg
:
self
.
assertEqual
(
response
.
status_code
,
403
)
response
=
c
.
get
(
'/dashboard/group/delete/
%
d/'
%
self
.
g1
.
pk
)
assert
msg
.
error
.
called
or
msg
.
warning
.
called
self
.
assertEqual
(
response
.
status_code
,
302
)
def
test_anon_group_delete
(
self
):
def
test_anon_group_delete
(
self
):
c
=
Client
()
c
=
Client
()
groupnum
=
Group
.
objects
.
count
()
response
=
c
.
get
(
'/dashboard/group/delete/
%
d/'
%
self
.
g1
.
pk
)
response
=
c
.
post
(
'/dashboard/group/delete/'
+
str
(
self
.
g1
.
pk
)
+
'/'
)
self
.
assertRedirects
(
response
,
'/accounts/login/?next=/dashboard/group/delete/5/'
,
status_code
=
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
Group
.
objects
.
count
(),
groupnum
)
def
test_unpermitted_group_delete
(
self
):
def
test_unpermitted_group_delete
(
self
):
c
=
Client
()
c
=
Client
()
...
@@ -1484,38 +1442,6 @@ class TransferOwnershipViewTest(LoginMixin, TestCase):
...
@@ -1484,38 +1442,6 @@ class TransferOwnershipViewTest(LoginMixin, TestCase):
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
self
.
assertEqual
(
self
.
u2
.
notification_set
.
count
(),
c2
+
1
)
self
.
assertEqual
(
self
.
u2
.
notification_set
.
count
(),
c2
+
1
)
def
test_transfer
(
self
):
self
.
skipTest
(
"How did this ever pass?"
)
c
=
Client
()
self
.
login
(
c
,
'user1'
)
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
url
=
response
.
context
[
'token'
]
c
=
Client
()
self
.
login
(
c
,
'user2'
)
response
=
c
.
post
(
url
)
self
.
assertEquals
(
Instance
.
objects
.
get
(
pk
=
1
)
.
owner
.
pk
,
self
.
u2
.
pk
)
def
test_transfer_token_used_by_others
(
self
):
self
.
skipTest
(
"How did this ever pass?"
)
c
=
Client
()
self
.
login
(
c
,
'user1'
)
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
url
=
response
.
context
[
'token'
]
response
=
c
.
post
(
url
)
# token is for user2
assert
response
.
status_code
==
403
self
.
assertEquals
(
Instance
.
objects
.
get
(
pk
=
1
)
.
owner
.
pk
,
self
.
u1
.
pk
)
def
test_transfer_by_superuser
(
self
):
self
.
skipTest
(
"How did this ever pass?"
)
c
=
Client
()
self
.
login
(
c
,
'superuser'
)
response
=
c
.
post
(
'/dashboard/vm/1/tx/'
,
{
'name'
:
'user2'
})
url
=
response
.
context
[
'token'
]
c
=
Client
()
self
.
login
(
c
,
'user2'
)
response
=
c
.
post
(
url
)
self
.
assertEquals
(
Instance
.
objects
.
get
(
pk
=
1
)
.
owner
.
pk
,
self
.
u2
.
pk
)
class
IndexViewTest
(
LoginMixin
,
TestCase
):
class
IndexViewTest
(
LoginMixin
,
TestCase
):
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
...
...
circle/dashboard/urls.py
View file @
7fed7d2c
...
@@ -25,12 +25,12 @@ from .views import (
...
@@ -25,12 +25,12 @@ from .views import (
GroupDetailView
,
GroupList
,
IndexView
,
GroupDetailView
,
GroupList
,
IndexView
,
InstanceActivityDetail
,
LeaseCreate
,
LeaseDelete
,
LeaseDetail
,
InstanceActivityDetail
,
LeaseCreate
,
LeaseDelete
,
LeaseDetail
,
MyPreferencesView
,
NodeAddTraitView
,
NodeCreate
,
NodeDelete
,
MyPreferencesView
,
NodeAddTraitView
,
NodeCreate
,
NodeDelete
,
NodeDetailView
,
NodeList
,
NodeStatus
,
NodeDetailView
,
NodeList
,
NotificationView
,
TemplateAclUpdateView
,
TemplateCreate
,
NotificationView
,
TemplateAclUpdateView
,
TemplateCreate
,
TemplateDelete
,
TemplateDetail
,
TemplateList
,
TemplateDelete
,
TemplateDetail
,
TemplateList
,
vm_activity
,
VmCreate
,
VmDetailView
,
vm_activity
,
VmCreate
,
VmDetailView
,
VmDetailVncTokenView
,
VmList
,
VmDetailVncTokenView
,
VmList
,
DiskRemoveView
,
get_disk_download_status
,
InterfaceDeleteView
,
DiskRemoveView
,
get_disk_download_status
,
GroupRemoveUserView
,
GroupRemoveUserView
,
GroupRemoveFutureUserView
,
GroupRemoveFutureUserView
,
GroupCreate
,
GroupProfileUpdate
,
GroupCreate
,
GroupProfileUpdate
,
...
@@ -51,6 +51,7 @@ from .views import (
...
@@ -51,6 +51,7 @@ from .views import (
TransferInstanceOwnershipView
,
TransferInstanceOwnershipConfirmView
,
TransferInstanceOwnershipView
,
TransferInstanceOwnershipConfirmView
,
TransferTemplateOwnershipView
,
TransferTemplateOwnershipConfirmView
,
TransferTemplateOwnershipView
,
TransferTemplateOwnershipConfirmView
,
OpenSearchDescriptionView
,
OpenSearchDescriptionView
,
NodeActivityView
,
)
)
from
.views.vm
import
vm_ops
,
vm_mass_ops
from
.views.vm
import
vm_ops
,
vm_mass_ops
from
.views.node
import
node_ops
from
.views.node
import
node_ops
...
@@ -94,7 +95,8 @@ urlpatterns = patterns(
...
@@ -94,7 +95,8 @@ urlpatterns = patterns(
url
(
r'^vm/list/$'
,
VmList
.
as_view
(),
name
=
'dashboard.views.vm-list'
),
url
(
r'^vm/list/$'
,
VmList
.
as_view
(),
name
=
'dashboard.views.vm-list'
),
url
(
r'^vm/create/$'
,
VmCreate
.
as_view
(),
url
(
r'^vm/create/$'
,
VmCreate
.
as_view
(),
name
=
'dashboard.views.vm-create'
),
name
=
'dashboard.views.vm-create'
),
url
(
r'^vm/(?P<pk>\d+)/activity/$'
,
vm_activity
),
url
(
r'^vm/(?P<pk>\d+)/activity/$'
,
vm_activity
,
name
=
'dashboard.views.vm-activity-list'
),
url
(
r'^vm/activity/(?P<pk>\d+)/$'
,
InstanceActivityDetail
.
as_view
(),
url
(
r'^vm/activity/(?P<pk>\d+)/$'
,
InstanceActivityDetail
.
as_view
(),
name
=
'dashboard.views.vm-activity'
),
name
=
'dashboard.views.vm-activity'
),
url
(
r'^vm/(?P<pk>\d+)/screenshot/$'
,
get_vm_screenshot
,
url
(
r'^vm/(?P<pk>\d+)/screenshot/$'
,
get_vm_screenshot
,
...
@@ -119,8 +121,8 @@ urlpatterns = patterns(
...
@@ -119,8 +121,8 @@ urlpatterns = patterns(
name
=
'dashboard.views.template-transfer-ownership-confirm'
),
name
=
'dashboard.views.template-transfer-ownership-confirm'
),
url
(
r'^node/delete/(?P<pk>\d+)/$'
,
NodeDelete
.
as_view
(),
url
(
r'^node/delete/(?P<pk>\d+)/$'
,
NodeDelete
.
as_view
(),
name
=
"dashboard.views.delete-node"
),
name
=
"dashboard.views.delete-node"
),
url
(
r'^node/
status/(?P<pk>\d+)/$'
,
NodeStatus
.
as_view
(),
url
(
r'^node/
(?P<pk>\d+)/activity/$'
,
NodeActivityView
.
as_view
(),
name
=
"dashboard.views.status-node"
),
name
=
'dashboard.views.node-activity-list'
),
url
(
r'^node/create/$'
,
NodeCreate
.
as_view
(),
url
(
r'^node/create/$'
,
NodeCreate
.
as_view
(),
name
=
'dashboard.views.node-create'
),
name
=
'dashboard.views.node-create'
),
...
@@ -156,9 +158,6 @@ urlpatterns = patterns(
...
@@ -156,9 +158,6 @@ urlpatterns = patterns(
url
(
r'^disk/(?P<pk>\d+)/status/$'
,
get_disk_download_status
,
url
(
r'^disk/(?P<pk>\d+)/status/$'
,
get_disk_download_status
,
name
=
"dashboard.views.disk-status"
),
name
=
"dashboard.views.disk-status"
),
url
(
r'^interface/(?P<pk>\d+)/delete/$'
,
InterfaceDeleteView
.
as_view
(),
name
=
"dashboard.views.interface-delete"
),
url
(
r'^profile/$'
,
MyPreferencesView
.
as_view
(),
url
(
r'^profile/$'
,
MyPreferencesView
.
as_view
(),
name
=
"dashboard.views.profile-preferences"
),
name
=
"dashboard.views.profile-preferences"
),
url
(
r'^subscribe/(?P<token>.*)/$'
,
UnsubscribeFormView
.
as_view
(),
url
(
r'^subscribe/(?P<token>.*)/$'
,
UnsubscribeFormView
.
as_view
(),
...
...
circle/dashboard/views/group.py
View file @
7fed7d2c
...
@@ -29,7 +29,7 @@ from django.core.urlresolvers import reverse, reverse_lazy
...
@@ -29,7 +29,7 @@ from django.core.urlresolvers import reverse, reverse_lazy
from
django.http
import
HttpResponse
,
Http404
from
django.http
import
HttpResponse
,
Http404
from
django.shortcuts
import
redirect
from
django.shortcuts
import
redirect
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.views.generic
import
UpdateView
,
DeleteView
,
TemplateView
from
django.views.generic
import
UpdateView
,
TemplateView
from
braces.views
import
SuperuserRequiredMixin
,
LoginRequiredMixin
from
braces.views
import
SuperuserRequiredMixin
,
LoginRequiredMixin
from
django_tables2
import
SingleTableView
from
django_tables2
import
SingleTableView
...
@@ -41,7 +41,8 @@ from ..forms import (
...
@@ -41,7 +41,8 @@ from ..forms import (
from
..models
import
FutureMember
,
GroupProfile
from
..models
import
FutureMember
,
GroupProfile
from
vm.models
import
Instance
,
InstanceTemplate
from
vm.models
import
Instance
,
InstanceTemplate
from
..tables
import
GroupListTable
from
..tables
import
GroupListTable
from
.util
import
CheckedDetailView
,
AclUpdateView
,
search_user
,
saml_available
from
.util
import
(
CheckedDetailView
,
AclUpdateView
,
search_user
,
saml_available
,
DeleteViewBase
)
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -224,15 +225,18 @@ class GroupList(LoginRequiredMixin, SingleTableView):
...
@@ -224,15 +225,18 @@ class GroupList(LoginRequiredMixin, SingleTableView):
return
groups
return
groups
class
GroupRemoveUserView
(
CheckedDetailView
,
DeleteView
):
class
GroupRemoveUserView
(
DeleteViewBase
):
model
=
Group
model
=
Group
slug_field
=
'pk'
slug_field
=
'pk'
slug_url_kwarg
=
'group_pk'
slug_url_kwarg
=
'group_pk'
read_
level
=
'operator'
level
=
'operator'
member_key
=
'member_pk'
member_key
=
'member_pk'
success_message
=
_
(
"Member successfully removed from group."
)
def
get_has_level
(
self
):
def
check_auth
(
self
):
return
self
.
object
.
profile
.
has_level
if
not
self
.
get_object
()
.
profile
.
has_level
(
self
.
request
.
user
,
self
.
level
):
raise
PermissionDenied
()
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
GroupRemoveUserView
,
self
)
.
get_context_data
(
**
kwargs
)
context
=
super
(
GroupRemoveUserView
,
self
)
.
get_context_data
(
**
kwargs
)
...
@@ -243,50 +247,24 @@ class GroupRemoveUserView(CheckedDetailView, DeleteView):
...
@@ -243,50 +247,24 @@ class GroupRemoveUserView(CheckedDetailView, DeleteView):
return
context
return
context
def
get_success_url
(
self
):
def
get_success_url
(
self
):
next
=
self
.
request
.
POST
.
get
(
'next'
)
return
reverse_lazy
(
"dashboard.views.group-detail"
,
if
next
:
kwargs
=
{
'pk'
:
self
.
get_object
()
.
pk
})
return
next
else
:
return
reverse_lazy
(
"dashboard.views.group-detail"
,
kwargs
=
{
'pk'
:
self
.
get_object
()
.
pk
})
def
get
(
self
,
request
,
member_pk
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
member_pk
,
*
args
,
**
kwargs
):
self
.
member_pk
=
member_pk
self
.
member_pk
=
member_pk
return
super
(
GroupRemoveUserView
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
return
super
(
GroupRemoveUserView
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-remove.html'
]
else
:
return
[
'dashboard/confirm/base-remove.html'
]
def
remove_member
(
self
,
pk
):
def
remove_member
(
self
,
pk
):
container
=
self
.
get_object
()
container
=
self
.
get_object
()
container
.
user_set
.
remove
(
User
.
objects
.
get
(
pk
=
pk
))
container
.
user_set
.
remove
(
User
.
objects
.
get
(
pk
=
pk
))
def
get_success_message
(
self
):
def
delete_obj
(
self
,
request
,
*
args
,
**
kwargs
):
return
_
(
"Member successfully removed from group."
)
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
object
=
self
.
get_object
()
if
not
object
.
profile
.
has_level
(
request
.
user
,
'operator'
):
raise
PermissionDenied
()
self
.
remove_member
(
kwargs
[
self
.
member_key
])
self
.
remove_member
(
kwargs
[
self
.
member_key
])
success_url
=
self
.
get_success_url
()
success_message
=
self
.
get_success_message
()
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
redirect
(
success_url
)
class
GroupRemoveFutureUserView
(
GroupRemoveUserView
):
class
GroupRemoveFutureUserView
(
GroupRemoveUserView
):
member_key
=
'member_org_id'
member_key
=
'member_org_id'
success_message
=
_
(
"Future user successfully removed from group."
)
def
get
(
self
,
request
,
member_org_id
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
member_org_id
,
*
args
,
**
kwargs
):
self
.
member_org_id
=
member_org_id
self
.
member_org_id
=
member_org_id
...
@@ -305,53 +283,17 @@ class GroupRemoveFutureUserView(GroupRemoveUserView):
...
@@ -305,53 +283,17 @@ class GroupRemoveFutureUserView(GroupRemoveUserView):
FutureMember
.
objects
.
filter
(
org_id
=
org_id
,
FutureMember
.
objects
.
filter
(
org_id
=
org_id
,
group
=
self
.
get_object
())
.
delete
()
group
=
self
.
get_object
())
.
delete
()
def
get_success_message
(
self
):
return
_
(
"Future user successfully removed from group."
)
class
GroupDelete
(
DeleteViewBase
):
class
GroupDelete
(
CheckedDetailView
,
DeleteView
):
"""This stuff deletes the group.
"""
model
=
Group
model
=
Group
template_name
=
"dashboard/confirm/base-delete.html"
success_message
=
_
(
"Group successfully deleted."
)
read_level
=
'operator'
def
get_has_level
(
self
):
return
self
.
object
.
profile
.
has_level
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
# github.com/django/django/blob/master/django/views/generic/edit.py#L245
def
check_auth
(
self
):
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
if
not
self
.
get_object
()
.
profile
.
has_level
(
self
.
request
.
user
,
'owner'
):
object
=
self
.
get_object
()
if
not
object
.
profile
.
has_level
(
request
.
user
,
'owner'
):
raise
PermissionDenied
()
raise
PermissionDenied
()
object
.
delete
()
success_url
=
self
.
get_success_url
()
success_message
=
_
(
"Group successfully deleted."
)
if
request
.
is_ajax
():
if
request
.
POST
.
get
(
'redirect'
)
.
lower
()
==
"true"
:
messages
.
success
(
request
,
success_message
)
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
redirect
(
success_url
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
next
=
self
.
request
.
POST
.
get
(
'next'
)
return
reverse_lazy
(
'dashboard.views.group-list'
)
if
next
:
return
next
else
:
return
reverse_lazy
(
'dashboard.index'
)
class
GroupCreate
(
GroupCodeMixin
,
LoginRequiredMixin
,
TemplateView
):
class
GroupCreate
(
GroupCodeMixin
,
LoginRequiredMixin
,
TemplateView
):
...
@@ -360,7 +302,7 @@ class GroupCreate(GroupCodeMixin, LoginRequiredMixin, TemplateView):
...
@@ -360,7 +302,7 @@ class GroupCreate(GroupCodeMixin, LoginRequiredMixin, TemplateView):
def
get_template_names
(
self
):
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
if
self
.
request
.
is_ajax
():
return
[
'dashboard/
modal-wrapper
.html'
]
return
[
'dashboard/
_modal
.html'
]
else
:
else
:
return
[
'dashboard/nojs-wrapper.html'
]
return
[
'dashboard/nojs-wrapper.html'
]
...
...
circle/dashboard/views/node.py
View file @
7fed7d2c
...
@@ -27,8 +27,10 @@ from django.db.models import Count
...
@@ -27,8 +27,10 @@ from django.db.models import Count
from
django.forms.models
import
inlineformset_factory
from
django.forms.models
import
inlineformset_factory
from
django.http
import
HttpResponse
from
django.http
import
HttpResponse
from
django.shortcuts
import
redirect
from
django.shortcuts
import
redirect
from
django.template
import
RequestContext
from
django.template.loader
import
render_to_string
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.views.generic
import
DetailView
,
TemplateView
,
Delete
View
from
django.views.generic
import
DetailView
,
TemplateView
,
View
from
braces.views
import
LoginRequiredMixin
,
SuperuserRequiredMixin
from
braces.views
import
LoginRequiredMixin
,
SuperuserRequiredMixin
from
django_tables2
import
SingleTableView
from
django_tables2
import
SingleTableView
...
@@ -38,7 +40,7 @@ from vm.models import Node, NodeActivity, Trait
...
@@ -38,7 +40,7 @@ from vm.models import Node, NodeActivity, Trait
from
..forms
import
TraitForm
,
HostForm
,
NodeForm
from
..forms
import
TraitForm
,
HostForm
,
NodeForm
from
..tables
import
NodeListTable
from
..tables
import
NodeListTable
from
.util
import
AjaxOperationMixin
,
OperationView
,
GraphMixin
from
.util
import
AjaxOperationMixin
,
OperationView
,
GraphMixin
,
DeleteViewBase
def
get_operations
(
instance
,
user
):
def
get_operations
(
instance
,
user
):
...
@@ -59,6 +61,8 @@ class NodeOperationView(AjaxOperationMixin, OperationView):
...
@@ -59,6 +61,8 @@ class NodeOperationView(AjaxOperationMixin, OperationView):
model
=
Node
model
=
Node
context_object_name
=
'node'
# much simpler to mock object
context_object_name
=
'node'
# much simpler to mock object
with_reload
=
True
wait_for_result
=
1
node_ops
=
OrderedDict
([
node_ops
=
OrderedDict
([
...
@@ -193,7 +197,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
...
@@ -193,7 +197,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
def
get_template_names
(
self
):
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
if
self
.
request
.
is_ajax
():
return
[
'dashboard/
modal-wrapper
.html'
]
return
[
'dashboard/
_modal
.html'
]
else
:
else
:
return
[
'dashboard/nojs-wrapper.html'
]
return
[
'dashboard/nojs-wrapper.html'
]
...
@@ -205,7 +209,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
...
@@ -205,7 +209,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
context
=
self
.
get_context_data
(
**
kwargs
)
context
=
self
.
get_context_data
(
**
kwargs
)
context
.
update
({
context
.
update
({
'template'
:
'dashboard/node-create.html'
,
'template'
:
'dashboard/node-create.html'
,
'box_title'
:
'Create a Node'
,
'box_title'
:
_
(
'Create a node'
)
,
'hostform'
:
hostform
,
'hostform'
:
hostform
,
'formset'
:
formset
,
'formset'
:
formset
,
...
@@ -238,44 +242,16 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
...
@@ -238,44 +242,16 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
return
redirect
(
path
)
return
redirect
(
path
)
class
NodeDelete
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
DeleteView
):
class
NodeDelete
(
SuperuserRequiredMixin
,
DeleteViewBase
):
"""This stuff deletes the node.
"""
model
=
Node
model
=
Node
template_name
=
"dashboard/confirm/base-delete.html"
success_message
=
_
(
"Node successfully deleted."
)
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
# github.com/django/django/blob/master/django/views/generic/edit.py#L245
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
object
=
self
.
get_object
()
object
.
delete
()
def
check_auth
(
self
):
success_url
=
self
.
get_success_url
()
# SuperuserRequiredMixin
success_message
=
_
(
"Node successfully deleted."
)
pass
if
request
.
is_ajax
():
if
request
.
POST
.
get
(
'redirect'
)
.
lower
()
==
"true"
:
messages
.
success
(
request
,
success_message
)
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
redirect
(
success_url
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
next
=
self
.
request
.
POST
.
get
(
'next'
)
return
reverse_lazy
(
'dashboard.views.node-list'
)
if
next
:
return
next
else
:
return
reverse_lazy
(
'dashboard.index'
)
class
NodeAddTraitView
(
SuperuserRequiredMixin
,
DetailView
):
class
NodeAddTraitView
(
SuperuserRequiredMixin
,
DetailView
):
...
@@ -311,55 +287,20 @@ class NodeAddTraitView(SuperuserRequiredMixin, DetailView):
...
@@ -311,55 +287,20 @@ class NodeAddTraitView(SuperuserRequiredMixin, DetailView):
return
self
.
get
(
self
,
request
,
pk
,
*
args
,
**
kwargs
)
return
self
.
get
(
self
,
request
,
pk
,
*
args
,
**
kwargs
)
class
NodeStatus
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
DetailView
):
class
NodeActivityView
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
View
):
template_name
=
"dashboard/confirm/node-status.html"
def
get
(
self
,
request
,
pk
):
model
=
Node
node
=
Node
.
objects
.
get
(
pk
=
pk
)
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-node-status.html'
]
else
:
return
[
'dashboard/confirm/node-status.html'
]
def
get_success_url
(
self
):
next
=
self
.
request
.
GET
.
get
(
'next'
)
if
next
:
return
next
else
:
return
reverse_lazy
(
"dashboard.views.node-detail"
,
kwargs
=
{
'pk'
:
self
.
object
.
pk
})
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
NodeStatus
,
self
)
.
get_context_data
(
**
kwargs
)
if
self
.
object
.
enabled
:
context
[
'status'
]
=
"disable"
else
:
context
[
'status'
]
=
"enable"
return
context
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
activities
=
NodeActivity
.
objects
.
filter
(
if
request
.
POST
.
get
(
'change_status'
)
is
not
None
:
node
=
node
,
parent
=
None
)
.
order_by
(
'-started'
)
.
select_related
()
return
self
.
__set_status
(
request
)
return
redirect
(
reverse_lazy
(
"dashboard.views.node-detail"
,
kwargs
=
{
'pk'
:
self
.
get_object
()
.
pk
}))
def
__set_status
(
self
,
request
):
response
=
{
self
.
object
=
self
.
get_object
()
'activities'
:
render_to_string
(
if
not
self
.
object
.
enabled
:
"dashboard/node-detail/_activity-timeline.html"
,
self
.
object
.
enable
(
user
=
request
.
user
)
RequestContext
(
request
,
{
'activities'
:
activities
}))
else
:
}
self
.
object
.
disable
(
user
=
request
.
user
)
success_message
=
_
(
"Node successfully changed status."
)
if
request
.
is_ajax
():
return
HttpResponse
(
response
=
{
json
.
dumps
(
response
),
'message'
:
success_message
,
content_type
=
"application/json"
'node_pk'
:
self
.
object
.
pk
)
}
return
HttpResponse
(
json
.
dumps
(
response
),
content_type
=
"application/json"
)
else
:
messages
.
success
(
request
,
success_message
)
return
redirect
(
self
.
get_success_url
())
circle/dashboard/views/template.py
View file @
7fed7d2c
...
@@ -28,7 +28,7 @@ from django.http import HttpResponse, HttpResponseRedirect
...
@@ -28,7 +28,7 @@ from django.http import HttpResponse, HttpResponseRedirect
from
django.shortcuts
import
redirect
,
get_object_or_404
from
django.shortcuts
import
redirect
,
get_object_or_404
from
django.utils.translation
import
ugettext
as
_
,
ugettext_noop
from
django.utils.translation
import
ugettext
as
_
,
ugettext_noop
from
django.views.generic
import
(
from
django.views.generic
import
(
TemplateView
,
CreateView
,
DeleteView
,
UpdateView
,
TemplateView
,
CreateView
,
UpdateView
,
)
)
from
braces.views
import
(
from
braces.views
import
(
...
@@ -47,6 +47,7 @@ from ..tables import TemplateListTable, LeaseListTable
...
@@ -47,6 +47,7 @@ from ..tables import TemplateListTable, LeaseListTable
from
.util
import
(
from
.util
import
(
AclUpdateView
,
FilterMixin
,
AclUpdateView
,
FilterMixin
,
TransferOwnershipConfirmView
,
TransferOwnershipView
,
TransferOwnershipConfirmView
,
TransferOwnershipView
,
DeleteViewBase
)
)
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -56,7 +57,7 @@ class TemplateChoose(LoginRequiredMixin, TemplateView):
...
@@ -56,7 +57,7 @@ class TemplateChoose(LoginRequiredMixin, TemplateView):
def
get_template_names
(
self
):
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
if
self
.
request
.
is_ajax
():
return
[
'dashboard/
modal-wrapper
.html'
]
return
[
'dashboard/
_modal
.html'
]
else
:
else
:
return
[
'dashboard/nojs-wrapper.html'
]
return
[
'dashboard/nojs-wrapper.html'
]
...
@@ -231,46 +232,17 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
...
@@ -231,46 +232,17 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
return
qs
.
select_related
(
"lease"
,
"owner"
,
"owner__profile"
)
return
qs
.
select_related
(
"lease"
,
"owner"
,
"owner__profile"
)
class
TemplateDelete
(
LoginRequiredMixin
,
DeleteView
):
class
TemplateDelete
(
DeleteViewBase
):
model
=
InstanceTemplate
model
=
InstanceTemplate
success_message
=
_
(
"Template successfully deleted."
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
return
reverse
(
"dashboard.views.template-list"
)
return
reverse
(
"dashboard.views.template-list"
)
def
get_template_names
(
self
):
def
delete_obj
(
self
,
request
,
*
args
,
**
kwargs
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
if
not
self
.
get_object
()
.
has_level
(
request
.
user
,
"owner"
):
message
=
_
(
"Only the owners can delete the selected template."
)
if
request
.
is_ajax
():
raise
PermissionDenied
()
else
:
messages
.
warning
(
request
,
message
)
return
redirect
(
self
.
get_success_url
())
return
super
(
TemplateDelete
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
object
=
self
.
get_object
()
object
=
self
.
get_object
()
if
not
object
.
has_level
(
request
.
user
,
'owner'
):
raise
PermissionDenied
()
object
.
destroy_disks
()
object
.
destroy_disks
()
object
.
delete
()
object
.
delete
()
success_url
=
self
.
get_success_url
()
success_message
=
_
(
"Template successfully deleted."
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
HttpResponseRedirect
(
success_url
)
class
TemplateDetail
(
LoginRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
class
TemplateDetail
(
LoginRequiredMixin
,
SuccessMessageMixin
,
UpdateView
):
...
@@ -333,25 +305,24 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
...
@@ -333,25 +305,24 @@ class TemplateDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return
kwargs
return
kwargs
class
DiskRemoveView
(
DeleteView
):
class
DiskRemoveView
(
DeleteView
Base
):
model
=
Disk
model
=
Disk
success_message
=
_
(
"Disk successfully removed."
)
def
get_queryset
(
self
):
def
get_queryset
(
self
):
qs
=
super
(
DiskRemoveView
,
self
)
.
get_queryset
()
qs
=
super
(
DiskRemoveView
,
self
)
.
get_queryset
()
return
qs
.
exclude
(
template_set
=
None
)
return
qs
.
exclude
(
template_set
=
None
)
def
get_template_names
(
self
):
def
check_auth
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
DiskRemoveView
,
self
)
.
get_context_data
(
**
kwargs
)
disk
=
self
.
get_object
()
disk
=
self
.
get_object
()
template
=
disk
.
template_set
.
get
()
template
=
disk
.
template_set
.
get
()
if
not
template
.
has_level
(
self
.
request
.
user
,
'owner'
):
if
not
template
.
has_level
(
self
.
request
.
user
,
'owner'
):
raise
PermissionDenied
()
raise
PermissionDenied
()
def
get_context_data
(
self
,
**
kwargs
):
disk
=
self
.
get_object
()
template
=
disk
.
template_set
.
get
()
context
=
super
(
DiskRemoveView
,
self
)
.
get_context_data
(
**
kwargs
)
context
[
'title'
]
=
_
(
"Disk remove confirmation"
)
context
[
'title'
]
=
_
(
"Disk remove confirmation"
)
context
[
'text'
]
=
_
(
"Are you sure you want to remove "
context
[
'text'
]
=
_
(
"Are you sure you want to remove "
"<strong>
%(disk)
s</strong> from "
"<strong>
%(disk)
s</strong> from "
...
@@ -360,29 +331,12 @@ class DiskRemoveView(DeleteView):
...
@@ -360,29 +331,12 @@ class DiskRemoveView(DeleteView):
)
)
return
context
return
context
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
def
delete
_obj
(
self
,
request
,
*
args
,
**
kwargs
):
disk
=
self
.
get_object
()
disk
=
self
.
get_object
()
template
=
disk
.
template_set
.
get
()
template
=
disk
.
template_set
.
get
()
template
.
remove_disk
(
disk
)
if
not
template
.
has_level
(
request
.
user
,
'owner'
):
raise
PermissionDenied
()
template
.
remove_disk
(
disk
=
disk
,
user
=
request
.
user
)
disk
.
destroy
()
disk
.
destroy
()
next_url
=
request
.
POST
.
get
(
"next"
)
success_url
=
next_url
if
next_url
else
template
.
get_absolute_url
()
success_message
=
_
(
"Disk successfully removed."
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
HttpResponseRedirect
(
"
%
s#resources"
%
success_url
)
class
LeaseCreate
(
LoginRequiredMixin
,
PermissionRequiredMixin
,
class
LeaseCreate
(
LoginRequiredMixin
,
PermissionRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
SuccessMessageMixin
,
CreateView
):
...
@@ -435,18 +389,13 @@ class LeaseDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
...
@@ -435,18 +389,13 @@ class LeaseDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return
super
(
LeaseDetail
,
self
)
.
post
(
request
,
*
args
,
**
kwargs
)
return
super
(
LeaseDetail
,
self
)
.
post
(
request
,
*
args
,
**
kwargs
)
class
LeaseDelete
(
LoginRequiredMixin
,
DeleteView
):
class
LeaseDelete
(
DeleteViewBase
):
model
=
Lease
model
=
Lease
success_message
=
_
(
"Lease successfully deleted."
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
return
reverse
(
"dashboard.views.template-list"
)
return
reverse
(
"dashboard.views.template-list"
)
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
c
=
super
(
LeaseDelete
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
c
=
super
(
LeaseDelete
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
lease
=
self
.
get_object
()
lease
=
self
.
get_object
()
...
@@ -461,36 +410,11 @@ class LeaseDelete(LoginRequiredMixin, DeleteView):
...
@@ -461,36 +410,11 @@ class LeaseDelete(LoginRequiredMixin, DeleteView):
c
[
'disable_submit'
]
=
True
c
[
'disable_submit'
]
=
True
return
c
return
c
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
delete_obj
(
self
,
request
,
*
args
,
**
kwargs
):
if
not
self
.
get_object
()
.
has_level
(
request
.
user
,
"owner"
):
message
=
_
(
"Only the owners can delete the selected lease."
)
if
request
.
is_ajax
():
raise
PermissionDenied
()
else
:
messages
.
warning
(
request
,
message
)
return
redirect
(
self
.
get_success_url
())
return
super
(
LeaseDelete
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
object
=
self
.
get_object
()
object
=
self
.
get_object
()
if
not
object
.
has_level
(
request
.
user
,
"owner"
):
raise
PermissionDenied
()
if
object
.
instancetemplate_set
.
count
()
>
0
:
if
object
.
instancetemplate_set
.
count
()
>
0
:
raise
SuspiciousOperation
()
raise
SuspiciousOperation
()
object
.
delete
()
object
.
delete
()
success_url
=
self
.
get_success_url
()
success_message
=
_
(
"Lease successfully deleted."
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
HttpResponseRedirect
(
success_url
)
class
TransferTemplateOwnershipConfirmView
(
TransferOwnershipConfirmView
):
class
TransferTemplateOwnershipConfirmView
(
TransferOwnershipConfirmView
):
...
...
circle/dashboard/views/user.py
View file @
7fed7d2c
...
@@ -35,7 +35,7 @@ from django.shortcuts import redirect, get_object_or_404
...
@@ -35,7 +35,7 @@ from django.shortcuts import redirect, get_object_or_404
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
django.views.decorators.http
import
require_POST
from
django.views.decorators.http
import
require_POST
from
django.views.generic
import
(
from
django.views.generic
import
(
TemplateView
,
DetailView
,
View
,
DeleteView
,
UpdateView
,
CreateView
,
TemplateView
,
DetailView
,
View
,
UpdateView
,
CreateView
,
)
)
from
django_sshkey.models
import
UserKey
from
django_sshkey.models
import
UserKey
...
@@ -50,7 +50,7 @@ from ..forms import (
...
@@ -50,7 +50,7 @@ from ..forms import (
from
..models
import
Profile
,
GroupProfile
,
ConnectCommand
,
create_profile
from
..models
import
Profile
,
GroupProfile
,
ConnectCommand
,
create_profile
from
..tables
import
UserKeyListTable
,
ConnectCommandListTable
from
..tables
import
UserKeyListTable
,
ConnectCommandListTable
from
.util
import
saml_available
from
.util
import
saml_available
,
DeleteViewBase
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -385,36 +385,17 @@ class UserKeyDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
...
@@ -385,36 +385,17 @@ class UserKeyDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
return
super
(
UserKeyDetail
,
self
)
.
post
(
self
,
request
,
args
,
kwargs
)
return
super
(
UserKeyDetail
,
self
)
.
post
(
self
,
request
,
args
,
kwargs
)
class
UserKeyDelete
(
LoginRequiredMixin
,
DeleteView
):
class
UserKeyDelete
(
DeleteViewBase
):
model
=
UserKey
model
=
UserKey
success_message
=
_
(
"SSH key successfully deleted."
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
return
reverse
(
"dashboard.views.profile-preferences"
)
return
reverse
(
"dashboard.views.profile-preferences"
)
def
get_template_names
(
self
):
def
check_auth
(
self
):
if
self
.
request
.
is_ajax
():
if
self
.
get_object
()
.
user
!=
self
.
request
.
user
:
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
object
=
self
.
get_object
()
if
object
.
user
!=
request
.
user
:
raise
PermissionDenied
()
raise
PermissionDenied
()
object
.
delete
()
success_url
=
self
.
get_success_url
()
success_message
=
_
(
"SSH key successfully deleted."
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
HttpResponseRedirect
(
success_url
)
class
UserKeyCreate
(
LoginRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
class
UserKeyCreate
(
LoginRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
UserKey
model
=
UserKey
...
@@ -460,36 +441,17 @@ class ConnectCommandDetail(LoginRequiredMixin, SuccessMessageMixin,
...
@@ -460,36 +441,17 @@ class ConnectCommandDetail(LoginRequiredMixin, SuccessMessageMixin,
return
kwargs
return
kwargs
class
ConnectCommandDelete
(
LoginRequiredMixin
,
DeleteView
):
class
ConnectCommandDelete
(
DeleteViewBase
):
model
=
ConnectCommand
model
=
ConnectCommand
success_message
=
_
(
"Command template successfully deleted."
)
def
get_success_url
(
self
):
def
get_success_url
(
self
):
return
reverse
(
"dashboard.views.profile-preferences"
)
return
reverse
(
"dashboard.views.profile-preferences"
)
def
get_template_names
(
self
):
def
check_auth
(
self
):
if
self
.
request
.
is_ajax
():
if
self
.
get_object
()
.
user
!=
self
.
request
.
user
:
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
object
=
self
.
get_object
()
if
object
.
user
!=
request
.
user
:
raise
PermissionDenied
()
raise
PermissionDenied
()
object
.
delete
()
success_url
=
self
.
get_success_url
()
success_message
=
_
(
"Command template successfully deleted."
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'message'
:
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
HttpResponseRedirect
(
success_url
)
class
ConnectCommandCreate
(
LoginRequiredMixin
,
SuccessMessageMixin
,
class
ConnectCommandCreate
(
LoginRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
CreateView
):
...
...
circle/dashboard/views/util.py
View file @
7fed7d2c
...
@@ -33,7 +33,7 @@ from django.db.models import Q
...
@@ -33,7 +33,7 @@ from django.db.models import Q
from
django.http
import
HttpResponse
,
Http404
,
HttpResponseRedirect
from
django.http
import
HttpResponse
,
Http404
,
HttpResponseRedirect
from
django.shortcuts
import
redirect
,
render
from
django.shortcuts
import
redirect
,
render
from
django.utils.translation
import
ugettext_lazy
as
_
,
ugettext_noop
from
django.utils.translation
import
ugettext_lazy
as
_
,
ugettext_noop
from
django.views.generic
import
DetailView
,
View
from
django.views.generic
import
DetailView
,
View
,
DeleteView
from
django.views.generic.detail
import
SingleObjectMixin
from
django.views.generic.detail
import
SingleObjectMixin
from
braces.views
import
LoginRequiredMixin
from
braces.views
import
LoginRequiredMixin
...
@@ -694,3 +694,45 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
...
@@ -694,3 +694,45 @@ class TransferOwnershipConfirmView(LoginRequiredMixin, View):
unicode
(
user
),
user
.
pk
,
new_owner
,
key
)
unicode
(
user
),
user
.
pk
,
new_owner
,
key
)
raise
PermissionDenied
()
raise
PermissionDenied
()
return
(
instance
,
new_owner
)
return
(
instance
,
new_owner
)
class
DeleteViewBase
(
LoginRequiredMixin
,
DeleteView
):
level
=
'owner'
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
def
check_auth
(
self
):
if
not
self
.
get_object
()
.
has_level
(
self
.
request
.
user
,
self
.
level
):
raise
PermissionDenied
()
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
self
.
check_auth
()
except
PermissionDenied
:
message
=
_
(
"Only the owners can delete the selected object."
)
if
request
.
is_ajax
():
raise
PermissionDenied
()
else
:
messages
.
warning
(
request
,
message
)
return
redirect
(
self
.
get_success_url
())
return
super
(
DeleteViewBase
,
self
)
.
get
(
request
,
*
args
,
**
kwargs
)
def
delete_obj
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
get_object
()
.
delete
()
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
check_auth
()
self
.
delete_obj
(
request
,
*
args
,
**
kwargs
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'message'
:
self
.
success_message
}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
self
.
success_message
)
return
HttpResponseRedirect
(
self
.
get_success_url
())
circle/dashboard/views/vm.py
View file @
7fed7d2c
...
@@ -37,7 +37,7 @@ from django.utils.translation import (
...
@@ -37,7 +37,7 @@ from django.utils.translation import (
)
)
from
django.views.decorators.http
import
require_GET
from
django.views.decorators.http
import
require_GET
from
django.views.generic
import
(
from
django.views.generic
import
(
UpdateView
,
ListView
,
TemplateView
,
DeleteView
UpdateView
,
ListView
,
TemplateView
)
)
from
braces.views
import
SuperuserRequiredMixin
,
LoginRequiredMixin
from
braces.views
import
SuperuserRequiredMixin
,
LoginRequiredMixin
...
@@ -64,6 +64,7 @@ from ..forms import (
...
@@ -64,6 +64,7 @@ from ..forms import (
VmDiskResizeForm
,
RedeployForm
,
VmDiskRemoveForm
,
VmDiskResizeForm
,
RedeployForm
,
VmDiskRemoveForm
,
VmMigrateForm
,
VmDeployForm
,
VmMigrateForm
,
VmDeployForm
,
VmPortRemoveForm
,
VmPortAddForm
,
VmPortRemoveForm
,
VmPortAddForm
,
VmRemoveInterfaceForm
,
)
)
from
..models
import
Favourite
from
..models
import
Favourite
...
@@ -324,6 +325,32 @@ def get_operations(instance, user):
...
@@ -324,6 +325,32 @@ def get_operations(instance, user):
return
ops
return
ops
class
VmRemoveInterfaceView
(
FormOperationMixin
,
VmOperationView
):
op
=
'remove_interface'
form_class
=
VmRemoveInterfaceForm
show_in_toolbar
=
False
wait_for_result
=
0.5
icon
=
'times'
effect
=
"danger"
with_reload
=
True
def
get_form_kwargs
(
self
):
instance
=
self
.
get_op
()
.
instance
choices
=
instance
.
interface_set
.
all
()
interface_pk
=
self
.
request
.
GET
.
get
(
'interface'
)
if
interface_pk
:
try
:
default
=
choices
.
get
(
pk
=
interface_pk
)
except
(
ValueError
,
Interface
.
DoesNotExist
):
raise
Http404
()
else
:
default
=
None
val
=
super
(
VmRemoveInterfaceView
,
self
)
.
get_form_kwargs
()
val
.
update
({
'choices'
:
choices
,
'default'
:
default
})
return
val
class
VmAddInterfaceView
(
FormOperationMixin
,
VmOperationView
):
class
VmAddInterfaceView
(
FormOperationMixin
,
VmOperationView
):
op
=
'add_interface'
op
=
'add_interface'
...
@@ -707,6 +734,7 @@ vm_ops = OrderedDict([
...
@@ -707,6 +734,7 @@ vm_ops = OrderedDict([
op
=
'remove_disk'
,
form_class
=
VmDiskRemoveForm
,
op
=
'remove_disk'
,
form_class
=
VmDiskRemoveForm
,
icon
=
'times'
,
effect
=
"danger"
)),
icon
=
'times'
,
effect
=
"danger"
)),
(
'add_interface'
,
VmAddInterfaceView
),
(
'add_interface'
,
VmAddInterfaceView
),
(
'remove_interface'
,
VmRemoveInterfaceView
),
(
'remove_port'
,
VmPortRemoveView
),
(
'remove_port'
,
VmPortRemoveView
),
(
'add_port'
,
VmPortAddView
),
(
'add_port'
,
VmPortAddView
),
(
'renew'
,
VmRenewView
),
(
'renew'
,
VmRenewView
),
...
@@ -951,10 +979,21 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -951,10 +979,21 @@ class VmCreate(LoginRequiredMixin, TemplateView):
def
get_template_names
(
self
):
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
if
self
.
request
.
is_ajax
():
return
[
'dashboard/
modal-wrapper
.html'
]
return
[
'dashboard/
_modal
.html'
]
else
:
else
:
return
[
'dashboard/nojs-wrapper.html'
]
return
[
'dashboard/nojs-wrapper.html'
]
def
get_template
(
self
,
request
,
pk
):
try
:
template
=
InstanceTemplate
.
objects
.
get
(
pk
=
int
(
pk
))
except
(
ValueError
,
InstanceTemplate
.
DoesNotExist
):
raise
Http404
()
if
not
template
.
has_level
(
request
.
user
,
'user'
):
raise
PermissionDenied
()
return
template
def
get
(
self
,
request
,
form
=
None
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
form
=
None
,
*
args
,
**
kwargs
):
if
not
request
.
user
.
has_perm
(
'vm.create_vm'
):
if
not
request
.
user
.
has_perm
(
'vm.create_vm'
):
raise
PermissionDenied
()
raise
PermissionDenied
()
...
@@ -965,9 +1004,7 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -965,9 +1004,7 @@ class VmCreate(LoginRequiredMixin, TemplateView):
template_pk
=
form
.
template
.
pk
template_pk
=
form
.
template
.
pk
if
template_pk
:
if
template_pk
:
template
=
get_object_or_404
(
InstanceTemplate
,
pk
=
template_pk
)
template
=
self
.
get_template
(
request
,
template_pk
)
if
not
template
.
has_level
(
request
.
user
,
'user'
):
raise
PermissionDenied
()
if
form
is
None
:
if
form
is
None
:
form
=
self
.
form_class
(
user
=
request
.
user
,
template
=
template
)
form
=
self
.
form_class
(
user
=
request
.
user
,
template
=
template
)
else
:
else
:
...
@@ -992,33 +1029,21 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -992,33 +1029,21 @@ class VmCreate(LoginRequiredMixin, TemplateView):
})
})
return
self
.
render_to_response
(
context
)
return
self
.
render_to_response
(
context
)
def
__create_normal
(
self
,
request
,
*
args
,
**
kwargs
):
def
__create_normal
(
self
,
request
,
template
,
*
args
,
**
kwargs
):
user
=
request
.
user
instances
=
[
Instance
.
create_from_template
(
template
=
InstanceTemplate
.
objects
.
get
(
template
=
template
,
pk
=
request
.
POST
.
get
(
"template"
))
owner
=
request
.
user
)]
# permission check
if
not
template
.
has_level
(
request
.
user
,
'user'
):
raise
PermissionDenied
()
args
=
{
"template"
:
template
,
"owner"
:
user
}
instances
=
[
Instance
.
create_from_template
(
**
args
)]
return
self
.
__deploy
(
request
,
instances
)
return
self
.
__deploy
(
request
,
instances
)
def
__create_customized
(
self
,
request
,
*
args
,
**
kwargs
):
def
__create_customized
(
self
,
request
,
template
,
*
args
,
**
kwargs
):
user
=
request
.
user
user
=
request
.
user
# no form yet, using POST directly:
# no form yet, using POST directly:
template
=
get_object_or_404
(
InstanceTemplate
,
pk
=
request
.
POST
.
get
(
"template"
))
form
=
self
.
form_class
(
form
=
self
.
form_class
(
request
.
POST
,
user
=
request
.
user
,
template
=
template
)
request
.
POST
,
user
=
request
.
user
,
template
=
template
)
if
not
form
.
is_valid
():
if
not
form
.
is_valid
():
return
self
.
get
(
request
,
form
,
*
args
,
**
kwargs
)
return
self
.
get
(
request
,
form
,
*
args
,
**
kwargs
)
post
=
form
.
cleaned_data
post
=
form
.
cleaned_data
if
not
template
.
has_level
(
user
,
'user'
):
raise
PermissionDenied
()
ikwargs
=
{
ikwargs
=
{
'name'
:
post
[
'name'
],
'name'
:
post
[
'name'
],
'template'
:
template
,
'template'
:
template
,
...
@@ -1071,6 +1096,8 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -1071,6 +1096,8 @@ class VmCreate(LoginRequiredMixin, TemplateView):
if
not
request
.
user
.
has_perm
(
'vm.create_vm'
):
if
not
request
.
user
.
has_perm
(
'vm.create_vm'
):
raise
PermissionDenied
()
raise
PermissionDenied
()
template
=
self
.
get_template
(
request
,
request
.
POST
.
get
(
"template"
))
# limit chekcs
# limit chekcs
try
:
try
:
limit
=
user
.
profile
.
instance_limit
limit
=
user
.
profile
.
instance_limit
...
@@ -1096,7 +1123,7 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -1096,7 +1123,7 @@ class VmCreate(LoginRequiredMixin, TemplateView):
request
.
POST
.
get
(
"customized"
)
is
None
else
request
.
POST
.
get
(
"customized"
)
is
None
else
self
.
__create_customized
)
self
.
__create_customized
)
return
create_func
(
request
,
*
args
,
**
kwargs
)
return
create_func
(
request
,
template
,
*
args
,
**
kwargs
)
@require_GET
@require_GET
...
@@ -1111,56 +1138,6 @@ def get_vm_screenshot(request, pk):
...
@@ -1111,56 +1138,6 @@ def get_vm_screenshot(request, pk):
return
HttpResponse
(
image
,
mimetype
=
"image/png"
)
return
HttpResponse
(
image
,
mimetype
=
"image/png"
)
class
InterfaceDeleteView
(
DeleteView
):
model
=
Interface
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/confirm/ajax-delete.html'
]
else
:
return
[
'dashboard/confirm/base-delete.html'
]
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
(
InterfaceDeleteView
,
self
)
.
get_context_data
(
**
kwargs
)
interface
=
self
.
get_object
()
context
[
'text'
]
=
_
(
"Are you sure you want to remove this interface "
"from <strong>
%(vm)
s</strong>?"
%
{
'vm'
:
interface
.
instance
.
name
})
return
context
def
delete
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
object
=
self
.
get_object
()
instance
=
self
.
object
.
instance
if
not
instance
.
has_level
(
request
.
user
,
"owner"
):
raise
PermissionDenied
()
instance
.
remove_interface
(
interface
=
self
.
object
,
user
=
request
.
user
)
success_url
=
self
.
get_success_url
()
success_message
=
_
(
"Interface successfully deleted."
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
(
{
'message'
:
success_message
,
'removed_network'
:
{
'vlan'
:
self
.
object
.
vlan
.
name
,
'vlan_pk'
:
self
.
object
.
vlan
.
pk
,
'managed'
:
self
.
object
.
host
is
not
None
,
}}),
content_type
=
"application/json"
,
)
else
:
messages
.
success
(
request
,
success_message
)
return
HttpResponseRedirect
(
"
%
s#network"
%
success_url
)
def
get_success_url
(
self
):
redirect
=
self
.
request
.
POST
.
get
(
"next"
)
if
redirect
:
return
redirect
self
.
object
.
instance
.
get_absolute_url
()
class
InstanceActivityDetail
(
CheckedDetailView
):
class
InstanceActivityDetail
(
CheckedDetailView
):
model
=
InstanceActivity
model
=
InstanceActivity
context_object_name
=
'instanceactivity'
# much simpler to mock object
context_object_name
=
'instanceactivity'
# much simpler to mock object
...
...
circle/vm/models/instance.py
View file @
7fed7d2c
...
@@ -354,6 +354,12 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
...
@@ -354,6 +354,12 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
def
create
(
cls
,
params
,
disks
,
networks
,
req_traits
,
tags
):
def
create
(
cls
,
params
,
disks
,
networks
,
req_traits
,
tags
):
""" Create new Instance object.
""" Create new Instance object.
"""
"""
# permission check
for
network
in
networks
:
if
not
network
.
vlan
.
has_level
(
params
[
'owner'
],
'user'
):
raise
PermissionDenied
()
# create instance and do additional setup
# create instance and do additional setup
inst
=
cls
(
**
params
)
inst
=
cls
(
**
params
)
...
@@ -408,10 +414,6 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
...
@@ -408,10 +414,6 @@ class Instance(AclBase, VirtualMachineDescModel, StatusModel, OperatedMixin,
networks
=
(
template
.
interface_set
.
all
()
if
networks
is
None
networks
=
(
template
.
interface_set
.
all
()
if
networks
is
None
else
networks
)
else
networks
)
for
network
in
networks
:
if
not
network
.
vlan
.
has_level
(
owner
,
'user'
):
raise
PermissionDenied
()
req_traits
=
(
template
.
req_traits
.
all
()
if
req_traits
is
None
req_traits
=
(
template
.
req_traits
.
all
()
if
req_traits
is
None
else
req_traits
)
else
req_traits
)
...
...
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