disable query editor for good until perf. issues are solved
[myslice.git] / portal / sliceview.py
1 from django.template                 import RequestContext
2 from django.shortcuts                import render_to_response
3
4 from unfold.loginrequired            import LoginRequiredAutoLogoutView
5
6 from unfold.page                     import Page
7 from manifold.core.query             import Query, AnalyzedQuery
8
9 from ui.topmenu                      import topmenu_items, the_user
10
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 # Thierry
21 # stay away from query editor for now as it seems to make things go very slow
22 # see https://lists.myslice.info/pipermail/devel-myslice/2013-December/000221.html 
23 #from plugins.query_editor            import QueryEditor
24 from plugins.active_filters          import ActiveFilters
25 from plugins.quickfilter             import QuickFilter
26 from plugins.messages                import Messages
27 from plugins.slicestat               import SliceStat
28
29 from myslice.config                  import Config
30
31 tmp_default_slice='ple.upmc.myslicedemo'
32
33 # temporary : turn off the users part to speed things up
34 #do_query_users=True
35 do_query_users=False
36
37 #do_query_leases=True
38 do_query_leases=False
39
40 insert_messages=False
41 #insert_messages=True
42
43 class SliceView (LoginRequiredAutoLogoutView):
44
45     def get (self,request, slicename=tmp_default_slice):
46     
47         page = Page(request)
48         page.add_css_files ('css/slice-view.css')
49         page.add_js_files  ( [ "js/common.functions.js" ] )
50         page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
51         page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
52         page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
53         config=Config()
54         page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
55         page.expose_js_metadata()
56     
57         metadata = page.get_metadata()
58         resource_md = metadata.details_by_object('resource')
59         resource_fields = [column['name'] for column in resource_md['column']]
60     
61         user_md = metadata.details_by_object('user')
62         user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
63     
64         # TODO The query to run is embedded in the URL
65         main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
66         main_query.select(
67                 'slice_hrn',
68                 'resource.hrn', 'resource.hostname', 'resource.type', 
69                 'resource.network_hrn',
70                 'lease.urn',
71                 'user.user_hrn',
72                 #'application.measurement_point.counter'
73         )
74         # for internal use in the querytable plugin;
75         # needs to be a unique column present for each returned record
76         main_query_key = 'hrn'
77     
78         query_resource_all = Query.get('resource').select(resource_fields)
79         if do_query_users:
80             query_user_all = Query.get('user').select(user_fields)
81     
82         aq = AnalyzedQuery(main_query, metadata=metadata)
83         page.enqueue_query(main_query, analyzed_query=aq)
84         page.enqueue_query(query_resource_all)
85         if do_query_users:
86             page.enqueue_query(query_user_all)
87     
88         # ... and for the relations
89         # XXX Let's hardcode resources for now
90         sq_resource    = aq.subquery('resource')
91         sq_user        = aq.subquery('user')
92         sq_lease       = aq.subquery('lease')
93         sq_measurement = aq.subquery('measurement')
94         
95     
96         # Prepare the display according to all metadata
97         # (some parts will be pending, others can be triggered by users).
98         # 
99         # For example slice measurements will not be requested by default...
100     
101         # Create the base layout (Stack)...
102         main_stack = Stack (
103             page=page,
104             title="Slice %s"%slicename,
105             sons=[],
106         )
107     
108         # ... responsible for the slice properties...
109     
110         # a nice header
111         main_stack.insert (
112             Raw (page=page,
113                  togglable=False, 
114                  toggled=True,
115                  html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
116         )
117     
118         # --------------------------------------------------------------------------
119         # QueryUpdater (Pending Operations)
120
121         main_stack.insert(QueryUpdater(
122             page                = page,
123             title               = 'Pending operations',
124             query               = main_query,
125             togglable           = True,
126             # start turned off, it will open up itself when stuff comes in
127             toggled             = False, 
128             domid               = 'pending',
129             outline_complete    = True,
130         ))
131
132         # --------------------------------------------------------------------------
133         # Filter Resources
134        
135 # turn off for now -- see above
136 #        filter_query_editor = QueryEditor(
137 #            page  = page,
138 #            query = sq_resource, 
139 #            query_all = query_resource_all,
140 #            title = "Select Columns",
141 #            domid = 'select-columns',
142 #            )
143         filter_active_filters = ActiveFilters(
144             page  = page,
145             query = sq_resource,
146             title = "Active Filters",
147             )
148         filters_area = Stack(
149             page                = page,
150             title               = 'Filter Resources',
151             domid               = 'filters',
152             sons                = [# filter_query_editor, 
153                                    filter_active_filters],
154             togglable           = True,
155             toggled             = 'persistent',
156             outline_complete    = True, 
157         )
158         main_stack.insert (filters_area)
159
160         # --------------------------------------------------------------------------
161         # RESOURCES
162         # the resources part is made of a Tabs (Geographic, List), 
163
164         resources_as_gmap = GoogleMap(
165             page       = page,
166             title      = 'Geographic view',
167             domid      = 'resources-map',
168             # tab's sons preferably turn this off
169             togglable  = False,
170             query      = sq_resource,
171             query_all  = query_resource_all,
172             googlemap_api_key = Config().googlemap_api_key(),
173             checkboxes = True,
174             # center on Paris
175             latitude   = 49.,
176             longitude  = 9,
177             zoom       = 4,
178         )
179
180         resources_as_3dmap = SensLabMap(
181             page       = page,
182             title      = '3D Map',
183             domid      = 'senslabmap',
184             query      = sq_resource,
185             query_all  = query_resource_all,
186         )
187
188         resources_as_list = QueryTable( 
189             page       = page,
190             domid      = 'resources-list',
191             title      = 'List view',
192             # this is the query at the core of the slice list
193             query      = sq_resource,
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,
197             checkboxes = True,
198             datatables_options = { 
199                 'iDisplayLength': 25,
200                 'bLengthChange' : True,
201                 'bAutoWidth'    : True,
202                 },
203             )
204
205         if do_query_leases:
206             resources_as_scheduler = Scheduler(
207                 page        = page,
208                 title       = 'Scheduler',
209                 domid       = 'scheduler',
210                 query       = sq_resource,
211                 query_all_resources = query_resource_all,
212                 query_lease = sq_lease,
213                 )
214
215        # with the new 'Filter' stuff on top, no need for anything but the querytable
216         resources_as_list_area = resources_as_list 
217
218         resources_sons = [
219             resources_as_gmap, 
220             resources_as_3dmap,
221             resources_as_scheduler,
222             resources_as_list_area,
223             ] if do_query_leases else [
224             resources_as_gmap, 
225             resources_as_3dmap,
226             resources_as_list_area,
227             ]
228
229         resources_area = Tabs ( page=page, 
230                                 domid="resources",
231                                 togglable=True,
232                                 title="Resources",
233                                 outline_complete=True,
234                                 sons= resources_sons,
235                                 active_domid = 'resources-map',
236                                 persistent_active=True,
237                                 )
238         main_stack.insert (resources_area)
239
240         # --------------------------------------------------------------------------
241         # USERS
242     
243         if do_query_users:
244             tab_users = Tabs(
245                 page                = page,
246                 domid               = 'users',
247                 outline_complete    = True,
248                 togglable           = True,
249                 title               = 'Users',
250                 active_domid        = 'users-list',
251                 )
252             main_stack.insert(tab_users)
253     
254             tab_users.insert(QueryTable( 
255                 page        = page,
256                 title       = 'Users List',
257                 domid       = 'users-list',
258                 # tab's sons preferably turn this off
259                 togglable   = False,
260                 # this is the query at the core of the slice list
261                 query       = sq_user,
262                 query_all  = query_user_all,
263                 checkboxes  = True,
264                 datatables_options = { 
265                     'iDisplayLength' : 25,
266                     'bLengthChange'  : True,
267                     'bAutoWidth'     : True,
268                 },
269             ))
270
271 # DEMO    
272         # --------------------------------------------------------------------------
273         # MEASUREMENTS
274         measurements_stats_cpu = SliceStat(
275             title = "CPU Usage",
276             domid = 'resources-stats-cpu',
277             page  = page,
278             stats = 'slice',
279             key   = 'hrn',
280             query = 'none',
281             slicename = slicename,
282             o = 'cpu'
283         )
284         
285         measurements_stats_mem = SliceStat(
286             title = "Memory Usage",
287             domid = 'resources-stats-mem',
288             page  = page,
289             stats = 'slice',
290             key   = 'hrn',
291             query = 'none',
292             slicename = slicename,
293             o = 'mem'
294         )
295         
296         measurements_stats_asb = SliceStat(
297             title = "Traffic Sent",
298             domid = 'resources-stats-asb',
299             page  = page,
300             stats = 'slice',
301             key   = 'hrn',
302             query = 'none',
303             slicename = slicename,
304             o = 'asb'
305         )
306         
307         measurements_stats_arb = SliceStat(
308             title = "Traffic Received",
309             domid = 'resources-stats-arb',
310             page  = page,
311             stats = 'slice',
312             key   = 'hrn',
313             query = 'none',
314             slicename = slicename,
315             o = 'arb'
316         )
317
318         tab_measurements = Tabs ( page=page,
319                                 domid="measurements",
320                                 togglable=True,
321                                 toggled  = False,
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',
326                                 )
327         main_stack.insert (tab_measurements)
328         
329 #        tab_measurements = Tabs (
330 #            page                = page,
331 #            active_domid        = 'measurements-list',
332 #            outline_complete    = True,
333 #            togglable           = True,
334 #            title               = 'Measurements',
335 #            domid               = 'measurements',
336 #        )
337 #        main_stack.insert(tab_measurements)
338 #    
339 #        tab_measurements.insert(QueryTable( 
340 #            page        = page,
341 #            title       = 'Measurements',
342 #            domid       = 'measurements-list',
343 #            # tab's sons preferably turn this off
344 #            togglable   = False,
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
349 #            checkboxes  = True,
350 #            datatables_options = { 
351 #                'iDisplayLength' : 25,
352 #                'bLengthChange'  : True,
353 #                'bAutoWidth'     : True,
354 #            },
355 #        ))
356 #    
357 #        # --------------------------------------------------------------------------
358 #        # MESSAGES (we use transient=False for now)
359         if insert_messages:
360             main_stack.insert(Messages(
361                     page   = page,
362                     title  = "Runtime messages for slice %s"%slicename,
363                     domid  = "msgs-pre",
364                     levels = "ALL",
365                     # plain messages are probably less nice for production but more reliable for development for now
366                     transient = False,
367                     # these make sense only in non-transient mode..
368                     togglable = True,
369                     toggled = 'persistent',
370                     outline_complete = True,
371                     ))
372     
373     
374         # variables that will get passed to the view-unfold1.html template
375         template_env = {}
376         
377         # define 'unfold_main' to the template engine - the main contents
378         template_env [ 'unfold_main' ] = main_stack.render(request)
379     
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) 
386     
387         # don't forget to run the requests
388         page.expose_queries ()
389     
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
392     
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))
399         return result