summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Schnell <tim.schnell@rackspace.com>2013-07-09 17:09:58 -0500
committerTim Schnell <tim.schnell@rackspace.com>2013-07-16 18:33:11 -0500
commit8914ed95fc8fa44771f5f3ec827e325a5855b60a (patch)
tree43e01abaa35762a675995bda301ab8e94811e311
parent3087c3486bda8b9deb87d3c7ec6ca1ef9812fe22 (diff)
downloadhorizon-2013.2.b2.tar.gz
Adding Heat Resource Topology to Horizon2013.2.b2
Change-Id: Ie9f2040850df3d7f1fcefe68430e9103c972f80f Implements: blueprint heat-ui-resource-topology
-rw-r--r--horizon/static/horizon/js/horizon.heattop.js275
-rw-r--r--horizon/templates/horizon/_scripts.html1
-rw-r--r--openstack_dashboard/dashboards/project/stacks/api.py84
-rw-r--r--openstack_dashboard/dashboards/project/stacks/mappings.py62
-rw-r--r--openstack_dashboard/dashboards/project/stacks/sro.py31
-rw-r--r--openstack_dashboard/dashboards/project/stacks/tabs.py18
-rw-r--r--openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html9
-rw-r--r--openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html10
-rw-r--r--openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html16
-rw-r--r--openstack_dashboard/dashboards/project/stacks/urls.py4
-rw-r--r--openstack_dashboard/dashboards/project/stacks/views.py2
-rw-r--r--openstack_dashboard/static/dashboard/img/db-gray.gifbin0 -> 12495 bytes
-rw-r--r--openstack_dashboard/static/dashboard/img/db-gray.svg85
-rw-r--r--openstack_dashboard/static/dashboard/img/db-green.svg85
-rw-r--r--openstack_dashboard/static/dashboard/img/db-red.svg85
-rw-r--r--openstack_dashboard/static/dashboard/img/lb-gray.gifbin0 -> 8447 bytes
-rw-r--r--openstack_dashboard/static/dashboard/img/lb-gray.svg43
-rw-r--r--openstack_dashboard/static/dashboard/img/lb-green.svg43
-rw-r--r--openstack_dashboard/static/dashboard/img/lb-red.svg43
-rw-r--r--openstack_dashboard/static/dashboard/img/server-gray.gifbin0 -> 7416 bytes
-rw-r--r--openstack_dashboard/static/dashboard/img/server-gray.svg50
-rw-r--r--openstack_dashboard/static/dashboard/img/server-green.svg50
-rw-r--r--openstack_dashboard/static/dashboard/img/server-red.svg50
-rw-r--r--openstack_dashboard/static/dashboard/img/stack-gray.gifbin0 -> 14409 bytes
-rw-r--r--openstack_dashboard/static/dashboard/img/stack-gray.svg73
-rw-r--r--openstack_dashboard/static/dashboard/img/stack-green.svg82
-rw-r--r--openstack_dashboard/static/dashboard/img/stack-red.svg92
-rw-r--r--openstack_dashboard/static/dashboard/img/unknown-gray.gifbin0 -> 10805 bytes
-rw-r--r--openstack_dashboard/static/dashboard/img/unknown-green.svg33
-rw-r--r--openstack_dashboard/static/dashboard/img/unknown-red.svg33
-rw-r--r--openstack_dashboard/static/dashboard/less/horizon.less20
31 files changed, 1376 insertions, 3 deletions
diff --git a/horizon/static/horizon/js/horizon.heattop.js b/horizon/static/horizon/js/horizon.heattop.js
new file mode 100644
index 000000000..baf9e72c6
--- /dev/null
+++ b/horizon/static/horizon/js/horizon.heattop.js
@@ -0,0 +1,275 @@
+/**
+ *
+ * HeatTop JS Framework
+ * Dependencies: jQuery 1.7.1 or later, d3 v3 or later
+ * Date: June 2013
+ * Description: JS Framework that subclasses the D3 Force Directed Graph library to create
+ * Heat-specific objects and relationships with the purpose of displaying
+ * Stacks, Resources, and related Properties in a Resource Topology Graph.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ not use this file except in compliance with the License. You may obtain
+ a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations
+ under the License.
+*/
+
+var container = "#heat_resource_topology";
+
+if ($(container).length){
+ var width = $(container).width(),
+ height = 500,
+ stack_id = $("#stack_id").data("stack_id"),
+ ajax_url = '/project/stacks/get_d3_data/'+stack_id+'/',
+ graph = $("#d3_data").data("d3_data"),
+ force = d3.layout.force()
+ .nodes(graph.nodes)
+ .links([])
+ .gravity(0.1)
+ .charge(-2000)
+ .linkDistance(100)
+ .size([width, height])
+ .on("tick",tick),
+ svg = d3.select(container).append("svg")
+ .attr("width", width)
+ .attr("height", height),
+ node = svg.selectAll(".node"),
+ link = svg.selectAll(".link"),
+ needs_update = false,
+ nodes = force.nodes(),
+ links = force.links();
+
+ build_links();
+ update();
+
+
+ function update(){
+ node = node.data(nodes, function(d){return d.name});
+ link = link.data(links);
+
+ var nodeEnter = node.enter().append("g")
+ .attr("class", "node")
+ .attr("node_name", function(d){ return d.name })
+ .attr("node_id", function(d){ return d.instance })
+ .call(force.drag);
+
+ nodeEnter.append("image")
+ .attr("xlink:href", function(d) { return d.image; })
+ .attr("id", function(d){return "image_"+ d.name})
+ .attr("x", function(d) { return d.image_x; })
+ .attr("y", function(d) { return d.image_y; })
+ .attr("width", function(d) { return d.image_size; })
+ .attr("height", function(d) { return d.image_size; });
+ node.exit().remove();
+
+ link.enter().insert("svg:line", "g.node")
+ .attr("class", "link")
+ .style("stroke-width", function(d) { return Math.sqrt(d.value); });
+ link.exit().remove();
+ //Setup click action for all nodes
+ node.on("mouseover", function(d) {
+ $("#info_box").html(d.info_box);
+ current_info = d.name;
+ });
+ node.on("mouseout", function(d) {
+ $("#info_box").html('');
+ });
+
+ force.start();
+ }
+ function tick() {
+ link.attr("x1", function(d) { return d.source.x; })
+ .attr("y1", function(d) { return d.source.y; })
+ .attr("x2", function(d) { return d.target.x; })
+ .attr("y2", function(d) { return d.target.y; });
+
+ node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
+ }
+
+ //Load initial Stack box
+ $("#stack_box").html(graph.stack.info_box);
+ //On Page load, set Action In Progress
+ var in_progress = false;
+ set_in_progress(graph.stack, node);
+
+ //If status is In Progress, start AJAX polling
+ var poll_time = 0;
+ if (in_progress == true){poll_time = 3000;}
+ else {poll_time = 30000;}
+ ajax_poll(poll_time);
+
+ function set_in_progress(stack, nodes) {
+ if (stack.in_progress == true){in_progress = true;}
+ for (var i=0;i<nodes.length;i++) {
+ var d = nodes[i];
+ if (d.in_progress == true){in_progress = true;return false;}
+ }
+ }
+ function findNode(name) {
+ for (var i=0;i<nodes.length;i++) {if (nodes[i].name === name){return nodes[i];}};
+ };
+
+ function findNodeIndex(name) {
+ for (var i=0;i<nodes.length;i++) {if (nodes[i].name==name){return i;}};
+ };
+ function addNode (node) {
+ nodes.push(node);
+ needs_update = true;
+ };
+ function removeNode (name) {
+ var i = 0;
+ var n = findNode(name);
+ while (i < links.length) {
+ if ((links[i]['source'] == n)||(links[i]['target'] == n))
+ {
+ links.splice(i,1);
+ }
+ else i++;
+ }
+ nodes.splice(findNodeIndex(name),1);
+ needs_update = true;
+ };
+ function remove_nodes(old_nodes, new_nodes){
+ //Check for removed nodes
+ for (var i=0;i<old_nodes.length;i++) {
+ var remove_node = true;
+ for (var j=0;j<new_nodes.length;j++) {
+ if (old_nodes[i].name==new_nodes[j].name){
+ remove_node = false;
+ break;
+ }
+ }
+ if (remove_node==true){
+ removeNode(old_nodes[i].name);
+ }
+ }
+ }
+ function build_links(){
+ for (var i=0;i<nodes.length;i++){
+ build_node_links(nodes[i]);
+ build_reverse_links(nodes[i]);
+ }
+ }
+ function build_node_links(node){
+ for (var j=0;j<node.required_by.length;j++){
+ var push_link = true;
+ var target_idx = '';
+ var source_idx = findNodeIndex(node.name);
+ //make sure target node exists
+ try {
+ target_idx = findNodeIndex(node.required_by[j]);
+ } catch(err) {
+ console.log(err);
+ push_link =false;
+ }
+ //check for duplicates
+ for (var lidx=0;lidx<links.length;lidx++) {
+ if ((links[lidx]['source'] == source_idx)&&(links[lidx]['target'] == target_idx))
+ {
+ push_link=false;
+ break;
+ }
+ }
+
+ if (push_link==true && (source_idx && target_idx)){
+ links.push({
+ 'source':source_idx,
+ 'target':target_idx,
+ 'value':1
+ });
+ }
+ }
+ }
+
+ function build_reverse_links(node){
+ for (var i=0;i<nodes.length;i++){
+ if(nodes[i].required_by){
+ for (var j=0;j<nodes[i].required_by.length;j++){
+ var dependency = nodes[i].required_by[j];
+ //if new node is required by existing node, push new link
+ if(node.name==dependency){
+ links.push({
+ 'source':findNodeIndex(nodes[i].name),
+ 'target':findNodeIndex(node.name),
+ 'value':1
+ })
+ }
+ }
+ }
+ }
+ }
+
+ function ajax_poll(poll_time){
+ setTimeout(function() {
+ $.getJSON(ajax_url, function(json) {
+ //update d3 data element
+ $("#d3_data").attr("data-d3_data", JSON.stringify(json));
+
+ //update stack
+ $("#stack_box").html(json.stack.info_box);
+ set_in_progress(json.stack, json.nodes);
+ needs_update = false;
+
+ //Check Remove nodes
+ remove_nodes(nodes, json.nodes);
+
+ //Check for updates and new nodes
+ json.nodes.forEach(function(d){
+ current_node = findNode(d.name);
+ //Check if node already exists
+ if (current_node) {
+ //Node already exists, just update it
+ current_node.status = d.status;
+
+ //Status has changed, image should be updated
+ if (current_node.image != d.image){
+ current_node.image = d.image;
+ var this_image = d3.select("#image_"+current_node.name);
+ this_image
+ .transition()
+ .attr("x", function(d) { return d.image_x + 5; })
+ .duration(100)
+ .transition()
+ .attr("x", function(d) { return d.image_x - 5; })
+ .duration(100)
+ .transition()
+ .attr("x", function(d) { return d.image_x + 5; })
+ .duration(100)
+ .transition()
+ .attr("x", function(d) { return d.image_x - 5; })
+ .duration(100)
+ .transition()
+ .attr("xlink:href", d.image)
+ .transition()
+ .attr("x", function(d) { return d.image_x; })
+ .duration(100)
+ .ease("bounce")
+ }
+
+ //Status has changed, update info_box
+ current_node.info_box = d.info_box;
+
+ } else {
+ addNode(d);
+ build_links();
+ }
+ });
+
+ //if any updates needed, do update now
+ if (needs_update==true){
+ update();
+ }
+ });
+ //if no nodes still in progress, slow AJAX polling
+ if (in_progress==false){poll_time = 30000;}
+ else {poll_time = 3000;}
+ ajax_poll(poll_time);
+ }, poll_time);
+ }
+} \ No newline at end of file
diff --git a/horizon/templates/horizon/_scripts.html b/horizon/templates/horizon/_scripts.html
index d6971eecb..b3edd2041 100644
--- a/horizon/templates/horizon/_scripts.html
+++ b/horizon/templates/horizon/_scripts.html
@@ -38,6 +38,7 @@
<script src='{{ STATIC_URL }}horizon/js/horizon.projects.js' type='text/javascript' charset='utf-8'></script>
<script src='{{ STATIC_URL }}horizon/js/horizon.networktopology.js' type='text/javascript' charset='utf-8'></script>
<script src='{{ STATIC_URL }}horizon/js/horizon.d3piechart.js' type='text/javascript' charset='utf-8'></script>
+<script src='{{ STATIC_URL }}horizon/js/horizon.heattop.js' type='text/javascript' charset='utf-8'></script>
{% block custom_js_files %}{% endblock %}
{% endcompress %}
diff --git a/openstack_dashboard/dashboards/project/stacks/api.py b/openstack_dashboard/dashboards/project/stacks/api.py
new file mode 100644
index 000000000..1572b5a98
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/stacks/api.py
@@ -0,0 +1,84 @@
+import json
+import logging
+
+from django.http import HttpResponse
+
+from openstack_dashboard.api.heat import resources_list
+from openstack_dashboard.api.heat import stack_get
+
+from openstack_dashboard.dashboards.project.stacks.mappings \
+ import get_resource_image
+from openstack_dashboard.dashboards.project.stacks.mappings \
+ import get_resource_status
+from openstack_dashboard.dashboards.project.stacks.sro import resource_info
+from openstack_dashboard.dashboards.project.stacks.sro import stack_info
+
+
+LOG = logging.getLogger(__name__)
+
+
+class Stack(object):
+ pass
+
+
+def d3_data(request, stack_id=''):
+ try:
+ stack = stack_get(request, stack_id)
+ except:
+ stack = Stack()
+ stack.id = stack_id
+ stack.stack_name = request.session.get('stack_name', '')
+ stack.stack_status = 'DELETE_COMPLETE'
+ stack.stack_status_reason = 'DELETE_COMPLETE'
+
+ try:
+ resources = resources_list(request, stack.stack_name)
+ except:
+ resources = []
+
+ d3_data = {"nodes": [], "stack": {}}
+ if stack:
+ stack_image = get_resource_image(stack.stack_status, 'stack')
+ stack_node = {
+ 'stack_id': stack.id,
+ 'name': stack.stack_name,
+ 'status': stack.stack_status,
+ 'image': stack_image,
+ 'image_size': 60,
+ 'image_x': -30,
+ 'image_y': -30,
+ 'text_x': 40,
+ 'text_y': ".35em",
+ 'in_progress': True if (get_resource_status(stack.stack_status) ==
+ 'IN_PROGRESS') else False,
+ 'info_box': stack_info(stack, stack_image)
+ }
+ d3_data['stack'] = stack_node
+
+ if resources:
+ for resource in resources:
+ resource_image = get_resource_image(resource.resource_status,
+ resource.resource_type)
+ in_progress = True if (
+ get_resource_status(resource.resource_status)
+ == 'IN_PROGRESS') else False
+ resource_node = {
+ 'name': resource.logical_resource_id,
+ 'status': resource.resource_status,
+ 'image': resource_image,
+ 'required_by': resource.required_by,
+ 'image_size': 50,
+ 'image_x': -25,
+ 'image_y': -25,
+ 'text_x': 35,
+ 'text_y': ".35em",
+ 'in_progress': in_progress,
+ 'info_box': resource_info(resource)
+ }
+ d3_data['nodes'].append(resource_node)
+ return json.dumps(d3_data)
+
+
+def get_d3_data(request, stack_id=''):
+ return HttpResponse(d3_data(request, stack_id=stack_id),
+ content_type="application/json")
diff --git a/openstack_dashboard/dashboards/project/stacks/mappings.py b/openstack_dashboard/dashboards/project/stacks/mappings.py
index 5b4f9ec7e..ac6d526ac 100644
--- a/openstack_dashboard/dashboards/project/stacks/mappings.py
+++ b/openstack_dashboard/dashboards/project/stacks/mappings.py
@@ -14,6 +14,7 @@
import json
import logging
+import re
import urlparse
from django.core.urlresolvers import reverse
@@ -81,3 +82,64 @@ def stack_output(output):
if parts.netloc and parts.scheme in ('http', 'https'):
return u'<a href="%s" target="_blank">%s</a>' % (output, output)
return unicode(output)
+
+
+resource_images = {
+ 'LB_FAILED': '/static/dashboard/img/lb-red.svg',
+ 'LB_DELETE': '/static/dashboard/img/lb-red.svg',
+ 'LB_IN_PROGRESS': '/static/dashboard/img/lb-gray.gif',
+ 'LB_COMPLETE': '/static/dashboard/img/lb-green.svg',
+ 'DB_FAILED': '/static/dashboard/img/db-red.svg',
+ 'DB_DELETE': '/static/dashboard/img/db-red.svg',
+ 'DB_IN_PROGRESS': '/static/dashboard/img/db-gray.gif',
+ 'DB_COMPLETE': '/static/dashboard/img/db-green.svg',
+ 'STACK_FAILED': '/static/dashboard/img/stack-red.svg',
+ 'STACK_DELETE': '/static/dashboard/img/stack-red.svg',
+ 'STACK_IN_PROGRESS': '/static/dashboard/img/stack-gray.gif',
+ 'STACK_COMPLETE': '/static/dashboard/img/stack-green.svg',
+ 'SERVER_FAILED': '/static/dashboard/img/server-red.svg',
+ 'SERVER_DELETE': '/static/dashboard/img/server-red.svg',
+ 'SERVER_IN_PROGRESS': '/static/dashboard/img/server-gray.gif',
+ 'SERVER_COMPLETE': '/static/dashboard/img/server-green.svg',
+ 'UNKNOWN_FAILED': '/static/dashboard/img/unknown-red.svg',
+ 'UNKNOWN_DELETE': '/static/dashboard/img/unknown-red.svg',
+ 'UNKNOWN_IN_PROGRESS': '/static/dashboard/img/unknown-gray.gif',
+ 'UNKNOWN_COMPLETE': '/static/dashboard/img/unknown-green.svg',
+}
+
+
+def get_resource_type(type):
+ if re.search('LoadBalancer', type):
+ return 'LB'
+ elif re.search('DBInstance', type):
+ return 'DB'
+ elif re.search('Instance', type):
+ return 'SERVER'
+ elif re.search('stack', type):
+ return 'STACK'
+ else:
+ return 'UNKNOWN'
+
+
+def get_resource_status(status):
+ if re.search('IN_PROGRESS', status):
+ return 'IN_PROGRESS'
+ elif re.search('FAILED', status):
+ return 'FAILED'
+ elif re.search('DELETE', status):
+ return 'DELETE'
+ else:
+ return 'COMPLETE'
+
+
+def get_resource_image(status, type):
+ '''
+ Sets the image url and in_progress action sw based on status.
+ '''
+ resource_type = get_resource_type(type)
+ resource_status = get_resource_status(status)
+ resource_state = resource_type + "_" + resource_status
+
+ for key in resource_images:
+ if key == resource_state:
+ return resource_images.get(key)
diff --git a/openstack_dashboard/dashboards/project/stacks/sro.py b/openstack_dashboard/dashboards/project/stacks/sro.py
new file mode 100644
index 000000000..f385ee556
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/stacks/sro.py
@@ -0,0 +1,31 @@
+from django.template.defaultfilters import title
+from django.template.loader import render_to_string
+
+from horizon.utils.filters import replace_underscores
+
+
+def stack_info(stack, stack_image):
+ stack.stack_status_desc = title(replace_underscores(stack.stack_status))
+ if stack.stack_status_reason:
+ stack.stack_status_reason = title(
+ replace_underscores(stack.stack_status_reason)
+ )
+ context = {}
+ context['stack'] = stack
+ context['stack_image'] = stack_image
+ return render_to_string('project/stacks/_stack_info.html',
+ context)
+
+
+def resource_info(resource):
+ resource.resource_status_desc = title(
+ replace_underscores(resource.resource_status)
+ )
+ if resource.resource_status_reason:
+ resource.resource_status_reason = title(
+ replace_underscores(resource.resource_status_reason)
+ )
+ context = {}
+ context['resource'] = resource
+ return render_to_string('project/stacks/_resource_info.html',
+ context)
diff --git a/openstack_dashboard/dashboards/project/stacks/tabs.py b/openstack_dashboard/dashboards/project/stacks/tabs.py
index c1adf35f3..9a736bb21 100644
--- a/openstack_dashboard/dashboards/project/stacks/tabs.py
+++ b/openstack_dashboard/dashboards/project/stacks/tabs.py
@@ -20,6 +20,7 @@ from horizon import messages
from horizon import tabs
from openstack_dashboard import api
+from openstack_dashboard.dashboards.project.stacks.api import d3_data
from openstack_dashboard.dashboards.project.stacks.tables import EventsTable
from openstack_dashboard.dashboards.project.stacks.tables import ResourcesTable
@@ -27,6 +28,20 @@ from openstack_dashboard.dashboards.project.stacks.tables import ResourcesTable
LOG = logging.getLogger(__name__)
+class StackTopologyTab(tabs.Tab):
+ name = _("Topology")
+ slug = "topology"
+ template_name = "project/stacks/_detail_topology.html"
+ preload = False
+
+ def get_context_data(self, request):
+ context = {}
+ stack = self.tab_group.kwargs['stack']
+ context['stack_id'] = stack.id
+ context['d3_data'] = d3_data(request, stack_id=stack.id)
+ return context
+
+
class StackOverviewTab(tabs.Tab):
name = _("Overview")
slug = "overview"
@@ -90,7 +105,8 @@ class StackResourcesTab(tabs.Tab):
class StackDetailTabs(tabs.TabGroup):
slug = "stack_details"
- tabs = (StackOverviewTab, StackResourcesTab, StackEventsTab)
+ tabs = (StackTopologyTab, StackOverviewTab, StackResourcesTab,
+ StackEventsTab)
sticky = True
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html
new file mode 100644
index 000000000..d906ceadd
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_detail_topology.html
@@ -0,0 +1,9 @@
+{% load i18n sizeformat %}
+
+<div id="resource_container">
+ <div id="info_box"></div>
+ <div id="stack_box"></div>
+ <div id="heat_resource_topology"></div>
+ <div id="stack_id" data-stack_id="{{ stack_id }}"></div>
+ <div id="d3_data" data-d3_data="{{ d3_data }}"></div>
+</div> \ No newline at end of file
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html
new file mode 100644
index 000000000..05a92ec37
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_resource_info.html
@@ -0,0 +1,10 @@
+<h3>{{ resource.logical_resource_id }}</h3>
+
+{% if resource.resource_status == 'CREATE_FAILED' %}
+<p class="error">{{ resource.resource_status_desc }}</p>
+<p class="error">{{ resource.resource_status_reason }}</p>
+{% else %}
+<p>{{ resource.resource_status_desc }}</p>
+{% endif %}
+
+<p>{{ resource.resource_type }}</p> \ No newline at end of file
diff --git a/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html
new file mode 100644
index 000000000..3b548aa58
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/stacks/templates/stacks/_stack_info.html
@@ -0,0 +1,16 @@
+<img src="{{ stack_image }}" width="35px" height="35px" />
+<div id="stack_info">
+ <h3>{{ stack.stack_name }}</h3>
+ <p class="error">{{ stack.stack_status_desc }}</p>
+</div>
+<div class="clear"></div>
+{% if stack.stack_status == 'CREATE_FAILED' %}
+ <p class="error">{{ stack.stack_status_reason }}</p>
+{% else %}
+ <p>{{ stack.stack_status_desc }}</p>
+{% endif %}
+{% for output in stack.outputs %}
+ {% if output.output_key == 'WebsiteURL' %}
+ <a href="{{ output.output_value }}">{{ output.description }}</a>
+ {% endif %}
+{% endfor %} \ No newline at end of file
diff --git a/openstack_dashboard/dashboards/project/stacks/urls.py b/openstack_dashboard/dashboards/project/stacks/urls.py
index 7271aeb30..157f38609 100644
--- a/openstack_dashboard/dashboards/project/stacks/urls.py
+++ b/openstack_dashboard/dashboards/project/stacks/urls.py
@@ -15,6 +15,7 @@
from django.conf.urls.defaults import patterns
from django.conf.urls.defaults import url
+from openstack_dashboard.dashboards.project.stacks.api import get_d3_data
from openstack_dashboard.dashboards.project.stacks.views import CreateStackView
from openstack_dashboard.dashboards.project.stacks.views import DetailView
from openstack_dashboard.dashboards.project.stacks.views import IndexView
@@ -32,4 +33,7 @@ urlpatterns = patterns(
url(r'^stack/(?P<stack_id>[^/]+)/$', DetailView.as_view(), name='detail'),
url(r'^stack/(?P<stack_id>[^/]+)/(?P<resource_name>[^/]+)/$',
ResourceView.as_view(), name='resource'),
+
+ #AJAX urls
+ url(r'^get_d3_data/(?P<stack_id>[^/]+)/$', get_d3_data, name='d3_data')
)
diff --git a/openstack_dashboard/dashboards/project/stacks/views.py b/openstack_dashboard/dashboards/project/stacks/views.py
index 2beda10e9..97640dff3 100644
--- a/openstack_dashboard/dashboards/project/stacks/views.py
+++ b/openstack_dashboard/dashboards/project/stacks/views.py
@@ -102,6 +102,8 @@ class DetailView(tabs.TabView):
try:
stack = api.heat.stack_get(request, stack_id)
self._stack = stack
+ request.session['stack_id'] = stack.id
+ request.session['stack_name'] = stack.stack_name
except:
msg = _("Unable to retrieve stack.")
redirect = reverse('horizon:project:stacks:index')
diff --git a/openstack_dashboard/static/dashboard/img/db-gray.gif b/openstack_dashboard/static/dashboard/img/db-gray.gif
new file mode 100644
index 000000000..7fbeb41af
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/db-gray.gif
Binary files differ
diff --git a/openstack_dashboard/static/dashboard/img/db-gray.svg b/openstack_dashboard/static/dashboard/img/db-gray.svg
new file mode 100644
index 000000000..58b3bbadb
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/db-gray.svg
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_2_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#808080" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<g id="XMLID_1_">
+ <g>
+ <path fill="#808080" d="M63.49,52.5v3.99c0,3.75-8.8,6.78-19.67,6.78s-19.67-3.03-19.67-6.78V52.5c0.01,0.01,0.01,0.01,0.02,0.021
+ c0.31,3.649,8.98,6.579,19.65,6.579s19.34-2.93,19.65-6.579C63.48,52.51,63.48,52.51,63.49,52.5z"/>
+ <path fill="#FFFFFF" d="M63.49,48.33v3.98c0,0.069,0,0.14-0.02,0.21c-2.69,3.239-11.07,5.09-19.65,5.09s-16.96-1.851-19.65-5.09
+ c-0.02-0.07-0.02-0.141-0.02-0.21v-3.98c0.04,0.05,0.09,0.11,0.14,0.16c1.27,3.16,9.53,5.63,19.53,5.63
+ c9.92,0,18.13-2.43,19.48-5.58C63.37,48.47,63.43,48.4,63.49,48.33z"/>
+ <path fill="#FFFFFF" d="M63.49,30.42l-0.03,4.21c-2.72,3-11.119,4.66-19.64,4.66c-8.55,0-16.98-1.67-19.67-4.69v-4.18
+ c0.04,0.05,0.09,0.09,0.14,0.14c1.12,2.94,9.43,5.23,19.53,5.23c10.1,0,18.41-2.29,19.53-5.23C63.4,30.51,63.45,30.47,63.49,30.42
+ z"/>
+ <path fill="#808080" d="M63.49,34.6l-0.03,4.54c-0.029,0.13-0.069,0.26-0.119,0.39c-2.83,3.04-11.091,4.74-19.521,4.74
+ c-8.5,0-16.82-1.73-19.59-4.81c-0.03-0.09-0.06-0.19-0.08-0.28v-4.17c0.68,3.2,9.22,5.77,19.67,5.77
+ c10.45,0,18.99-2.57,19.64-5.82v-0.33C63.47,34.62,63.48,34.61,63.49,34.6z"/>
+ <path fill="#FFFFFF" d="M63.49,39.37l-0.02,4.2c-2.71,3.13-11.09,4.88-19.65,4.88c-8.58,0-16.98-1.76-19.67-4.9v-4.18
+ c0.03,0.03,0.05,0.06,0.08,0.09c1.1,3.07,9.44,5.5,19.59,5.5c10.03,0,18.29-2.37,19.521-5.43C63.4,39.48,63.44,39.42,63.49,39.37z
+ "/>
+ <path fill="#808080" d="M63.49,43.55l-0.02,4.4c-0.03,0.2-0.09,0.39-0.17,0.59c-2.86,3.12-11.07,4.9-19.48,4.9
+ c-8.46,0-16.71-1.801-19.53-4.95c-0.07-0.17-0.11-0.34-0.14-0.51V43.8c0.54,3.4,9.14,6.14,19.67,6.14
+ c10.53,0,19.13-2.74,19.65-6.17v-0.2C63.48,43.56,63.48,43.56,63.49,43.55z"/>
+ <path fill="#808080" d="M63.47,43.57v0.2c-0.521,3.43-9.12,6.17-19.65,6.17c-10.53,0-19.13-2.74-19.67-6.14v-0.25
+ c2.69,3.14,11.09,4.9,19.67,4.9C52.38,48.45,60.76,46.7,63.47,43.57z"/>
+ <path fill="#808080" d="M63.459,34.63v0.33c-0.649,3.25-9.189,5.82-19.64,5.82c-10.45,0-18.99-2.57-19.67-5.77V34.6
+ c2.69,3.02,11.12,4.69,19.67,4.69C52.34,39.29,60.74,37.63,63.459,34.63z"/>
+ <path fill="#636464" d="M63.49,29.87c0,0.23-0.04,0.46-0.14,0.69c-2.811,2.93-11.11,4.55-19.53,4.55s-16.72-1.62-19.53-4.55
+ c-0.1-0.23-0.14-0.46-0.14-0.69c0-3.27,8.8-5.92,19.67-5.92S63.49,26.6,63.49,29.87z"/>
+ <path fill="#636464" d="M63.35,30.56c-1.12,2.94-9.431,5.23-19.53,5.23c-10.1,0-18.41-2.29-19.53-5.23
+ c2.81,2.93,11.11,4.55,19.53,4.55S60.54,33.49,63.35,30.56z"/>
+ <path fill="#808080" d="M63.47,52.521C63.16,56.17,54.49,59.1,43.82,59.1s-19.34-2.93-19.65-6.579
+ c2.69,3.239,11.07,5.09,19.65,5.09S60.78,55.76,63.47,52.521z"/>
+ <path fill="#808080" d="M63.3,48.54c-1.351,3.15-9.561,5.58-19.48,5.58c-10,0-18.26-2.47-19.53-5.63
+ c2.82,3.149,11.07,4.95,19.53,4.95C52.23,53.44,60.44,51.66,63.3,48.54z"/>
+ <path fill="#808080" d="M63.34,39.53c-1.23,3.06-9.49,5.43-19.521,5.43c-10.15,0-18.49-2.43-19.59-5.5
+ c2.77,3.08,11.09,4.81,19.59,4.81C52.25,44.27,60.51,42.57,63.34,39.53z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.35,30.56
+ c0.05-0.05,0.1-0.09,0.14-0.14l-0.03,4.21"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.15,34.6v-4.18
+ c0.04,0.05,0.09,0.09,0.14,0.14"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.3,48.54
+ c0.069-0.07,0.13-0.14,0.189-0.21v3.98c0,0.069,0,0.14-0.02,0.21"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.17,52.521
+ c-0.02-0.07-0.02-0.141-0.02-0.21v-3.98c0.04,0.05,0.09,0.11,0.14,0.16"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.15,43.55
+ v-4.18c0.03,0.03,0.05,0.06,0.08,0.09"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.34,39.53
+ c0.06-0.05,0.1-0.11,0.149-0.16l-0.02,4.2"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.23,39.46
+ c-0.03-0.09-0.06-0.19-0.08-0.28v-4.17V34.6c2.69,3.02,11.12,4.69,19.67,4.69c8.521,0,16.92-1.66,19.64-4.66
+ c0.011-0.01,0.021-0.02,0.03-0.03l-0.03,4.54c-0.029,0.13-0.069,0.26-0.119,0.39c-1.23,3.06-9.49,5.43-19.521,5.43
+ C33.67,44.96,25.33,42.53,24.23,39.46z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.47,52.521
+ c0.01-0.011,0.01-0.011,0.02-0.021v3.99c0,3.75-8.8,6.78-19.67,6.78s-19.67-3.03-19.67-6.78V52.5c0.01,0.01,0.01,0.01,0.02,0.021
+ c2.69,3.239,11.07,5.09,19.65,5.09S60.78,55.76,63.47,52.521z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.47,43.57
+ c0.01-0.01,0.01-0.01,0.02-0.02l-0.02,4.4c-0.03,0.2-0.09,0.39-0.17,0.59c-1.351,3.15-9.561,5.58-19.48,5.58
+ c-10,0-18.26-2.47-19.53-5.63c-0.07-0.17-0.11-0.34-0.14-0.51V43.8v-0.25c2.69,3.14,11.09,4.9,19.67,4.9
+ C52.38,48.45,60.76,46.7,63.47,43.57z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.29,30.56
+ c-0.1-0.23-0.14-0.46-0.14-0.69c0-3.27,8.8-5.92,19.67-5.92s19.67,2.65,19.67,5.92c0,0.23-0.04,0.46-0.14,0.69
+ c-1.12,2.94-9.431,5.23-19.53,5.23C33.72,35.79,25.41,33.5,24.29,30.56z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/db-green.svg b/openstack_dashboard/static/dashboard/img/db-green.svg
new file mode 100644
index 000000000..aea48b9d7
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/db-green.svg
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_2_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#186735" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<g id="XMLID_1_">
+ <g>
+ <path fill="#166734" d="M63.49,52.5v3.99c0,3.75-8.8,6.78-19.67,6.78s-19.67-3.03-19.67-6.78V52.5c0.01,0.01,0.01,0.01,0.02,0.021
+ c0.31,3.649,8.98,6.579,19.65,6.579s19.34-2.93,19.65-6.579C63.48,52.51,63.48,52.51,63.49,52.5z"/>
+ <path fill="#FFFFFF" d="M63.49,48.33v3.98c0,0.069,0,0.14-0.02,0.21c-2.69,3.239-11.07,5.09-19.65,5.09s-16.96-1.851-19.65-5.09
+ c-0.02-0.07-0.02-0.141-0.02-0.21v-3.98c0.04,0.05,0.09,0.11,0.14,0.16c1.27,3.16,9.53,5.63,19.53,5.63
+ c9.92,0,18.13-2.43,19.48-5.58C63.37,48.47,63.43,48.4,63.49,48.33z"/>
+ <path fill="#FFFFFF" d="M63.49,30.42l-0.03,4.21c-2.72,3-11.119,4.66-19.64,4.66c-8.55,0-16.98-1.67-19.67-4.69v-4.18
+ c0.04,0.05,0.09,0.09,0.14,0.14c1.12,2.94,9.43,5.23,19.53,5.23c10.1,0,18.41-2.29,19.53-5.23C63.4,30.51,63.45,30.47,63.49,30.42
+ z"/>
+ <path fill="#166734" d="M63.49,34.6l-0.03,4.54c-0.029,0.13-0.069,0.26-0.119,0.39c-2.83,3.04-11.091,4.74-19.521,4.74
+ c-8.5,0-16.82-1.73-19.59-4.81c-0.03-0.09-0.06-0.19-0.08-0.28v-4.17c0.68,3.2,9.22,5.77,19.67,5.77
+ c10.45,0,18.99-2.57,19.64-5.82v-0.33C63.47,34.62,63.48,34.61,63.49,34.6z"/>
+ <path fill="#FFFFFF" d="M63.49,39.37l-0.02,4.2c-2.71,3.13-11.09,4.88-19.65,4.88c-8.58,0-16.98-1.76-19.67-4.9v-4.18
+ c0.03,0.03,0.05,0.06,0.08,0.09c1.1,3.07,9.44,5.5,19.59,5.5c10.03,0,18.29-2.37,19.521-5.43C63.4,39.48,63.44,39.42,63.49,39.37z
+ "/>
+ <path fill="#166734" d="M63.49,43.55l-0.02,4.4c-0.03,0.2-0.09,0.39-0.17,0.59c-2.86,3.12-11.07,4.9-19.48,4.9
+ c-8.46,0-16.71-1.801-19.53-4.95c-0.07-0.17-0.11-0.34-0.14-0.51V43.8c0.54,3.4,9.14,6.14,19.67,6.14
+ c10.53,0,19.13-2.74,19.65-6.17v-0.2C63.48,43.56,63.48,43.56,63.49,43.55z"/>
+ <path fill="#0F8140" d="M63.47,43.57v0.2c-0.521,3.43-9.12,6.17-19.65,6.17c-10.53,0-19.13-2.74-19.67-6.14v-0.25
+ c2.69,3.14,11.09,4.9,19.67,4.9C52.38,48.45,60.76,46.7,63.47,43.57z"/>
+ <path fill="#0F8140" d="M63.459,34.63v0.33c-0.649,3.25-9.189,5.82-19.64,5.82c-10.45,0-18.99-2.57-19.67-5.77V34.6
+ c2.69,3.02,11.12,4.69,19.67,4.69C52.34,39.29,60.74,37.63,63.459,34.63z"/>
+ <path fill="#1F572B" d="M63.49,29.87c0,0.23-0.04,0.46-0.14,0.69c-2.811,2.93-11.11,4.55-19.53,4.55s-16.72-1.62-19.53-4.55
+ c-0.1-0.23-0.14-0.46-0.14-0.69c0-3.27,8.8-5.92,19.67-5.92S63.49,26.6,63.49,29.87z"/>
+ <path fill="#0F8140" d="M63.35,30.56c-1.12,2.94-9.431,5.23-19.53,5.23c-10.1,0-18.41-2.29-19.53-5.23
+ c2.81,2.93,11.11,4.55,19.53,4.55S60.54,33.49,63.35,30.56z"/>
+ <path fill="#0F8140" d="M63.47,52.521C63.16,56.17,54.49,59.1,43.82,59.1s-19.34-2.93-19.65-6.579
+ c2.69,3.239,11.07,5.09,19.65,5.09S60.78,55.76,63.47,52.521z"/>
+ <path fill="#0F8140" d="M63.3,48.54c-1.351,3.15-9.561,5.58-19.48,5.58c-10,0-18.26-2.47-19.53-5.63
+ c2.82,3.149,11.07,4.95,19.53,4.95C52.23,53.44,60.44,51.66,63.3,48.54z"/>
+ <path fill="#0F8140" d="M63.34,39.53c-1.23,3.06-9.49,5.43-19.521,5.43c-10.15,0-18.49-2.43-19.59-5.5
+ c2.77,3.08,11.09,4.81,19.59,4.81C52.25,44.27,60.51,42.57,63.34,39.53z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.35,30.56
+ c0.05-0.05,0.1-0.09,0.14-0.14l-0.03,4.21"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.15,34.6v-4.18
+ c0.04,0.05,0.09,0.09,0.14,0.14"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.3,48.54
+ c0.069-0.07,0.13-0.14,0.189-0.21v3.98c0,0.069,0,0.14-0.02,0.21"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.17,52.521
+ c-0.02-0.07-0.02-0.141-0.02-0.21v-3.98c0.04,0.05,0.09,0.11,0.14,0.16"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.15,43.55
+ v-4.18c0.03,0.03,0.05,0.06,0.08,0.09"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.34,39.53
+ c0.06-0.05,0.1-0.11,0.149-0.16l-0.02,4.2"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.23,39.46
+ c-0.03-0.09-0.06-0.19-0.08-0.28v-4.17V34.6c2.69,3.02,11.12,4.69,19.67,4.69c8.521,0,16.92-1.66,19.64-4.66
+ c0.011-0.01,0.021-0.02,0.03-0.03l-0.03,4.54c-0.029,0.13-0.069,0.26-0.119,0.39c-1.23,3.06-9.49,5.43-19.521,5.43
+ C33.67,44.96,25.33,42.53,24.23,39.46z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.47,52.521
+ c0.01-0.011,0.01-0.011,0.02-0.021v3.99c0,3.75-8.8,6.78-19.67,6.78s-19.67-3.03-19.67-6.78V52.5c0.01,0.01,0.01,0.01,0.02,0.021
+ c2.69,3.239,11.07,5.09,19.65,5.09S60.78,55.76,63.47,52.521z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.47,43.57
+ c0.01-0.01,0.01-0.01,0.02-0.02l-0.02,4.4c-0.03,0.2-0.09,0.39-0.17,0.59c-1.351,3.15-9.561,5.58-19.48,5.58
+ c-10,0-18.26-2.47-19.53-5.63c-0.07-0.17-0.11-0.34-0.14-0.51V43.8v-0.25c2.69,3.14,11.09,4.9,19.67,4.9
+ C52.38,48.45,60.76,46.7,63.47,43.57z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.29,30.56
+ c-0.1-0.23-0.14-0.46-0.14-0.69c0-3.27,8.8-5.92,19.67-5.92s19.67,2.65,19.67,5.92c0,0.23-0.04,0.46-0.14,0.69
+ c-1.12,2.94-9.431,5.23-19.53,5.23C33.72,35.79,25.41,33.5,24.29,30.56z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/db-red.svg b/openstack_dashboard/static/dashboard/img/db-red.svg
new file mode 100644
index 000000000..9154fcd58
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/db-red.svg
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_2_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#C82128" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<g id="XMLID_1_">
+ <g>
+ <path fill="#C82027" d="M63.49,52.5v3.99c0,3.75-8.8,6.78-19.67,6.78s-19.67-3.03-19.67-6.78V52.5c0.01,0.01,0.01,0.01,0.02,0.021
+ c0.31,3.649,8.98,6.579,19.65,6.579s19.34-2.93,19.65-6.579C63.48,52.51,63.48,52.51,63.49,52.5z"/>
+ <path fill="#FFFFFF" d="M63.49,48.33v3.98c0,0.069,0,0.14-0.02,0.21c-2.69,3.239-11.07,5.09-19.65,5.09s-16.96-1.851-19.65-5.09
+ c-0.02-0.07-0.02-0.141-0.02-0.21v-3.98c0.04,0.05,0.09,0.11,0.14,0.16c1.27,3.16,9.53,5.63,19.53,5.63
+ c9.92,0,18.13-2.43,19.48-5.58C63.37,48.47,63.43,48.4,63.49,48.33z"/>
+ <path fill="#FFFFFF" d="M63.49,30.42l-0.03,4.21c-2.72,3-11.119,4.66-19.64,4.66c-8.55,0-16.98-1.67-19.67-4.69v-4.18
+ c0.04,0.05,0.09,0.09,0.14,0.14c1.12,2.94,9.43,5.23,19.53,5.23c10.1,0,18.41-2.29,19.53-5.23C63.4,30.51,63.45,30.47,63.49,30.42
+ z"/>
+ <path fill="#C82027" d="M63.49,34.6l-0.03,4.54c-0.029,0.13-0.069,0.26-0.119,0.39c-2.83,3.04-11.091,4.74-19.521,4.74
+ c-8.5,0-16.82-1.73-19.59-4.81c-0.03-0.09-0.06-0.19-0.08-0.28v-4.17c0.68,3.2,9.22,5.77,19.67,5.77
+ c10.45,0,18.99-2.57,19.64-5.82v-0.33C63.47,34.62,63.48,34.61,63.49,34.6z"/>
+ <path fill="#FFFFFF" d="M63.49,39.37l-0.02,4.2c-2.71,3.13-11.09,4.88-19.65,4.88c-8.58,0-16.98-1.76-19.67-4.9v-4.18
+ c0.03,0.03,0.05,0.06,0.08,0.09c1.1,3.07,9.44,5.5,19.59,5.5c10.03,0,18.29-2.37,19.521-5.43C63.4,39.48,63.44,39.42,63.49,39.37z
+ "/>
+ <path fill="#C82027" d="M63.49,43.55l-0.02,4.4c-0.03,0.2-0.09,0.39-0.17,0.59c-2.86,3.12-11.07,4.9-19.48,4.9
+ c-8.46,0-16.71-1.801-19.53-4.95c-0.07-0.17-0.11-0.34-0.14-0.51V43.8c0.54,3.4,9.14,6.14,19.67,6.14
+ c10.53,0,19.13-2.74,19.65-6.17v-0.2C63.48,43.56,63.48,43.56,63.49,43.55z"/>
+ <path fill="#C82027" d="M63.47,43.57v0.2c-0.521,3.43-9.12,6.17-19.65,6.17c-10.53,0-19.13-2.74-19.67-6.14v-0.25
+ c2.69,3.14,11.09,4.9,19.67,4.9C52.38,48.45,60.76,46.7,63.47,43.57z"/>
+ <path fill="#C82027" d="M63.459,34.63v0.33c-0.649,3.25-9.189,5.82-19.64,5.82c-10.45,0-18.99-2.57-19.67-5.77V34.6
+ c2.69,3.02,11.12,4.69,19.67,4.69C52.34,39.29,60.74,37.63,63.459,34.63z"/>
+ <path fill="#9F1D20" d="M63.49,29.87c0,0.23-0.04,0.46-0.14,0.69c-2.811,2.93-11.11,4.55-19.53,4.55s-16.72-1.62-19.53-4.55
+ c-0.1-0.23-0.14-0.46-0.14-0.69c0-3.27,8.8-5.92,19.67-5.92S63.49,26.6,63.49,29.87z"/>
+ <path fill="#9F1D20" d="M63.35,30.56c-1.12,2.94-9.431,5.23-19.53,5.23c-10.1,0-18.41-2.29-19.53-5.23
+ c2.81,2.93,11.11,4.55,19.53,4.55S60.54,33.49,63.35,30.56z"/>
+ <path fill="#C82027" d="M63.47,52.521C63.16,56.17,54.49,59.1,43.82,59.1s-19.34-2.93-19.65-6.579
+ c2.69,3.239,11.07,5.09,19.65,5.09S60.78,55.76,63.47,52.521z"/>
+ <path fill="#C82027" d="M63.3,48.54c-1.351,3.15-9.561,5.58-19.48,5.58c-10,0-18.26-2.47-19.53-5.63
+ c2.82,3.149,11.07,4.95,19.53,4.95C52.23,53.44,60.44,51.66,63.3,48.54z"/>
+ <path fill="#C82027" d="M63.34,39.53c-1.23,3.06-9.49,5.43-19.521,5.43c-10.15,0-18.49-2.43-19.59-5.5
+ c2.77,3.08,11.09,4.81,19.59,4.81C52.25,44.27,60.51,42.57,63.34,39.53z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.35,30.56
+ c0.05-0.05,0.1-0.09,0.14-0.14l-0.03,4.21"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.15,34.6v-4.18
+ c0.04,0.05,0.09,0.09,0.14,0.14"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.3,48.54
+ c0.069-0.07,0.13-0.14,0.189-0.21v3.98c0,0.069,0,0.14-0.02,0.21"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.17,52.521
+ c-0.02-0.07-0.02-0.141-0.02-0.21v-3.98c0.04,0.05,0.09,0.11,0.14,0.16"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.15,43.55
+ v-4.18c0.03,0.03,0.05,0.06,0.08,0.09"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.34,39.53
+ c0.06-0.05,0.1-0.11,0.149-0.16l-0.02,4.2"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.23,39.46
+ c-0.03-0.09-0.06-0.19-0.08-0.28v-4.17V34.6c2.69,3.02,11.12,4.69,19.67,4.69c8.521,0,16.92-1.66,19.64-4.66
+ c0.011-0.01,0.021-0.02,0.03-0.03l-0.03,4.54c-0.029,0.13-0.069,0.26-0.119,0.39c-1.23,3.06-9.49,5.43-19.521,5.43
+ C33.67,44.96,25.33,42.53,24.23,39.46z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.47,52.521
+ c0.01-0.011,0.01-0.011,0.02-0.021v3.99c0,3.75-8.8,6.78-19.67,6.78s-19.67-3.03-19.67-6.78V52.5c0.01,0.01,0.01,0.01,0.02,0.021
+ c2.69,3.239,11.07,5.09,19.65,5.09S60.78,55.76,63.47,52.521z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M63.47,43.57
+ c0.01-0.01,0.01-0.01,0.02-0.02l-0.02,4.4c-0.03,0.2-0.09,0.39-0.17,0.59c-1.351,3.15-9.561,5.58-19.48,5.58
+ c-10,0-18.26-2.47-19.53-5.63c-0.07-0.17-0.11-0.34-0.14-0.51V43.8v-0.25c2.69,3.14,11.09,4.9,19.67,4.9
+ C52.38,48.45,60.76,46.7,63.47,43.57z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="square" stroke-linejoin="round" stroke-miterlimit="10" d="M24.29,30.56
+ c-0.1-0.23-0.14-0.46-0.14-0.69c0-3.27,8.8-5.92,19.67-5.92s19.67,2.65,19.67,5.92c0,0.23-0.04,0.46-0.14,0.69
+ c-1.12,2.94-9.431,5.23-19.53,5.23C33.72,35.79,25.41,33.5,24.29,30.56z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/lb-gray.gif b/openstack_dashboard/static/dashboard/img/lb-gray.gif
new file mode 100644
index 000000000..9b1c51626
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/lb-gray.gif
Binary files differ
diff --git a/openstack_dashboard/static/dashboard/img/lb-gray.svg b/openstack_dashboard/static/dashboard/img/lb-gray.svg
new file mode 100644
index 000000000..eb858750c
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/lb-gray.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_3_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#808080" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<g id="XMLID_2_">
+ <g>
+ <path fill="#808080" d="M68.8,41.85v12.52H18.83V41.92c0-0.02,0.01-0.04,0.02-0.07H68.79C68.79,41.88,68.8,41.83,68.8,41.85z
+ M55.31,48.36c0-1.11-0.9-2-2-2c-1.11,0-2,0.89-2,2c0,1.109,0.89,2,2,2C54.41,50.36,55.31,49.47,55.31,48.36z M46.31,48.36
+ c0-1.11-0.891-2-1.99-2c-1.11,0-2,0.89-2,2c0,1.109,0.89,2,2,2C45.419,50.36,46.31,49.47,46.31,48.36z M37.32,48.36
+ c0-1.11-0.89-2-2-2c-1.1,0-2,0.89-2,2c0,1.109,0.9,2,2,2C36.43,50.36,37.32,49.47,37.32,48.36z"/>
+ <polygon fill="#636464" points="61.82,32.33 68.79,41.85 18.85,41.85 25.81,32.33 "/>
+ <path fill="#FFFFFF" d="M53.31,46.36c1.1,0,2,0.89,2,2c0,1.109-0.9,2-2,2c-1.11,0-2-0.891-2-2C51.31,47.25,52.2,46.36,53.31,46.36
+ z"/>
+ <path fill="#FFFFFF" d="M44.32,46.36c1.1,0,1.99,0.89,1.99,2c0,1.109-0.891,2-1.99,2c-1.11,0-2-0.891-2-2
+ C42.32,47.25,43.21,46.36,44.32,46.36z"/>
+ <path fill="#FFFFFF" d="M35.32,46.36c1.11,0,2,0.89,2,2c0,1.109-0.89,2-2,2c-1.1,0-2-0.891-2-2
+ C33.32,47.25,34.22,46.36,35.32,46.36z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.79,41.85 61.82,32.33 25.81,32.33 18.85,41.85 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M18.85,41.85
+ c-0.01,0.03-0.02,0.05-0.02,0.07v12.45H68.8V41.85c0-0.02-0.011,0.03-0.011,0H18.85z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/lb-green.svg b/openstack_dashboard/static/dashboard/img/lb-green.svg
new file mode 100644
index 000000000..770ffc798
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/lb-green.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_3_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#156734" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<g id="XMLID_2_">
+ <g>
+ <path fill="#166734" d="M18.85,41.85H68.79c0,0.03,0.011-0.02,0.011,0v12.52H18.83V41.92C18.83,41.9,18.84,41.88,18.85,41.85z
+ M55.31,48.36c0-1.11-0.9-2-2-2c-1.11,0-2,0.89-2,2c0,1.109,0.89,2,2,2C54.41,50.36,55.31,49.47,55.31,48.36z M46.31,48.36
+ c0-1.11-0.891-2-1.99-2c-1.11,0-2,0.89-2,2c0,1.109,0.89,2,2,2C45.419,50.36,46.31,49.47,46.31,48.36z M37.32,48.36
+ c0-1.11-0.89-2-2-2c-1.1,0-2,0.89-2,2c0,1.109,0.9,2,2,2C36.43,50.36,37.32,49.47,37.32,48.36z"/>
+ <path fill="#FFFFFF" d="M53.31,46.36c1.1,0,2,0.89,2,2c0,1.109-0.9,2-2,2c-1.11,0-2-0.891-2-2C51.31,47.25,52.2,46.36,53.31,46.36
+ z"/>
+ <path fill="#FFFFFF" d="M44.32,46.36c1.1,0,1.99,0.89,1.99,2c0,1.109-0.891,2-1.99,2c-1.11,0-2-0.891-2-2
+ C42.32,47.25,43.21,46.36,44.32,46.36z"/>
+ <path fill="#FFFFFF" d="M35.32,46.36c1.11,0,2,0.89,2,2c0,1.109-0.89,2-2,2c-1.1,0-2-0.891-2-2
+ C33.32,47.25,34.22,46.36,35.32,46.36z"/>
+ <polygon fill="#1F572B" points="18.85,41.85 25.81,32.33 61.82,32.33 68.79,41.85 "/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.79,41.85 61.82,32.33 25.81,32.33 18.85,41.85 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M18.85,41.85
+ c-0.01,0.03-0.02,0.05-0.02,0.07v12.45H68.8V41.85c0-0.02-0.011,0.03-0.011,0H18.85z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/lb-red.svg b/openstack_dashboard/static/dashboard/img/lb-red.svg
new file mode 100644
index 000000000..12434fd1a
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/lb-red.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_3_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#C82128" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<g id="XMLID_2_">
+ <g>
+ <path fill="#C82027" d="M18.85,41.85H68.79c0,0.03,0.011-0.02,0.011,0v12.52H18.83V41.92C18.83,41.9,18.84,41.88,18.85,41.85z
+ M55.31,48.36c0-1.11-0.9-2-2-2c-1.11,0-2,0.89-2,2c0,1.109,0.89,2,2,2C54.41,50.36,55.31,49.47,55.31,48.36z M46.31,48.36
+ c0-1.11-0.891-2-1.99-2c-1.11,0-2,0.89-2,2c0,1.109,0.89,2,2,2C45.419,50.36,46.31,49.47,46.31,48.36z M37.32,48.36
+ c0-1.11-0.89-2-2-2c-1.1,0-2,0.89-2,2c0,1.109,0.9,2,2,2C36.43,50.36,37.32,49.47,37.32,48.36z"/>
+ <path fill="#FFFFFF" d="M53.31,46.36c1.1,0,2,0.89,2,2c0,1.109-0.9,2-2,2c-1.11,0-2-0.891-2-2C51.31,47.25,52.2,46.36,53.31,46.36
+ z"/>
+ <path fill="#FFFFFF" d="M44.32,46.36c1.1,0,1.99,0.89,1.99,2c0,1.109-0.891,2-1.99,2c-1.11,0-2-0.891-2-2
+ C42.32,47.25,43.21,46.36,44.32,46.36z"/>
+ <path fill="#FFFFFF" d="M35.32,46.36c1.11,0,2,0.89,2,2c0,1.109-0.89,2-2,2c-1.1,0-2-0.891-2-2
+ C33.32,47.25,34.22,46.36,35.32,46.36z"/>
+ <polygon fill="#9F1D20" points="18.85,41.85 25.81,32.33 61.82,32.33 68.79,41.85 "/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.79,41.85 61.82,32.33 25.81,32.33 18.85,41.85 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M18.85,41.85
+ c-0.01,0.03-0.02,0.05-0.02,0.07v12.45H68.8V41.85c0-0.02-0.011,0.03-0.011,0H18.85z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/server-gray.gif b/openstack_dashboard/static/dashboard/img/server-gray.gif
new file mode 100644
index 000000000..7f411c0dd
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/server-gray.gif
Binary files differ
diff --git a/openstack_dashboard/static/dashboard/img/server-gray.svg b/openstack_dashboard/static/dashboard/img/server-gray.svg
new file mode 100644
index 000000000..9e17b0bdf
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/server-gray.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.7 92 92" enable-background="new -3.1 -2.7 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_3_">
+ <g>
+ <path fill="#FFFFFF" d="M43.3,1.5c23.1,0,41.8,18.7,41.8,41.8c0,23.1-18.7,41.8-41.8,41.8c-23.1,0-41.8-18.7-41.8-41.8
+ C1.5,20.2,20.2,1.5,43.3,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#808080" stroke-width="3" stroke-miterlimit="10" d="M85.2,43.3c0,23.1-18.7,41.8-41.8,41.8
+ c-23.1,0-41.8-18.7-41.8-41.8c0-23.1,18.7-41.8,41.8-41.8C66.4,1.5,85.2,20.2,85.2,43.3z"/>
+ </g>
+</g>
+<g id="XMLID_1_">
+ <g>
+ <path fill="#808080" d="M68.6,42.4V55H39v-2.8h2V45v-2.6H68.6C68.5,42.5,68.6,42.4,68.6,42.4z M63,48.7c0-1.2-0.9-2.1-2-2.1
+ c-1.1,0-2,0.9-2,2.1c0,1.1,0.9,2.1,2,2.1C62.2,50.8,63,49.8,63,48.7z"/>
+ <polygon fill="#636464" points="61.6,33 68.5,42.4 41,42.4 18.5,42.4 25.5,33 "/>
+ <path fill="#FFFFFF" d="M61,46.6c1.1,0,2,0.9,2,2.1c0,1.1-0.9,2.1-2,2.1c-1.1,0-2-0.9-2-2.1C59,47.5,59.9,46.6,61,46.6z"/>
+ <rect x="39" y="45" fill="#808080" width="2" height="7.3"/>
+ <path fill="#808080" d="M41,42.4V45h-2v7.3V55H18.5V42.5c0,0,0,0,0-0.1H41z M36,52.2V45h-2v7.3H36z M31,52.2V45h-2v7.3H31z
+ M26,52.2V45h-2v7.3H26z"/>
+ <rect x="34" y="45" fill="#808080" width="2" height="7.3"/>
+ <rect x="29" y="45" fill="#808080" width="2" height="7.3"/>
+ <rect x="24" y="45" fill="#808080" width="2" height="7.3"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.5,42.4 61.6,33 25.5,33 18.5,42.4 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M39,55h29.5V42.4
+ c0,0,0,0,0,0H41H18.5c0,0,0,0.1,0,0.1V55H39z"/>
+
+ <rect x="24" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="29" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="34" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="39" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/server-green.svg b/openstack_dashboard/static/dashboard/img/server-green.svg
new file mode 100644
index 000000000..52ac168ce
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/server-green.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.7 92 92" enable-background="new -3.1 -2.7 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_3_">
+ <g>
+ <path fill="#FFFFFF" d="M43.3,1.5c23.1,0,41.8,18.7,41.8,41.8c0,23.1-18.7,41.8-41.8,41.8c-23.1,0-41.8-18.7-41.8-41.8
+ C1.5,20.2,20.2,1.5,43.3,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#156734" stroke-width="3" stroke-miterlimit="10" d="M85.2,43.3c0,23.1-18.7,41.8-41.8,41.8
+ c-23.1,0-41.8-18.7-41.8-41.8c0-23.1,18.7-41.8,41.8-41.8C66.4,1.5,85.2,20.2,85.2,43.3z"/>
+ </g>
+</g>
+<g id="XMLID_1_">
+ <g>
+ <polygon fill="#0F8140" points="61.6,33 68.5,42.4 41,42.4 18.5,42.4 25.5,33 "/>
+ <path fill="#FFFFFF" d="M61,46.6c1.1,0,2,0.9,2,2.1c0,1.1-0.9,2.1-2,2.1c-1.1,0-2-0.9-2-2.1C59,47.5,59.9,46.6,61,46.6z"/>
+ <path fill="#156734" d="M63,48.7c0-1.2-0.9-2.1-2-2.1c-1.1,0-2,0.9-2,2.1c0,1.1,0.9,2.1,2,2.1C62.2,50.8,63,49.8,63,48.7z
+ M68.6,42.4V55H39v-2.8h2V45v-2.6H68.6C68.5,42.5,68.6,42.4,68.6,42.4z"/>
+ <rect x="39" y="45" fill="#156734" width="2" height="7.3"/>
+ <rect x="34" y="45" fill="#156734" width="2" height="7.3"/>
+ <rect x="29" y="45" fill="#156734" width="2" height="7.3"/>
+ <rect x="24" y="45" fill="#156734" width="2" height="7.3"/>
+ <path fill="#156734" d="M24,52.2h2V45h-2V52.2z M29,52.2h2V45h-2V52.2z M18.5,42.4H41V45h-2v7.3V55H18.5L18.5,42.4
+ C18.5,42.5,18.5,42.5,18.5,42.4z M34,45v7.3h2V45H34z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.5,42.4 61.6,33 25.5,33 18.5,42.4 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M39,55h29.5V42.4
+ c0,0,0,0,0,0H41H18.5c0,0,0,0.1,0,0.1V55H39z"/>
+
+ <rect x="24" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="29" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="34" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="39" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/server-red.svg b/openstack_dashboard/static/dashboard/img/server-red.svg
new file mode 100644
index 000000000..ecce52df9
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/server-red.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.7 92 92" enable-background="new -3.1 -2.7 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_3_">
+ <g>
+ <path fill="#FFFFFF" d="M43.3,1.5c23.1,0,41.8,18.7,41.8,41.8c0,23.1-18.7,41.8-41.8,41.8c-23.1,0-41.8-18.7-41.8-41.8
+ C1.5,20.2,20.2,1.5,43.3,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#C82027" stroke-width="3" stroke-miterlimit="10" d="M85.2,43.3c0,23.1-18.7,41.8-41.8,41.8
+ c-23.1,0-41.8-18.7-41.8-41.8c0-23.1,18.7-41.8,41.8-41.8C66.4,1.5,85.2,20.2,85.2,43.3z"/>
+ </g>
+</g>
+<g id="XMLID_1_">
+ <g>
+ <path fill="#C82027" d="M68.6,42.4V55H39v-2.8h2V45v-2.6H68.6C68.5,42.5,68.6,42.4,68.6,42.4z M63,48.7c0-1.2-0.9-2.1-2-2.1
+ c-1.1,0-2,0.9-2,2.1c0,1.1,0.9,2.1,2,2.1C62.2,50.8,63,49.8,63,48.7z"/>
+ <polygon fill="#9F1D20" points="61.6,33 68.5,42.4 41,42.4 18.5,42.4 25.5,33 "/>
+ <path fill="#FFFFFF" d="M61,46.6c1.1,0,2,0.9,2,2.1c0,1.1-0.9,2.1-2,2.1c-1.1,0-2-0.9-2-2.1C59,47.5,59.9,46.6,61,46.6z"/>
+ <rect x="39" y="45" fill="#C82027" width="2" height="7.3"/>
+ <path fill="#C82027" d="M41,42.4V45h-2v7.3V55H18.5V42.5c0,0,0,0,0-0.1H41z M36,52.2V45h-2v7.3H36z M31,52.2V45h-2v7.3H31z
+ M26,52.2V45h-2v7.3H26z"/>
+ <rect x="34" y="45" fill="#C82027" width="2" height="7.3"/>
+ <rect x="29" y="45" fill="#C82027" width="2" height="7.3"/>
+ <rect x="24" y="45" fill="#C82027" width="2" height="7.3"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.5,42.4 61.6,33 25.5,33 18.5,42.4 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M39,55h29.5V42.4
+ c0,0,0,0,0,0H41H18.5c0,0,0,0.1,0,0.1V55H39z"/>
+
+ <rect x="24" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="29" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="34" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="39" y="45" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/stack-gray.gif b/openstack_dashboard/static/dashboard/img/stack-gray.gif
new file mode 100644
index 000000000..54a2cee49
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/stack-gray.gif
Binary files differ
diff --git a/openstack_dashboard/static/dashboard/img/stack-gray.svg b/openstack_dashboard/static/dashboard/img/stack-gray.svg
new file mode 100644
index 000000000..71134ee3c
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/stack-gray.svg
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.7 92 92" enable-background="new -3.1 -2.7 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<circle fill="#FFFFFF" stroke="#808080" stroke-width="3" stroke-miterlimit="10" cx="43.3" cy="43.3" r="41.8"/>
+<g id="XMLID_6_">
+ <g>
+ <path fill="#808080" d="M68.5,51.9v12.6h-50V52c0,0,0,0,0-0.1H68.5C68.5,52,68.5,51.9,68.5,51.9z"/>
+ <polygon fill="#0F8140" points="61.6,42.5 68.5,51.9 18.5,51.9 25.5,42.5 "/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.5,51.9 61.6,42.5 25.5,42.5 18.5,51.9 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M18.5,51.9
+ C18.5,52,18.5,52,18.5,51.9l0,12.6h50V51.9c0,0,0,0,0,0H18.5z"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="27" y1="55.5" x2="60" y2="55.5"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="27" y1="58.5" x2="60" y2="58.5"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="27" y1="61.5" x2="60" y2="61.5"/>
+ </g>
+</g>
+<g id="XMLID_5_">
+ <g>
+ <path fill="#808080" d="M68.5,39.4V52H39v-2.8h2V42v-2.6H68.5C68.5,39.5,68.5,39.4,68.5,39.4z M63,45.7c0-1.2-0.9-2.1-2-2.1
+ c-1.1,0-2,0.9-2,2.1c0,1.1,0.9,2.1,2,2.1C62.1,47.8,63,46.8,63,45.7z"/>
+ <polygon fill="#0F8140" points="61.6,30 68.5,39.4 41,39.4 18.5,39.4 25.5,30 "/>
+ <path fill="#FFFFFF" d="M61,43.6c1.1,0,2,0.9,2,2.1c0,1.1-0.9,2.1-2,2.1c-1.1,0-2-0.9-2-2.1C59,44.5,59.9,43.6,61,43.6z"/>
+ <rect x="39" y="42" fill="#808080" width="2" height="7.3"/>
+ <path fill="#808080" d="M41,39.4V42h-2v7.3V52H18.5V39.5c0,0,0,0,0-0.1H41z M36,49.3V42h-2v7.3H36z M31,49.3V42h-2v7.3H31z
+ M26,49.3V42h-2v7.3H26z"/>
+ <rect x="34" y="42" fill="#808080" width="2" height="7.3"/>
+ <rect x="29" y="42" fill="#808080" width="2" height="7.3"/>
+ <rect x="24" y="42" fill="#808080" width="2" height="7.3"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.5,39.4 61.6,30 25.5,30 18.5,39.4 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M39,52h29.5V39.4
+ c0,0,0,0,0,0H41H18.5c0,0,0,0.1,0,0.1V52H39z"/>
+
+ <rect x="24" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="29" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="34" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="39" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+ </g>
+</g>
+<g id="XMLID_4_">
+ <g>
+ <path fill="#808080" d="M68.5,27v12.5h-50V27.1c0,0,0,0,0-0.1H68.5C68.5,27,68.5,27,68.5,27z M55,33.5c0-1.1-0.9-2-2-2
+ c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2C54.1,35.5,55,34.6,55,33.5z M46,33.5c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2
+ C45.1,35.5,46,34.6,46,33.5z M37,33.5c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2C36.1,35.5,37,34.6,37,33.5z"/>
+ <polygon fill="#636565" points="61.5,17.5 68.5,27 18.5,27 25.5,17.5 "/>
+ <path fill="#FFFFFF" d="M53,31.5c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C51,32.4,51.9,31.5,53,31.5z"/>
+ <path fill="#FFFFFF" d="M44,31.5c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C42,32.4,42.9,31.5,44,31.5z"/>
+ <path fill="#FFFFFF" d="M35,31.5c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C33,32.4,33.9,31.5,35,31.5z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="68.5,27
+ 61.5,17.5 25.5,17.5 18.5,27 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M18.5,27
+ C18.5,27,18.5,27.1,18.5,27l0,12.5h50V27c0,0,0,0,0,0H18.5z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/stack-green.svg b/openstack_dashboard/static/dashboard/img/stack-green.svg
new file mode 100644
index 000000000..3faac892f
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/stack-green.svg
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.7 92 92" enable-background="new -3.1 -2.7 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_8_">
+ <g>
+ <path fill="#FFFFFF" d="M43.3,1.5c23.1,0,41.8,18.7,41.8,41.8c0,23.1-18.7,41.8-41.8,41.8c-23.1,0-41.8-18.7-41.8-41.8
+ C1.5,20.2,20.2,1.5,43.3,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#156734" stroke-width="3" stroke-miterlimit="10" d="M85.2,43.3c0,23.1-18.7,41.8-41.8,41.8
+ c-23.1,0-41.8-18.7-41.8-41.8c0-23.1,18.7-41.8,41.8-41.8C66.4,1.5,85.2,20.2,85.2,43.3z"/>
+ </g>
+</g>
+<g id="XMLID_7_">
+ <g>
+ <polygon fill="#0F8140" points="68.5,51.9 18.5,51.9 25.5,42.5 61.6,42.5 "/>
+ <path fill="#156734" d="M68.6,64.5h-50V52c0,0,0,0,0-0.1h50c0,0,0,0,0,0V64.5z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.5,51.9 61.6,42.5 25.5,42.5 18.5,51.9 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M18.5,51.9
+ C18.5,52,18.5,52,18.5,51.9l0,12.6h50V51.9c0,0,0,0,0,0H18.5z"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="27" y1="55.5" x2="60" y2="55.5"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="27" y1="58.5" x2="60" y2="58.5"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="27" y1="61.5" x2="60" y2="61.5"/>
+ </g>
+</g>
+<g id="XMLID_6_">
+ <g>
+ <polygon fill="#0F8140" points="61.6,30 68.5,39.4 41,39.4 18.5,39.4 25.5,30 "/>
+ <path fill="#FFFFFF" d="M61,43.6c1.1,0,2,0.9,2,2.1c0,1.1-0.9,2.1-2,2.1c-1.1,0-2-0.9-2-2.1C59,44.5,59.9,43.6,61,43.6z"/>
+ <path fill="#156734" d="M63,45.7c0-1.2-0.9-2.1-2-2.1c-1.1,0-2,0.9-2,2.1c0,1.1,0.9,2.1,2,2.1C62.2,47.8,63,46.8,63,45.7z
+ M68.6,39.4V52H39v-2.8h2V42v-2.6H68.6C68.5,39.5,68.6,39.4,68.6,39.4z"/>
+ <rect x="39" y="42" fill="#156734" width="2" height="7.3"/>
+ <rect x="34" y="42" fill="#156734" width="2" height="7.3"/>
+ <rect x="29" y="42" fill="#156734" width="2" height="7.3"/>
+ <rect x="24" y="42" fill="#156734" width="2" height="7.3"/>
+ <path fill="#156734" d="M24,49.2h2V42h-2V49.2z M29,49.2h2V42h-2V49.2z M18.5,39.4H41V42h-2v7.3V52H18.5L18.5,39.4
+ C18.5,39.5,18.5,39.5,18.5,39.4z M34,42v7.3h2V42H34z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 68.5,39.4 61.6,30 25.5,30 18.5,39.4 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M39,52h29.5V39.4
+ c0,0,0,0,0,0H41H18.5c0,0,0,0.1,0,0.1V52H39z"/>
+
+ <rect x="24" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="29" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="34" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+
+ <rect x="39" y="42" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.3"/>
+ </g>
+</g>
+<g id="XMLID_5_">
+ <g>
+ <path fill="#156734" d="M68.5,27v12.5h-50V27.1c0,0,0,0,0-0.1H68.5C68.5,27,68.5,27,68.5,27z M55,33.5c0-1.1-0.9-2-2-2
+ c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2C54.1,35.5,55,34.6,55,33.5z M46,33.5c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2
+ C45.1,35.5,46,34.6,46,33.5z M37,33.5c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2C36.1,35.5,37,34.6,37,33.5z"/>
+ <polygon fill="#1E572B" points="61.5,17.5 68.5,27 18.5,27 25.5,17.5 "/>
+ <path fill="#FFFFFF" d="M53,31.5c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C51,32.4,51.9,31.5,53,31.5z"/>
+ <path fill="#FFFFFF" d="M44,31.5c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C42,32.4,42.9,31.5,44,31.5z"/>
+ <path fill="#FFFFFF" d="M35,31.5c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C33,32.4,33.9,31.5,35,31.5z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="68.5,27
+ 61.5,17.5 25.5,17.5 18.5,27 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M18.5,27
+ C18.5,27,18.5,27.1,18.5,27l0,12.5h50V27c0,0,0,0,0,0H18.5z"/>
+ </g>
+</g>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/stack-red.svg b/openstack_dashboard/static/dashboard/img/stack-red.svg
new file mode 100644
index 000000000..14bf3cd84
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/stack-red.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="90.5px" height="91px" viewBox="49 -16.5 90.5 91" enable-background="new 49 -16.5 90.5 91" xml:space="preserve">
+<title>Compute</title>
+<g>
+ <circle fill="#FFFFFF" stroke="#C90505" stroke-width="3" stroke-miterlimit="10" cx="93.934" cy="29.499" r="41.833"/>
+ <g>
+ <g>
+ <g id="XMLID_3_">
+ <g>
+ <path fill="#C90505" d="M119.15,50.666h-50.04v-12.5c0-0.01,0.01-0.04,0.01-0.08h50.01c0.01,0.04,0.02-0.02,0.02,0V50.666z"/>
+ <polygon fill="#008000" points="112.161,28.666 119.131,38.086 69.121,38.086 76.101,28.666 "/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 119.131,38.086 112.161,28.666 76.101,28.666 69.121,38.086 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M69.121,38.086
+ c0,0.04-0.01,0.07-0.01,0.08v12.5h50.04v-12.58c0-0.02-0.01,0.04-0.02,0H69.121z"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="77.61" y1="41.666" x2="110.641" y2="41.666"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="77.61" y1="44.666" x2="110.641" y2="44.666"/>
+ <line fill="none" stroke="#FFFFFF" stroke-miterlimit="10" x1="77.61" y1="47.666" x2="110.641" y2="47.666"/>
+ </g>
+ </g>
+ </g>
+ <g>
+ <title>Compute</title>
+ <g>
+ <g id="XMLID_2_">
+ <g>
+ <path fill="#C90505" d="M119.15,25.596v12.57H89.61v-2.75h2v-7.25v-2.57h27.521C119.141,25.626,119.15,25.576,119.15,25.596z
+ M113.641,31.866c0-1.16-0.89-2.101-2-2.101c-1.1,0-2,0.94-2,2.101c0,1.149,0.9,2.09,2,2.09
+ C112.751,33.956,113.641,33.016,113.641,31.866z"/>
+ <polygon fill="#008000" points="112.161,16.166 119.131,25.596 91.61,25.596 69.121,25.596 76.101,16.166 "/>
+ <path fill="#FFFFFF" d="M111.641,29.766c1.11,0,2,0.94,2,2.101c0,1.149-0.89,2.09-2,2.09c-1.1,0-2-0.94-2-2.09
+ C109.641,30.706,110.541,29.766,111.641,29.766z"/>
+ <rect x="89.61" y="28.166" fill="#C90505" width="2" height="7.25"/>
+ <rect x="84.61" y="28.166" fill="#C90505" width="2" height="7.25"/>
+ <rect x="79.61" y="28.166" fill="#C90505" width="2" height="7.25"/>
+ <rect x="74.611" y="28.166" fill="#C90505" width="2" height="7.25"/>
+ <path fill="#C90505" d="M74.611,35.416h2v-7.25h-2V35.416z M79.61,35.416h2v-7.25h-2V35.416z M84.61,35.416h2v-7.25h-2V35.416
+ z M89.61,28.166v7.25v2.75h-20.5v-12.49c0-0.02,0.01-0.05,0.01-0.08h22.49v2.57H89.61z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 119.131,25.596 112.161,16.166 76.101,16.166 69.121,25.596 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M89.61,38.166
+ h29.54v-12.57c0-0.02-0.01,0.03-0.02,0H91.61h-22.49c0,0.03-0.01,0.061-0.01,0.08v12.49H89.61z"/>
+
+ <rect x="74.611" y="28.166" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.25"/>
+
+ <rect x="79.61" y="28.166" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.25"/>
+
+ <rect x="84.61" y="28.166" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.25"/>
+
+ <rect x="89.61" y="28.166" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" width="2" height="7.25"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ <g>
+ <title>Load Balancer</title>
+ <g>
+ <g id="XMLID_1_">
+ <g>
+ <path fill="#C90505" d="M119.081,13.186v12.52h-49.97v-12.45c0-0.02,0.01-0.04,0.02-0.07h49.939
+ C119.07,13.216,119.081,13.166,119.081,13.186z M105.591,19.696c0-1.11-0.9-2-2-2c-1.11,0-2,0.89-2,2c0,1.11,0.89,2,2,2
+ C104.69,21.696,105.591,20.806,105.591,19.696z M96.591,19.696c0-1.11-0.891-2-1.99-2c-1.11,0-2,0.89-2,2c0,1.11,0.89,2,2,2
+ C95.7,21.696,96.591,20.806,96.591,19.696z M87.601,19.696c0-1.11-0.89-2-2-2c-1.1,0-2,0.89-2,2c0,1.11,0.9,2,2,2
+ C86.711,21.696,87.601,20.806,87.601,19.696z"/>
+ <polygon fill="#A00202" points="112.101,3.666 119.07,13.186 69.131,13.186 76.091,3.666 "/>
+ <path fill="#FFFFFF" d="M103.591,17.696c1.1,0,2,0.89,2,2c0,1.11-0.9,2-2,2c-1.11,0-2-0.89-2-2
+ C101.591,18.586,102.48,17.696,103.591,17.696z"/>
+ <path fill="#FFFFFF" d="M94.601,17.696c1.1,0,1.99,0.89,1.99,2c0,1.11-0.891,2-1.99,2c-1.11,0-2-0.89-2-2
+ C92.601,18.586,93.49,17.696,94.601,17.696z"/>
+ <path fill="#FFFFFF" d="M85.601,17.696c1.11,0,2,0.89,2,2c0,1.11-0.89,2-2,2c-1.1,0-2-0.89-2-2
+ C83.601,18.586,84.501,17.696,85.601,17.696z"/>
+ </g>
+ <g>
+ <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
+ 119.07,13.186 112.101,3.666 76.091,3.666 69.131,13.186 "/>
+ <path fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M69.131,13.186
+ c-0.01,0.03-0.02,0.05-0.02,0.07v12.45h49.97v-12.52c0-0.02-0.011,0.03-0.011,0H69.131z"/>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</g>
+<line fill="none" x1="41" y1="42.25" x2="90.969" y2="42.25"/>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/unknown-gray.gif b/openstack_dashboard/static/dashboard/img/unknown-gray.gif
new file mode 100644
index 000000000..c90d8d8aa
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/unknown-gray.gif
Binary files differ
diff --git a/openstack_dashboard/static/dashboard/img/unknown-green.svg b/openstack_dashboard/static/dashboard/img/unknown-green.svg
new file mode 100644
index 000000000..a619d05d6
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/unknown-green.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_1_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#186735" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<rect x="26.899" y="28.166" fill="none" stroke="#186735" stroke-miterlimit="10" width="13.333" height="13.333"/>
+<rect x="40.232" y="40.966" fill="none" stroke="#186735" stroke-miterlimit="10" width="13.334" height="13.333"/>
+<rect x="26.899" y="40.966" fill="#21572C" stroke="#186735" stroke-miterlimit="10" width="13.334" height="13.333"/>
+<rect x="40.232" y="28.166" fill="#21572C" stroke="#186735" stroke-miterlimit="10" width="13.334" height="13.333"/>
+<rect x="46.634" y="35.5" fill="#FFFFFF" stroke="#186735" stroke-miterlimit="10" width="13.332" height="13.334"/>
+<rect x="33.833" y="48.832" fill="#FFFFFF" stroke="#186735" stroke-miterlimit="10" width="13.334" height="13.334"/>
+<rect x="33.833" y="35.5" fill="#21572C" stroke="#186735" stroke-miterlimit="10" width="13.334" height="13.334"/>
+<rect x="46.634" y="48.832" fill="#21572C" stroke="#186735" stroke-miterlimit="10" width="13.332" height="13.334"/>
+<line fill="none" stroke="#186735" stroke-miterlimit="10" x1="33.833" y1="62.166" x2="26.899" y2="54.299"/>
+<line fill="none" stroke="#186735" stroke-miterlimit="10" x1="33.833" y1="35.5" x2="26.899" y2="28.166"/>
+<line fill="none" stroke="#186735" stroke-miterlimit="10" x1="59.966" y1="35.5" x2="53.566" y2="28.166"/>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/img/unknown-red.svg b/openstack_dashboard/static/dashboard/img/unknown-red.svg
new file mode 100644
index 000000000..90fd38dbb
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/img/unknown-red.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
+]>
+<svg version="1.1"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+ x="0px" y="0px" width="92px" height="92px" viewBox="-3.1 -2.67 92 92" enable-background="new -3.1 -2.67 92 92"
+ xml:space="preserve">
+<defs>
+</defs>
+<g id="XMLID_1_">
+ <g>
+ <path fill="#FFFFFF" d="M43.33,1.5c23.11,0,41.839,18.73,41.839,41.83c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5z"/>
+ </g>
+ <g>
+ <path fill="none" stroke="#C82128" stroke-width="3" stroke-miterlimit="10" d="M85.169,43.33c0,23.1-18.729,41.83-41.839,41.83
+ c-23.1,0-41.83-18.73-41.83-41.83C1.5,20.23,20.23,1.5,43.33,1.5C66.44,1.5,85.169,20.23,85.169,43.33z"/>
+ </g>
+</g>
+<rect x="26.899" y="28.166" fill="none" stroke="#C82128" stroke-miterlimit="10" width="13.333" height="13.333"/>
+<rect x="40.232" y="40.966" fill="none" stroke="#186735" stroke-miterlimit="10" width="13.334" height="13.333"/>
+<rect x="26.899" y="40.966" fill="#9F1E22" stroke="#C82128" stroke-miterlimit="10" width="13.334" height="13.333"/>
+<rect x="40.232" y="28.166" fill="#9F1E22" stroke="#C82128" stroke-miterlimit="10" width="13.334" height="13.333"/>
+<rect x="46.634" y="35.5" fill="#FFFFFF" stroke="#C82128" stroke-miterlimit="10" width="13.332" height="13.334"/>
+<rect x="33.833" y="48.832" fill="#FFFFFF" stroke="#C82128" stroke-miterlimit="10" width="13.334" height="13.334"/>
+<rect x="33.833" y="35.5" fill="#9F1E22" stroke="#C82128" stroke-miterlimit="10" width="13.334" height="13.334"/>
+<rect x="46.634" y="48.832" fill="#9F1E22" stroke="#C82128" stroke-miterlimit="10" width="13.332" height="13.334"/>
+<line fill="none" stroke="#C82128" stroke-miterlimit="10" x1="33.833" y1="62.166" x2="26.899" y2="54.299"/>
+<line fill="none" stroke="#C82128" stroke-miterlimit="10" x1="33.833" y1="35.5" x2="26.899" y2="28.166"/>
+<line fill="none" stroke="#C82128" stroke-miterlimit="10" x1="59.966" y1="35.5" x2="53.566" y2="28.166"/>
+</svg>
diff --git a/openstack_dashboard/static/dashboard/less/horizon.less b/openstack_dashboard/static/dashboard/less/horizon.less
index f62f6233f..9d6fa717d 100644
--- a/openstack_dashboard/static/dashboard/less/horizon.less
+++ b/openstack_dashboard/static/dashboard/less/horizon.less
@@ -2085,5 +2085,21 @@ div.network {
}
}
-
-
+/**** Resource Topology CSS ****/
+.link {stroke: #000;stroke-width: 1.5px;}
+.node {cursor:pointer;}
+.node text {font: 12px sans-serif;}
+
+#resource_container {position:relative;}
+#stack_box {position:absolute;width:300px;top:10px;left:10px;}
+#stack_box h3 {font-size:11pt;line-height:20px;}
+#stack_box p {margin:0;font-size:9pt;line-height:14px;}
+#stack_box a {margin:0;font-size:9pt;line-height:14px;}
+#stack_box img {float:left;}
+#stack_box #stack_info {float:left;white-space:normal;width:200px;}
+
+#info_box {position:absolute;width:300px;top:100px;left:10px;}
+#info_box h3 {font-size:9pt;line-height:20px;}
+#info_box p {margin:0;font-size:9pt;line-height:14px;}
+#info_box a {margin:0;font-size:9pt;line-height:14px;}
+#info_box .error {color:darkred;}