Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
8fd80cf1
authored
Jan 09, 2014
by
Oláh István Gergely
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashboard: add node create form
parent
e029a56b
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
228 additions
and
470 deletions
+228
-470
circle/dashboard/forms.py
+170
-5
circle/dashboard/static/dashboard/dashboard.js
+6
-6
circle/dashboard/static/dashboard/node-create.js
+0
-273
circle/dashboard/static/dashboard/vm-create.js
+4
-4
circle/dashboard/templates/dashboard/modal-wrapper.html
+1
-1
circle/dashboard/templates/dashboard/node-create.html
+4
-133
circle/dashboard/views.py
+35
-47
circle/vm/models/node.py
+8
-1
No files found.
circle/dashboard/forms.py
View file @
8fd80cf1
from
datetime
import
timedelta
from
django
import
forms
from
vm.models
import
InstanceTemplate
,
Lease
,
InterfaceTemplate
from
vm.models
import
InstanceTemplate
,
Lease
,
InterfaceTemplate
,
Node
from
storage.models
import
Disk
from
firewall.models
import
Vlan
# from django.core.urlresolvers import reverse_lazy
from
firewall.models
import
Vlan
,
Host
from
crispy_forms.helper
import
FormHelper
from
crispy_forms.layout
import
(
Layout
,
Div
,
BaseInput
,
Field
,
HTML
,
Submit
,
Fieldset
)
...
...
@@ -13,8 +11,12 @@ from crispy_forms.utils import render_field
from
django.template
import
Context
from
django.template.loader
import
render_to_string
from
django.forms.widgets
import
TextInput
from
django.forms
import
ModelForm
from
crispy_forms.bootstrap
import
FormActions
from
django.forms.models
import
BaseInlineFormSet
from
django.utils.translation
import
ugettext
as
_
# from crispy_forms.bootstrap import FormActions
VLANS
=
Vlan
.
objects
.
all
()
...
...
@@ -292,6 +294,169 @@ class VmCreateForm(forms.Form):
)
class
HostForm
(
forms
.
ModelForm
):
def
setowner
(
self
,
user
):
self
.
instance
.
owner
=
user
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
HostForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
helper
=
FormHelper
(
self
)
self
.
helper
.
form_show_labels
=
False
self
.
helper
.
form_tag
=
False
self
.
helper
.
layout
=
Layout
(
Div
(
Div
(
# host
Div
(
AnyTag
(
'h3'
,
HTML
(
_
(
"Host"
)),
),
css_class
=
"col-sm-3"
,
),
css_class
=
"row"
,
),
Div
(
# host data
Div
(
# hostname
HTML
(
'<label for="node-hostname-box">'
'Name'
'</label>'
),
css_class
=
"col-sm-3"
,
),
Div
(
# hostname
'hostname'
,
css_class
=
"col-sm-9"
,
),
Div
(
# mac
HTML
(
'<label for="node-mac-box">'
'MAC'
'</label>'
),
css_class
=
"col-sm-3"
,
),
Div
(
'mac'
,
css_class
=
"col-sm-9"
,
),
Div
(
# ip
HTML
(
'<label for="node-ip-box">'
'IP'
'</label>'
),
css_class
=
"col-sm-3"
,
),
Div
(
'ipv4'
,
css_class
=
"col-sm-9"
,
),
Div
(
# vlan
HTML
(
'<label for="node-vlan-box">'
'VLAN'
'</label>'
),
css_class
=
"col-sm-3"
,
),
Div
(
'vlan'
,
css_class
=
"col-sm-9"
,
),
css_class
=
"row"
,
),
),
)
class
Meta
:
model
=
Host
fields
=
[
'hostname'
,
'vlan'
,
'mac'
,
'ipv4'
,
]
class
NodeForm
(
forms
.
ModelForm
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
NodeForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
helper
=
FormHelper
(
self
)
self
.
helper
.
form_show_labels
=
False
self
.
helper
.
layout
=
Layout
(
Div
(
Div
(
Div
(
Div
(
AnyTag
(
'h3'
,
HTML
(
_
(
"Node"
)),
),
css_class
=
"col-sm-3"
,
),
css_class
=
"row"
,
),
Div
(
Div
(
# nodename
HTML
(
'<label for="node-nodename-box">'
'Name'
'</label>'
),
css_class
=
"col-sm-3"
,
),
Div
(
'name'
,
css_class
=
"col-sm-9"
,
),
css_class
=
"row"
,
),
Div
(
Div
(
# priority
HTML
(
'<label for="node-nodename-box">'
'Priority'
'</label>'
),
css_class
=
"col-sm-3"
,
),
Div
(
'priority'
,
css_class
=
"col-sm-9"
,
),
css_class
=
"row"
,
),
Div
(
Div
(
# enabled
HTML
(
'<label for="node-nodename-box">'
'Enabled'
'</label>'
),
css_class
=
"col-sm-3"
,
),
Div
(
'enabled'
,
css_class
=
"col-sm-9"
,
),
css_class
=
"row"
,
),
Div
(
# nested host
HTML
(
"""{
%
load crispy_forms_tags
%
}
{
%
crispy hostform
%
}
"""
)
),
Div
(
Div
(
AnyTag
(
# tip: don't try to use Button class
"button"
,
AnyTag
(
"i"
,
css_class
=
"icon-play"
),
HTML
(
"Start"
),
css_id
=
"node-create-submit"
,
css_class
=
"btn btn-success"
,
),
css_class
=
"col-sm-12 text-right"
,
),
css_class
=
"row"
,
),
css_class
=
"col-sm-11"
,
),
css_class
=
"row"
,
),
)
class
Meta
:
model
=
Node
fields
=
[
'name'
,
'priority'
,
'enabled'
,
]
class
TemplateForm
(
forms
.
ModelForm
):
managed_networks
=
forms
.
ModelMultipleChoiceField
(
queryset
=
VLANS
,
required
=
False
)
...
...
circle/dashboard/static/dashboard/dashboard.js
View file @
8fd80cf1
...
...
@@ -7,9 +7,9 @@ $(function () {
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
addSliderMiscs
();
$
(
'#
vm-
create-modal'
).
modal
(
'show'
);
$
(
'#
vm-
create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#
vm-
create-modal'
).
remove
();
$
(
'#create-modal'
).
modal
(
'show'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
remove
();
});
}
});
...
...
@@ -24,9 +24,9 @@ $(function () {
$
(
'body'
).
append
(
data
);
nodeCreateLoaded
();
addSliderMiscs
();
$
(
'#
node-
create-modal'
).
modal
(
'show'
);
$
(
'#
node-
create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#
node-
create-modal'
).
remove
();
$
(
'#create-modal'
).
modal
(
'show'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
remove
();
});
}
});
...
...
circle/dashboard/static/dashboard/node-create.js
View file @
8fd80cf1
var
vlans
=
[];
var
disks
=
[];
$
(
function
()
{
nodeCreateLoaded
();
});
function
nodeCreateLoaded
()
{
$
(
'.node-create-advanced'
).
hide
();
$
(
'.node-create-advanced-btn'
).
click
(
function
()
{
$
(
'.vm-create-advanced'
).
stop
().
slideToggle
();
if
(
$
(
'.node-create-advanced-icon'
).
hasClass
(
'icon-caret-down'
))
{
$
(
'.node-create-advanced-icon'
).
removeClass
(
'icon-caret-down'
).
addClass
(
'icon-caret-up'
);
}
else
{
$
(
'.node-create-advanced-icon'
).
removeClass
(
'icon-caret-up'
).
addClass
(
'icon-caret-down'
);
}
});
$
(
'#node-create-template-select'
).
change
(
function
()
{
nodeCreateTemplateChange
(
this
);
});
/* network thingies */
/* add network */
$
(
'#node-create-network-add-button'
).
click
(
function
()
{
var
vlan_pk
=
$
(
'#node-create-network-add-select :selected'
).
val
();
var
managed
=
$
(
'#node-create-network-add-checkbox-managed'
).
prop
(
'checked'
);
var
name
=
$
(
'#node-create-network-add-select :selected'
).
text
();
if
(
$
(
'#node-create-network-list'
).
children
(
'span'
).
length
<
1
)
{
$
(
'#node-create-network-list'
).
html
(
''
);
}
$
(
'#node-create-network-list'
).
append
(
nodeCreateNetworkLabel
(
vlan_pk
,
name
,
managed
)
);
/* select the network from the managed/unmanaged multiple select */
if
(
managed
)
{
$
(
'#node-create-network-add-managed option[value="'
+
vlan_pk
+
'"]'
).
prop
(
'selected'
,
true
);
}
else
{
$
(
'#node-create-network-add-unmanaged option[value="'
+
vlan_pk
+
'"]'
).
prop
(
'selected'
,
true
);
}
$
(
'option:selected'
,
$
(
'#node-create-network-add-select'
)).
remove
();
/* add dummy text if no more networks are available */
if
(
$
(
'#node-create-network-add-select option'
).
length
<
1
)
{
$
(
'#node-create-network-add-button'
).
attr
(
'disabled'
,
true
);
$
(
'#node-create-network-add-select'
).
html
(
'<option value="-1">We are out of <options> hehe</option>'
);
}
return
false
;
});
/* remove network */
// event for network remove button (icon, X)
$
(
'body'
).
on
(
'click'
,
'.node-create-remove-network'
,
function
()
{
var
vlan_pk
=
(
$
(
this
).
parent
(
'span'
).
prop
(
'id'
)).
replace
(
'vlan-'
,
''
)
// if it's "blue" then it's managed, kinda not cool
var
managed
=
$
(
this
).
parent
(
'span'
).
hasClass
(
'label-primary'
);
$
(
this
).
parent
(
'span'
).
fadeOut
(
500
,
function
()
{
/* if ther are no more vlans disabled the add button */
if
(
$
(
'#node-create-network-add-select option'
)[
0
].
value
==
-
1
)
{
$
(
'#node-create-network-add-button'
).
attr
(
'disabled'
,
false
);
$
(
'#node-create-network-add-select'
).
html
(
''
);
}
/* remove the network label */
$
(
this
).
remove
();
var
vlan_name
=
$
(
this
).
text
();
$
(
'#node-create-network-add-select'
).
append
(
$
(
'<option>'
,
{
value
:
vlan_pk
,
text
:
vlan_name
}));
/* remove the selection from the multiple select */
$
(
'#node-create-network-add-'
+
(
managed
?
''
:
'un'
)
+
'managed option[value="'
+
vlan_pk
+
'"]'
).
prop
(
'selected'
,
false
);
if
(
$
(
'#node-create-network-list'
).
children
(
'span'
).
length
<
1
)
{
$
(
'#node-create-network-list'
).
append
(
'Not added to any network!'
);
}
});
return
false
;
});
/* copy networks from hidden select */
$
(
'#node-create-network-add-select'
).
html
(
$
(
'#node-create-network-add-managed'
).
html
());
/* build up network list */
$
(
'#node-create-network-add-select option'
).
each
(
function
()
{
vlans
.
push
({
'name'
:
$
(
this
).
text
(),
'pk'
:
parseInt
(
$
(
this
).
val
())
});
});
/* ----- end of networks thingies ----- */
/* add disk */
$
(
'#node-create-disk-add-button'
).
click
(
function
()
{
var
disk_pk
=
$
(
'#node-create-disk-add-select :selected'
).
val
();
var
name
=
$
(
'#node-create-disk-add-select :selected'
).
text
();
if
(
$
(
'#node-create-disk-list'
).
children
(
'span'
).
length
<
1
)
{
$
(
'#node-create-disk-list'
).
html
(
''
);
}
$
(
'#node-create-disk-list'
).
append
(
nodeCreateDiskLabel
(
disk_pk
,
name
)
);
/* select the disk from the multiple select */
$
(
'#node-create-disk-add-form option[value="'
+
disk_pk
+
'"]'
).
prop
(
'selected'
,
true
);
$
(
'option:selected'
,
$
(
'#node-create-disk-add-select'
)).
remove
();
/* add dummy text if no more disks are available */
if
(
$
(
'#node-create-disk-add-select option'
).
length
<
1
)
{
$
(
'#node-create-disk-add-button'
).
attr
(
'disabled'
,
true
);
$
(
'#node-create-disk-add-select'
).
html
(
'<option value="-1">We are out of <options> hehe</option>'
);
}
return
false
;
});
/* remove disk */
// event for disk remove button (icon, X)
$
(
'body'
).
on
(
'click'
,
'.node-create-remove-disk'
,
function
()
{
var
disk_pk
=
(
$
(
this
).
parent
(
'span'
).
prop
(
'id'
)).
replace
(
'vlan-'
,
''
)
$
(
this
).
parent
(
'span'
).
fadeOut
(
500
,
function
()
{
/* if ther are no more disks disabled the add button */
if
(
$
(
'#node-create-disk-add-select option'
)[
0
].
value
==
-
1
)
{
$
(
'#node-create-disk-add-button'
).
attr
(
'disabled'
,
false
);
$
(
'#node-create-disk-add-select'
).
html
(
''
);
}
/* remove the disk label */
$
(
this
).
remove
();
var
disk_name
=
$
(
this
).
text
();
$
(
'#node-create-disk-add-select'
).
append
(
$
(
'<option>'
,
{
value
:
disk_pk
,
text
:
disk_name
}));
/* remove the selection from the multiple select */
$
(
'#node-create-disk-add-form option[value="'
+
disk_pk
+
'"]'
).
prop
(
'selected'
,
false
);
if
(
$
(
'#node-create-disk-list'
).
children
(
'span'
).
length
<
1
)
{
$
(
'#node-create-disk-list'
).
append
(
'No disks are added!'
);
}
});
return
false
;
});
/* copy disks from hidden select */
$
(
'#node-create-disk-add-select'
).
html
(
$
(
'#node-create-disk-add-form'
).
html
());
/* build up disk list */
$
(
'#node-create-disk-add-select option'
).
each
(
function
()
{
disks
.
push
({
'name'
:
$
(
this
).
text
(),
'pk'
:
parseInt
(
$
(
this
).
val
())
});
});
/* add button */
$
(
'#node-create-submit'
).
click
(
function
()
{
$
.
ajax
({
url
:
'/dashboard/node/create/'
,
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
type
:
'POST'
,
data
:
$
(
'form'
).
serialize
(),
success
:
function
(
data
,
textStatus
,
xhr
)
{
if
(
data
.
pk
)
{
window
.
location
.
replace
(
'/dashboard/node/'
+
data
.
pk
+
'/#activity'
);
}
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
if
(
xhr
.
status
==
500
)
{
alert
(
"uhuhuhuhuhuh"
);
}
else
{
alert
(
"unknown error"
);
}
}
});
return
false
;
});
/* no js compatibility */
$
(
'.no-js-hidden'
).
show
();
$
(
'.js-hidden'
).
hide
();
}
function
nodeCreateTemplateChange
(
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
$
(
'#node-cpu-priority-slider'
).
slider
(
"setValue"
,
data
[
'priority'
]);
$
(
'#node-cpu-count-slider'
).
slider
(
"setValue"
,
data
[
'num_cores'
]);
$
(
'#node-ram-size-slider'
).
slider
(
"setValue"
,
data
[
'ram_size'
]);
/* slider doesn't have change event ........................ */
refreshSliders
();
/* clear selections */
$
(
'select[id^="node-create-network-add"], select[id$="managed"]'
).
find
(
'option'
).
prop
(
'selected'
,
false
);
$
(
'#node-create-disk-add-form'
).
find
(
'option'
).
prop
(
'selected'
,
false
);
/* 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
]
$
(
'#node-create-network-list'
).
append
(
nodeCreateNetworkLabel
(
nn
.
vlan_pk
,
nn
.
vlan
,
nn
.
managed
)
);
$
(
'#node-create-network-add-'
+
(
nn
.
managed
?
''
:
'un'
)
+
'managed option[value="'
+
nn
.
vlan_pk
+
'"]'
).
prop
(
'selected'
,
true
);
added_vlans
.
push
(
nn
.
vlan_pk
);
}
/* remove already added vlans from dropdown or add new ones */
$
(
'#node-create-network-add-select'
).
html
(
''
);
for
(
var
i
=
0
;
i
<
vlans
.
length
;
i
++
)
if
(
added_vlans
.
indexOf
(
vlans
[
i
].
pk
)
==
-
1
)
$
(
'#node-create-network-add-select'
).
append
(
$
(
'<option>'
,
{
value
:
vlans
[
i
].
pk
,
text
:
vlans
[
i
].
name
}));
/* enalbe the network add button if there are not added vlans */
if
(
added_vlans
.
length
!=
vlans
.
length
)
{
$
(
'#node-create-network-add-button'
).
attr
(
'disabled'
,
false
);
}
else
{
$
(
'#node-create-network-add-select'
).
html
(
'<option value="-1">We are out of <options> hehe</option>'
);
$
(
'#node-create-network-add-button'
).
attr
(
'disabled'
,
true
);
}
/* append disks */
$
(
'#node-create-disk-list'
).
html
(
''
);
var
added_disks
=
[]
for
(
var
d
=
0
;
d
<
data
[
'disks'
].
length
;
d
++
)
{
dd
=
data
[
'disks'
][
d
]
$
(
'#node-create-disk-list'
).
append
(
nodeCreateDiskLabel
(
dd
.
pk
,
dd
.
name
)
);
$
(
'#node-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 */
$
(
'#node-create-disk-add-select'
).
html
(
''
);
for
(
var
i
=
0
;
i
<
disks
.
length
;
i
++
)
if
(
added_disks
.
indexOf
(
disks
[
i
].
pk
)
==
-
1
)
$
(
'#node-create-disk-add-select'
).
append
(
$
(
'<option>'
,
{
value
:
disks
[
i
].
pk
,
text
:
disks
[
i
].
name
}));
/* enalbe the disk add button if there are not added disks */
if
(
added_disks
.
length
!=
disks
.
length
)
{
$
(
'#node-create-disk-add-button'
).
attr
(
'disabled'
,
false
);
}
else
{
$
(
'#node-create-disk-add-select'
).
html
(
'<option value="-1">We are out of <options> hehe</option>'
);
$
(
'#node-create-disk-add-button'
).
attr
(
'disabled'
,
true
);
}
}
}
});
}
circle/dashboard/static/dashboard/vm-create.js
View file @
8fd80cf1
...
...
@@ -181,13 +181,13 @@ function vmCreateLoaded() {
window
.
location
.
replace
(
data
.
redirect
+
'#activity'
);
}
else
{
var
r
=
$
(
'#
vm-
create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
var
r
=
$
(
'#create-modal'
);
r
.
next
(
'div'
).
remove
();
r
.
remove
();
$
(
'body'
).
append
(
data
);
vmCreateLoaded
();
addSliderMiscs
();
$
(
'#
vm-
create-modal'
).
modal
(
'show'
);
$
(
'#
vm-
create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#
vm-
create-modal'
).
remove
();
$
(
'#create-modal'
).
modal
(
'show'
);
$
(
'#create-modal'
).
on
(
'hidden.bs.modal'
,
function
()
{
$
(
'#create-modal'
).
remove
();
});
}
},
...
...
circle/dashboard/templates/dashboard/modal-wrapper.html
View file @
8fd80cf1
<div
class=
"modal fade"
id=
"
vm-
create-modal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal fade"
id=
"create-modal"
tabindex=
"-1"
role=
"dialog"
>
<div
class=
"modal-dialog"
>
<div
class=
"modal-content"
>
<div
class=
"modal-header"
>
...
...
circle/dashboard/templates/dashboard/node-create.html
View file @
8fd80cf1
{% load crispy_forms_tags %}
<style>
.row
{
margin-bottom
:
15px
;
}
</style>
<form
method=
"POST"
action=
"/dashboard/vm/create/"
>
{% csrf_token %}
<div
class=
"row"
>
<div
class=
"col-sm-5"
>
<a
class=
"btn btn-info vm-create-advanced-btn"
>
Advanced
<i
class=
"vm-create-advanced-icon icon-caret-down"
></i></a>
</div>
<div
class=
"col-sm-5 text-right"
>
<button
id=
"vm-create-submit"
type=
"submit"
class=
"btn btn-success "
><i
class=
"icon-play"
></i>
Start
</button>
</div>
</div>
<div
class=
"vm-create-advanced"
>
<div
class=
"row"
>
<div
class=
"col-sm-12"
>
<h2>
Resources
</h2>
</div>
<p
class=
"row"
>
<div
class=
"col-sm-3"
>
<label
for=
"vm-cpu-priority-slider"
><i
class=
"icon-trophy"
></i>
CPU priority
</label>
</div>
<div
class=
"col-sm-9"
>
<input
name=
"cpu-priority"
type=
"text"
id=
"vm-cpu-priority-slider"
class=
"vm-slider"
value=
"20"
data-slider-min=
"0"
data-slider-max=
"100"
data-slider-step=
"1"
data-slider-value=
"20"
data-slider-orientation=
"horizontal"
data-slider-handle=
"square"
data-slider-tooltip=
"hide"
/>
</div>
</p>
<p
class=
"row"
>
<div
class=
"col-sm-3"
>
<label
for=
"cpu-count-slider"
><i
class=
"icon-cogs"
></i>
CPU count
</label>
</div>
<div
class=
"col-sm-9"
>
<input
name=
"cpu-count"
type=
"text"
id=
"vm-cpu-count-slider"
class=
"vm-slider"
value=
"2"
data-slider-min=
"0"
data-slider-max=
"8"
data-slider-step=
"1"
data-slider-value=
"2"
data-slider-orientation=
"horizontal"
data-slider-handle=
"square"
data-slider-tooltip=
"hide"
/>
</div>
</p>
<p
class=
"row"
>
<div
class=
"col-sm-3"
>
<label
for=
"ram-slider"
><i
class=
"icon-ticket"
></i>
RAM amount
</label>
</div>
<div
class=
"col-sm-9"
>
<input
name=
"ram-size"
type=
"text"
id=
"vm-ram-size-slider"
class=
"vm-slider"
value=
"512"
data-slider-min=
"128"
data-slider-max=
"4096"
data-slider-step=
"128"
data-slider-value=
"512"
data-slider-orientation=
"horizontal"
data-slider-handle=
"square"
data-slider-tooltip=
"hide"
/>
MiB
</div>
</p>
</div>
<!-- disk -->
<div
class=
"row"
>
<div
class=
"col-sm-4"
>
<h2>
Disks
</h2>
</div>
<div
class=
"col-sm-8"
style=
"padding-top: 3px;"
>
<div
class=
"js-hidden"
style=
"padding-top: 15px; max-width: 450px;"
>
<select
class=
"form-control"
id=
"vm-create-disk-add-form"
multiple
name=
"disks"
>
{% for d in disks %}
<option
value=
"{{ d.pk }}"
>
{{ d.name }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"no-js-hidden"
>
<h3
id=
"vm-create-disk-list"
>
No disks are added!
</h3>
<h3
id=
"vm-create-disk-add"
>
<div
class=
"input-group"
style=
"max-width: 330px;"
>
<select
class=
"form-control"
id=
"vm-create-disk-add-select"
>
<!-- options should be copied via js from above -->
</select>
<div
class=
"input-group-btn"
>
<!--<input type="submit" value="Add to network" class="btn btn-success"/>-->
<a
href=
"#"
id=
"vm-create-disk-add-button"
class=
"btn btn-success"
><i
class=
"icon-plus-sign"
></i></a>
</div>
</div>
</h3>
</div>
</div>
</div>
<!-- network -->
<div
class=
"row"
>
<div
class=
"col-sm-4"
>
<h2>
Network
</h2>
</div>
<style>
/* temporary inline css for dev */
a
.hover-black
{
color
:
white
;
}
.hover-black
:hover
{
color
:
black
/*#d9534f*/
;
text-decoration
:
none
;
}
.no-js-hidden
{
display
:
none
;
}
</style>
<div
class=
"col-sm-8"
style=
"padding-top: 3px;"
>
<div
class=
"js-hidden"
style=
"padding-top: 15px; max-width: 450px;"
>
<h4>
Managed networks
</h4>
<select
class=
"form-control"
id=
"vm-create-network-add-managed"
multiple
name=
"managed-vlans"
>
{% for v in vlans %}
<option
value=
"{{ v.pk }}"
>
{{ v.name }}
</option>
{% endfor %}
</select>
<h4>
Unmanaged networks
</h4>
<select
class=
"form-control"
id=
"vm-create-network-add-unmanaged"
multiple
name=
"unmanaged-vlans"
>
{% for v in vlans %}
<option
value=
"{{ v.pk }}"
>
{{ v.name }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"no-js-hidden"
>
<h3
id=
"vm-create-network-list"
>
Not added to any network!
</h3>
<h3
id=
"vm-create-network-add"
>
<div
class=
"input-group"
style=
"max-width: 330px;"
>
<select
class=
"form-control"
id=
"vm-create-network-add-select"
>
<!-- options should be copied via js from above -->
</select>
<span
class=
"input-group-addon"
>
<input
id=
"vm-create-network-add-checkbox-managed"
type=
"checkbox"
title
data-original-title=
"Managed network?"
style=
"-webkit-transform: scale(1.4, 1.4); margin-top: 4px;"
checked
/>
</span>
<div
class=
"input-group-btn"
>
<!--<input type="submit" value="Add to network" class="btn btn-success"/>-->
<a
href=
"#"
id=
"vm-create-network-add-button"
class=
"btn btn-success"
><i
class=
"icon-plus-sign"
></i></a>
</div>
</div>
</h3>
</div>
</div>
</div>
</div>
<form
method=
"POST"
action=
"/dashboard/node/create/"
>
{% csrf_token %}
{% crispy formset formset.form.helper %}
</form>
circle/dashboard/views.py
View file @
8fd80cf1
...
...
@@ -19,10 +19,11 @@ from django.views.generic import (TemplateView, DetailView, View, DeleteView,
from
django.contrib
import
messages
from
django.utils.translation
import
ugettext
as
_
from
django.forms.models
import
inlineformset_factory
from
django_tables2
import
SingleTableView
from
braces.views
import
LoginRequiredMixin
,
SuperuserRequiredMixin
from
.forms
import
VmCreateForm
,
TemplateForm
,
LeaseForm
from
.forms
import
VmCreateForm
,
TemplateForm
,
LeaseForm
,
NodeForm
,
HostForm
from
.tables
import
(
VmListTable
,
NodeListTable
,
NodeVmListTable
,
TemplateListTable
,
LeaseListTable
)
from
vm.models
import
(
Instance
,
InstanceTemplate
,
InterfaceTemplate
,
...
...
@@ -517,17 +518,30 @@ class VmCreate(LoginRequiredMixin, TemplateView):
class
NodeCreate
(
LoginRequiredMixin
,
SuperuserRequiredMixin
,
TemplateView
):
form_class
=
HostForm
hostform
=
None
formset_class
=
inlineformset_factory
(
Host
,
Node
,
form
=
NodeForm
,
extra
=
1
)
formset
=
None
def
get_template_names
(
self
):
if
self
.
request
.
is_ajax
():
return
[
'dashboard/modal-wrapper.html'
]
else
:
return
[
'dashboard/nojs-wrapper.html'
]
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
hostform
=
None
,
formset
=
None
,
*
args
,
**
kwargs
):
if
hostform
is
None
:
hostform
=
self
.
form_class
()
if
formset
is
None
:
formset
=
self
.
formset_class
(
instance
=
Host
())
context
=
self
.
get_context_data
(
**
kwargs
)
context
.
update
({
'template'
:
'dashboard/node-create.html'
,
'box_title'
:
'Create a Node'
'box_title'
:
'Create a Node'
,
'hostform'
:
hostform
,
'formset'
:
formset
,
})
return
self
.
render_to_response
(
context
)
...
...
@@ -535,60 +549,34 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
context
=
super
(
NodeCreate
,
self
)
.
get_context_data
(
**
kwargs
)
# TODO acl
context
.
update
({
'templates'
:
InstanceTemplate
.
objects
.
all
(),
'vlans'
:
Vlan
.
objects
.
all
(),
'disks'
:
Disk
.
objects
.
exclude
(
type
=
"qcow2-snap"
)
})
return
context
# TODO handle not ajax posts
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
if
self
.
request
.
user
.
is_authenticated
():
user
=
self
.
request
.
user
else
:
user
=
None
resp
=
{}
try
:
ikwargs
=
{
'num_cores'
:
int
(
request
.
POST
.
get
(
'cpu-count'
)),
'ram_size'
:
int
(
request
.
POST
.
get
(
'ram-size'
)),
'priority'
:
int
(
request
.
POST
.
get
(
'cpu-priority'
)),
}
networks
=
[
InterfaceTemplate
(
vlan
=
Vlan
.
objects
.
get
(
pk
=
l
),
managed
=
True
)
for
l
in
request
.
POST
.
getlist
(
'managed-vlans'
)
]
networks
.
extend
([
InterfaceTemplate
(
vlan
=
Vlan
.
objects
.
get
(
pk
=
l
),
managed
=
False
)
for
l
in
request
.
POST
.
getlist
(
'unmanaged-vlans'
)
])
disks
=
Disk
.
objects
.
filter
(
pk__in
=
request
.
POST
.
getlist
(
'disks'
))
template
=
InstanceTemplate
.
objects
.
get
(
pk
=
request
.
POST
.
get
(
'template-pk'
))
inst
=
Instance
.
create_from_template
(
template
=
template
,
owner
=
user
,
networks
=
networks
,
disks
=
disks
,
**
ikwargs
)
inst
.
deploy_async
(
user
=
request
.
user
)
if
not
self
.
request
.
user
.
is_authenticated
():
raise
PermissionDenied
()
resp
[
'pk'
]
=
inst
.
pk
hostform
=
self
.
form_class
(
request
.
POST
)
formset
=
self
.
formset_class
(
request
.
POST
,
Host
())
if
not
hostform
.
is_valid
():
return
self
.
get
(
request
,
hostform
,
formset
,
*
args
,
**
kwargs
)
hostform
.
setowner
(
request
.
user
)
savedform
=
hostform
.
save
(
commit
=
False
)
formset
=
self
.
formset_class
(
request
.
POST
,
instance
=
savedform
)
if
not
formset
.
is_valid
():
return
self
.
get
(
request
,
hostform
,
formset
,
*
args
,
**
kwargs
)
savedform
.
save
()
nodemodel
=
formset
.
save
()
messages
.
success
(
request
,
_
(
'Node successfully created!'
))
except
InstanceTemplate
.
DoesNotExist
:
resp
[
'error'
]
=
True
except
Exception
,
e
:
print
e
resp
[
'error'
]
=
True
path
=
nodemodel
[
0
]
.
get_absolute_url
()
if
request
.
is_ajax
():
return
HttpResponse
(
json
.
dumps
(
resp
),
content_type
=
"application/json"
,
status
=
500
if
resp
.
get
(
'error'
)
else
200
)
return
HttpResponse
(
json
.
dumps
({
'redirect'
:
path
}),
content_type
=
"application/json"
)
else
:
return
redirect
(
reverse_lazy
(
'dashboard.views.detail'
,
resp
)
)
return
redirect
(
path
)
class
VmDelete
(
LoginRequiredMixin
,
DeleteView
):
...
...
circle/vm/models/node.py
View file @
8fd80cf1
...
...
@@ -3,7 +3,7 @@ from logging import getLogger
from
django.db.models
import
(
CharField
,
IntegerField
,
ForeignKey
,
BooleanField
,
ManyToManyField
,
FloatField
,
FloatField
,
permalink
,
)
from
django.utils.translation
import
ugettext_lazy
as
_
...
...
@@ -143,3 +143,10 @@ class Node(TimeStampedModel):
def
get_state_count
(
cls
,
online
,
enabled
):
return
len
([
1
for
i
in
cls
.
objects
.
filter
(
enabled
=
enabled
)
.
all
()
if
i
.
online
==
online
])
@permalink
def
get_absolute_url
(
self
):
return
(
'dashboard.views.node-detail'
,
None
,
{
'pk'
:
self
.
id
})
def
pr
():
print
"irdki"
Bach Dániel
@bachdaniel
mentioned in issue
#113 (closed)
Jun 05, 2014
mentioned in issue
#113 (closed)
mentioned in issue #113
Toggle commit list
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