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