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