1 from django.template import RequestContext
2 from django.shortcuts import render_to_response
4 from unfold.loginrequired import LoginRequiredAutoLogoutView
6 from unfold.page import Page
7 from manifold.core.query import Query, AnalyzedQuery
9 from ui.topmenu import topmenu_items, the_user
11 from plugins.raw import Raw
12 from plugins.stack import Stack
13 from plugins.tabs import Tabs
14 from plugins.querytable import QueryTable
15 from plugins.querygrid import QueryGrid
16 from plugins.queryupdater import QueryUpdater
17 from plugins.googlemap import GoogleMap
18 from plugins.senslabmap import SensLabMap
19 from plugins.scheduler import Scheduler
20 from plugins.querycode import QueryCode
22 # stay away from query editor for now as it seems to make things go very slow
23 # see https://lists.myslice.info/pipermail/devel-myslice/2013-December/000221.html
24 #from plugins.query_editor import QueryEditor
25 from plugins.active_filters import ActiveFilters
26 from plugins.quickfilter import QuickFilter
27 from plugins.messages import Messages
28 from plugins.slicestat import SliceStat
30 from myslice.config import Config
32 tmp_default_slice='ple.upmc.myslicedemo'
34 # temporary : turn off the users part to speed things up
47 class SliceView (LoginRequiredAutoLogoutView):
49 def get (self,request, slicename=tmp_default_slice):
52 page.add_css_files ('css/slice-view.css')
53 page.add_js_files ( [ "js/common.functions.js" ] )
54 page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
55 page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
56 page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
58 page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
59 page.expose_js_metadata()
61 metadata = page.get_metadata()
62 resource_md = metadata.details_by_object('resource')
63 resource_fields = [column['name'] for column in resource_md['column']]
65 user_md = metadata.details_by_object('user')
66 user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
68 # TODO The query to run is embedded in the URL
69 main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
72 'resource.hrn', 'resource.urn', 'resource.hostname', 'resource.type',
73 'resource.network_hrn',
76 #'application.measurement_point.counter'
78 # for internal use in the querytable plugin;
79 # needs to be a unique column present for each returned record
80 #main_query_key = 'hrn'
82 query_resource_all = Query.get('resource').select(resource_fields)
84 query_user_all = Query.get('user').select(user_fields)
86 aq = AnalyzedQuery(main_query, metadata=metadata)
87 page.enqueue_query(main_query, analyzed_query=aq)
88 page.enqueue_query(query_resource_all)
90 page.enqueue_query(query_user_all)
92 # ... and for the relations
93 # XXX Let's hardcode resources for now
94 sq_resource = aq.subquery('resource')
95 sq_user = aq.subquery('user')
96 sq_lease = aq.subquery('lease')
97 sq_measurement = aq.subquery('measurement')
100 # Prepare the display according to all metadata
101 # (some parts will be pending, others can be triggered by users).
103 # For example slice measurements will not be requested by default...
105 # Create the base layout (Stack)...
108 title="Slice %s"%slicename,
112 # ... responsible for the slice properties...
119 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
122 # --------------------------------------------------------------------------
123 # QueryUpdater (Pending Operations)
125 main_stack.insert(QueryUpdater(
127 title = 'Pending operations',
130 # start turned off, it will open up itself when stuff comes in
133 outline_complete = True,
136 # --------------------------------------------------------------------------
139 # turn off for now -- see above
140 # filter_query_editor = QueryEditor(
142 # query = sq_resource,
143 # query_all = query_resource_all,
144 # title = "Select Columns",
145 # domid = 'select-columns',
147 filter_active_filters = ActiveFilters(
150 title = "Active Filters",
152 filters_area = Stack(
154 title = 'Filter Resources',
156 sons = [# filter_query_editor,
157 filter_active_filters],
159 toggled = 'persistent',
160 outline_complete = True,
162 main_stack.insert (filters_area)
164 # --------------------------------------------------------------------------
166 # the resources part is made of a Tabs (Geographic, List),
168 resources_as_gmap = GoogleMap(
170 title = 'Geographic view',
171 domid = 'resources-map',
172 # tab's sons preferably turn this off
175 query_all = query_resource_all,
176 googlemap_api_key = Config().googlemap_api_key(),
184 resources_as_3dmap = SensLabMap(
187 domid = 'senslabmap',
189 query_all = query_resource_all,
192 resources_as_list = QueryTable(
194 domid = 'resources-list',
196 # this is the query at the core of the slice list
198 query_all = query_resource_all,
199 # safer to use 'hrn' as the internal unique key for this plugin
200 #id_key = main_query_key,
202 datatables_options = {
203 'iDisplayLength': 25,
204 'bLengthChange' : True,
210 resources_as_grid = QueryGrid(
212 domid = 'resources-grid',
214 # this is the query at the core of the slice list
216 query_all = query_resource_all,
217 # safer to use 'hrn' as the internal unique key for this plugin
218 id_key = main_query_key,
223 resources_as_scheduler = Scheduler(
228 query_all_resources = query_resource_all,
229 query_lease = sq_lease,
232 # with the new 'Filter' stuff on top, no need for anything but the querytable
233 resources_as_list_area = resources_as_list
238 resources_as_scheduler,
239 resources_as_list_area,
240 ] if do_query_leases else [
243 resources_as_list_area,
246 resources_sons.append(resources_as_grid)
248 print 40*'+-',"resources_sons has",len(resources_sons),"son"
250 resources_area = Tabs ( page=page,
254 outline_complete=True,
255 sons= resources_sons,
256 active_domid = 'resources-map',
257 persistent_active=True,
259 main_stack.insert (resources_area)
261 # --------------------------------------------------------------------------
268 outline_complete = True,
271 active_domid = 'users-list',
273 main_stack.insert(tab_users)
275 tab_users.insert(QueryTable(
277 title = 'Users List',
278 domid = 'users-list',
279 # tab's sons preferably turn this off
281 # this is the query at the core of the slice list
283 query_all = query_user_all,
285 datatables_options = {
286 'iDisplayLength' : 25,
287 'bLengthChange' : True,
293 # --------------------------------------------------------------------------
295 measurements_stats_cpu = SliceStat(
297 domid = 'resources-stats-cpu',
302 slicename = slicename,
306 measurements_stats_mem = SliceStat(
307 title = "Memory Usage",
308 domid = 'resources-stats-mem',
313 slicename = slicename,
317 measurements_stats_asb = SliceStat(
318 title = "Traffic Sent",
319 domid = 'resources-stats-asb',
324 slicename = slicename,
328 measurements_stats_arb = SliceStat(
329 title = "Traffic Received",
330 domid = 'resources-stats-arb',
335 slicename = slicename,
339 tab_measurements = Tabs ( page=page,
340 domid="measurements",
343 title="Measurements",
344 outline_complete=True,
345 sons=[ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
346 active_domid = 'measurements_stats_cpu',
348 main_stack.insert (tab_measurements)
350 # tab_measurements = Tabs (
352 # active_domid = 'measurements-list',
353 # outline_complete = True,
355 # title = 'Measurements',
356 # domid = 'measurements',
358 # main_stack.insert(tab_measurements)
360 # tab_measurements.insert(QueryTable(
362 # title = 'Measurements',
363 # domid = 'measurements-list',
364 # # tab's sons preferably turn this off
366 # # this is the query at the core of the slice list
367 # query = sq_measurement,
368 # # do NOT set checkboxes to False
369 # # this table being otherwise empty, it just does not fly with dataTables
371 # datatables_options = {
372 # 'iDisplayLength' : 25,
373 # 'bLengthChange' : True,
374 # 'bAutoWidth' : True,
378 # # --------------------------------------------------------------------------
379 # # MESSAGES (we use transient=False for now)
381 main_stack.insert(Messages(
383 title = "Runtime messages for slice %s"%slicename,
386 # plain messages are probably less nice for production but more reliable for development for now
388 # these make sense only in non-transient mode..
390 toggled = 'persistent',
391 outline_complete = True,
395 # variables that will get passed to the view-unfold1.html template
398 # define 'unfold_main' to the template engine - the main contents
399 template_env [ 'unfold_main' ] = main_stack.render(request)
401 # more general variables expected in the template
402 template_env [ 'title' ] = '%(slicename)s'%locals()
403 # the menu items on the top
404 template_env [ 'topmenu_items' ] = topmenu_items('Slice', request)
405 # so we can sho who is logged
406 template_env [ 'username' ] = the_user (request)
408 # don't forget to run the requests
409 page.expose_queries ()
411 # xxx create another plugin with the same query and a different layout (with_datatables)
412 # show that it worls as expected, one single api call to backend and 2 refreshed views
414 # the prelude object in page contains a summary of the requirements() for all plugins
415 # define {js,css}_{files,chunks}
416 prelude_env = page.prelude_env()
417 template_env.update(prelude_env)
418 result=render_to_response ('view-unfold1.html',template_env,
419 context_instance=RequestContext(request))