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