Merge "Add sexy boxes to the deployment status page"
This commit is contained in:
commit
bdc4f301c7
@ -17,6 +17,20 @@ from tuskar_ui.infrastructure.overview import views
|
||||
from tuskar_boxes.overview import forms
|
||||
|
||||
|
||||
NODE_STATE_ICON = {
|
||||
api.node.DISCOVERING_STATE: 'fa-search',
|
||||
api.node.DISCOVERED_STATE: 'fa-search-plus',
|
||||
api.node.DISCOVERY_FAILED_STATE: 'fa-search-minus',
|
||||
api.node.MAINTENANCE_STATE: 'fa-exclamation-triangle',
|
||||
api.node.FREE_STATE: 'fa-minus',
|
||||
api.node.PROVISIONING_STATE: 'fa-spinner fa-spin',
|
||||
api.node.PROVISIONED_STATE: 'fa-check',
|
||||
api.node.DELETING_STATE: 'fa-spinner fa-spin',
|
||||
api.node.PROVISIONING_FAILED_STATE: 'fa-exclamation-circle',
|
||||
None: 'fa-question',
|
||||
}
|
||||
|
||||
|
||||
def flavor_nodes(request, flavor):
|
||||
"""Lists all nodes that match the given flavor exactly."""
|
||||
for node in api.node.Node.list(request, maintenance=False):
|
||||
@ -29,6 +43,14 @@ def flavor_nodes(request, flavor):
|
||||
yield node
|
||||
|
||||
|
||||
def node_role(request, node):
|
||||
try:
|
||||
resource = api.heat.Resource.get_by_node(request, node)
|
||||
except LookupError:
|
||||
return None
|
||||
return resource.role
|
||||
|
||||
|
||||
class IndexView(views.IndexView):
|
||||
template_name = "tuskar_boxes/overview/index.html"
|
||||
form_class = forms.EditPlan
|
||||
@ -40,27 +62,35 @@ class IndexView(views.IndexView):
|
||||
for role in context['roles']:
|
||||
flavor = role['role'].flavor(context['plan'])
|
||||
role['flavor_name'] = flavor.name if flavor else ''
|
||||
context['flavors'] = []
|
||||
for flavor in flavors:
|
||||
nodes = [{
|
||||
'role': '',
|
||||
} for node in flavor_nodes(self.request, flavor)]
|
||||
roles = [role for role in context['roles']
|
||||
if role['flavor_name'] == flavor.name]
|
||||
flavor = {
|
||||
'name': flavor.name,
|
||||
'vcpus': flavor.vcpus,
|
||||
'ram': flavor.ram,
|
||||
'disk': flavor.disk,
|
||||
'cpu_arch': flavor.cpu_arch,
|
||||
'nodes': nodes,
|
||||
'roles': roles,
|
||||
}
|
||||
if nodes or roles: # Don't list empty flavors
|
||||
context['flavors'].append(flavor)
|
||||
context['free_roles'] = [role for role in context['roles']
|
||||
if not role['flavor_name']]
|
||||
if not context['stack']:
|
||||
context['flavors'] = []
|
||||
for flavor in flavors:
|
||||
nodes = [{
|
||||
'role': '',
|
||||
} for node in flavor_nodes(self.request, flavor)]
|
||||
roles = [role for role in context['roles']
|
||||
if role['flavor_name'] == flavor.name]
|
||||
flavor = {
|
||||
'name': flavor.name,
|
||||
'vcpus': flavor.vcpus,
|
||||
'ram': flavor.ram,
|
||||
'disk': flavor.disk,
|
||||
'cpu_arch': flavor.cpu_arch,
|
||||
'nodes': nodes,
|
||||
'roles': roles,
|
||||
}
|
||||
if nodes or roles: # Don't list empty flavors
|
||||
context['flavors'].append(flavor)
|
||||
context['free_roles'] = [role for role in context['roles']
|
||||
if not role['flavor_name']]
|
||||
for role in context['roles']:
|
||||
role['flavor_field'] = context['form'][role['id'] + '-flavor']
|
||||
else:
|
||||
context['nodes'] = [{
|
||||
'uuid': node.uuid,
|
||||
'role': node_role(self.request, node),
|
||||
'state': node.state,
|
||||
'state_icon': NODE_STATE_ICON.get(node.state,
|
||||
NODE_STATE_ICON[None]),
|
||||
} for node in api.node.Node.list(self.request, maintenance=False)]
|
||||
return context
|
||||
|
@ -29,12 +29,15 @@
|
||||
opacity: 0.75;
|
||||
padding: 6px;
|
||||
border: 1px solid;
|
||||
cursor: move;
|
||||
border-radius: 2px;
|
||||
background-color: #fce94f;
|
||||
border-color: #edd400;
|
||||
color: #c4a000;
|
||||
margin: 0 0 4px 0;
|
||||
cursor: move;
|
||||
}
|
||||
.deploy-role-status .boxes-role {
|
||||
cursor: default;
|
||||
}
|
||||
.boxes-available-roles .boxes-role {
|
||||
display: inline-block;
|
||||
|
@ -42,7 +42,7 @@
|
||||
</div>
|
||||
<div class="col-xs-8">
|
||||
{% if stack %}
|
||||
{% include "infrastructure/overview/role_nodes_status.html" %}
|
||||
{% include "tuskar_boxes/overview/role_nodes_status.html" %}
|
||||
{% else %}
|
||||
{% include "tuskar_boxes/overview/role_nodes_edit.html" %}
|
||||
{% endif %}
|
||||
|
@ -0,0 +1,48 @@
|
||||
{% load i18n %}
|
||||
{% load url from future %}
|
||||
{% load horizon %}
|
||||
|
||||
<h4>{% trans "Deployment Roles" %}</h4>
|
||||
<div class="row">
|
||||
<div class="deploy-role-status col-xs-5">
|
||||
{% for role in roles %}
|
||||
<div class="boxes-role boxes-role-{{ role.name|slugify }} clearfix">
|
||||
<div class="col-xs-2 deploy-role-count">
|
||||
{% if role.finished %}
|
||||
{{ role.deployed_node_count }}
|
||||
{% else %}
|
||||
{{ role.deployed_node_count }}<small class="text-muted">/{{ role.planned_node_count }}</small>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-xs-10 deploy-role-name">
|
||||
<strong class="deployment-roles-label">{{ role.name|capfirst }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="col-xs-7 boxes-nodes">
|
||||
{% for node in nodes %}{% spaceless %}
|
||||
<div class="boxes-node boxes-role-{{ node.role.name|slugify }} status-{{ node.status|slugify }}" title="{{ node.uuid }}">
|
||||
<i class="fa fa-lg {{ node.state_icon }}"></i>
|
||||
</div>
|
||||
{% endspaceless %}{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="roles-template">{% spaceless %}{% jstemplate %}
|
||||
[[#roles]]
|
||||
<div class="boxes-role boxes-role boxes-role[[ slug ]] clearfix">
|
||||
<div class="col-xs-2 deploy-role-count">
|
||||
[[#finished]]
|
||||
[[ deployed_node_count ]]
|
||||
[[/finished]]
|
||||
[[^finished]]
|
||||
[[ deployed_node_count ]]<small class="text-muted">/[[ planned_node_count ]]</small>
|
||||
[[/finished]]
|
||||
</div>
|
||||
<div class="col-xs-10 deploy-role-name">
|
||||
<strong class="deployment-roles-label" >[[ name ]]</strong>
|
||||
</div>
|
||||
</div>
|
||||
[[/roles]]
|
||||
{% endjstemplate %}{% endspaceless %}</script>
|
Loading…
x
Reference in New Issue
Block a user