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
acfa3715
authored
Jan 19, 2015
by
Kálmán Viktor
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'issue-291' into 'master'
Trait fixes closes #291 See merge request !284
parents
ebdf3b7e
921944e9
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
87 additions
and
7 deletions
+87
-7
circle/dashboard/forms.py
+30
-2
circle/dashboard/templates/dashboard/_vm-migrate.html
+25
-1
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 @
acfa3715
...
@@ -41,6 +41,7 @@ from django.forms.widgets import TextInput, HiddenInput
...
@@ -41,6 +41,7 @@ from django.forms.widgets import TextInput, HiddenInput
from
django.template
import
Context
from
django.template
import
Context
from
django.template.loader
import
render_to_string
from
django.template.loader
import
render_to_string
from
django.utils.html
import
escape
,
format_html
from
django.utils.html
import
escape
,
format_html
from
django.utils.safestring
import
mark_safe
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
sizefield.widgets
import
FileSizeWidget
from
sizefield.widgets
import
FileSizeWidget
from
django.core.urlresolvers
import
reverse_lazy
from
django.core.urlresolvers
import
reverse_lazy
...
@@ -951,18 +952,45 @@ class VmAddInterfaceForm(OperationForm):
...
@@ -951,18 +952,45 @@ class VmAddInterfaceForm(OperationForm):
self
.
fields
[
'vlan'
]
=
field
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
):
class
VmDeployForm
(
OperationForm
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
choices
=
kwargs
.
pop
(
'choices'
,
None
)
choices
=
kwargs
.
pop
(
'choices'
,
None
)
instance
=
kwargs
.
pop
(
"instance"
)
super
(
VmDeployForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
VmDeployForm
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
if
choices
is
not
None
:
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
=
_
(
queryset
=
choices
,
required
=
False
,
label
=
_
(
'Node'
),
help_text
=
_
(
"Deploy virtual machine to this node "
"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
):
class
VmPortRemoveForm
(
OperationForm
):
...
...
circle/dashboard/templates/dashboard/_vm-migrate.html
View file @
acfa3715
...
@@ -23,11 +23,35 @@ Choose a compute node to migrate {{obj}} to.
...
@@ -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>
<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 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 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>
</label>
<input
id=
"migrate-to-{{n.pk}}"
type=
"radio"
name=
"to_node"
value=
"{{ n.pk }}"
style=
"float: right;"
<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
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 "CPU load" %}: {{ n.cpu_usage }}
</span>
<span
class=
"vm-migrate-node-property"
>
<span
class=
"vm-migrate-node-property"
>
{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}
</span>
{% trans "RAM usage" %}: {{ n.byte_ram_usage|filesize }}/{{ n.ram_size|filesize }}
</span>
...
...
circle/dashboard/templates/dashboard/node-detail.html
View file @
acfa3715
...
@@ -73,7 +73,7 @@
...
@@ -73,7 +73,7 @@
</a>
</a>
</li>
</li>
<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"
>
target=
"blank"
class=
"text-center"
>
<i
class=
"fa fa-desktop fa-2x"
></i><br>
<i
class=
"fa fa-desktop fa-2x"
></i><br>
{% trans "Virtual Machines" %}
{% trans "Virtual Machines" %}
...
...
circle/dashboard/views/node.py
View file @
acfa3715
...
@@ -143,8 +143,13 @@ class NodeDetailView(LoginRequiredMixin,
...
@@ -143,8 +143,13 @@ class NodeDetailView(LoginRequiredMixin,
def
__remove_trait
(
self
,
request
):
def
__remove_trait
(
self
,
request
):
try
:
try
:
to_remove
=
request
.
POST
.
get
(
'to_remove'
)
to_remove
=
request
.
POST
.
get
(
'to_remove'
)
self
.
object
=
self
.
get_object
()
trait
=
Trait
.
objects
.
get
(
pk
=
to_remove
)
self
.
object
.
traits
.
remove
(
to_remove
)
node
=
self
.
get_object
()
node
.
traits
.
remove
(
to_remove
)
if
not
trait
.
in_use
:
trait
.
delete
()
message
=
u"Success"
message
=
u"Success"
except
:
# note this won't really happen
except
:
# note this won't really happen
message
=
u"Not success"
message
=
u"Not success"
...
@@ -155,7 +160,7 @@ class NodeDetailView(LoginRequiredMixin,
...
@@ -155,7 +160,7 @@ class NodeDetailView(LoginRequiredMixin,
content_type
=
"application/json"
content_type
=
"application/json"
)
)
else
:
else
:
return
redirect
(
self
.
object
.
get_absolute_url
())
return
redirect
(
node
.
get_absolute_url
())
class
NodeList
(
LoginRequiredMixin
,
GraphMixin
,
SingleTableView
):
class
NodeList
(
LoginRequiredMixin
,
GraphMixin
,
SingleTableView
):
...
...
circle/dashboard/views/vm.py
View file @
acfa3715
...
@@ -67,6 +67,7 @@ from ..forms import (
...
@@ -67,6 +67,7 @@ from ..forms import (
VmRemoveInterfaceForm
,
VmRemoveInterfaceForm
,
)
)
from
..models
import
Favourite
from
..models
import
Favourite
from
manager.scheduler
import
has_traits
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -444,6 +445,20 @@ class VmMigrateView(FormOperationMixin, VmOperationView):
...
@@ -444,6 +445,20 @@ class VmMigrateView(FormOperationMixin, VmOperationView):
val
.
update
({
'choices'
:
choices
,
'default'
:
default
})
val
.
update
({
'choices'
:
choices
,
'default'
:
default
})
return
val
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
):
class
VmPortRemoveView
(
FormOperationMixin
,
VmOperationView
):
...
@@ -698,6 +713,7 @@ class VmDeployView(FormOperationMixin, VmOperationView):
...
@@ -698,6 +713,7 @@ class VmDeployView(FormOperationMixin, VmOperationView):
online
=
(
n
.
pk
for
n
in
online
=
(
n
.
pk
for
n
in
Node
.
objects
.
filter
(
enabled
=
True
)
if
n
.
online
)
Node
.
objects
.
filter
(
enabled
=
True
)
if
n
.
online
)
kwargs
[
'choices'
]
=
Node
.
objects
.
filter
(
pk__in
=
online
)
kwargs
[
'choices'
]
=
Node
.
objects
.
filter
(
pk__in
=
online
)
kwargs
[
'instance'
]
=
self
.
get_object
()
return
kwargs
return
kwargs
...
...
circle/vm/models/common.py
View file @
acfa3715
...
@@ -170,3 +170,10 @@ class Trait(Model):
...
@@ -170,3 +170,10 @@ class Trait(Model):
def
__unicode__
(
self
):
def
__unicode__
(
self
):
return
self
.
name
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