Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gutyán Gábor
/
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
9e2f21e1
authored
Mar 28, 2014
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature-working-vm-create'
Conflicts: circle/dashboard/static/dashboard/dashboard.css
parents
586cb8ad
9a95ba6b
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
178 additions
and
86 deletions
+178
-86
circle/dashboard/forms.py
+46
-31
circle/dashboard/static/dashboard/dashboard.css
+14
-1
circle/dashboard/static/dashboard/dashboard.js
+29
-15
circle/dashboard/static/dashboard/vm-create.js
+15
-16
circle/dashboard/templates/dashboard/_vm-create-1.html
+7
-2
circle/dashboard/templates/dashboard/index-vm.html
+18
-9
circle/dashboard/templates/dashboard/nojs-wrapper.html
+1
-0
circle/dashboard/tests/test_views.py
+18
-0
circle/dashboard/views.py
+30
-12
No files found.
circle/dashboard/forms.py
View file @
9e2f21e1
...
@@ -33,6 +33,7 @@ class VmCustomizeForm(forms.Form):
...
@@ -33,6 +33,7 @@ class VmCustomizeForm(forms.Form):
cpu_priority
=
forms
.
IntegerField
()
cpu_priority
=
forms
.
IntegerField
()
cpu_count
=
forms
.
IntegerField
()
cpu_count
=
forms
.
IntegerField
()
ram_size
=
forms
.
IntegerField
()
ram_size
=
forms
.
IntegerField
()
amount
=
forms
.
IntegerField
(
min_value
=
0
,
initial
=
1
)
disks
=
forms
.
ModelMultipleChoiceField
(
disks
=
forms
.
ModelMultipleChoiceField
(
queryset
=
None
,
required
=
True
)
queryset
=
None
,
required
=
True
)
...
@@ -68,12 +69,21 @@ class VmCustomizeForm(forms.Form):
...
@@ -68,12 +69,21 @@ class VmCustomizeForm(forms.Form):
self
.
initial
[
'template'
]
=
self
.
template
.
pk
self
.
initial
[
'template'
]
=
self
.
template
.
pk
self
.
initial
[
'customized'
]
=
self
.
template
.
pk
self
.
initial
[
'customized'
]
=
self
.
template
.
pk
# set widget for amount
self
.
fields
[
'amount'
]
.
widget
=
NumberInput
()
self
.
helper
=
FormHelper
(
self
)
self
.
helper
=
FormHelper
(
self
)
self
.
helper
.
form_show_labels
=
False
# don't show labels for the sliders
self
.
helper
.
form_show_labels
=
True
self
.
fields
[
'cpu_count'
]
.
label
=
""
self
.
fields
[
'ram_size'
]
.
label
=
""
self
.
fields
[
'cpu_priority'
]
.
label
=
""
self
.
helper
.
layout
=
Layout
(
self
.
helper
.
layout
=
Layout
(
Field
(
"template"
,
type
=
"hidden"
),
Field
(
"template"
,
type
=
"hidden"
),
Field
(
"customized"
,
type
=
"hidden"
),
Field
(
"customized"
,
type
=
"hidden"
),
Div
(
# buttons
Div
(
Div
(
Div
(
AnyTag
(
# tip: don't try to use Button class
AnyTag
(
# tip: don't try to use Button class
"button"
,
"button"
,
...
@@ -84,16 +94,17 @@ class VmCustomizeForm(forms.Form):
...
@@ -84,16 +94,17 @@ class VmCustomizeForm(forms.Form):
HTML
(
" Start"
),
HTML
(
" Start"
),
css_id
=
"vm-create-customized-start"
,
css_id
=
"vm-create-customized-start"
,
css_class
=
"btn btn-success"
,
css_class
=
"btn btn-success"
,
style
=
"float: right; margin-top: 24px;"
,
),
),
css_class
=
"col-sm-11 text-right"
,
Field
(
"name"
,
style
=
"max-width: 350px;"
),
css_class
=
"col-sm-12"
,
),
),
css_class
=
"row"
,
css_class
=
"row"
,
),
),
Div
(
Div
(
Div
(
Div
(
Field
(
"
name
"
),
Field
(
"
amount"
,
min
=
"1"
,
style
=
"max-width: 60px;
"
),
css_class
=
"col-sm-
5
"
,
css_class
=
"col-sm-
10
"
,
),
),
css_class
=
"row"
,
css_class
=
"row"
,
),
),
...
@@ -185,32 +196,36 @@ class VmCustomizeForm(forms.Form):
...
@@ -185,32 +196,36 @@ class VmCustomizeForm(forms.Form):
HTML
(
_
(
"No disks are added!"
)),
HTML
(
_
(
"No disks are added!"
)),
css_id
=
"vm-create-disk-list"
,
css_id
=
"vm-create-disk-list"
,
),
),
AnyTag
(
Div
(
"h3"
,
HTML
(
""
),
Div
(
style
=
"clear: both;"
,
AnyTag
(
"select"
,
css_class
=
"form-control"
,
css_id
=
"vm-create-disk-add-select"
,
),
Div
(
AnyTag
(
"a"
,
AnyTag
(
"i"
,
css_class
=
"icon-plus-sign"
,
),
href
=
"#"
,
css_id
=
"vm-create-disk-add-button"
,
css_class
=
"btn btn-success"
,
),
css_class
=
"input-group-btn"
),
css_class
=
"input-group"
,
style
=
"max-width: 330px;"
,
),
css_id
=
"vm-create-disk-add"
,
),
),
# AnyTag(
# "h3",
# Div(
# AnyTag(
# "select",
# css_class="form-control",
# css_id="vm-create-disk-add-select",
# ),
# Div(
# AnyTag(
# "a",
# AnyTag(
# "i",
# css_class="icon-plus-sign",
# ),
# href="#",
# css_id="vm-create-disk-add-button",
# css_class="btn btn-success",
# ),
# css_class="input-group-btn"
# ),
# css_class="input-group",
# style="max-width: 330px;",
# ),
# css_id="vm-create-disk-add",
# ),
css_class
=
"no-js-hidden"
,
css_class
=
"no-js-hidden"
,
),
),
css_class
=
"col-sm-8"
,
css_class
=
"col-sm-8"
,
...
...
circle/dashboard/static/dashboard/dashboard.css
View file @
9e2f21e1
...
@@ -410,7 +410,7 @@ footer a, footer a:hover, footer a:visited {
...
@@ -410,7 +410,7 @@ footer a, footer a:hover, footer a:visited {
color
:
white
;
color
:
white
;
text-decoration
:
underline
;
text-decoration
:
underline
;
}
}
.template-disk-list
{
.template-disk-list
{
list-style
:
none
;
list-style
:
none
;
padding-left
:
0
;
padding-left
:
0
;
...
@@ -423,3 +423,16 @@ footer a, footer a:hover, footer a:visited {
...
@@ -423,3 +423,16 @@ footer a, footer a:hover, footer a:visited {
#node-info-pane
{
#node-info-pane
{
margin-bottom
:
20px
;
margin-bottom
:
20px
;
}
}
.index-vm-list-name
{
display
:
inline-block
;
max-width
:
70%
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
overflow
:
hidden
;
float
:
left
;
}
#dashboard-vm-list
a
small
{
padding-left
:
10px
;
}
circle/dashboard/static/dashboard/dashboard.js
View file @
9e2f21e1
...
@@ -3,7 +3,7 @@ $(function () {
...
@@ -3,7 +3,7 @@ $(function () {
var
template
=
$
(
this
).
data
(
"template"
);
var
template
=
$
(
this
).
data
(
"template"
);
$
.
ajax
({
$
.
ajax
({
type
:
'GET'
,
type
:
'GET'
,
url
:
'/dashboard/vm/create/'
,
url
:
'/dashboard/vm/create/'
+
(
typeof
template
===
"undefined"
?
''
:
'?template='
+
template
)
,
success
:
function
(
data
)
{
success
:
function
(
data
)
{
$
(
'body'
).
append
(
data
);
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
vmCreateLoaded
();
...
@@ -12,9 +12,6 @@ $(function () {
...
@@ -12,9 +12,6 @@ $(function () {
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
remove
();
$
(
'#create-modal'
).
remove
();
});
});
if
(
template
)
{
$
(
'#vm-create-template-select option[value="'
+
template
+
'"]'
).
prop
(
"selected"
,
true
).
trigger
(
"change"
);
}
}
}
});
});
return
false
;
return
false
;
...
@@ -191,6 +188,9 @@ $(function () {
...
@@ -191,6 +188,9 @@ $(function () {
'name'
:
result
[
i
].
name
.
toLowerCase
(),
'name'
:
result
[
i
].
name
.
toLowerCase
(),
'state'
:
result
[
i
].
state
,
'state'
:
result
[
i
].
state
,
'fav'
:
result
[
i
].
fav
,
'fav'
:
result
[
i
].
fav
,
'host'
:
result
[
i
].
host
,
'icon'
:
result
[
i
].
icon
,
'status'
:
result
[
i
].
status
,
});
});
}
}
});
});
...
@@ -207,7 +207,9 @@ $(function () {
...
@@ -207,7 +207,9 @@ $(function () {
}
}
search_result
.
sort
(
compareVmByFav
);
search_result
.
sort
(
compareVmByFav
);
for
(
var
i
=
0
;
i
<
5
&&
i
<
search_result
.
length
;
i
++
)
for
(
var
i
=
0
;
i
<
5
&&
i
<
search_result
.
length
;
i
++
)
html
+=
generateVmHTML
(
search_result
[
i
].
pk
,
search_result
[
i
].
name
,
search_result
[
i
].
fav
);
html
+=
generateVmHTML
(
search_result
[
i
].
pk
,
search_result
[
i
].
name
,
search_result
[
i
].
host
,
search_result
[
i
].
icon
,
search_result
[
i
].
status
,
search_result
[
i
].
fav
);
if
(
search_result
.
length
==
0
)
if
(
search_result
.
length
==
0
)
html
+=
'<div class="list-group-item">No result</div>'
;
html
+=
'<div class="list-group-item">No result</div>'
;
$
(
"#dashboard-vm-list"
).
html
(
html
);
$
(
"#dashboard-vm-list"
).
html
(
html
);
...
@@ -233,21 +235,33 @@ $(function () {
...
@@ -233,21 +235,33 @@ $(function () {
});
});
});
});
function
generateVmHTML
(
pk
,
name
,
fav
)
{
function
generateVmHTML
(
pk
,
name
,
host
,
icon
,
_status
,
fav
)
{
return
'<a href="/dashboard/vm/'
+
pk
+
'/" class="list-group-item">'
+
return
'<a href="/dashboard/vm/'
+
pk
+
'/" class="list-group-item">'
+
'<i class="icon-play-sign"></i> '
+
name
+
'<span class="index-vm-list-name">'
+
'<div class="pull-right dashboard-vm-favourite" data-vm="'
+
pk
+
'">'
+
'<i class="'
+
icon
+
'" title="'
+
_status
+
'"></i> '
+
name
+
'<i class="title-favourite icon-star'
+
(
fav
?
""
:
"-empty"
)
+
' text-primary" title="" data-original-title="'
+
'</span>'
+
(
fav
?
"Un"
:
"Mark as "
)
+
'favourite"></i>'
+
'<small class="text-muted"> '
+
host
+
'</small>'
+
'</div>'
+
'<div class="pull-right dashboard-vm-favourite" data-vm="'
+
pk
+
'">'
+
'</a>'
;
(
fav
?
'<i class="icon-star text-primary title-favourite" title="Unfavourite"></i>'
:
'<i class="icon-star-empty text-primary title-favourite" title="Mark as favorite"></i>'
)
+
'</div>'
+
'<div style="clear: both;"></div>'
+
'</a>'
;
}
}
/* copare vm-s by fav, pk order */
function
compareVmByFav
(
a
,
b
)
{
function
compareVmByFav
(
a
,
b
)
{
if
(
a
.
fav
)
if
(
a
.
fav
&&
b
.
fav
)
{
return
a
.
pk
<
b
.
pk
?
-
1
:
1
;
}
else
if
(
a
.
fav
&&
!
b
.
fav
)
{
return
-
1
;
return
-
1
;
else
}
else
if
(
!
a
.
fav
&&
b
.
fav
)
{
return
1
;
return
1
;
}
else
return
a
.
pk
<
b
.
pk
?
-
1
:
1
;
}
}
function
addSliderMiscs
()
{
function
addSliderMiscs
()
{
...
...
circle/dashboard/static/dashboard/vm-create.js
View file @
9e2f21e1
...
@@ -14,7 +14,6 @@ function vmCreateLoaded() {
...
@@ -14,7 +14,6 @@ function vmCreateLoaded() {
$
(
".customize-vm"
).
click
(
function
()
{
$
(
".customize-vm"
).
click
(
function
()
{
var
template
=
$
(
this
).
data
(
"template-pk"
);
var
template
=
$
(
this
).
data
(
"template-pk"
);
console
.
log
(
template
);
$
.
get
(
"/dashboard/vm/create/?template="
+
template
,
function
(
data
)
{
$
.
get
(
"/dashboard/vm/create/?template="
+
template
,
function
(
data
)
{
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
...
@@ -142,7 +141,6 @@ function vmCustomizeLoaded() {
...
@@ -142,7 +141,6 @@ function vmCustomizeLoaded() {
text
=
raw_text
.
replace
(
"unmanaged -"
,
""
);
text
=
raw_text
.
replace
(
"unmanaged -"
,
""
);
}
}
var
html
=
'<option data-managed="'
+
(
managed
?
1
:
0
)
+
'" value="'
+
pk
+
'">'
+
text
+
'</option>'
;
var
html
=
'<option data-managed="'
+
(
managed
?
1
:
0
)
+
'" value="'
+
pk
+
'">'
+
text
+
'</option>'
;
if
(
$
(
'#vm-create-network-list span'
).
length
<
1
)
{
if
(
$
(
'#vm-create-network-list span'
).
length
<
1
)
{
$
(
"#vm-create-network-list"
).
html
(
""
);
$
(
"#vm-create-network-list"
).
html
(
""
);
...
@@ -152,8 +150,14 @@ function vmCustomizeLoaded() {
...
@@ -152,8 +150,14 @@ function vmCustomizeLoaded() {
}
else
{
}
else
{
$
(
'#vm-create-network-add-select'
).
append
(
html
);
$
(
'#vm-create-network-add-select'
).
append
(
html
);
}
}
});
});
// if all networks are added add a dummy and disable the add button
if
(
$
(
"#vm-create-network-add-select option"
).
length
<
1
)
{
$
(
"#vm-create-network-add-select"
).
html
(
'<option value="-1">No more networks!</option>'
);
$
(
'#vm-create-network-add-button'
).
attr
(
'disabled'
,
true
);
}
/* build up network list */
/* build up network list */
$
(
'#vm-create-network-add-vlan option'
).
each
(
function
()
{
$
(
'#vm-create-network-add-vlan option'
).
each
(
function
()
{
...
@@ -197,24 +201,14 @@ function vmCustomizeLoaded() {
...
@@ -197,24 +201,14 @@ function vmCustomizeLoaded() {
/* remove disk */
/* remove disk */
// event for disk remove button (icon, X)
// event for disk remove button (icon, X)
$
(
'body'
).
on
(
'click'
,
'.vm-create-remove-disk'
,
function
()
{
$
(
'body'
).
on
(
'click'
,
'.vm-create-remove-disk'
,
function
()
{
var
disk_pk
=
(
$
(
this
).
parent
(
'span'
).
prop
(
'id'
)).
replace
(
'
vlan
-'
,
''
)
var
disk_pk
=
(
$
(
this
).
parent
(
'span'
).
prop
(
'id'
)).
replace
(
'
disk
-'
,
''
)
$
(
this
).
parent
(
'span'
).
fadeOut
(
500
,
function
()
{
$
(
this
).
parent
(
'span'
).
fadeOut
(
500
,
function
()
{
/* if ther are no more disks disabled the add button */
if
(
$
(
'#vm-create-disk-add-select option'
)[
0
].
value
==
-
1
)
{
$
(
'#vm-create-disk-add-button'
).
attr
(
'disabled'
,
false
);
$
(
'#vm-create-disk-add-select'
).
html
(
''
);
}
/* remove the disk label */
/* remove the disk label */
$
(
this
).
remove
();
$
(
this
).
remove
();
var
disk_name
=
$
(
this
).
text
();
var
disk_name
=
$
(
this
).
text
();
$
(
'#vm-create-disk-add-select'
).
append
(
$
(
'<option>'
,
{
value
:
disk_pk
,
text
:
disk_name
}));
/* remove the selection from the multiple select */
/* remove the selection from the multiple select */
$
(
'#vm-create-disk-add-form option[value="'
+
disk_pk
+
'"]'
).
prop
(
'selected'
,
false
);
$
(
'#vm-create-disk-add-form option[value="'
+
disk_pk
+
'"]'
).
prop
(
'selected'
,
false
);
if
(
$
(
'#vm-create-disk-list'
).
children
(
'span'
).
length
<
1
)
{
if
(
$
(
'#vm-create-disk-list'
).
children
(
'span'
).
length
<
1
)
{
...
@@ -257,7 +251,11 @@ function vmCustomizeLoaded() {
...
@@ -257,7 +251,11 @@ function vmCustomizeLoaded() {
data
:
$
(
'form'
).
serialize
(),
data
:
$
(
'form'
).
serialize
(),
success
:
function
(
data
,
textStatus
,
xhr
)
{
success
:
function
(
data
,
textStatus
,
xhr
)
{
if
(
data
.
redirect
)
{
if
(
data
.
redirect
)
{
window
.
location
.
replace
(
data
.
redirect
+
'#activity'
);
/* it won't redirect to the same page */
if
(
window
.
location
.
pathname
==
data
.
redirect
)
{
window
.
location
.
reload
();
}
window
.
location
.
href
=
data
.
redirect
+
'#activity'
;
}
}
else
{
else
{
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
...
@@ -295,5 +293,6 @@ function vmCreateNetworkLabel(pk, name, managed) {
...
@@ -295,5 +293,6 @@ function vmCreateNetworkLabel(pk, name, managed) {
function
vmCreateDiskLabel
(
pk
,
name
)
{
function
vmCreateDiskLabel
(
pk
,
name
)
{
return
'<span id="vlan-'
+
pk
+
'" class="label label-primary"><i class="icon-file"></i> '
+
name
+
' <a href="#" class="hover-black vm-create-remove-disk"><i class="icon-remove-sign"></i></a></span> '
;
var
style
=
"float: left; margin: 5px 5px 5px 0;"
;
return
'<span id="disk-'
+
pk
+
'" class="label label-primary" style="'
+
style
+
'"><i class="icon-file"></i> '
+
name
+
' <a href="#" class="hover-black vm-create-remove-disk"><i class="icon-remove-sign"></i></a></span> '
;
}
}
circle/dashboard/templates/dashboard/_vm-create-1.html
View file @
9e2f21e1
...
@@ -58,12 +58,17 @@
...
@@ -58,12 +58,17 @@
</li>
</li>
</ul>
</ul>
<div
style=
"margin-top: 20px; padding: 0 15px; width: 100%"
>
<div
style=
"margin-top: 20px; padding: 0 15px; width: 100%"
>
<a
class=
"btn btn-primary btn-xs customize-vm"
data-template-pk=
"{{ t.pk }}"
href=
"{% url "
dashboard
.
views
.
vm-create
"
%}?
template=
{{
t
.
pk
}}"
><i
class=
"icon-wrench"
></i>
Customize
</a>
{% if perms.vm_set_resources %}
<a
class=
"btn btn-primary btn-xs customize-vm"
data-template-pk=
"{{ t.pk }}"
href=
"{% url "
dashboard
.
views
.
vm-create
"
%}?
template=
{{
t
.
pk
}}"
><i
class=
"icon-wrench"
></i>
{% trans "Customize" %}
</a>
{% endif %}
<form
class=
"pull-right text-right"
method=
"POST"
action=
"{% url "
dashboard
.
views
.
vm-create
"
%}"
>
<form
class=
"pull-right text-right"
method=
"POST"
action=
"{% url "
dashboard
.
views
.
vm-create
"
%}"
>
{% csrf_token %}
{% csrf_token %}
<input
type=
"hidden"
name=
"template"
value=
"{{ t.pk }}"
/>
<input
type=
"hidden"
name=
"template"
value=
"{{ t.pk }}"
/>
<button
class=
"btn btn-success btn-xs vm-create-start"
data-template-pk=
"{{ t.pk }}"
type=
"submit"
><i
class=
"icon-play"
></i>
Start
</button>
<button
class=
"btn btn-success btn-xs vm-create-start"
data-template-pk=
"{{ t.pk }}"
type=
"submit"
>
<i
class=
"icon-play"
></i>
{% trans "Start" %}
</button>
</form>
</form>
<div
style=
"clear: both;"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
...
...
circle/dashboard/templates/dashboard/index-vm.html
View file @
9e2f21e1
...
@@ -16,8 +16,11 @@
...
@@ -16,8 +16,11 @@
<div
id=
"dashboard-vm-list"
>
<div
id=
"dashboard-vm-list"
>
{% for i in instances %}
{% for i in instances %}
<a
href=
"{{ i.get_absolute_url }}"
class=
"list-group-item"
>
<a
href=
"{{ i.get_absolute_url }}"
class=
"list-group-item"
>
<i
class=
"{{ i.get_status_icon }}"
title=
"{{ i.get_status_display }}"
></i>
{{ i.name }}
<span
class=
"index-vm-list-name"
>
<small
class=
"text-muted"
>
{{ i.primary_host.hostname }}
</small>
<i
class=
"{{ i.get_status_icon }}"
title=
"{{ i.get_status_display }}"
></i>
{{ i.name }}
</span>
<small
class=
"text-muted"
>
{{ i.primary_host.hostname }}
</small>
<div
class=
"pull-right dashboard-vm-favourite"
data-vm=
"{{ i.pk }}"
>
<div
class=
"pull-right dashboard-vm-favourite"
data-vm=
"{{ i.pk }}"
>
{% if i.fav %}
{% if i.fav %}
<i
class=
"icon-star text-primary title-favourite"
title=
"{% trans "
Unfavourite
"
%}"
></i>
<i
class=
"icon-star text-primary title-favourite"
title=
"{% trans "
Unfavourite
"
%}"
></i>
...
@@ -25,6 +28,7 @@
...
@@ -25,6 +28,7 @@
<i
class=
"icon-star-empty text-primary title-favourite"
title=
"{% trans "
Mark
as
favorite
"
%}"
></i>
<i
class=
"icon-star-empty text-primary title-favourite"
title=
"{% trans "
Mark
as
favorite
"
%}"
></i>
{% endif %}
{% endif %}
</div>
</div>
<div
style=
"clear: both;"
></div>
</a>
</a>
{% endfor %}
{% endfor %}
</div>
</div>
...
@@ -50,19 +54,24 @@
...
@@ -50,19 +54,24 @@
<div
class=
"panel-body"
id=
"vm-graph-view"
style=
"display: none"
>
<div
class=
"panel-body"
id=
"vm-graph-view"
style=
"display: none"
>
<p
class=
"pull-right"
>
<input
class=
"knob"
data-fgColor=
"chartreuse"
data-thickness=
".4"
data-max=
"{{ request.user.profile.instance_limit }}"
data-width=
"100"
data-height=
"100"
data-readOnly=
"true"
value=
"{{ instances|length|add:more_instances }}"
></p>
<p
class=
"pull-right"
>
<input
class=
"knob"
data-fgColor=
"chartreuse"
data-thickness=
".4"
data-max=
"{{ request.user.profile.instance_limit }}"
data-width=
"100"
data-height=
"100"
data-readOnly=
"true"
value=
"{{ instances|length|add:more_instances }}"
></p>
<p><span
class=
"bigbig"
>
{% blocktrans with count=running_vm_num %}
<big>
{{ count }}
</big>
running{% endblocktrans %}
</span>
<p><span
class=
"bigbig"
>
{% blocktrans with count=running_vm_num %}
<big>
{{ count }}
</big>
running{% endblocktrans %}
</span>
<ul
class=
"list-inline"
>
<ul
class=
"list-inline"
style=
"max-height: 95px; overflow: hidden;"
>
{% for vm in running_vms %}
{% for vm in running_vms %}
<li
class=
"label label-success"
>
<li
style=
"display: inline-block; padding: 2px;"
>
<a
href=
"vm.get_absolute_url"
title=
"{{vm.primary_host.get_fqdn}}"
><i
class=
"{{vm.get_status_icon}}"
></i>
{{vm.name}}
</a>
<a
href=
"{{vm.get_absolute_url}}"
title=
"{{vm.primary_host.get_fqdn}}"
class=
"label label-success"
>
</li>
<i
class=
"{{vm.get_status_icon}}"
></i>
{{vm.name}}
</a>
</li>
{% endfor %}
{% endfor %}
</ul>
</ul>
</p>
</p>
<p
class=
"big text-warning"
>
{% blocktrans with count=stopped_vm_num %}
<big>
{{ count }}
</big>
stopped{% endblocktrans %}
</p>
<div
class=
"clearfix"
></div>
<div
class=
"clearfix"
></div>
<div
class=
"text-right"
>
<div>
<a
href=
"{% url "
dashboard
.
views
.
vm-list
"
%}"
class=
"btn btn-primary btn-xs"
><i
class=
"icon-chevron-sign-right"
></i>
<strong>
{{ instances|length|add:more_instances }}
</strong>
machines total
</a>
<a
style=
"float: right; margin-top: 17px;"
href=
"{% url "
dashboard
.
views
.
vm-list
"
%}"
class=
"btn btn-primary btn-xs"
>
<i
class=
"icon-chevron-sign-right"
></i>
<strong>
{{ instances|length|add:more_instances }}
</strong>
machines total
</a>
<p
class=
"big text-warning"
>
{% blocktrans with count=stopped_vm_num %}
<big>
{{ count }}
</big>
stopped{% endblocktrans %}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
circle/dashboard/templates/dashboard/nojs-wrapper.html
View file @
9e2f21e1
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
<div
class=
"panel-body"
>
<div
class=
"panel-body"
>
{% include template %}
{% include template %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock %}
...
...
circle/dashboard/tests/test_views.py
View file @
9e2f21e1
...
@@ -530,6 +530,24 @@ class VmDetailTest(LoginMixin, TestCase):
...
@@ -530,6 +530,24 @@ class VmDetailTest(LoginMixin, TestCase):
response
=
c
.
get
(
"/dashboard/template/111111/"
)
response
=
c
.
get
(
"/dashboard/template/111111/"
)
self
.
assertEqual
(
response
.
status_code
,
404
)
self
.
assertEqual
(
response
.
status_code
,
404
)
def
test_permitted_customized_vm_create
(
self
):
c
=
Client
()
self
.
login
(
c
,
"superuser"
)
instance_count
=
Instance
.
objects
.
all
()
.
count
()
response
=
c
.
post
(
"/dashboard/vm/create/"
,
{
'name'
:
'vm'
,
'amount'
:
2
,
'customized'
:
1
,
'template'
:
1
,
'cpu_priority'
:
1
,
'cpu_count'
:
1
,
'ram_size'
:
1
,
'network'
:
[],
'disks'
:
[
Disk
.
objects
.
get
(
id
=
1
)
.
pk
],
})
self
.
assertEqual
(
response
.
status_code
,
302
)
self
.
assertEqual
(
instance_count
+
2
,
Instance
.
objects
.
all
()
.
count
())
class
VmDetailVncTest
(
LoginMixin
,
TestCase
):
class
VmDetailVncTest
(
LoginMixin
,
TestCase
):
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
fixtures
=
[
'test-vm-fixture.json'
,
'node.json'
]
...
...
circle/dashboard/views.py
View file @
9e2f21e1
...
@@ -921,7 +921,9 @@ class VmList(LoginRequiredMixin, ListView):
...
@@ -921,7 +921,9 @@ class VmList(LoginRequiredMixin, ListView):
instances
=
[{
instances
=
[{
'pk'
:
i
.
pk
,
'pk'
:
i
.
pk
,
'name'
:
i
.
name
,
'name'
:
i
.
name
,
'state'
:
i
.
state
,
'icon'
:
i
.
get_status_icon
(),
'host'
:
""
if
not
i
.
primary_host
else
i
.
primary_host
.
hostname
,
'status'
:
i
.
get_status_display
(),
'fav'
:
i
.
pk
in
favs
}
for
i
in
instances
]
'fav'
:
i
.
pk
in
favs
}
for
i
in
instances
]
return
HttpResponse
(
return
HttpResponse
(
json
.
dumps
(
list
(
instances
)),
# instances is ValuesQuerySet
json
.
dumps
(
list
(
instances
)),
# instances is ValuesQuerySet
...
@@ -1098,9 +1100,9 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -1098,9 +1100,9 @@ class VmCreate(LoginRequiredMixin, TemplateView):
if
not
template
.
has_level
(
request
.
user
,
'user'
):
if
not
template
.
has_level
(
request
.
user
,
'user'
):
raise
PermissionDenied
()
raise
PermissionDenied
()
inst
=
Instance
.
create_from_template
(
inst
ances
=
[
Instance
.
create_from_template
(
template
=
template
,
owner
=
user
)
template
=
template
,
owner
=
user
)
]
return
self
.
__deploy
(
request
,
inst
)
return
self
.
__deploy
(
request
,
inst
ances
)
def
__create_customized
(
self
,
request
,
*
args
,
**
kwargs
):
def
__create_customized
(
self
,
request
,
*
args
,
**
kwargs
):
user
=
request
.
user
user
=
request
.
user
...
@@ -1129,17 +1131,33 @@ class VmCreate(LoginRequiredMixin, TemplateView):
...
@@ -1129,17 +1131,33 @@ class VmCreate(LoginRequiredMixin, TemplateView):
networks
=
[
InterfaceTemplate
(
vlan
=
l
,
managed
=
l
.
managed
)
networks
=
[
InterfaceTemplate
(
vlan
=
l
,
managed
=
l
.
managed
)
for
l
in
post
[
'networks'
]]
for
l
in
post
[
'networks'
]]
disks
=
post
[
'disks'
]
disks
=
post
[
'disks'
]
inst
=
Instance
.
create_from_template
(
template
=
template
,
owner
=
user
,
networks
=
networks
,
ikwargs
.
update
({
disks
=
disks
,
**
ikwargs
)
'template'
:
template
,
return
self
.
__deploy
(
request
,
inst
)
'owner'
:
user
,
'networks'
:
networks
,
'disks'
:
disks
,
})
amount
=
post
[
'amount'
]
instances
=
Instance
.
mass_create_from_template
(
amount
=
amount
,
**
ikwargs
)
return
self
.
__deploy
(
request
,
instances
)
else
:
else
:
raise
PermissionDenied
()
raise
PermissionDenied
()
def
__deploy
(
self
,
request
,
instance
,
*
args
,
**
kwargs
):
def
__deploy
(
self
,
request
,
instances
,
*
args
,
**
kwargs
):
instance
.
deploy_async
(
user
=
request
.
user
)
for
i
in
instances
:
messages
.
success
(
request
,
_
(
'VM successfully created!'
))
i
.
deploy_async
(
user
=
request
.
user
)
path
=
instance
.
get_absolute_url
()
if
len
(
instances
)
>
1
:
messages
.
success
(
request
,
_
(
"Successfully created
%
d VMs!"
%
len
(
instances
)))
path
=
reverse
(
"dashboard.index"
)
else
:
messages
.
success
(
request
,
_
(
"VM successfully created!"
))
path
=
instances
[
0
]
.
get_absolute_url
()
if
request
.
is_ajax
():
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
path
}),
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
path
}),
content_type
=
"application/json"
)
content_type
=
"application/json"
)
...
...
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