534ed78a76726612bb18ace2d70a174d614cc102
[myslice.git] / portal / sliceview.py
1 # Create your views here.
2
3 from django.template                 import RequestContext
4 from django.shortcuts                import render_to_response
5 from django.contrib.auth.decorators  import login_required
6 from django.http                     import HttpResponseRedirect
7
8 from unfold.page                     import Page
9 from manifold.core.query             import Query, AnalyzedQuery
10 from manifold.manifoldresult         import ManifoldException
11 from manifold.metadata               import MetaData as Metadata
12 # need to remove this dep.
13 from trash.trashutils                import quickfilter_criterias
14 from myslice.viewutils               import topmenu_items, the_user
15
16 from plugins.raw.raw                 import Raw
17 from plugins.stack.stack             import Stack
18 from plugins.tabs.tabs               import Tabs
19 from plugins.lists.slicelist         import SliceList
20 from plugins.hazelnut                import Hazelnut 
21 from plugins.resources_selected      import ResourcesSelected
22 from plugins.googlemaps              import GoogleMaps
23 from plugins.senslabmap.senslabmap   import SensLabMap
24 from plugins.querycode.querycode     import QueryCode
25 from plugins.query_editor            import QueryEditor
26 from plugins.active_filters          import ActiveFilters
27 from plugins.quickfilter.quickfilter import QuickFilter
28 from plugins.messages.messages       import Messages
29 #from plugins.updater                 import Updater
30
31 tmp_default_slice='ple.upmc.myslicedemo'
32 debug = True
33
34 @login_required
35 def slice_view (request, slicename=tmp_default_slice):
36     # xxx Thierry - ugly hack
37     # fetching metadata here might fail - e.g. with an expired session..
38     # let's catch this early on and log out our user if needed
39     # it should of course be handled in a more generic way
40     try:
41         return _slice_view(request,slicename)
42     except ManifoldException, manifold_result:
43         # xxx needs a means to display this message to user...
44         from django.contrib.auth import logout
45         logout(request)
46         return HttpResponseRedirect ('/')
47     except Exception, e:
48         # xxx we need to sugarcoat this error message in some error template...
49         print "Unexpected exception",e
50         import traceback
51         traceback.print_exc()
52         # return ...
53
54 def _slice_view (request, slicename):
55
56     page = Page(request)
57     page.expose_js_metadata()
58
59     metadata = page.get_metadata()
60     resource_md = metadata.details_by_object('resource')
61     resource_fields = [column['name'] for column in resource_md['column']]
62
63     user_md = metadata.details_by_object('user')
64     user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
65
66     # TODO The query to run is embedded in the URL
67     main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
68     main_query.select(
69             'slice_hrn',
70             'resource.resource_hrn', 'resource.hostname', 'resource.type', 'resource.network_hrn',
71             #'lease.urn',
72             'user.user_hrn',
73             #'application.measurement_point.counter'
74     )
75
76     query_resource_all = Query.get('resource').select(resource_fields)
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     page.enqueue_query(query_user_all)
83
84     # Prepare the display according to all metadata
85     # (some parts will be pending, others can be triggered by users).
86     # 
87     # For example slice measurements will not be requested by default...
88
89     # Create the base layout (Stack)...
90     main_plugin = Stack (
91         page=page,
92         title="Slice !!view for %s"%slicename,
93         sons=[],
94     )
95
96     # ... responsible for the slice properties...
97
98
99     main_plugin.insert (
100         Raw (page=page,togglable=False, toggled=True,html="<h2> Slice page for %s</h2>"%slicename)
101     )
102
103     main_plugin.insert(
104         Raw (page=page,togglable=False, toggled=True,html='<b>Description:</b> TODO')
105     )
106
107     sq_plugin = Tabs (
108         page=page,
109         title="Slice view for %s"%slicename,
110         togglable=False,
111         sons=[],
112     )
113
114
115     # ... and for the relations
116     # XXX Let's hardcode resources for now
117     sq_resource = aq.subquery('resource')
118     sq_user     = aq.subquery('user')
119     sq_lease    = aq.subquery('lease')
120     sq_measurement = aq.subquery('measurement')
121     
122
123     ############################################################################
124     # RESOURCES
125     # 
126     # A stack inserted in the subquery tab that will hold all operations
127     # related to resources
128     # 
129     
130     stack_resources = Stack(
131         page = page,
132         title        = 'Resources',
133         sons=[],
134     )
135
136     resource_query_editor = QueryEditor(
137         page  = page,
138         query = sq_resource,
139     )
140     stack_resources.insert(resource_query_editor)
141
142     resource_active_filters = ActiveFilters(
143         page  = page,
144         query = sq_resource,
145     )
146     stack_resources.insert(resource_active_filters)
147
148     # --------------------------------------------------------------------------
149     # Different displays = DataTables + GoogleMaps
150     #
151     tab_resource_plugins = Tabs(
152         page    = page,
153         sons = []
154     )
155
156     tab_resource_plugins.insert(Hazelnut( 
157         page       = page,
158         title      = 'List',
159         domid      = 'checkboxes',
160         # this is the query at the core of the slice list
161         query      = sq_resource,
162         query_all  = query_resource_all,
163         checkboxes = True,
164         datatables_options = { 
165             # for now we turn off sorting on the checkboxes columns this way
166             # this of course should be automatic in hazelnut
167             'aoColumns'      : [None, None, None, None, {'bSortable': False}],
168             'iDisplayLength' : 25,
169             'bLengthChange'  : True,
170         },
171     ))
172
173     tab_resource_plugins.insert(GoogleMaps(
174         page       = page,
175         title      = 'Geographic view',
176         domid      = 'gmap',
177         # tab's sons preferably turn this off
178         togglable  = False,
179         query      = sq_resource,
180         query_all  = query_resource_all,
181         checkboxes = True,
182         # center on Paris
183         latitude   = 49.,
184         longitude  = 2.2,
185         zoom       = 3,
186     ))
187
188     stack_resources.insert(tab_resource_plugins)
189
190     sq_plugin.insert(stack_resources)
191
192     ############################################################################
193     # USERS
194     # 
195
196     tab_users = Tabs(
197         page         = page,
198         title        = 'Users',
199         domid        = 'thetabs2',
200         # activeid   = 'checkboxes',
201         active_domid = 'checkboxes2',
202     )
203     sq_plugin.insert(tab_users)
204
205     tab_users.insert(Hazelnut( 
206         page        = page,
207         title       = 'List',
208         domid       = 'checkboxes2',
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             # for now we turn off sorting on the checkboxes columns this way
217             # this of course should be automatic in hazelnut
218             'aoColumns'      : [None, None, None, None, {'bSortable': False}],
219             'iDisplayLength' : 25,
220             'bLengthChange'  : True,
221         },
222     ))
223
224     tab_measurements = Tabs (
225         page         = page,
226         title        = 'Measurements',
227         domid        = 'thetabs3',
228         # activeid   = 'checkboxes',
229         active_domid = 'checkboxes3',
230     )
231     sq_plugin.insert(tab_measurements)
232
233     tab_measurements.insert(Hazelnut( 
234         page        = page,
235         title       = 'List',
236         domid       = 'checkboxes3',
237         # tab's sons preferably turn this off
238         togglable   = False,
239         # this is the query at the core of the slice list
240         query       = sq_measurement,
241         checkboxes  = True,
242         datatables_options = { 
243             # for now we turn off sorting on the checkboxes columns this way
244             # this of course should be automatic in hazelnut
245             'aoColumns'      : [None, None, None, None, {'bSortable': False}],
246             'iDisplayLength' : 25,
247             'bLengthChange'  : True,
248         },
249     ))
250
251     main_plugin.insert(sq_plugin)
252
253     # --------------------------------------------------------------------------
254     # ResourcesSelected
255     #
256     main_plugin.insert(ResourcesSelected(
257         page                = page,
258         title               = 'Pending operations',
259         query               = main_query,
260         togglable           = True,
261     ))
262
263     main_plugin.insert(Messages(
264         page   = page,
265         title  = "Runtime messages for slice %s"%slicename,
266         domid  = "msgs-pre",
267         levels = "ALL",
268     ))
269 #    main_plugin.insert(Updater(
270 #        page   = page,
271 #        title  = "wont show up as non togglable by default",
272 #        query  = main_query,
273 #        label  = "Update slice",
274 #    ))
275     
276
277
278     # variables that will get passed to the view-unfold1.html template
279     template_env = {}
280     
281     # define 'unfold1_main' to the template engine - the main contents
282     template_env [ 'unfold1_main' ] = main_plugin.render(request)
283
284     # more general variables expected in the template
285     template_env [ 'title' ] = '%(slicename)s (test view that combines various plugins)'%locals()
286     # the menu items on the top
287     template_env [ 'topmenu_items' ] = topmenu_items('Slice', request) 
288     # so we can sho who is logged
289     template_env [ 'username' ] = the_user (request) 
290
291     # don't forget to run the requests
292     page.expose_queries ()
293
294     # xxx create another plugin with the same query and a different layout (with_datatables)
295     # show that it worls as expected, one single api call to backend and 2 refreshed views
296
297     # the prelude object in page contains a summary of the requirements() for all plugins
298     # define {js,css}_{files,chunks}
299     prelude_env = page.prelude_env()
300     template_env.update(prelude_env)
301     result=render_to_response ('view-unfold1.html',template_env,
302                                context_instance=RequestContext(request))
303     return result