Implement service graph; add service graph to service grid; add add-service to service grid
diff --git a/xos/core/static/primarycons_blue/plus.png b/xos/core/static/primarycons_blue/plus.png
new file mode 100644
index 0000000..a00ab89
--- /dev/null
+++ b/xos/core/static/primarycons_blue/plus.png
Binary files differ
diff --git a/xos/core/views/services.py b/xos/core/views/services.py
index 76180e7..6f24609 100644
--- a/xos/core/views/services.py
+++ b/xos/core/views/services.py
@@ -6,6 +6,7 @@
import json
import os
import time
+import tempfile
class ServiceGridView(TemplateView):
head_template = r"""{% extends "admin/dashboard/dashboard_base.html" %}
@@ -21,11 +22,8 @@
html = '<table><tr>'
- i=0
+ icons=[]
for service in Service.objects.all():
- if (i%4) == 0:
- html = html + '</tr><tr>'
-
view_url = service.view_url
if (not view_url):
view_url = "/admin/core/service/$id$/"
@@ -35,8 +33,26 @@
if (not image_url):
image_url = "/static/primarycons_blue/gear_2.png"
+ icons.append( {"name": service.name, "view_url": view_url, "image_url": image_url} )
+
+ icons.append( {"name": "Tenancy Graph", "view_url": "/serviceGraph.png", "image_url": "/static/primarycons_blue/service_graph.png", "horiz_rule": True} )
+ icons.append( {"name": "Add Service", "view_url": "/admin/core/service/add/", "image_url": "/static/primarycons_blue/plus.png"} )
+
+ i=0
+ for icon in icons:
+ if icon.get("horiz_rule", False):
+ html = html + "</tr><tr><td colspan=4><hr></td></tr><tr>"
+ i=0
+
+ service_name = icon["name"]
+ view_url = icon["view_url"]
+ image_url = icon["image_url"]
+
+ if (i%4) == 0:
+ html = html + '</tr><tr>'
+
html = html + '<td width=96 height=128 valign=top align=center><a href="%s"><img src="%s" height=64 width=64></img></a>' % (view_url, image_url)
- html = html + '<p><a href="%s">%s</a></p></td>' % (view_url, service.name)
+ html = html + '<p><a href="%s">%s</a></p></td>' % (view_url, service_name)
i=i+1
html = html + '</tr></table>'
@@ -50,4 +66,76 @@
template = t,
**response_kwargs)
+class ServiceGraphViewOld(TemplateView):
+ # this attempt used networkx
+ # yum -y install python-matplotlib python-networkx
+ # pip-python install -upgrade networkx
+ # pip-python install graphviz pygraphviz
+ def get(self, request, name="root", *args, **kwargs):
+ import networkx as nx
+ import matplotlib as mpl
+ mpl.use("Agg")
+ import matplotlib.pyplot as plt
+ import nxedges
+
+ plt.figure(figsize=(10,8))
+
+ g = nx.DiGraph()
+
+ labels = {}
+ for service in Service.objects.all():
+ g.add_node(service.id)
+ if len(service.name)>8:
+ labels[service.id] = service.name[:8] + "\n" + service.name[8:]
+ else:
+ labels[service.id] = service.name
+
+ for tenant in CoarseTenant.objects.all():
+ if (not tenant.provider_service) or (not tenant.subscriber_service):
+ continue
+ g.add_edge(tenant.subscriber_service.id, tenant.provider_service.id)
+
+ pos = nx.graphviz_layout(g)
+ nxedges.xos_draw_networkx_edges(g,pos,arrow_len=30)
+ nx.draw_networkx_nodes(g,pos,node_size=5000)
+ nx.draw_networkx_labels(g,pos,labels,font_size=12)
+ #plt.axis('off')
+ plt.savefig("/tmp/foo.png")
+
+ return HttpResponse(open("/tmp/foo.png","r").read(), content_type="image/png")
+
+class ServiceGraphView(TemplateView):
+ # this attempt just uses graphviz directly
+ # yum -y install graphviz
+ # pip-python install pygraphviz
+
+ def get(self, request, name="root", *args, **kwargs):
+ import pygraphviz as pgv
+
+ g = pgv.AGraph(directed=True)
+ g.graph_attr.update(size="8,4!")
+ g.graph_attr.update(dpi="100")
+ #g.graph_attr.update(nodesep="2.5")
+ g.graph_attr.update(overlap="false")
+ g.graph_attr.update(graphdir="TB")
+
+ for service in Service.objects.all():
+ provided_tenants = CoarseTenant.get_tenant_objects().filter(provider_service=service)
+ subscribed_tenants = CoarseTenant.get_tenant_objects().filter(subscriber_service=service)
+ if not (provided_tenants or subscribed_tenants):
+ # nodes with no edges aren't interesting
+ continue
+ g.add_node(service.id, label=service.name)
+
+ for tenant in CoarseTenant.get_tenant_objects().all():
+ if (not tenant.provider_service) or (not tenant.subscriber_service):
+ continue
+ g.add_edge(tenant.subscriber_service.id, tenant.provider_service.id)
+
+ tf = tempfile.TemporaryFile()
+ g.layout(prog="dot")
+ g.draw(path=tf, format="png")
+ tf.seek(0)
+
+ return HttpResponse(tf.read(), content_type="image/png")
diff --git a/xos/xos/urls.py b/xos/xos/urls.py
index 7f7f5bc..0adf32d 100644
--- a/xos/xos/urls.py
+++ b/xos/xos/urls.py
@@ -7,7 +7,7 @@
from xosapi import *
from core.views.legacyapi import LegacyXMLRPC
-from core.views.services import ServiceGridView
+from core.views.services import ServiceGridView, ServiceGraphView
#from core.views.analytics import AnalyticsAjaxView
from core.models import *
from rest_framework import generics
@@ -28,6 +28,7 @@
url(r'^stats', 'core.views.stats.Stats', name='stats'),
url(r'^observer', 'core.views.observer.Observer', name='observer'),
url(r'^serviceGrid', ServiceGridView.as_view(), name='serviceGrid'),
+ url(r'^serviceGraph.png', ServiceGraphView.as_view(), name='serviceGraph'),
url(r'^hpcConfig', 'core.views.hpc_config.HpcConfig', name='hpcConfig'),
url(r'^docs/', include('rest_framework_swagger.urls')),