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
c5f2291b
authored
Jan 20, 2015
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into feature-jshint
Conflicts: circle/dashboard/static/dashboard/group-details.js
parents
f47965c1
bd898707
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
120 additions
and
45 deletions
+120
-45
circle/dashboard/forms.py
+30
-2
circle/dashboard/static/dashboard/dashboard.less
+6
-2
circle/dashboard/static/dashboard/group-details.js
+12
-11
circle/dashboard/templates/dashboard/_vm-migrate.html
+25
-1
circle/dashboard/templates/dashboard/group-detail.html
+15
-25
circle/dashboard/templates/dashboard/node-detail.html
+1
-1
circle/dashboard/views/node.py
+8
-3
circle/dashboard/views/vm.py
+16
-0
circle/vm/models/common.py
+7
-0
No files found.
circle/dashboard/forms.py
View file @
c5f2291b
...
...
@@ -41,6 +41,7 @@ from django.forms.widgets import TextInput, HiddenInput
from
django.template
import
Context
from
django.template.loader
import
render_to_string
from
django.utils.html
import
escape
,
format_html
from
django.utils.safestring
import
mark_safe
from
django.utils.translation
import
ugettext_lazy
as
_
from
sizefield.widgets
import
FileSizeWidget
from
django.core.urlresolvers
import
reverse_lazy
...
...
@@ -951,18 +952,45 @@ class VmAddInterfaceForm(OperationForm):
self
.
fields
[
'vlan'
]
=
field
class
DeployChoiceField
(
forms
.
ModelChoiceField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
instance
=
kwargs
.
pop
(
"instance"
)
super
(
DeployChoiceField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
label_from_instance
(
self
,
obj
):
traits
=
set
(
obj
.
traits
.
all
())
req_traits
=
set
(
self
.
instance
.
req_traits
.
all
())
# if the subset is empty the node satisfies the required traits
subset
=
req_traits
-
traits
label
=
"
%
s
%
s"
%
(
""
if
subset
else
""
,
escape
(
obj
.
name
),
)
if
subset
:
missing_traits
=
", "
.
join
(
map
(
lambda
x
:
escape
(
x
.
name
),
subset
))
label
+=
_
(
" (missing_traits:
%
s)"
)
%
missing_traits
return
mark_safe
(
label
)
class
VmDeployForm
(
OperationForm
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
choices
=
kwargs
.
pop
(
'choices'
,
None
)
instance
=
kwargs
.
pop
(
"instance"
)
super
(
VmDeployForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
if
choices
is
not
None
:
self
.
fields
.
insert
(
0
,
'node'
,
forms
.
Model
ChoiceField
(
self
.
fields
.
insert
(
0
,
'node'
,
Deploy
ChoiceField
(
queryset
=
choices
,
required
=
False
,
label
=
_
(
'Node'
),
help_text
=
_
(
"Deploy virtual machine to this node "
"(blank allows scheduling automatically)."
)))
"(blank allows scheduling automatically)."
),
widget
=
forms
.
Select
(
attrs
=
{
'class'
:
"font-awesome-font"
,
}),
instance
=
instance
))
class
VmPortRemoveForm
(
OperationForm
):
...
...
circle/dashboard/static/dashboard/dashboard.less
View file @
c5f2291b
...
...
@@ -188,11 +188,15 @@ html {
display: none;
}
.vm-details-home-name {
#group-details-rename-form {
display: inline-block;
}
.vm-details-home-name, #group-details-rename-form .input-group {
max-width: 401px;
}
#node-details-rename-name
, #group-details-rename-name
{
#node-details-rename-name {
max-width: 160px;
}
...
...
circle/dashboard/static/dashboard/group-details.js
View file @
c5f2291b
$
(
function
()
{
/* rename */
$
(
"#group-details-h1-name, .group-details-rename-button"
).
click
(
function
()
{
$
(
"#group-details-h1-name"
).
hide
();
$
(
"#group-details-rename
"
).
css
(
'display'
,
'inline
'
);
$
(
"#group-details-rename-name"
).
focus
();
$
(
"#group-details-h1-name
span
"
).
hide
();
$
(
"#group-details-rename
-form"
).
show
().
css
(
'display'
,
'inline-block
'
);
$
(
"#group-details-rename-name"
).
select
();
});
/* rename ajax */
$
(
'#group-details-rename-submit'
).
click
(
function
()
{
if
(
!
$
(
"#group-details-rename-name"
)[
0
].
checkValidity
())
{
return
true
;
}
var
name
=
$
(
'#group-details-rename-name'
).
val
();
$
.
ajax
({
method
:
'POST'
,
url
:
location
.
href
,
data
:
{
'new_name'
:
name
},
headers
:
{
"X-CSRFToken"
:
getCookie
(
'csrftoken'
)},
success
:
function
(
data
,
textStatus
,
xhr
)
{
$
(
"#group-details-h1-name"
).
text
(
data
.
new_name
).
show
();
$
(
'#group-details-rename'
).
hide
();
// addMessage(data['message'], "success");
$
(
"#group-details-h1-name span"
).
text
(
data
.
new_name
).
show
();
$
(
'#group-details-rename-form'
).
hide
();
},
error
:
function
(
xhr
,
textStatus
,
error
)
{
addMessage
(
"Error during renaming
!
"
,
"danger"
);
addMessage
(
"Error during renaming
.
"
,
"danger"
);
}
});
return
false
;
});
$
(
".group-details-help-button"
).
click
(
function
()
{
$
(
".group-details-help"
).
stop
().
slideToggle
();
});
});
circle/dashboard/templates/dashboard/_vm-migrate.html
View file @
c5f2291b
...
...
@@ -23,11 +23,35 @@ Choose a compute node to migrate {{obj}} to.
<i
class=
"fa {{n.get_status_icon}}"
></i>
{{n.get_status_display}}
</div>
{% if current == n.pk %}
<div
class=
"label label-info"
>
{% trans "current" %}
</div>
{% endif %}
{% if recommended == n.pk %}
<div
class=
"label label-success"
>
{% trans "recommended" %}
</div>
{% endif %}
{% if n.pk not in nodes_w_traits %}
<div
class=
"label label-warning"
>
<i
class=
"fa fa-warning"
></i>
{% trans "missing traits" %}
</div>
{% endif %}
</label>
<input
id=
"migrate-to-{{n.pk}}"
type=
"radio"
name=
"to_node"
value=
"{{ n.pk }}"
style=
"float: right;"
{%
if
current =
=
n
.
pk
%}
disabled=
"disabled"
{%
endif
%}
{%
if
recommended =
=
n
.
pk
%}
checked=
"checked"
{%
endif
%}
{%
if
recommended =
=
n
.
pk
and
n
.
pk
!=
current
%}
checked=
"checked"
{%
endif
%}
/>
{% if n.pk not in nodes_w_traits %}
<span
class=
"vm-migrate-node-property"
>
{% trans "Node traits" %}:
{% if n.traits.all %}
{{ n.traits.all|join:", " }}
{% else %}
-
{% endif %}
</span>
<span
class=
"vm-migrate-node-property"
>
{% trans "Required traits" %}:
{% if object.req_traits.all %}
{{ object.req_traits.all|join:", " }}
{% else %}
-
{% endif %}
</span>
<hr
/>
{% endif %}
<span
class=
"vm-migrate-node-property"
>
{% trans "CPU load" %}: {{ n.cpu_usage }}
</span>
<span
class=
"vm-migrate-node-property"
>
{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}
</span>
...
...
circle/dashboard/templates/dashboard/group-detail.html
View file @
c5f2291b
...
...
@@ -9,43 +9,33 @@
<div
class=
"body-content"
>
<div
class=
"page-header"
>
<div
class=
"pull-right"
style=
"padding-top: 15px;"
>
<a
title=
"{% trans "
Rename
"
%}"
href=
"#"
class=
"btn btn-default btn-xs group-details-rename-button"
>
<a
title=
"{% trans "
Rename
"
%}"
class=
"btn btn-default btn-xs group-details-rename-button"
>
<i
class=
"fa fa-pencil"
></i>
</a>
<a
title=
"{% trans "
Delete
"
%}"
data-group-pk=
"{{ group.pk }}"
class=
"btn btn-default btn-xs real-link group-delete"
href=
"{% url "
dashboard
.
views
.
delete-group
"
pk=
group.pk
%}"
>
<i
class=
"fa fa-trash-o"
></i>
</a>
<a
title=
"{% trans "
Help
"
%}"
href=
"#"
class=
"btn btn-default btn-xs group-details-help-button"
>
<i
class=
"fa fa-question"
></i>
</a>
</div>
<h1>
<div
id=
"group-details-rename"
>
<form
action=
""
method=
"POST"
id=
"group-details-rename-form"
>
{% csrf_token %}
<input
id=
"group-details-rename-name"
class=
"form-control"
name=
"new_name"
type=
"text"
value=
"{{ group.name }}"
/>
<button
type=
"submit"
id=
"group-details-rename-submit"
class=
"btn"
>
{% trans "Rename" %}
</button>
</form>
</div>
<h1>
<form
action=
""
method=
"POST"
id=
"group-details-rename-form"
class=
"js-hidden"
>
{% csrf_token %}
<div
class=
"input-group"
>
<input
id=
"group-details-rename-name"
class=
"form-control"
name=
"new_name"
type=
"text"
value=
"{{ group.name }}"
required
/>
<span
class=
"input-group-btn"
>
<button
type=
"submit"
id=
"group-details-rename-submit"
class=
"btn"
>
{% trans "Rename" %}
</button>
</span>
</div>
</form>
<div
id=
"group-details-h1-name"
>
{{ group.name }}
<span
class=
"no-js-hidden"
>
{{ group.name }}
</span>
{% if group.groupprofile.org_id %}
<small>
{{group.groupprofile.org_id}}
</small>
{% endif %}
</div>
</h1>
<div
class=
"group-details-help js-hidden"
>
<ul
style=
"list-style: none;"
>
<li>
<strong>
{% trans "Rename" %}:
</strong>
{% trans "Change the name of the group." %}
</li>
<li>
<strong>
{% trans "Delete" %}:
</strong>
{% trans "Delete group." %}
</li>
</ul>
</div>
</div>
<!-- .page-header -->
<div
class=
"row"
>
<div
class=
"col-md-12"
id=
"group-detail-pane"
>
...
...
circle/dashboard/templates/dashboard/node-detail.html
View file @
c5f2291b
...
...
@@ -73,7 +73,7 @@
</a>
</li>
<li>
<a
href=
"{% url "
dashboard
.
views
.
vm-list
"
%}?
s=
node
:{{
node
.
name
}}"
<a
href=
"{% url "
dashboard
.
views
.
vm-list
"
%}?
s=
node
_exact:{{
node
.
name
}}"
target=
"blank"
class=
"text-center"
>
<i
class=
"fa fa-desktop fa-2x"
></i><br>
{% trans "Virtual Machines" %}
...
...
circle/dashboard/views/node.py
View file @
c5f2291b
...
...
@@ -143,8 +143,13 @@ class NodeDetailView(LoginRequiredMixin,
def
__remove_trait
(
self
,
request
):
try
:
to_remove
=
request
.
POST
.
get
(
'to_remove'
)
self
.
object
=
self
.
get_object
()
self
.
object
.
traits
.
remove
(
to_remove
)
trait
=
Trait
.
objects
.
get
(
pk
=
to_remove
)
node
=
self
.
get_object
()
node
.
traits
.
remove
(
to_remove
)
if
not
trait
.
in_use
:
trait
.
delete
()
message
=
u"Success"
except
:
# note this won't really happen
message
=
u"Not success"
...
...
@@ -155,7 +160,7 @@ class NodeDetailView(LoginRequiredMixin,
content_type
=
"application/json"
)
else
:
return
redirect
(
self
.
object
.
get_absolute_url
())
return
redirect
(
node
.
get_absolute_url
())
class
NodeList
(
LoginRequiredMixin
,
GraphMixin
,
SingleTableView
):
...
...
circle/dashboard/views/vm.py
View file @
c5f2291b
...
...
@@ -67,6 +67,7 @@ from ..forms import (
VmRemoveInterfaceForm
,
)
from
..models
import
Favourite
from
manager.scheduler
import
has_traits
logger
=
logging
.
getLogger
(
__name__
)
...
...
@@ -444,6 +445,20 @@ class VmMigrateView(FormOperationMixin, VmOperationView):
val
.
update
({
'choices'
:
choices
,
'default'
:
default
})
return
val
def
get_context_data
(
self
,
*
args
,
**
kwargs
):
ctx
=
super
(
VmMigrateView
,
self
)
.
get_context_data
(
*
args
,
**
kwargs
)
inst
=
self
.
get_object
()
if
isinstance
(
inst
,
Instance
):
nodes_w_traits
=
[
n
.
pk
for
n
in
Node
.
objects
.
filter
(
enabled
=
True
)
if
n
.
online
and
has_traits
(
inst
.
req_traits
.
all
(),
n
)
]
ctx
[
'nodes_w_traits'
]
=
nodes_w_traits
return
ctx
class
VmPortRemoveView
(
FormOperationMixin
,
VmOperationView
):
...
...
@@ -698,6 +713,7 @@ class VmDeployView(FormOperationMixin, VmOperationView):
online
=
(
n
.
pk
for
n
in
Node
.
objects
.
filter
(
enabled
=
True
)
if
n
.
online
)
kwargs
[
'choices'
]
=
Node
.
objects
.
filter
(
pk__in
=
online
)
kwargs
[
'instance'
]
=
self
.
get_object
()
return
kwargs
...
...
circle/vm/models/common.py
View file @
c5f2291b
...
...
@@ -170,3 +170,10 @@ class Trait(Model):
def
__unicode__
(
self
):
return
self
.
name
@property
def
in_use
(
self
):
return
(
self
.
instance_set
.
exists
()
or
self
.
node_set
.
exists
()
or
self
.
instancetemplate_set
.
exists
()
)
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