Fix topology page issue with deps and images

Topology page now shows dependencies between apps or networks
Add app images to topology page
Show real app images instead of dummy app icon.

Change-Id: Ia8c1588239a4d6ea185866f0dd536f2c18178761
Closes-Bug: #1336587
Closes-Bug: #1336587
This commit is contained in:
Georgy Okrokvertskhov 2014-07-01 17:20:52 -07:00 committed by Timur Sufiev
parent d3a6d9bc81
commit b3d13d2f70
5 changed files with 64 additions and 19 deletions

View File

@ -314,4 +314,4 @@ def get_deployment_descr(request, environment_id, deployment_id):
def load_environment_data(request, environment_id): def load_environment_data(request, environment_id):
environment = environment_get(request, environment_id) environment = environment_get(request, environment_id)
return topology.render_d3_data(environment) return topology.render_d3_data(request, environment)

View File

@ -16,8 +16,20 @@ import json
import types import types
from django.contrib.staticfiles.templatetags.staticfiles import static from django.contrib.staticfiles.templatetags.staticfiles import static
from django.core.urlresolvers import reverse
from django.template import loader from django.template import loader
from muranodashboard.api import packages as pkg_cli
def get_app_image(request, app_fqdn):
package = pkg_cli.app_by_fqn(request, app_fqdn)
url = static('dashboard/img/stack-green.svg')
if package:
app_id = package.id
url = reverse("horizon:murano:catalog:images", args=(app_id,))
return url
def _get_environment_status_message(entity): def _get_environment_status_message(entity):
if hasattr(entity, 'status'): if hasattr(entity, 'status'):
@ -62,6 +74,13 @@ def _application_info(application, app_image, status):
context) context)
def _network_info(name, image):
context = {'name': name,
'image': image}
return loader.render_to_string('services/_network_info.html',
context)
def _unit_info(unit, unit_image): def _unit_info(unit, unit_image):
data = dict(unit) data = dict(unit)
data['type'] = _truncate_type(data['type'], 45) data['type'] = _truncate_type(data['type'], 45)
@ -98,9 +117,12 @@ def _create_empty_node():
def _create_ext_network_node(name): def _create_ext_network_node(name):
node = _create_empty_node() node = _create_empty_node()
node.update({'name': name, node.update({'id': name,
'image': static('dashboard/img/lb-green.svg'), 'image': static('muranodashboard/images/ext-net.png'),
'link_type': 'relation'}) 'link_type': 'relation',
'info_box': _network_info(name, static(
'dashboard/img/lb-green.svg'))}
)
return node return node
@ -119,7 +141,16 @@ def _is_atomic(elt):
return not isinstance(value, (types.DictType, types.ListType)) return not isinstance(value, (types.DictType, types.ListType))
def render_d3_data(environment): def check_service_references(node, node_data, srv_list):
node_id = node_data['?']['id']
for service in srv_list:
for k, v in service.iteritems():
if v == node_id:
node['required_by'].append(service['?']['id'])
node['link_type'] = 'relation'
def render_d3_data(request, environment):
if not environment: if not environment:
return None return None
@ -138,13 +169,13 @@ def render_d3_data(environment):
}) })
d3_data['environment'] = environment_node d3_data['environment'] = environment_node
service_image = static('dashboard/img/stack-green.svg')
unit_image = static('dashboard/img/server-green.svg') unit_image = static('dashboard/img/server-green.svg')
for service in environment.services: for service in environment.services:
in_progress, status_message = _get_environment_status_message(service) in_progress, status_message = _get_environment_status_message(service)
required_by = None required_by = None
if hasattr(service, 'assignFloatingIP'): if 'instance' in service:
if service['instance'].get('assignFloatingIp', False):
if ext_net_name: if ext_net_name:
required_by = ext_net_name required_by = ext_net_name
else: else:
@ -154,18 +185,20 @@ def render_d3_data(environment):
required_by = ext_net_name required_by = ext_net_name
service_node = _create_empty_node() service_node = _create_empty_node()
service_image = get_app_image(request, service['?']['type'])
service_node.update({ service_node.update({
'name': service.get('name', ''), 'name': service.get('name', ''),
'status': status_message, 'status': status_message,
'image': service_image, 'image': service_image,
'id': service['?']['id'], 'id': service['?']['id'],
'link_type': 'unit', 'link_type': 'relation',
'in_progress': in_progress, 'in_progress': in_progress,
'info_box': _application_info( 'info_box': _application_info(
service, service_image, status_message) service, service_image, status_message)
}) })
if required_by: if required_by:
service_node['required_by'] = [required_by] service_node['required_by'].append(required_by)
check_service_references(service_node, service, environment.services)
d3_data['nodes'].append(service_node) d3_data['nodes'].append(service_node)
def rec(node_data, node_key, parent_node=None): def rec(node_data, node_key, parent_node=None):
@ -180,7 +213,8 @@ def render_d3_data(environment):
('type', node_type), ('type', node_type),
('name', node_data.get('name', node_key))]) ('name', node_data.get('name', node_key))])
if parent_node is not None: if parent_node is not None:
node['required_by'] = [parent_node['?']['id']] node['required_by'].append(parent_node['?']['id'])
node.update({ node.update({
'id': node_data['?']['id'], 'id': node_data['?']['id'],
'info_box': _unit_info(atomics, unit_image), 'info_box': _unit_info(atomics, unit_image),

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -36,13 +36,16 @@ function update(){
.attr("node_id", function(d) { return d.id; }) .attr("node_id", function(d) { return d.id; })
.call(force.drag); .call(force.drag);
nodeEnter.append("image") nodeEnter.append("image")
.attr("xlink:href", function(d) { return d.image; }) .attr("xlink:href", function(d) { return d.image; })
.attr("id", function(d){ return "image_"+ d.id; }) .attr("id", function(d){ return "image_"+ d.id; })
.attr("x", function(d) { return d.image_x; }) .attr("x", function(d) { return d.image_x; })
.attr("y", function(d) { return d.image_y; }) .attr("y", function(d) { return d.image_y; })
.attr("width", function(d) { return d.image_size; }) .attr("width", function(d) { return d.image_size; })
.attr("height", function(d) { return d.image_size; }); .attr("height", function(d) { return d.image_size; })
.attr("clip-path","url(#clipCircle)");
node.exit().remove(); node.exit().remove();
link.enter().insert("path", "g.node") link.enter().insert("path", "g.node")
@ -175,7 +178,7 @@ function build_reverse_links(node){
'source':findNodeIndex(nodes[i].id), 'source':findNodeIndex(nodes[i].id),
'target':findNodeIndex(node.id), 'target':findNodeIndex(node.id),
'value':1, 'value':1,
'link_type': node.link_type 'link_type': nodes[i].link_type
}); });
} }
} }
@ -273,6 +276,11 @@ if ($(murano_container).length){
needs_update = false, needs_update = false,
nodes = force.nodes(), nodes = force.nodes(),
links = force.links(); links = force.links();
svg.append("svg:clipPath")
.attr("id","clipCircle")
.append("svg:circle")
.attr("cursor","pointer")
.attr("r", "28px");
build_links(); build_links();
update(); update();

View File

@ -0,0 +1,3 @@
<img src="{{ image }}" width="35px" height="35px" />
<h3>Name: {{ name }}</h3>