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
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
228 additions
and
197 deletions
+228
-197
circle/dashboard/forms.py
+170
-5
circle/dashboard/static/dashboard/dashboard.js
+6
-6
circle/dashboard/static/dashboard/node-create.js
+0
-0
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
This diff is collapsed.
Click to expand it.
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