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',
73 'resource.hostname', 'resource.type',
74 'resource.network_hrn',
77 #'application.measurement_point.counter'
79 # for internal use in the querytable plugin;
80 # needs to be a unique column present for each returned record
81 main_query_init_key = 'hostname'
83 query_resource_all = Query.get('resource').select(resource_fields)
85 query_user_all = Query.get('user').select(user_fields)
87 aq = AnalyzedQuery(main_query, metadata=metadata)
88 page.enqueue_query(main_query, analyzed_query=aq)
89 page.enqueue_query(query_resource_all)
91 page.enqueue_query(query_user_all)
93 # ... and for the relations
94 # XXX Let's hardcode resources for now
95 sq_resource = aq.subquery('resource')
96 sq_user = aq.subquery('user')
97 sq_lease = aq.subquery('lease')
98 sq_measurement = aq.subquery('measurement')
101 # Prepare the display according to all metadata
102 # (some parts will be pending, others can be triggered by users).
104 # For example slice measurements will not be requested by default...
106 # Create the base layout (Stack)...
109 title="Slice %s"%slicename,
113 # ... responsible for the slice properties...
120 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
123 # --------------------------------------------------------------------------
124 # QueryUpdater (Pending Operations)
126 main_stack.insert(QueryUpdater(
128 title = 'Pending operations',
131 # start turned off, it will open up itself when stuff comes in
134 outline_complete = True,
137 # --------------------------------------------------------------------------
140 # turn off for now -- see above
141 # filter_query_editor = QueryEditor(
143 # query = sq_resource,
144 # query_all = query_resource_all,
145 # title = "Select Columns",
146 # domid = 'select-columns',
148 filter_active_filters = ActiveFilters(
151 title = "Active Filters",
153 filters_area = Stack(
155 title = 'Filter Resources',
157 sons = [# filter_query_editor,
158 filter_active_filters],
160 toggled = 'persistent',
161 outline_complete = True,
163 main_stack.insert (filters_area)
165 # --------------------------------------------------------------------------
167 # the resources part is made of a Tabs (Geographic, List),
169 resources_as_gmap = GoogleMap(
171 title = 'Geographic view',
172 domid = 'resources-map',
173 # tab's sons preferably turn this off
176 query_all = query_resource_all,
177 # this key is the one issued by google
178 googlemap_api_key = Config().googlemap_api_key(),
179 # the key to use at init-time
180 init_key = main_query_init_key,
188 resources_as_3dmap = SensLabMap(
191 domid = 'senslabmap',
193 query_all = query_resource_all,
196 resources_as_list = QueryTable(
198 domid = 'resources-list',
200 # this is the query at the core of the slice list
202 query_all = query_resource_all,
203 # use 'hrn' as the internal unique key for this plugin
204 init_key = main_query_init_key,
206 datatables_options = {
207 'iDisplayLength': 25,
208 'bLengthChange' : True,
214 resources_as_grid = QueryGrid(
216 domid = 'resources-grid',
218 # this is the query at the core of the slice list
220 query_all = query_resource_all,
221 # use 'hrn' as the internal unique key for this plugin
222 # xxx todo on querygrid as well
223 # init_key = main_query_init_key,
228 resources_as_scheduler = Scheduler(
233 query_all_resources = query_resource_all,
234 query_lease = sq_lease,
237 # with the new 'Filter' stuff on top, no need for anything but the querytable
238 resources_as_list_area = resources_as_list
243 resources_as_scheduler,
244 resources_as_list_area,
245 ] if do_query_leases else [
248 resources_as_list_area,
251 resources_sons.append(resources_as_grid)
253 resources_area = Tabs ( page=page,
257 outline_complete=True,
258 sons= resources_sons,
259 active_domid = 'resources-map',
260 persistent_active=True,
262 main_stack.insert (resources_area)
264 # --------------------------------------------------------------------------
271 outline_complete = True,
274 active_domid = 'users-list',
276 main_stack.insert(tab_users)
278 tab_users.insert(QueryTable(
280 title = 'Users List',
281 domid = 'users-list',
282 # tab's sons preferably turn this off
284 # this is the query at the core of the slice list
286 query_all = query_user_all,
288 datatables_options = {
289 'iDisplayLength' : 25,
290 'bLengthChange' : True,
296 # --------------------------------------------------------------------------
298 measurements_stats_cpu = SliceStat(
300 domid = 'resources-stats-cpu',
305 slicename = slicename,
309 measurements_stats_mem = SliceStat(
310 title = "Memory Usage",
311 domid = 'resources-stats-mem',
316 slicename = slicename,
320 measurements_stats_asb = SliceStat(
321 title = "Traffic Sent",
322 domid = 'resources-stats-asb',
327 slicename = slicename,
331 measurements_stats_arb = SliceStat(
332 title = "Traffic Received",
333 domid = 'resources-stats-arb',
338 slicename = slicename,
342 tab_measurements = Tabs ( page=page,
343 domid="measurements",
346 title="Measurements",
347 outline_complete=True,
348 sons=[ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
349 active_domid = 'measurements_stats_cpu',
351 main_stack.insert (tab_measurements)
353 # tab_measurements = Tabs (
355 # active_domid = 'measurements-list',
356 # outline_complete = True,
358 # title = 'Measurements',
359 # domid = 'measurements',
361 # main_stack.insert(tab_measurements)
363 # tab_measurements.insert(QueryTable(
365 # title = 'Measurements',
366 # domid = 'measurements-list',
367 # # tab's sons preferably turn this off
369 # # this is the query at the core of the slice list
370 # query = sq_measurement,
371 # # do NOT set checkboxes to False
372 # # this table being otherwise empty, it just does not fly with dataTables
374 # datatables_options = {
375 # 'iDisplayLength' : 25,
376 # 'bLengthChange' : True,
377 # 'bAutoWidth' : True,
381 # # --------------------------------------------------------------------------
382 # # MESSAGES (we use transient=False for now)
384 main_stack.insert(Messages(
386 title = "Runtime messages for slice %s"%slicename,
389 # plain messages are probably less nice for production but more reliable for development for now
391 # these make sense only in non-transient mode..
393 toggled = 'persistent',
394 outline_complete = True,
398 # variables that will get passed to the view-unfold1.html template
401 # define 'unfold_main' to the template engine - the main contents
402 template_env [ 'unfold_main' ] = main_stack.render(request)
404 # more general variables expected in the template
405 template_env [ 'title' ] = '%(slicename)s'%locals()
406 # the menu items on the top
407 template_env [ 'topmenu_items' ] = topmenu_items('Slice', request)
408 # so we can sho who is logged
409 template_env [ 'username' ] = the_user (request)
411 # don't forget to run the requests
412 page.expose_queries ()
414 # xxx create another plugin with the same query and a different layout (with_datatables)
415 # show that it worls as expected, one single api call to backend and 2 refreshed views
417 # the prelude object in page contains a summary of the requirements() for all plugins
418 # define {js,css}_{files,chunks}
419 prelude_env = page.prelude_env()
420 template_env.update(prelude_env)
421 result=render_to_response ('view-unfold1.html',template_env,
422 context_instance=RequestContext(request))