Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Gelencsér Szabolcs
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
10fc46ee
authored
Feb 18, 2014
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashboard: new vm create modal
parent
66c1cfd4
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
370 additions
and
194 deletions
+370
-194
circle/dashboard/forms.py
+49
-37
circle/dashboard/static/dashboard/vm-create.js
+85
-107
circle/dashboard/templates/dashboard/_vm-create-1.html
+146
-0
circle/dashboard/templates/dashboard/_vm-create-2.html
+6
-0
circle/dashboard/templates/dashboard/modal-wrapper.html
+2
-0
circle/dashboard/templates/dashboard/nojs-wrapper.html
+1
-1
circle/dashboard/templates/dashboard/vm-create.html
+0
-11
circle/dashboard/views.py
+81
-38
No files found.
circle/dashboard/forms.py
View file @
10fc46ee
...
...
@@ -23,48 +23,53 @@ VLANS = Vlan.objects.all()
DISKS
=
Disk
.
objects
.
exclude
(
type
=
"qcow2-snap"
)
class
VmCreateForm
(
forms
.
Form
):
template
=
forms
.
ModelChoiceField
(
queryset
=
InstanceTemplate
.
objects
.
all
(),
empty_label
=
"Select pls"
)
class
VmCustomizeForm
(
forms
.
Form
):
name
=
forms
.
CharField
()
cpu_priority
=
forms
.
IntegerField
()
cpu_count
=
forms
.
IntegerField
()
ram_size
=
forms
.
IntegerField
()
disks
=
forms
.
ModelMultipleChoiceField
(
queryset
=
DISKS
,
required
=
False
)
queryset
=
None
,
required
=
True
)
networks
=
forms
.
ModelMultipleChoiceField
(
queryset
=
VLANS
,
required
=
False
)
queryset
=
None
,
required
=
False
)
template
=
forms
.
CharField
()
customized
=
forms
.
CharField
()
# dummy flag field
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
VmCreateForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
user
=
kwargs
.
pop
(
"user"
,
None
)
self
.
template
=
kwargs
.
pop
(
"template"
,
None
)
super
(
VmCustomizeForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
# set displayed disk and network list
self
.
fields
[
'disks'
]
.
queryset
=
Disk
.
get_objects_with_level
(
'user'
,
self
.
user
)
.
exclude
(
type
=
"qcow2-snap"
)
self
.
fields
[
'networks'
]
.
queryset
=
Vlan
.
get_objects_with_level
(
'user'
,
self
.
user
)
# set initial for disk and network list
self
.
initial
[
'disks'
]
=
self
.
template
.
disks
.
all
()
self
.
initial
[
'networks'
]
=
InterfaceTemplate
.
objects
.
filter
(
template
=
self
.
template
)
.
values_list
(
"vlan"
,
flat
=
True
)
# set initial for resources
self
.
initial
[
'cpu_priority'
]
=
self
.
template
.
priority
self
.
initial
[
'cpu_count'
]
=
self
.
template
.
num_cores
self
.
initial
[
'ram_size'
]
=
self
.
template
.
ram_size
# initial name and template pk
self
.
initial
[
'name'
]
=
self
.
template
.
name
self
.
initial
[
'template'
]
=
self
.
template
.
pk
self
.
initial
[
'customized'
]
=
self
.
template
.
pk
self
.
helper
=
FormHelper
(
self
)
self
.
helper
.
form_show_labels
=
False
self
.
helper
.
layout
=
Layout
(
Div
(
Div
(
Field
(
'template'
,
id
=
"vm-create-template-select"
,
css_class
=
"select form-control"
),
css_class
=
"col-sm-10"
,
),
css_class
=
"row"
,
),
Field
(
"template"
,
type
=
"hidden"
),
Field
(
"customized"
,
type
=
"hidden"
),
Div
(
# buttons
Div
(
AnyTag
(
"a"
,
HTML
(
"
%
s "
%
_
(
"Advanced"
)),
AnyTag
(
"i"
,
css_class
=
"vm-create-advanced-icon icon-caret-down"
),
css_class
=
"btn btn-info vm-create-advanced-btn"
,
),
css_class
=
"col-sm-5"
,
),
Div
(
AnyTag
(
# tip: don't try to use Button class
"button"
,
AnyTag
(
...
...
@@ -72,15 +77,21 @@ class VmCreateForm(forms.Form):
css_class
=
"icon-play"
),
HTML
(
" Start"
),
css_id
=
"vm-create-
submi
t"
,
css_id
=
"vm-create-
customized-star
t"
,
css_class
=
"btn btn-success"
,
),
css_class
=
"col-sm-5 text-right"
,
css_class
=
"col-sm-11 text-right"
,
),
css_class
=
"row"
,
),
Div
(
Div
(
Field
(
"name"
),
css_class
=
"col-sm-5"
,
),
css_class
=
"row"
,
),
Div
(
# vm-create-advanced
Div
(
Div
(
AnyTag
(
...
...
@@ -102,7 +113,8 @@ class VmCreateForm(forms.Form):
Field
(
'cpu_priority'
,
id
=
"vm-cpu-priority-slider"
,
css_class
=
"vm-slider"
,
data_slider_min
=
"0"
,
data_slider_max
=
"100"
,
data_slider_step
=
"1"
,
data_slider_value
=
"20"
,
data_slider_step
=
"1"
,
data_slider_value
=
self
.
template
.
priority
,
data_slider_handle
=
"square"
,
data_slider_tooltip
=
"hide"
),
css_class
=
"col-sm-9"
...
...
@@ -120,7 +132,8 @@ class VmCreateForm(forms.Form):
Field
(
'cpu_count'
,
id
=
"vm-cpu-count-slider"
,
css_class
=
"vm-slider"
,
data_slider_min
=
"1"
,
data_slider_max
=
"8"
,
data_slider_step
=
"1"
,
data_slider_value
=
"2"
,
data_slider_step
=
"1"
,
data_slider_value
=
self
.
template
.
num_cores
,
data_slider_handle
=
"square"
,
data_slider_tooltip
=
"hide"
),
css_class
=
"col-sm-9"
...
...
@@ -138,7 +151,8 @@ class VmCreateForm(forms.Form):
Field
(
'ram_size'
,
id
=
"vm-ram-size-slider"
,
css_class
=
"vm-slider"
,
data_slider_min
=
"128"
,
data_slider_max
=
"4096"
,
data_slider_step
=
"128"
,
data_slider_value
=
"512"
,
data_slider_step
=
"128"
,
data_slider_value
=
self
.
template
.
ram_size
,
data_slider_handle
=
"square"
,
data_slider_tooltip
=
"hide"
),
css_class
=
"col-sm-9"
...
...
@@ -257,8 +271,6 @@ class VmCreateForm(forms.Form):
),
css_class
=
"row"
),
# end of network
css_class
=
"vm-create-advanced"
),
)
...
...
circle/dashboard/static/dashboard/vm-create.js
View file @
10fc46ee
...
...
@@ -2,24 +2,72 @@ var vlans = [];
var
disks
=
[];
$
(
function
()
{
vmC
reat
eLoaded
();
vmC
ustomiz
eLoaded
();
});
function
vmCreateLoaded
()
{
$
(
'.vm-create-advanced'
).
hide
();
$
(
'.vm-create-advanced-btn'
).
click
(
function
()
{
$
(
'.vm-create-advanced'
).
stop
().
slideToggle
();
if
(
$
(
'.vm-create-advanced-icon'
).
hasClass
(
'icon-caret-down'
))
{
$
(
'.vm-create-advanced-icon'
).
removeClass
(
'icon-caret-down'
).
addClass
(
'icon-caret-up'
);
}
else
{
$
(
'.vm-create-advanced-icon'
).
removeClass
(
'icon-caret-up'
).
addClass
(
'icon-caret-down'
);
$
(
".vm-create-template-details"
).
hide
();
$
(
".vm-create-template-summary"
).
click
(
function
()
{
$
(
this
).
next
(
".vm-create-template-details"
).
slideToggle
();
});
$
(
".customize-vm"
).
click
(
function
()
{
var
template
=
$
(
this
).
data
(
"template-pk"
);
console
.
log
(
template
);
$
.
get
(
"/dashboard/vm/create/?template="
+
template
,
function
(
data
)
{
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
addSliderMiscs
();
$
(
'#create-modal'
).
modal
(
'show'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
remove
();
});
});
return
false
;
});
/* start vm button clicks */
$
(
'.vm-create-start'
).
click
(
function
()
{
template
=
$
(
this
).
data
(
"template-pk"
);
$
.
ajax
({
url
:
'/dashboard/vm/create/'
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
type
:
'POST'
,
data
:
{
'template'
:
template
},
success
:
function
(
data
,
textStatus
,
xhr
)
{
if
(
data
.
redirect
)
{
window
.
location
.
replace
(
data
.
redirect
+
'#activity'
);
}
else
{
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
addSliderMiscs
();
$
(
'#create-modal'
).
modal
(
'show'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
remove
();
});
}
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
$
(
'#vm-create-template-select'
).
change
(
function
()
{
vmCreateTemplateChange
(
this
);
if
(
xhr
.
status
==
500
)
{
addMessage
(
"500 Internal Server Error"
,
"danger"
);
}
else
{
addMessage
(
xhr
.
status
+
" Unknown Error"
,
"danger"
);
}
}
});
return
false
;
});
}
function
vmCustomizeLoaded
()
{
/* network thingies */
/* add network */
...
...
@@ -86,15 +134,24 @@ function vmCreateLoaded() {
/* copy networks from hidden select */
$
(
'#vm-create-network-add-vlan option'
).
each
(
function
()
{
var
managed
=
$
(
this
).
text
().
indexOf
(
"mana"
)
==
0
;
var
text
=
$
(
this
).
text
();
var
raw_
text
=
$
(
this
).
text
();
var
pk
=
$
(
this
).
val
();
if
(
managed
)
{
text
=
text
.
replace
(
"managed -"
,
""
);
text
=
raw_
text
.
replace
(
"managed -"
,
""
);
}
else
{
text
=
text
.
replace
(
"unmanaged -"
,
""
);
text
=
raw_
text
.
replace
(
"unmanaged -"
,
""
);
}
var
html
=
'<option data-managed="'
+
(
managed
?
1
:
0
)
+
'" value="'
+
pk
+
'">'
+
text
+
'</option>'
;
if
(
$
(
'#vm-create-network-list span'
).
length
<
1
)
{
$
(
"#vm-create-network-list"
).
html
(
""
);
}
if
(
$
(
this
).
is
(
":selected"
))
{
$
(
"#vm-create-network-list"
).
append
(
vmCreateNetworkLabel
(
pk
,
raw_text
.
replace
(
"unmanaged -"
,
""
).
replace
(
"managed -"
,
""
),
managed
));
}
else
{
$
(
'#vm-create-network-add-select'
).
append
(
html
);
}
});
...
...
@@ -168,8 +225,20 @@ function vmCreateLoaded() {
});
/* copy disks from hidden select */
$
(
'#vm-create-disk-add-select'
).
html
(
$
(
'#vm-create-disk-add-form'
).
html
());
$
(
'#vm-create-disk-add-form option'
).
each
(
function
()
{
var
text
=
$
(
this
).
text
();
var
pk
=
$
(
this
).
val
();
var
html
=
'<option value="'
+
pk
+
'">'
+
text
+
'</option>'
;
if
(
$
(
'#vm-create-disk-list span'
).
length
<
1
)
{
$
(
"#vm-create-disk-list"
).
html
(
""
);
}
if
(
$
(
this
).
is
(
":selected"
))
{
$
(
"#vm-create-disk-list"
).
append
(
vmCreateDiskLabel
(
pk
,
text
));
}
else
{
$
(
'#vm-create-disk-add-select'
).
append
(
html
);
}
});
/* build up disk list */
$
(
'#vm-create-disk-add-select option'
).
each
(
function
()
{
...
...
@@ -179,8 +248,8 @@ function vmCreateLoaded() {
});
});
/*
add button
*/
$
(
'#vm-create-
submi
t'
).
click
(
function
()
{
/*
start vm button clicks
*/
$
(
'#vm-create-
customized-star
t'
).
click
(
function
()
{
$
.
ajax
({
url
:
'/dashboard/vm/create/'
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
...
...
@@ -219,97 +288,6 @@ function vmCreateLoaded() {
$
(
'.js-hidden'
).
hide
();
}
function
vmCreateTemplateChange
(
new_this
)
{
this
.
value
=
new_this
.
value
;
if
(
this
.
value
<
0
)
return
;
$
.
ajax
({
url
:
'/dashboard/template/'
+
this
.
value
,
type
:
'GET'
,
success
:
function
(
data
,
textStatus
,
xhr
)
{
if
(
xhr
.
status
==
200
)
{
// set sliders
$
(
'#vm-cpu-priority-slider'
).
slider
(
"setValue"
,
data
[
'priority'
]);
$
(
'#vm-cpu-count-slider'
).
slider
(
"setValue"
,
data
[
'num_cores'
]);
$
(
'#vm-ram-size-slider'
).
slider
(
"setValue"
,
data
[
'ram_size'
]);
/* slider doesn't have change event ........................ */
refreshSliders
();
/* clear selections */
$
(
"#vm-create-network-add-vlan"
).
find
(
'option'
).
prop
(
'selected'
,
false
);
$
(
'#vm-create-disk-add-form'
).
find
(
'option'
).
prop
(
'selected'
,
false
);
/* clear the network select */
$
(
"#vm-create-network-add-select"
).
html
(
''
);
/* append vlans from InterfaceTemplates */
$
(
'#vm-create-network-list'
).
html
(
""
);
var
added_vlans
=
[]
for
(
var
n
=
0
;
n
<
data
[
'network'
].
length
;
n
++
)
{
nn
=
data
[
'network'
][
n
]
$
(
'#vm-create-network-list'
).
append
(
vmCreateNetworkLabel
(
nn
.
vlan_pk
,
nn
.
vlan
,
nn
.
managed
)
);
$
(
'#vm-create-network-add-vlan option[value="'
+
nn
.
vlan_pk
+
'"]'
).
prop
(
'selected'
,
true
);
added_vlans
.
push
(
nn
.
vlan_pk
);
}
/* remove already added vlans from dropdown or add new ones */
$
(
'#vm-create-network-add-select'
).
html
(
''
);
// this is working because the vlans array already has the icon's hex code
for
(
var
i
=
0
;
i
<
vlans
.
length
;
i
++
)
if
(
added_vlans
.
indexOf
(
vlans
[
i
].
pk
)
==
-
1
)
{
var
html
=
'<option data-managed="'
+
(
vlans
[
i
].
managed
?
1
:
0
)
+
'" value="'
+
vlans
[
i
].
pk
+
'">'
+
vlans
[
i
].
name
+
'</option>'
;
$
(
'#vm-create-network-add-select'
).
append
(
html
);
}
/* enable the network add button if there are not added vlans */
if
(
added_vlans
.
length
!=
vlans
.
length
)
{
$
(
'#vm-create-network-add-button'
).
attr
(
'disabled'
,
false
);
}
else
{
$
(
'#vm-create-network-add-select'
).
html
(
'<option value="-1">No more networks!</option>'
);
$
(
'#vm-create-network-add-button'
).
attr
(
'disabled'
,
true
);
}
/* if there are no added vlans print it out */
if
(
added_vlans
.
length
<
1
)
{
$
(
'#vm-create-network-list'
).
html
(
"Not added to any network!"
);
}
/* append disks */
$
(
'#vm-create-disk-list'
).
html
(
''
);
var
added_disks
=
[]
for
(
var
d
=
0
;
d
<
data
[
'disks'
].
length
;
d
++
)
{
dd
=
data
[
'disks'
][
d
]
$
(
'#vm-create-disk-list'
).
append
(
vmCreateDiskLabel
(
dd
.
pk
,
dd
.
name
)
);
$
(
'#vm-create-disk-add-form option[value="'
+
dd
.
pk
+
'"]'
).
prop
(
'selected'
,
true
);
added_disks
.
push
(
dd
.
pk
);
}
/* remove already added disks from dropdown or add new ones */
$
(
'#vm-create-disk-add-select'
).
html
(
''
);
for
(
var
i
=
0
;
i
<
disks
.
length
;
i
++
)
if
(
added_disks
.
indexOf
(
disks
[
i
].
pk
)
==
-
1
)
$
(
'#vm-create-disk-add-select'
).
append
(
$
(
'<option>'
,
{
value
:
disks
[
i
].
pk
,
text
:
disks
[
i
].
name
}));
/* enable the disk add button if there are not added disks */
if
(
added_disks
.
length
!=
disks
.
length
)
{
$
(
'#vm-create-disk-add-button'
).
attr
(
'disabled'
,
false
);
}
else
{
$
(
'#vm-create-disk-add-select'
).
html
(
'<option value="-1">We are out of <options> hehe</option>'
);
$
(
'#vm-create-disk-add-button'
).
attr
(
'disabled'
,
true
);
}
}
}
});
}
function
vmCreateNetworkLabel
(
pk
,
name
,
managed
)
{
return
'<span id="vlan-'
+
pk
+
'" class="label label-'
+
(
managed
?
'primary'
:
'default'
)
+
'"><i class="icon-'
+
(
managed
?
'globe'
:
'link'
)
+
'"></i> '
+
name
+
' <a href="#" class="hover-black vm-create-remove-network"><i class="icon-remove-sign"></i></a></span> '
;
...
...
circle/dashboard/templates/dashboard/_vm-create-1.html
0 → 100644
View file @
10fc46ee
{% load sizefieldtags %}
<div
class=
"vm-create-template-list"
>
{% for t in templates %}
<div
class=
"vm-create-template"
>
<div
class=
"vm-create-template-summary"
>
{{ t.name }}
<span
class=
"pull-right"
><i
class=
"icon-{{ t.os_type }}"
></i>
{{ t.system }}
</span>
</div>
<div
class=
"vm-create-template-details"
>
<ul>
<li>
<i
class=
"icon-gears"
></i>
CPU
<div
class=
"progress pull-right"
>
<div
class=
"progress-bar progress-bar-success"
role=
"progressbar"
aria-valuenow=
"{{ t.num_cores }}"
aria-valuemin=
"0"
aria-valuemax=
"8"
style=
"width: 80%"
>
<span
class=
"progress-bar-text"
>
{{ t.num_cores }} cores
</span>
</div>
</div>
</li>
<li>
<i
class=
"icon-ticket"
></i>
Memory
<div
class=
"progress pull-right"
>
<div
class=
"progress-bar progress-bar-info"
role=
"progressbar"
aria-valuenow=
"{{ t.ram_size }}"
aria-valuemin=
"0"
aria-valuemax=
"4096"
style=
"width: 80%"
>
<span
class=
"progress-bar-text"
>
{{ t.ram_size }} MB
</span>
</div>
</div>
</li>
<li>
<i
class=
"icon-file"
></i>
Disks
<span
style=
"float: right;"
>
{% for d in t.disks.all %}{{ d.name }} ({{ d.size|filesize }}){% if not forloop.last %}, {% endif %}{% endfor %}
</span>
</li>
<li>
<i
class=
"icon-globe"
></i>
Network:
<span
style=
"float: right;"
>
{% for i in t.interface_set.all %}{{ i.vlan.name }}{% if not forloop.last %}, {% endif %}{% endfor %}
</span>
</li>
<li>
<i
class=
"icon-tag"
></i>
Típus: {{ t.lease.name }}
<span
style=
"float: right;"
>
<i
class=
"icon-pause"
></i>
{{ t.lease.get_readable_suspend_time }}
<i
class=
"icon-remove"
></i>
{{ t.lease.get_readable_delete_time }}
</span>
</li>
<li>
<i
class=
"icon-hand-right"
></i>
Description:
<span
style=
"float: right; max-width: 350px;"
>
{{ t.description }}
</span>
<div
class=
"clearfix"
></div>
</li>
</ul>
<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>
<form
class=
"pull-right text-right"
method=
"POST"
action=
"{% url "
dashboard
.
views
.
vm-create
"
%}"
>
{% csrf_token %}
<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>
</form>
</div>
</div>
</div>
{% endfor %}
</div>
<style>
.row
{
margin-bottom
:
15px
;
}
.vm-create-template
{
max-width
:
800px
;
border
:
1px
solid
black
;
border-bottom
:
none
;
}
.vm-create-template-list
.vm-create-template
:last-child
{
border-bottom
:
1px
solid
black
;
}
.vm-create-template-summary
{
padding
:
15px
;
cursor
:
pointer
;
}
.vm-create-template
:nth-child
(
odd
)
.vm-create-template-summary
{
background
:
#F5F5F5
;
}
.vm-create-template-list
.vm-create-template-summary
:hover
{
background
:
#D2D2D2
;
}
.vm-create-template-details
{
border-top
:
1px
dashed
#D3D3D3
;
padding
:
15px
;
}
.vm-create-template-details
ul
{
list-style
:
none
;
padding
:
0
15px
;
}
.vm-create-template-details
li
{
border-bottom
:
1px
dotted
#aaa
;
padding
:
5px
0px
;
}
.progress
{
position
:
relative
;
width
:
200px
;
height
:
12px
;
margin-bottom
:
0px
;
margin-top
:
5px
;
}
.progress-bar-text
{
position
:
absolute
;
display
:
block
;
width
:
100%
;
color
:
white
;
/* outline */
text-shadow
:
-1px
-1px
0
#000
,
1px
-1px
0
#000
,
-1px
1px
0
#000
,
1px
1px
0
#000
;
font-size
:
10px
;
}
</style>
{% block "extra-js" %}
<script>
$
(
'.progress-bar'
).
each
(
function
()
{
var
min
=
$
(
this
).
attr
(
'aria-valuemin'
);
var
max
=
$
(
this
).
attr
(
'aria-valuemax'
);
var
now
=
$
(
this
).
attr
(
'aria-valuenow'
);
var
siz
=
(
now
-
min
)
*
100
/
(
max
-
min
);
$
(
this
).
css
(
'width'
,
siz
+
'%'
);
});
</script>
{% endblock %}
circle/dashboard/templates/dashboard/_vm-create-2.html
0 → 100644
View file @
10fc46ee
{% load crispy_forms_tags %}
{% load sizefieldtags %}
{% crispy vm_create_form %}
<script
src=
"/static/dashboard/vm-create.js"
></script>
circle/dashboard/templates/dashboard/modal-wrapper.html
View file @
10fc46ee
<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>
...
...
circle/dashboard/templates/dashboard/nojs-wrapper.html
View file @
10fc46ee
...
...
@@ -15,7 +15,7 @@
{% endblock %}
{% block extra_js %}
{% if template == "dashboard/
vm-create
.html" %}
{% if template == "dashboard/
_vm-create-1
.html" %}
<script
src=
"{{ STATIC_URL }}dashboard/vm-create.js"
></script>
{% endif %}
{% endblock %}
circle/dashboard/templates/dashboard/vm-create.html
deleted
100644 → 0
View file @
66c1cfd4
{% load crispy_forms_tags %}
<style>
.row
{
margin-bottom
:
15px
;
}
</style>
<form
method=
"POST"
action=
"/dashboard/vm/create/"
>
{% csrf_token %}
{% crispy vm_create_form %}
</form>
circle/dashboard/views.py
View file @
10fc46ee
...
...
@@ -28,7 +28,8 @@ from django_tables2 import SingleTableView
from
braces.views
import
LoginRequiredMixin
,
SuperuserRequiredMixin
from
.forms
import
(
VmCreateForm
,
TemplateForm
,
LeaseForm
,
NodeForm
,
HostForm
,
DiskAddForm
,
VmCustomizeForm
,
TemplateForm
,
LeaseForm
,
NodeForm
,
HostForm
,
DiskAddForm
,
)
from
.tables
import
(
VmListTable
,
NodeListTable
,
NodeVmListTable
,
TemplateListTable
,
LeaseListTable
,
GroupListTable
,)
...
...
@@ -36,7 +37,6 @@ from vm.models import (Instance, InstanceTemplate, InterfaceTemplate,
InstanceActivity
,
Node
,
instance_activity
,
Lease
,
Interface
)
from
firewall.models
import
Vlan
,
Host
,
Rule
from
storage.models
import
Disk
from
dashboard.models
import
Favourite
logger
=
logging
.
getLogger
(
__name__
)
...
...
@@ -952,7 +952,7 @@ class GroupDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
class
VmCreate
(
LoginRequiredMixin
,
TemplateView
):
form_class
=
VmC
reat
eForm
form_class
=
VmC
ustomiz
eForm
form
=
None
def
get_template_names
(
self
):
...
...
@@ -962,51 +962,66 @@ class VmCreate(LoginRequiredMixin, TemplateView):
return
[
'dashboard/nojs-wrapper.html'
]
def
get
(
self
,
request
,
form
=
None
,
*
args
,
**
kwargs
):
if
form
is
None
:
form
=
self
.
form_class
()
form
.
fields
[
'disks'
]
.
queryset
=
Disk
.
get_objects_with_level
(
'user'
,
request
.
user
)
.
exclude
(
type
=
"qcow2-snap"
)
form
.
fields
[
'networks'
]
.
queryset
=
Vlan
.
get_objects_with_level
(
'user'
,
request
.
user
)
form_error
=
form
is
not
None
template
=
(
form
.
template
.
pk
if
form_error
else
request
.
GET
.
get
(
"template"
))
templates
=
InstanceTemplate
.
get_objects_with_level
(
'user'
,
request
.
user
)
form
.
fields
[
'template'
]
.
queryset
=
templates
if
form
is
None
and
template
:
form
=
self
.
form_class
(
user
=
request
.
user
,
template
=
templates
.
get
(
pk
=
template
))
context
=
self
.
get_context_data
(
**
kwargs
)
if
template
:
context
.
update
({
'template'
:
'dashboard/vm-create.html'
,
'box_title'
:
'Create a VM'
,
'template'
:
'dashboard/_vm-create-2.html'
,
'box_title'
:
_
(
'Customize VM'
),
'ajax_title'
:
False
,
'vm_create_form'
:
form
,
'template_o'
:
templates
.
get
(
pk
=
template
),
})
else
:
context
.
update
({
'template'
:
'dashboard/_vm-create-1.html'
,
'box_title'
:
_
(
'Create a VM'
),
'ajax_title'
:
False
,
'templates'
:
templates
.
all
(),
})
return
self
.
render_to_response
(
context
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
form
=
self
.
form_class
(
request
.
POST
)
def
__create_normal
(
self
,
request
,
*
args
,
**
kwargs
):
user
=
request
.
user
template
=
InstanceTemplate
.
objects
.
get
(
pk
=
request
.
POST
.
get
(
"template"
))
# permission check
if
not
template
.
has_level
(
request
.
user
,
'user'
):
raise
PermissionDenied
()
inst
=
Instance
.
create_from_template
(
template
=
template
,
owner
=
user
)
return
self
.
__deploy
(
request
,
inst
)
def
__create_customized
(
self
,
request
,
*
args
,
**
kwargs
):
user
=
request
.
user
form
=
self
.
form_class
(
request
.
POST
,
user
=
request
.
user
,
template
=
InstanceTemplate
.
objects
.
get
(
pk
=
request
.
POST
.
get
(
"template"
)
)
)
if
not
form
.
is_valid
():
return
self
.
get
(
request
,
form
,
*
args
,
**
kwargs
)
post
=
form
.
cleaned_data
user
=
request
.
user
try
:
limit
=
user
.
profile
.
instance_limit
except
Exception
as
e
:
logger
.
debug
(
'No profile or instance limit:
%
s'
,
e
)
else
:
current
=
Instance
.
active
.
filter
(
owner
=
user
)
.
count
()
logger
.
debug
(
'current use:
%
d, limit:
%
d'
,
current
,
limit
)
if
limit
<
current
:
messages
.
error
(
request
,
_
(
'Instance limit (
%
d) exceeded.'
)
%
limit
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
'/'
}),
content_type
=
"application/json"
)
else
:
return
redirect
(
'/'
)
template
=
post
[
'template'
]
if
not
template
.
has_level
(
request
.
user
,
'user'
):
template
=
InstanceTemplate
.
objects
.
get
(
pk
=
post
[
'template'
])
# permission check
if
not
template
.
has_level
(
user
,
'user'
):
raise
PermissionDenied
()
if
request
.
user
.
has_perm
(
'vm.set_resources'
):
ikwargs
=
{
'name'
:
post
[
'name'
],
'num_cores'
:
post
[
'cpu_count'
],
'ram_size'
:
post
[
'ram_size'
],
'priority'
:
post
[
'cpu_priority'
],
...
...
@@ -1017,17 +1032,45 @@ class VmCreate(LoginRequiredMixin, TemplateView):
inst
=
Instance
.
create_from_template
(
template
=
template
,
owner
=
user
,
networks
=
networks
,
disks
=
disks
,
**
ikwargs
)
return
self
.
__deploy
(
request
,
inst
)
else
:
inst
=
Instance
.
create_from_template
(
template
=
template
,
owner
=
user
)
inst
.
deploy_async
(
user
=
request
.
user
)
raise
PermissionDenied
()
def
__deploy
(
self
,
request
,
instance
,
*
args
,
**
kwargs
):
instance
.
deploy_async
(
user
=
request
.
user
)
messages
.
success
(
request
,
_
(
'VM successfully created!'
))
path
=
inst
.
get_absolute_url
()
path
=
inst
ance
.
get_absolute_url
()
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
path
}),
content_type
=
"application/json"
)
else
:
return
redirect
(
path
)
return
redirect
(
"
%
s#activity"
%
path
)
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
user
=
request
.
user
# limit chekcs
try
:
limit
=
user
.
profile
.
instance_limit
except
Exception
as
e
:
logger
.
debug
(
'No profile or instance limit:
%
s'
,
e
)
else
:
current
=
Instance
.
active
.
filter
(
owner
=
user
)
.
count
()
logger
.
debug
(
'current use:
%
d, limit:
%
d'
,
current
,
limit
)
if
limit
<
current
:
messages
.
error
(
request
,
_
(
'Instance limit (
%
d) exceeded.'
)
%
limit
)
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
'/'
}),
content_type
=
"application/json"
)
else
:
return
redirect
(
'/'
)
create_func
=
(
self
.
__create_normal
if
request
.
POST
.
get
(
"customized"
)
is
None
else
self
.
__create_customized
)
return
create_func
(
request
,
*
args
,
**
kwargs
)
class
NodeCreate
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
TemplateView
):
...
...
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