Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 1 | from django.http import HttpResponse |
| 2 | from django.views.generic import TemplateView, View |
| 3 | from django import template |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 4 | from core.models import * |
Matteo Scandolo | f05cf36 | 2016-05-09 10:31:21 -0700 | [diff] [blame] | 5 | from core.dashboard.views import DashboardDynamicView |
| 6 | from xos.config import XOS_DIR |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 7 | import json |
| 8 | import os |
| 9 | import time |
Scott Baker | 9a42e6f | 2015-04-27 16:00:27 -0700 | [diff] [blame] | 10 | import tempfile |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 11 | |
Matteo Scandolo | f05cf36 | 2016-05-09 10:31:21 -0700 | [diff] [blame] | 12 | |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 13 | class ServiceGridView(TemplateView): |
Matteo Scandolo | f05cf36 | 2016-05-09 10:31:21 -0700 | [diff] [blame] | 14 | |
| 15 | head_template = r"""{% extends "admin/dashboard/dashboard_base.html" %} |
| 16 | {% load admin_static %} |
| 17 | {% block content %} |
| 18 | """ |
| 19 | |
| 20 | tail_template = r"{% endblock %}" |
| 21 | |
| 22 | def readTemplate(self, fn): |
| 23 | TEMPLATE_DIRS = [XOS_DIR + "/templates/admin/dashboard/", |
| 24 | XOS_DIR + "/core/xoslib/dashboards/"] |
| 25 | |
| 26 | for template_dir in TEMPLATE_DIRS: |
| 27 | pathname = os.path.join(template_dir, fn) + ".html" |
| 28 | if os.path.exists(pathname): |
| 29 | break |
| 30 | else: |
| 31 | return "failed to find %s in %s" % (fn, TEMPLATE_DIRS) |
| 32 | |
| 33 | template = open(pathname, "r").read() |
| 34 | return template |
| 35 | |
| 36 | def get(self, request, name="root", *args, **kwargs): |
| 37 | |
Matteo Scandolo | f05cf36 | 2016-05-09 10:31:21 -0700 | [diff] [blame] | 38 | dash = DashboardView.objects.get(name="Services Grid") |
| 39 | |
| 40 | gridTemplate = self.readTemplate(dash.url[9:]) |
| 41 | |
| 42 | t = template.Template(self.head_template + gridTemplate + self.tail_template) |
| 43 | |
| 44 | response_kwargs = {} |
| 45 | response_kwargs.setdefault('content_type', self.content_type) |
| 46 | |
| 47 | return self.response_class( |
| 48 | request=request, |
| 49 | template=t, |
| 50 | **response_kwargs) |
| 51 | |
| 52 | |
| 53 | class ServiceGridViewPy(TemplateView): |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 54 | head_template = r"""{% extends "admin/dashboard/dashboard_base.html" %} |
| 55 | {% load admin_static %} |
| 56 | {% block content %} |
| 57 | """ |
| 58 | |
| 59 | tail_template = r"{% endblock %}" |
| 60 | |
| 61 | def get(self, request, name="root", *args, **kwargs): |
| 62 | head_template = self.head_template |
| 63 | tail_template = self.tail_template |
| 64 | |
Scott Baker | b350050 | 2015-06-10 15:47:30 -0700 | [diff] [blame] | 65 | html = '<table class="service-grid"><tr>' |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 66 | |
Scott Baker | 9a42e6f | 2015-04-27 16:00:27 -0700 | [diff] [blame] | 67 | icons=[] |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 68 | for service in Service.objects.all(): |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 69 | view_url = service.view_url |
| 70 | if (not view_url): |
| 71 | view_url = "/admin/core/service/$id$/" |
| 72 | view_url = view_url.replace("$id$", str(service.id)) |
| 73 | |
| 74 | image_url = service.icon_url |
| 75 | if (not image_url): |
| 76 | image_url = "/static/primarycons_blue/gear_2.png" |
| 77 | |
Scott Baker | 9a42e6f | 2015-04-27 16:00:27 -0700 | [diff] [blame] | 78 | icons.append( {"name": service.name, "view_url": view_url, "image_url": image_url} ) |
| 79 | |
| 80 | icons.append( {"name": "Tenancy Graph", "view_url": "/serviceGraph.png", "image_url": "/static/primarycons_blue/service_graph.png", "horiz_rule": True} ) |
| 81 | icons.append( {"name": "Add Service", "view_url": "/admin/core/service/add/", "image_url": "/static/primarycons_blue/plus.png"} ) |
| 82 | |
| 83 | i=0 |
| 84 | for icon in icons: |
| 85 | if icon.get("horiz_rule", False): |
| 86 | html = html + "</tr><tr><td colspan=4><hr></td></tr><tr>" |
| 87 | i=0 |
| 88 | |
| 89 | service_name = icon["name"] |
| 90 | view_url = icon["view_url"] |
| 91 | image_url = icon["image_url"] |
| 92 | |
| 93 | if (i%4) == 0: |
| 94 | html = html + '</tr><tr>' |
| 95 | |
Scott Baker | b350050 | 2015-06-10 15:47:30 -0700 | [diff] [blame] | 96 | html = html + '<td width=96 height=128 valign=top align=center><a class="service-grid-icon" href="%s"><img src="%s" height=64 width=64></img></a>' % (view_url, image_url) |
| 97 | html = html + '<p><a class="service-grid-icon-link" href="%s">%s</a></p></td>' % (view_url, service_name) |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 98 | i=i+1 |
| 99 | |
| 100 | html = html + '</tr></table>' |
| 101 | |
| 102 | t = template.Template(head_template + html + self.tail_template) |
| 103 | |
| 104 | response_kwargs = {} |
| 105 | response_kwargs.setdefault('content_type', self.content_type) |
| 106 | return self.response_class( |
| 107 | request = request, |
| 108 | template = t, |
| 109 | **response_kwargs) |
| 110 | |
Scott Baker | 9a42e6f | 2015-04-27 16:00:27 -0700 | [diff] [blame] | 111 | class ServiceGraphViewOld(TemplateView): |
| 112 | # this attempt used networkx |
| 113 | # yum -y install python-matplotlib python-networkx |
| 114 | # pip-python install -upgrade networkx |
| 115 | # pip-python install graphviz pygraphviz |
Scott Baker | f812070 | 2015-02-26 17:06:46 -0800 | [diff] [blame] | 116 | |
Scott Baker | 9a42e6f | 2015-04-27 16:00:27 -0700 | [diff] [blame] | 117 | def get(self, request, name="root", *args, **kwargs): |
| 118 | import networkx as nx |
| 119 | import matplotlib as mpl |
| 120 | mpl.use("Agg") |
| 121 | import matplotlib.pyplot as plt |
| 122 | import nxedges |
| 123 | |
| 124 | plt.figure(figsize=(10,8)) |
| 125 | |
| 126 | g = nx.DiGraph() |
| 127 | |
| 128 | labels = {} |
| 129 | for service in Service.objects.all(): |
| 130 | g.add_node(service.id) |
| 131 | if len(service.name)>8: |
| 132 | labels[service.id] = service.name[:8] + "\n" + service.name[8:] |
| 133 | else: |
| 134 | labels[service.id] = service.name |
| 135 | |
| 136 | for tenant in CoarseTenant.objects.all(): |
| 137 | if (not tenant.provider_service) or (not tenant.subscriber_service): |
| 138 | continue |
| 139 | g.add_edge(tenant.subscriber_service.id, tenant.provider_service.id) |
| 140 | |
| 141 | pos = nx.graphviz_layout(g) |
| 142 | nxedges.xos_draw_networkx_edges(g,pos,arrow_len=30) |
| 143 | nx.draw_networkx_nodes(g,pos,node_size=5000) |
| 144 | nx.draw_networkx_labels(g,pos,labels,font_size=12) |
| 145 | #plt.axis('off') |
| 146 | plt.savefig("/tmp/foo.png") |
| 147 | |
| 148 | return HttpResponse(open("/tmp/foo.png","r").read(), content_type="image/png") |
| 149 | |
| 150 | class ServiceGraphView(TemplateView): |
| 151 | # this attempt just uses graphviz directly |
| 152 | # yum -y install graphviz |
| 153 | # pip-python install pygraphviz |
| 154 | |
| 155 | def get(self, request, name="root", *args, **kwargs): |
| 156 | import pygraphviz as pgv |
| 157 | |
| 158 | g = pgv.AGraph(directed=True) |
| 159 | g.graph_attr.update(size="8,4!") |
| 160 | g.graph_attr.update(dpi="100") |
| 161 | #g.graph_attr.update(nodesep="2.5") |
| 162 | g.graph_attr.update(overlap="false") |
| 163 | g.graph_attr.update(graphdir="TB") |
| 164 | |
| 165 | for service in Service.objects.all(): |
Scott Baker | c6f0eb8 | 2015-10-21 16:04:46 -0700 | [diff] [blame] | 166 | provided_tenants = Tenant.objects.filter(provider_service=service, subscriber_service__isnull=False) |
| 167 | subscribed_tenants = Tenant.objects.filter(subscriber_service=service, provider_service__isnull=False) |
Scott Baker | 9a42e6f | 2015-04-27 16:00:27 -0700 | [diff] [blame] | 168 | if not (provided_tenants or subscribed_tenants): |
| 169 | # nodes with no edges aren't interesting |
| 170 | continue |
| 171 | g.add_node(service.id, label=service.name) |
| 172 | |
Scott Baker | c6f0eb8 | 2015-10-21 16:04:46 -0700 | [diff] [blame] | 173 | for tenant in Tenant.objects.all(): |
Scott Baker | 9a42e6f | 2015-04-27 16:00:27 -0700 | [diff] [blame] | 174 | if (not tenant.provider_service) or (not tenant.subscriber_service): |
| 175 | continue |
| 176 | g.add_edge(tenant.subscriber_service.id, tenant.provider_service.id) |
| 177 | |
| 178 | tf = tempfile.TemporaryFile() |
| 179 | g.layout(prog="dot") |
| 180 | g.draw(path=tf, format="png") |
| 181 | tf.seek(0) |
| 182 | |
| 183 | return HttpResponse(tf.read(), content_type="image/png") |