bebce2136c3dbd47400c760c13581b16f697f60f
[myslice.git] / portal / sliceview.py
1 from django.template                 import RequestContext
2 from django.shortcuts                import render_to_response
3
4 from portal.templateviews            import LoginRequiredAutoLogoutView
5
6 from unfold.page                     import Page
7 from manifold.core.query             import Query, AnalyzedQuery
8
9 from myslice.viewutils               import topmenu_items, the_user
10
11 from plugins.raw.raw                 import Raw
12 from plugins.stack.stack             import Stack
13 from plugins.tabs.tabs               import Tabs
14 from plugins.hazelnut                import Hazelnut 
15 from plugins.resources_selected      import ResourcesSelected
16 from plugins.googlemaps              import GoogleMaps
17 from plugins.senslabmap.senslabmap   import SensLabMap
18 from plugins.querycode.querycode     import QueryCode
19 from plugins.query_editor            import QueryEditor
20 from plugins.active_filters          import ActiveFilters
21 from plugins.quickfilter.quickfilter import QuickFilter
22 from plugins.messages.messages       import Messages
23 #from plugins.updater                 import Updater
24
25 tmp_default_slice='ple.upmc.myslicedemo'
26
27 # temporary : turn off the users part to speed things up
28 do_query_users=true
29
30 class SliceView (LoginRequiredAutoLogoutView):
31
32     def get (self,request, slicename=tmp_default_slice):
33     
34         page = Page(request)
35         page.add_css_files ('css/slice-view.css')
36         page.add_js_chunks ('$(function() { console.log("sliceview: jQuery version " + $.fn.jquery); });')
37         page.expose_js_metadata()
38     
39         metadata = page.get_metadata()
40         resource_md = metadata.details_by_object('resource')
41         resource_fields = [column['name'] for column in resource_md['column']]
42     
43         user_md = metadata.details_by_object('user')
44         user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
45     
46         # TODO The query to run is embedded in the URL
47         main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
48         main_query.select(
49                 'slice_hrn',
50                 'resource.resource_hrn', 'resource.hostname', 'resource.type', 'resource.network_hrn',
51                 #'lease.urn',
52                 'user.user_hrn',
53                 #'application.measurement_point.counter'
54         )
55     
56         query_resource_all = Query.get('resource').select(resource_fields)
57         if do_query_users:
58             query_user_all = Query.get('user').select(user_fields)
59     
60         aq = AnalyzedQuery(main_query, metadata=metadata)
61         page.enqueue_query(main_query, analyzed_query=aq)
62         page.enqueue_query(query_resource_all)
63         if do_query_users:
64             page.enqueue_query(query_user_all)
65     
66         # ... and for the relations
67         # XXX Let's hardcode resources for now
68         sq_resource    = aq.subquery('resource')
69         sq_user        = aq.subquery('user')
70         sq_lease       = aq.subquery('lease')
71         sq_measurement = aq.subquery('measurement')
72         
73     
74         # Prepare the display according to all metadata
75         # (some parts will be pending, others can be triggered by users).
76         # 
77         # For example slice measurements will not be requested by default...
78     
79         # Create the base layout (Stack)...
80         main_stack = Stack (
81             page=page,
82             title="Slice %s"%slicename,
83             sons=[],
84         )
85     
86         # ... responsible for the slice properties...
87     
88         # a nice header
89         main_stack.insert (
90             Raw (page=page,
91                  togglable=False, 
92                  toggled=True,
93                  html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
94         )
95     
96         # --------------------------------------------------------------------------
97         # ResourcesSelected
98         #
99         main_stack.insert(ResourcesSelected(
100             page                = page,
101             title               = 'Pending operations',
102             query               = main_query,
103             togglable           = True,
104             domid               = 'pending',
105             outline_complete    = True,
106         ))
107     
108 #        main_stack.insert(
109 #            Raw (page=page,togglable=False, toggled=True,html='<b>Description:</b> TODO')
110 #        )
111     
112         # the resources part is made of a Stack, 
113         # with first a Tabs (List, Geographic), 
114         # and second the QueryEditor to tweak the set of attributes to show
115         resources_as_list = Hazelnut( 
116             page       = page,
117             title      = 'Resources as a List',
118             domid      = 'checkboxes',
119             # this is the query at the core of the slice list
120             query      = sq_resource,
121             query_all  = query_resource_all,
122             checkboxes = True,
123             datatables_options = { 
124                 # for now we turn off sorting on the checkboxes columns this way
125                 # this of course should be automatic in hazelnut
126                 'aoColumns'      : [None, None, None, None, {'bSortable': False}],
127                 'iDisplayLength' : 25,
128                 'bLengthChange'  : True,
129                 },
130             )
131
132         resources_as_map = GoogleMaps(
133             page       = page,
134             title      = 'Geographic view',
135             domid      = 'gmap',
136             # tab's sons preferably turn this off
137             togglable  = False,
138             query      = sq_resource,
139             query_all  = query_resource_all,
140             checkboxes = True,
141             # center on Paris
142             latitude   = 49.,
143             longitude  = 2.2,
144             zoom       = 3,
145         )
146
147         resources_query_editor = QueryEditor(
148             page  = page,
149             query = sq_resource,
150             )
151         resources_active_filters = ActiveFilters(
152             page  = page,
153             query = sq_resource,
154             )
155
156         resources_area = Stack (
157             page=page,
158             domid="resources",
159             togglable=True,
160             title="Resources",
161             outline_complete=True,
162             sons = [
163                 Tabs ( page=page, 
164                        sons=[ resources_as_list, resources_as_map, ] 
165                        ),
166                 Stack ( page=page,
167                         title="Customize",
168                         togglable=True,
169                         sons = [ resources_query_editor, resources_active_filters, ]
170                         ),
171                 ]
172             )
173
174         main_stack.insert (resources_area)
175
176
177 #        sq_plugin = Tabs (
178 #            page=page,
179 #            title="Slice view for %s"%slicename,
180 #            togglable=True,
181 #            sons=[],
182 #        )
183     
184     
185         ############################################################################
186         # RESOURCES
187         # 
188         # A stack inserted in the subquery tab that will hold all operations
189         # related to resources
190         # 
191         
192 #        stack_resources = Stack(
193 #            page = page,
194 #            title = 'Resources',
195 #            sons=[],
196 #        )
197     
198 #        stack_resources.insert(resource_active_filters)
199 #    
200 #    
201 #        stack_resources.insert(tab_resource_plugins)
202     
203 #        sq_plugin.insert(stack_resources)
204     
205         ############################################################################
206         # USERS
207         # 
208     
209         tab_users = Tabs(
210             page                = page,
211             domid               = 'users',
212             outline_complete    = True,
213             togglable           = True,
214             title               = 'Users',
215             active_domid        = 'checkboxes2',
216         )
217         main_stack.insert(tab_users)
218     
219 #        tab_users.insert(Hazelnut( 
220 #            page        = page,
221 #            title       = 'Users List',
222 #            domid       = 'checkboxes2',
223 #            # tab's sons preferably turn this off
224 #            togglable   = False,
225 #            # this is the query at the core of the slice list
226 #            query       = sq_user,
227 #            query_all  = query_user_all,
228 #            checkboxes  = True,
229 #            datatables_options = { 
230 #                # for now we turn off sorting on the checkboxes columns this way
231 #                # this of course should be automatic in hazelnut
232 #                'aoColumns'      : [None, None, None, None, {'bSortable': False}],
233 #                'iDisplayLength' : 25,
234 #                'bLengthChange'  : True,
235 #            },
236 #        ))
237     
238         tab_measurements = Tabs (
239             page                = page,
240             active_domid        = 'checkboxes3',
241             outline_complete    = True,
242             togglable           = True,
243             title               = 'Measurements',
244             domid               = 'measurements',
245         )
246         main_stack.insert(tab_measurements)
247     
248         tab_measurements.insert(Hazelnut( 
249             page        = page,
250             title       = 'Measurements',
251             domid       = 'checkboxes3',
252             # tab's sons preferably turn this off
253             togglable   = False,
254             # this is the query at the core of the slice list
255             query       = sq_measurement,
256             checkboxes  = True,
257             datatables_options = { 
258                 # for now we turn off sorting on the checkboxes columns this way
259                 # this of course should be automatic in hazelnut
260                 'aoColumns'      : [None, None, None, None, {'bSortable': False}],
261                 'iDisplayLength' : 25,
262                 'bLengthChange'  : True,
263             },
264         ))
265     
266         main_stack.insert(Messages(
267             page   = page,
268             title  = "Runtime messages for slice %s"%slicename,
269             domid  = "msgs-pre",
270             levels = "ALL",
271             # plain messages are probably less nice for production but more reliable for development for now
272             transient = False,
273             # these make sense only in non-transient mode..
274             togglable = True,
275             toggled = 'persistent',
276             outline_complete = True,
277         ))
278     
279     
280         # variables that will get passed to the view-unfold1.html template
281         template_env = {}
282         
283         # define 'unfold1_main' to the template engine - the main contents
284         template_env [ 'unfold1_main' ] = main_stack.render(request)
285     
286         # more general variables expected in the template
287         template_env [ 'title' ] = '%(slicename)s'%locals()
288         # the menu items on the top
289         template_env [ 'topmenu_items' ] = topmenu_items('Slice', request) 
290         # so we can sho who is logged
291         template_env [ 'username' ] = the_user (request) 
292     
293         # don't forget to run the requests
294         page.expose_queries ()
295     
296         # xxx create another plugin with the same query and a different layout (with_datatables)
297         # show that it worls as expected, one single api call to backend and 2 refreshed views
298     
299         # the prelude object in page contains a summary of the requirements() for all plugins
300         # define {js,css}_{files,chunks}
301         prelude_env = page.prelude_env()
302         template_env.update(prelude_env)
303         result=render_to_response ('view-unfold1.html',template_env,
304                                    context_instance=RequestContext(request))
305         return result