homeview and platformsview now use layout-unfold1 or layout-unfold2 depending on...
[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.resources_selected      import ResourcesSelected
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         # ResourcesSelected (Pending Operations)
106
107         main_stack.insert(ResourcesSelected(
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_list = QueryTable( 
164             page       = page,
165             domid      = 'resources-list',
166             title      = 'List view',
167             # this is the query at the core of the slice list
168             query      = sq_resource,
169             query_all  = query_resource_all,
170             checkboxes = True,
171             datatables_options = { 
172                 'iDisplayLength': 25,
173                 'bLengthChange' : True,
174                 'bAutoWidth'    : True,
175                 },
176             )
177
178        # with the new 'Filter' stuff on top, no need for anything but the querytable
179         resources_as_list_area = resources_as_list 
180
181         resources_area = Tabs ( page=page, 
182                                 domid="resources",
183                                 togglable=True,
184                                 title="Resources",
185                                 outline_complete=True,
186                                 sons=[ resources_as_map, resources_as_list_area ],
187                                 active_domid = 'resources-map',
188                                 )
189         main_stack.insert (resources_area)
190
191         # --------------------------------------------------------------------------
192         # USERS
193     
194         if do_query_users:
195             tab_users = Tabs(
196                 page                = page,
197                 domid               = 'users',
198                 outline_complete    = True,
199                 togglable           = True,
200                 title               = 'Users',
201                 active_domid        = 'users-list',
202                 )
203             main_stack.insert(tab_users)
204     
205             tab_users.insert(QueryTable( 
206                 page        = page,
207                 title       = 'Users List',
208                 domid       = 'users-list',
209                 # tab's sons preferably turn this off
210                 togglable   = False,
211                 # this is the query at the core of the slice list
212                 query       = sq_user,
213                 query_all  = query_user_all,
214                 checkboxes  = True,
215                 datatables_options = { 
216                     'iDisplayLength' : 25,
217                     'bLengthChange'  : True,
218                     'bAutoWidth'     : True,
219                 },
220             ))
221
222 # DEMO    
223         # --------------------------------------------------------------------------
224         # MEASUREMENTS
225         measurements_stats_cpu = SliceStat(
226             title = "CPU Usage",
227             domid = 'resources-stats-cpu',
228             page  = page,
229             stats = 'slice',
230             key   = 'hrn',
231             query = 'none',
232             slicename = slicename,
233             o = 'cpu'
234         )
235         
236         measurements_stats_mem = SliceStat(
237             title = "Memory Usage",
238             domid = 'resources-stats-mem',
239             page  = page,
240             stats = 'slice',
241             key   = 'hrn',
242             query = 'none',
243             slicename = slicename,
244             o = 'mem'
245         )
246         
247         measurements_stats_asb = SliceStat(
248             title = "Traffic Sent",
249             domid = 'resources-stats-asb',
250             page  = page,
251             stats = 'slice',
252             key   = 'hrn',
253             query = 'none',
254             slicename = slicename,
255             o = 'asb'
256         )
257         
258         measurements_stats_arb = SliceStat(
259             title = "Traffic Received",
260             domid = 'resources-stats-arb',
261             page  = page,
262             stats = 'slice',
263             key   = 'hrn',
264             query = 'none',
265             slicename = slicename,
266             o = 'arb'
267         )
268
269         tab_measurements = Tabs ( page=page,
270                                 domid="measurements",
271                                 togglable=True,
272                                 toggled  = False,
273                                 title="Measurements",
274                                 outline_complete=True,
275                                 sons=[ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
276                                 active_domid = 'measurements_stats_cpu',
277                                 )
278         main_stack.insert (tab_measurements)
279         
280 #        tab_measurements = Tabs (
281 #            page                = page,
282 #            active_domid        = 'measurements-list',
283 #            outline_complete    = True,
284 #            togglable           = True,
285 #            title               = 'Measurements',
286 #            domid               = 'measurements',
287 #        )
288 #        main_stack.insert(tab_measurements)
289 #    
290 #        tab_measurements.insert(QueryTable( 
291 #            page        = page,
292 #            title       = 'Measurements',
293 #            domid       = 'measurements-list',
294 #            # tab's sons preferably turn this off
295 #            togglable   = False,
296 #            # this is the query at the core of the slice list
297 #            query       = sq_measurement,
298 #            # do NOT set checkboxes to False
299 #            # this table being otherwise empty, it just does not fly with dataTables
300 #            checkboxes  = True,
301 #            datatables_options = { 
302 #                'iDisplayLength' : 25,
303 #                'bLengthChange'  : True,
304 #                'bAutoWidth'     : True,
305 #            },
306 #        ))
307 #    
308 #        # --------------------------------------------------------------------------
309 #        # MESSAGES (we use transient=False for now)
310 #        main_stack.insert(Messages(
311 #            page   = page,
312 #            title  = "Runtime messages for slice %s"%slicename,
313 #            domid  = "msgs-pre",
314 #            levels = "ALL",
315 #            # plain messages are probably less nice for production but more reliable for development for now
316 #            transient = False,
317 #            # these make sense only in non-transient mode..
318 #            togglable = True,
319 #            toggled = 'persistent',
320 #            outline_complete = True,
321 #        ))
322 #    
323     
324         # variables that will get passed to the view-unfold1.html template
325         template_env = {}
326         
327         # define 'unfold_main' to the template engine - the main contents
328         template_env [ 'unfold_main' ] = main_stack.render(request)
329     
330         # more general variables expected in the template
331         template_env [ 'title' ] = '%(slicename)s'%locals()
332         # the menu items on the top
333         template_env [ 'topmenu_items' ] = topmenu_items('Slice', request) 
334         # so we can sho who is logged
335         template_env [ 'username' ] = the_user (request) 
336     
337         # don't forget to run the requests
338         page.expose_queries ()
339     
340         # xxx create another plugin with the same query and a different layout (with_datatables)
341         # show that it worls as expected, one single api call to backend and 2 refreshed views
342     
343         # the prelude object in page contains a summary of the requirements() for all plugins
344         # define {js,css}_{files,chunks}
345         prelude_env = page.prelude_env()
346         template_env.update(prelude_env)
347         result=render_to_response ('view-unfold1.html',template_env,
348                                    context_instance=RequestContext(request))
349         return result