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.queryupdater import QueryUpdater
16 from plugins.googlemap import GoogleMap
17 from plugins.senslabmap import SensLabMap
18 from plugins.scheduler import Scheduler
19 from plugins.querycode import QueryCode
20 # stay away from query editor for now as it seems to make things go very slow
21 # see https://lists.myslice.info/pipermail/devel-myslice/2013-December/000221.html
22 #from plugins.query_editor import QueryEditor
23 from plugins.active_filters import ActiveFilters
24 from plugins.quickfilter import QuickFilter
25 from plugins.messages import Messages
26 from plugins.slicestat import SliceStat
28 from myslice.config import Config
30 tmp_default_slice='ple.upmc.myslicedemo'
32 # temporary : turn off the users part to speed things up
42 class SliceView (LoginRequiredAutoLogoutView):
44 def get (self,request, slicename=tmp_default_slice):
47 page.add_css_files ('css/slice-view.css')
48 page.add_js_files ( [ "js/common.functions.js" ] )
49 page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
50 page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
51 page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
53 page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
54 page.expose_js_metadata()
56 metadata = page.get_metadata()
57 resource_md = metadata.details_by_object('resource')
58 resource_fields = [column['name'] for column in resource_md['column']]
60 user_md = metadata.details_by_object('user')
61 user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
63 # TODO The query to run is embedded in the URL
64 main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
67 'resource.hrn', 'resource.hostname', 'resource.type',
68 'resource.network_hrn',
71 #'application.measurement_point.counter'
73 # for internal use in the querytable plugin;
74 # needs to be a unique column present for each returned record
75 main_query_key = 'hrn'
77 query_resource_all = Query.get('resource').select(resource_fields)
79 query_user_all = Query.get('user').select(user_fields)
81 aq = AnalyzedQuery(main_query, metadata=metadata)
82 page.enqueue_query(main_query, analyzed_query=aq)
83 page.enqueue_query(query_resource_all)
85 page.enqueue_query(query_user_all)
87 # ... and for the relations
88 # XXX Let's hardcode resources for now
89 sq_resource = aq.subquery('resource')
90 sq_user = aq.subquery('user')
91 sq_lease = aq.subquery('lease')
92 sq_measurement = aq.subquery('measurement')
95 # Prepare the display according to all metadata
96 # (some parts will be pending, others can be triggered by users).
98 # For example slice measurements will not be requested by default...
100 # Create the base layout (Stack)...
103 title="Slice %s"%slicename,
107 # ... responsible for the slice properties...
114 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
117 # --------------------------------------------------------------------------
118 # QueryUpdater (Pending Operations)
120 main_stack.insert(QueryUpdater(
122 title = 'Pending operations',
125 # start turned off, it will open up itself when stuff comes in
128 outline_complete = True,
131 # --------------------------------------------------------------------------
134 # see above the warning about performance issues with this plugin
135 # filter_query_editor = QueryEditor(
137 # query = sq_resource,
138 # query_all = query_resource_all,
139 # title = "Select Columns",
140 # domid = 'select-columns',
142 filter_active_filters = ActiveFilters(
145 title = "Active Filters",
147 filters_area = Stack(
149 title = 'Filter Resources',
152 # filter_query_editor,
153 filter_active_filters],
155 toggled = 'persistent',
156 outline_complete = True,
158 main_stack.insert (filters_area)
160 # --------------------------------------------------------------------------
162 # the resources part is made of a Tabs (Geographic, List),
164 resources_as_gmap = GoogleMap(
166 title = 'Geographic view',
167 domid = 'resources-map',
168 # tab's sons preferably turn this off
171 query_all = query_resource_all,
172 googlemap_api_key = Config().googlemap_api_key(),
180 resources_as_3dmap = SensLabMap(
183 domid = 'senslabmap',
185 query_all = query_resource_all,
188 resources_as_list = QueryTable(
190 domid = 'resources-list',
192 # this is the query at the core of the slice list
194 query_all = query_resource_all,
195 # safer to use 'hrn' as the internal unique key for this plugin
196 id_key = main_query_key,
198 datatables_options = {
199 'iDisplayLength': 25,
200 'bLengthChange' : True,
206 resources_as_scheduler = Scheduler(
211 query_all_resources = query_resource_all,
212 query_lease = sq_lease,
215 # with the new 'Filter' stuff on top, no need for anything but the querytable
216 resources_as_list_area = resources_as_list
221 resources_as_scheduler,
222 resources_as_list_area,
223 ] if do_query_leases else [
226 resources_as_list_area,
229 resources_area = Tabs ( page=page,
233 outline_complete=True,
234 sons= resources_sons,
235 active_domid = 'resources-map',
236 persistent_active=True,
238 main_stack.insert (resources_area)
240 # --------------------------------------------------------------------------
247 outline_complete = True,
250 active_domid = 'users-list',
252 main_stack.insert(tab_users)
254 tab_users.insert(QueryTable(
256 title = 'Users List',
257 domid = 'users-list',
258 # tab's sons preferably turn this off
260 # this is the query at the core of the slice list
262 query_all = query_user_all,
264 datatables_options = {
265 'iDisplayLength' : 25,
266 'bLengthChange' : True,
272 # --------------------------------------------------------------------------
274 measurements_stats_cpu = SliceStat(
276 domid = 'resources-stats-cpu',
281 slicename = slicename,
285 measurements_stats_mem = SliceStat(
286 title = "Memory Usage",
287 domid = 'resources-stats-mem',
292 slicename = slicename,
296 measurements_stats_asb = SliceStat(
297 title = "Traffic Sent",
298 domid = 'resources-stats-asb',
303 slicename = slicename,
307 measurements_stats_arb = SliceStat(
308 title = "Traffic Received",
309 domid = 'resources-stats-arb',
314 slicename = slicename,
318 tab_measurements = Tabs ( page=page,
319 domid="measurements",
322 title="Measurements",
323 outline_complete=True,
324 sons=[ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
325 active_domid = 'measurements_stats_cpu',
327 main_stack.insert (tab_measurements)
329 # tab_measurements = Tabs (
331 # active_domid = 'measurements-list',
332 # outline_complete = True,
334 # title = 'Measurements',
335 # domid = 'measurements',
337 # main_stack.insert(tab_measurements)
339 # tab_measurements.insert(QueryTable(
341 # title = 'Measurements',
342 # domid = 'measurements-list',
343 # # tab's sons preferably turn this off
345 # # this is the query at the core of the slice list
346 # query = sq_measurement,
347 # # do NOT set checkboxes to False
348 # # this table being otherwise empty, it just does not fly with dataTables
350 # datatables_options = {
351 # 'iDisplayLength' : 25,
352 # 'bLengthChange' : True,
353 # 'bAutoWidth' : True,
357 # # --------------------------------------------------------------------------
358 # # MESSAGES (we use transient=False for now)
360 main_stack.insert(Messages(
362 title = "Runtime messages for slice %s"%slicename,
365 # plain messages are probably less nice for production but more reliable for development for now
367 # these make sense only in non-transient mode..
369 toggled = 'persistent',
370 outline_complete = True,
374 # variables that will get passed to the view-unfold1.html template
377 # define 'unfold_main' to the template engine - the main contents
378 template_env [ 'unfold_main' ] = main_stack.render(request)
380 # more general variables expected in the template
381 template_env [ 'title' ] = '%(slicename)s'%locals()
382 # the menu items on the top
383 template_env [ 'topmenu_items' ] = topmenu_items('Slice', request)
384 # so we can sho who is logged
385 template_env [ 'username' ] = the_user (request)
387 # don't forget to run the requests
388 page.expose_queries ()
390 # xxx create another plugin with the same query and a different layout (with_datatables)
391 # show that it worls as expected, one single api call to backend and 2 refreshed views
393 # the prelude object in page contains a summary of the requirements() for all plugins
394 # define {js,css}_{files,chunks}
395 prelude_env = page.prelude_env()
396 template_env.update(prelude_env)
397 result=render_to_response ('view-unfold1.html',template_env,
398 context_instance=RequestContext(request))