Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
[myslice.git] / portal / sliceviewold.py
1 import json
2 from django.template                 import RequestContext
3 from django.shortcuts                import render_to_response
4
5 from unfold.loginrequired            import LoginRequiredAutoLogoutView
6
7 from unfold.page                     import Page
8 from manifold.core.query             import Query, AnalyzedQuery
9 from manifoldapi.manifoldapi         import execute_query
10
11 from ui.topmenu                      import topmenu_items_live, the_user
12
13 from plugins.raw                     import Raw
14 from plugins.stack                   import Stack
15 from plugins.tabs                    import Tabs
16 from plugins.querytable              import QueryTable 
17 from plugins.querygrid               import QueryGrid
18 from plugins.queryupdater            import QueryUpdater
19 from plugins.googlemap               import GoogleMap
20 from plugins.senslabmap              import SensLabMap
21 from plugins.scheduler               import Scheduler
22 from plugins.querycode               import QueryCode
23 # Thierry
24 # stay away from query editor for now as it seems to make things go very slow
25 # see https://lists.myslice.info/pipermail/devel-myslice/2013-December/000221.html 
26 from plugins.query_editor            import QueryEditor
27 from plugins.active_filters          import ActiveFilters
28 from plugins.quickfilter             import QuickFilter
29 from plugins.messages                import Messages
30 from plugins.slicestat               import SliceStat
31
32 from myslice.configengine            import ConfigEngine
33
34 from myslice.theme import ThemeView
35
36 tmp_default_slice='ple.upmc.myslicedemo'
37
38 # temporary : turn off the users part to speed things up
39 #do_query_users=True
40 do_query_users=False
41
42 #do_query_leases=True
43 do_query_leases=False
44
45 insert_grid=False
46 #insert_grid=True
47
48 insert_messages=False
49 #insert_messages=True
50
51 class SliceView (LoginRequiredAutoLogoutView, ThemeView):
52
53     def get (self,request, slicename=tmp_default_slice):
54     
55         page = Page(request)
56         page.add_css_files ('css/slice-view.css')
57         page.add_js_files  ( [ "js/common.functions.js" ] )
58         page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
59         page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
60         page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
61         page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(ConfigEngine().manifold_url()))
62
63         metadata = page.get_metadata()
64         resource_md = metadata.details_by_object('resource')
65         resource_fields = [column['name'] for column in resource_md['column']]
66     
67         user_md = metadata.details_by_object('user')
68         user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
69     
70         # TODO The query to run is embedded in the URL
71         main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
72         main_query.select(
73                 'slice_hrn',
74                 #'resource.hrn', 'resource.urn', 
75                 'resource.hostname', 'resource.type', 
76                 'resource.network_hrn',
77                 'lease.urn',
78                 'user.user_hrn',
79                 #'application.measurement_point.counter'
80         )
81         # for internal use in the querytable plugin;
82         # needs to be a unique column present for each returned record
83         main_query_init_key = 'hostname'
84     
85         query_resource_all = Query.get('resource').select(resource_fields)
86
87         aq = AnalyzedQuery(main_query, metadata=metadata)
88         page.enqueue_query(main_query, analyzed_query=aq)
89         page.enqueue_query(query_resource_all)
90         if do_query_users:
91             # Required: the user must have an authority in its user.config
92             # XXX Temporary solution
93             user_query  = Query().get('local:user').select('config','email')
94             user_details = execute_query(self.request, user_query)
95             
96             # not always found in user_details...
97             config={}
98 #            for user_detail in user_details:
99 #                #email = user_detail['email']
100 #                if user_detail['config']:
101 #                    config = json.loads(user_detail['config'])
102 #            user_detail['authority'] = config.get('authority',"Unknown Authority")
103 #
104 #            if user_detail['authority'] is not None:
105 #                sub_authority = user_detail['authority'].split('.')
106 #                root_authority = sub_authority[0]
107 #                query_user_all = Query.get(root_authority+':user').select(user_fields)
108 #
109 #                # XXX TODO this filter doesn't work - to be improved in Manifold
110 #                #.filter_by('authority.authority_hrn', '=', user_detail['authority'])
111 #
112 #                page.enqueue_query(query_user_all)
113 #            else:
114 #                print "authority of the user is not in local:user db"
115             query_user_all = Query.get('user').select(user_fields)
116             #    query_user_all = None
117     
118         # ... and for the relations
119         # XXX Let's hardcode resources for now
120         sq_resource    = aq.subquery('resource')
121         sq_user        = aq.subquery('user')
122         sq_lease       = aq.subquery('lease')
123         sq_measurement = aq.subquery('measurement')
124         
125     
126         # Prepare the display according to all metadata
127         # (some parts will be pending, others can be triggered by users).
128         # 
129         # For example slice measurements will not be requested by default...
130     
131         # Create the base layout (Stack)...
132         main_stack = Stack (
133             page=page,
134             title="Slice %s"%slicename,
135             sons=[],
136         )
137     
138         # ... responsible for the slice properties...
139     
140         # a nice header
141         main_stack.insert (
142             Raw (page=page,
143                  togglable=False, 
144                  toggled=True,
145                  html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
146         )
147     
148         # --------------------------------------------------------------------------
149         # QueryUpdater (Pending Operations)
150
151         main_stack.insert(QueryUpdater(
152             page                = page,
153             title               = 'Pending operations',
154             query               = main_query,
155             togglable           = True,
156             # start turned off, it will open up itself when stuff comes in
157             toggled             = False, 
158             domid               = 'pending',
159             outline_complete    = True,
160         ))
161
162         # --------------------------------------------------------------------------
163         # Filter Resources
164        
165 # turn off for now -- see above
166         filter_query_editor = QueryEditor(
167             page  = page,
168             query = sq_resource, 
169             query_all = query_resource_all,
170             title = "Select Columns",
171             domid = 'select-columns',
172             )
173         filter_active_filters = ActiveFilters(
174             page  = page,
175             query = sq_resource,
176             title = "Active Filters",
177             )
178         filters_area = Stack(
179             page                = page,
180             title               = 'Filter Resources',
181             domid               = 'filters',
182             sons                = [filter_query_editor, 
183                                    filter_active_filters],
184             togglable           = True,
185             toggled             = 'persistent',
186             outline_complete    = True, 
187         )
188         main_stack.insert (filters_area)
189
190         # --------------------------------------------------------------------------
191         # RESOURCES
192         # the resources part is made of a Tabs (Geographic, List), 
193
194         resources_as_gmap = GoogleMap(
195             page       = page,
196             title      = 'Geographic view',
197             domid      = 'resources-map',
198             # tab's sons preferably turn this off
199             togglable  = False,
200             query      = sq_resource,
201             query_all  = query_resource_all,
202             # this key is the one issued by google
203             googlemap_api_key = ConfigEngine().googlemap_api_key(),
204             # the key to use at init-time
205             init_key   = main_query_init_key,
206             checkboxes = True,
207             # center on Paris
208             latitude   = 49.,
209             longitude  = 9,
210             zoom       = 4,
211         )
212
213         resources_as_3dmap = SensLabMap(
214             page       = page,
215             title      = '3D Map',
216             domid      = 'senslabmap',
217             query      = sq_resource,
218             query_all  = query_resource_all,
219         )
220
221         resources_as_list = QueryTable( 
222             page       = page,
223             domid      = 'resources-list',
224             title      = 'List view',
225             # this is the query at the core of the slice list
226             query      = sq_resource,
227             query_all  = query_resource_all,
228             init_key     = main_query_init_key,
229             checkboxes = True,
230             datatables_options = { 
231                 'iDisplayLength': 25,
232                 'bLengthChange' : True,
233                 'bAutoWidth'    : True,
234                 },
235             )
236
237         if insert_grid:
238             resources_as_grid = QueryGrid( 
239                 page       = page,
240                 domid      = 'resources-grid',
241                 title      = 'Grid view',
242                 # this is the query at the core of the slice list
243                 query      = sq_resource,
244                 query_all  = query_resource_all,
245                 init_key     = main_query_init_key,
246                 checkboxes = True,
247                 )
248
249         if do_query_leases:
250             resources_as_scheduler = Scheduler(
251                 page        = page,
252                 title       = 'Scheduler',
253                 domid       = 'scheduler',
254                 query       = sq_resource,
255                 query_all_resources = query_resource_all,
256                 query_lease = sq_lease,
257                 )
258
259        # with the new 'Filter' stuff on top, no need for anything but the querytable
260         resources_as_list_area = resources_as_list 
261
262         resources_sons = [
263             resources_as_gmap, 
264             resources_as_3dmap,
265             resources_as_scheduler,
266             resources_as_list_area,
267             ] if do_query_leases else [
268             resources_as_gmap, 
269             resources_as_3dmap,
270             resources_as_list_area,
271             ]
272         if insert_grid:
273             resources_sons.append(resources_as_grid)
274
275         resources_area = Tabs ( page=page, 
276                                 domid="resources",
277                                 togglable=True,
278                                 title="Resources",
279                                 outline_complete=True,
280                                 sons= resources_sons,
281                                 active_domid = 'resources-map',
282                                 persistent_active=True,
283                                 )
284         main_stack.insert (resources_area)
285
286         # --------------------------------------------------------------------------
287         # USERS
288     
289         if do_query_users and query_user_all is not None:
290             tab_users = Tabs(
291                 page                = page,
292                 domid               = 'users',
293                 outline_complete    = True,
294                 togglable           = True,
295                 title               = 'Users',
296                 active_domid        = 'users-list',
297                 )
298             main_stack.insert(tab_users)
299     
300             tab_users.insert(QueryTable( 
301                 page        = page,
302                 title       = 'Users List',
303                 domid       = 'users-list',
304                 # tab's sons preferably turn this off
305                 togglable   = False,
306                 # this is the query at the core of the slice list
307                 query       = sq_user,
308                 query_all  = query_user_all,
309                 checkboxes  = True,
310                 datatables_options = { 
311                     'iDisplayLength' : 25,
312                     'bLengthChange'  : True,
313                     'bAutoWidth'     : True,
314                 },
315             ))
316
317 # DEMO    
318         # --------------------------------------------------------------------------
319         # MEASUREMENTS
320         measurements_stats_cpu = SliceStat(
321             title = "CPU Usage",
322             domid = 'resources-stats-cpu',
323             page  = page,
324             stats = 'slice',
325             key   = 'hrn',
326             query = 'none',
327             slicename = slicename,
328             o = 'cpu'
329         )
330         
331         measurements_stats_mem = SliceStat(
332             title = "Memory Usage",
333             domid = 'resources-stats-mem',
334             page  = page,
335             stats = 'slice',
336             key   = 'hrn',
337             query = 'none',
338             slicename = slicename,
339             o = 'mem'
340         )
341         
342         measurements_stats_asb = SliceStat(
343             title = "Traffic Sent",
344             domid = 'resources-stats-asb',
345             page  = page,
346             stats = 'slice',
347             key   = 'hrn',
348             query = 'none',
349             slicename = slicename,
350             o = 'asb'
351         )
352         
353         measurements_stats_arb = SliceStat(
354             title = "Traffic Received",
355             domid = 'resources-stats-arb',
356             page  = page,
357             stats = 'slice',
358             key   = 'hrn',
359             query = 'none',
360             slicename = slicename,
361             o = 'arb'
362         )
363
364         tab_measurements = Tabs ( page=page,
365                                 domid = "measurements",
366                                 togglable = True,
367                                 toggled = 'persistent',
368                                 title = "Measurements",
369                                 outline_complete=True,
370                                 sons = [ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
371                                 active_domid = 'resources-stats-cpu',
372                                 persistent_active = True,
373                                 )
374         main_stack.insert (tab_measurements)
375         
376 #        tab_measurements = Tabs (
377 #            page                = page,
378 #            active_domid        = 'measurements-list',
379 #            outline_complete    = True,
380 #            togglable           = True,
381 #            title               = 'Measurements',
382 #            domid               = 'measurements',
383 #        )
384 #        main_stack.insert(tab_measurements)
385 #    
386 #        tab_measurements.insert(QueryTable( 
387 #            page        = page,
388 #            title       = 'Measurements',
389 #            domid       = 'measurements-list',
390 #            # tab's sons preferably turn this off
391 #            togglable   = False,
392 #            # this is the query at the core of the slice list
393 #            query       = sq_measurement,
394 #            # do NOT set checkboxes to False
395 #            # this table being otherwise empty, it just does not fly with dataTables
396 #            checkboxes  = True,
397 #            datatables_options = { 
398 #                'iDisplayLength' : 25,
399 #                'bLengthChange'  : True,
400 #                'bAutoWidth'     : True,
401 #            },
402 #        ))
403 #    
404 #        # --------------------------------------------------------------------------
405 #        # MESSAGES (we use transient=False for now)
406         if insert_messages:
407             main_stack.insert(Messages(
408                     page   = page,
409                     title  = "Runtime messages for slice %s"%slicename,
410                     domid  = "msgs-pre",
411                     levels = "ALL",
412                     # plain messages are probably less nice for production but more reliable for development for now
413                     transient = False,
414                     # these make sense only in non-transient mode..
415                     togglable = True,
416                     toggled = 'persistent',
417                     outline_complete = True,
418                     ))
419     
420         # variables that will get passed to the view-unfold1.html template
421         template_env = {}
422         
423         # define 'unfold_main' to the template engine - the main contents
424         template_env [ 'unfold_main' ] = main_stack.render(request)
425     
426         # more general variables expected in the template
427         template_env [ 'title' ] = '%(slicename)s'%locals()
428         # the menu items on the top
429         template_env [ 'topmenu_items' ] = topmenu_items_live('Slice', page) 
430         # so we can sho who is logged
431         template_env [ 'username' ] = the_user (request) 
432         
433         template_env ['theme'] = self.theme
434         
435         # don't forget to run the requests
436         page.expose_js_metadata()
437         # the prelude object in page contains a summary of the requirements() for all plugins
438         # define {js,css}_{files,chunks}
439         template_env.update(page.prelude_env())
440
441         return render_to_response ('view-unfold1.html',template_env,
442                                    context_instance=RequestContext(request))