2 from django.template import RequestContext
3 from django.shortcuts import render_to_response
5 from unfold.loginrequired import LoginRequiredAutoLogoutView
7 from unfold.page import Page
8 from manifold.core.query import Query, AnalyzedQuery
9 from manifold.manifoldapi import execute_query
11 from ui.topmenu import topmenu_items_live, the_user
13 from plugins.raw import Raw
14 from plugins.stack import Stack
15 from plugins.tabs import Tabs
16 from plugins.querytable import QueryTable
17 from plugins.querygrid import QueryGrid
18 from plugins.queryupdater import QueryUpdater
19 from plugins.googlemap import GoogleMap
20 from plugins.senslabmap import SensLabMap
21 from plugins.scheduler import Scheduler
22 from plugins.querycode import QueryCode
24 # stay away from query editor for now as it seems to make things go very slow
25 # see https://lists.myslice.info/pipermail/devel-myslice/2013-December/000221.html
26 from plugins.query_editor import QueryEditor
27 from plugins.active_filters import ActiveFilters
28 from plugins.quickfilter import QuickFilter
29 from plugins.messages import Messages
30 from plugins.slicestat import SliceStat
32 from myslice.configengine import ConfigEngine
34 tmp_default_slice='ple.upmc.myslicedemo'
36 # temporary : turn off the users part to speed things up
49 class SliceView (LoginRequiredAutoLogoutView):
51 def get (self,request, slicename=tmp_default_slice):
54 page.add_css_files ('css/slice-view.css')
55 page.add_js_files ( [ "js/common.functions.js" ] )
56 page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
57 page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
58 page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
59 page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(ConfigEngine().manifold_url()))
61 metadata = page.get_metadata()
62 resource_md = metadata.details_by_object('resource')
63 resource_fields = [column['name'] for column in resource_md['column']]
65 user_md = metadata.details_by_object('user')
66 user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
68 # TODO The query to run is embedded in the URL
69 main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
72 #'resource.hrn', 'resource.urn',
73 'resource.hostname', 'resource.type',
74 'resource.network_hrn',
77 #'application.measurement_point.counter'
79 # for internal use in the querytable plugin;
80 # needs to be a unique column present for each returned record
81 main_query_init_key = 'hostname'
83 query_resource_all = Query.get('resource').select(resource_fields)
85 aq = AnalyzedQuery(main_query, metadata=metadata)
86 page.enqueue_query(main_query, analyzed_query=aq)
87 page.enqueue_query(query_resource_all)
89 # Required: the user must have an authority in its user.config
90 # XXX Temporary solution
91 user_query = Query().get('local:user').select('config','email')
92 user_details = execute_query(self.request, user_query)
94 # not always found in user_details...
96 # for user_detail in user_details:
97 # #email = user_detail['email']
98 # if user_detail['config']:
99 # config = json.loads(user_detail['config'])
100 # user_detail['authority'] = config.get('authority',"Unknown Authority")
102 # if user_detail['authority'] is not None:
103 # sub_authority = user_detail['authority'].split('.')
104 # root_authority = sub_authority[0]
105 # query_user_all = Query.get(root_authority+':user').select(user_fields)
107 # # XXX TODO this filter doesn't work - to be improved in Manifold
108 # #.filter_by('authority.authority_hrn', '=', user_detail['authority'])
110 # page.enqueue_query(query_user_all)
112 # print "authority of the user is not in local:user db"
113 query_user_all = Query.get('user').select(user_fields)
114 # query_user_all = None
116 # ... and for the relations
117 # XXX Let's hardcode resources for now
118 sq_resource = aq.subquery('resource')
119 sq_user = aq.subquery('user')
120 sq_lease = aq.subquery('lease')
121 sq_measurement = aq.subquery('measurement')
124 # Prepare the display according to all metadata
125 # (some parts will be pending, others can be triggered by users).
127 # For example slice measurements will not be requested by default...
129 # Create the base layout (Stack)...
132 title="Slice %s"%slicename,
136 # ... responsible for the slice properties...
143 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
146 # --------------------------------------------------------------------------
147 # QueryUpdater (Pending Operations)
149 main_stack.insert(QueryUpdater(
151 title = 'Pending operations',
154 # start turned off, it will open up itself when stuff comes in
157 outline_complete = True,
160 # --------------------------------------------------------------------------
163 # turn off for now -- see above
164 filter_query_editor = QueryEditor(
167 query_all = query_resource_all,
168 title = "Select Columns",
169 domid = 'select-columns',
171 filter_active_filters = ActiveFilters(
174 title = "Active Filters",
176 filters_area = Stack(
178 title = 'Filter Resources',
180 sons = [filter_query_editor,
181 filter_active_filters],
183 toggled = 'persistent',
184 outline_complete = True,
186 main_stack.insert (filters_area)
188 # --------------------------------------------------------------------------
190 # the resources part is made of a Tabs (Geographic, List),
192 resources_as_gmap = GoogleMap(
194 title = 'Geographic view',
195 domid = 'resources-map',
196 # tab's sons preferably turn this off
199 query_all = query_resource_all,
200 # this key is the one issued by google
201 googlemap_api_key = ConfigEngine().googlemap_api_key(),
202 # the key to use at init-time
203 init_key = main_query_init_key,
211 resources_as_3dmap = SensLabMap(
214 domid = 'senslabmap',
216 query_all = query_resource_all,
219 resources_as_list = QueryTable(
221 domid = 'resources-list',
223 # this is the query at the core of the slice list
225 query_all = query_resource_all,
226 init_key = main_query_init_key,
228 datatables_options = {
229 'iDisplayLength': 25,
230 'bLengthChange' : True,
236 resources_as_grid = QueryGrid(
238 domid = 'resources-grid',
240 # this is the query at the core of the slice list
242 query_all = query_resource_all,
243 init_key = main_query_init_key,
248 resources_as_scheduler = Scheduler(
253 query_all_resources = query_resource_all,
254 query_lease = sq_lease,
257 # with the new 'Filter' stuff on top, no need for anything but the querytable
258 resources_as_list_area = resources_as_list
263 resources_as_scheduler,
264 resources_as_list_area,
265 ] if do_query_leases else [
268 resources_as_list_area,
271 resources_sons.append(resources_as_grid)
273 resources_area = Tabs ( page=page,
277 outline_complete=True,
278 sons= resources_sons,
279 active_domid = 'resources-map',
280 persistent_active=True,
282 main_stack.insert (resources_area)
284 # --------------------------------------------------------------------------
287 if do_query_users and query_user_all is not None:
291 outline_complete = True,
294 active_domid = 'users-list',
296 main_stack.insert(tab_users)
298 tab_users.insert(QueryTable(
300 title = 'Users List',
301 domid = 'users-list',
302 # tab's sons preferably turn this off
304 # this is the query at the core of the slice list
306 query_all = query_user_all,
308 datatables_options = {
309 'iDisplayLength' : 25,
310 'bLengthChange' : True,
316 # --------------------------------------------------------------------------
318 measurements_stats_cpu = SliceStat(
320 domid = 'resources-stats-cpu',
325 slicename = slicename,
329 measurements_stats_mem = SliceStat(
330 title = "Memory Usage",
331 domid = 'resources-stats-mem',
336 slicename = slicename,
340 measurements_stats_asb = SliceStat(
341 title = "Traffic Sent",
342 domid = 'resources-stats-asb',
347 slicename = slicename,
351 measurements_stats_arb = SliceStat(
352 title = "Traffic Received",
353 domid = 'resources-stats-arb',
358 slicename = slicename,
362 tab_measurements = Tabs ( page=page,
363 domid = "measurements",
365 toggled = 'persistent',
366 title = "Measurements",
367 outline_complete=True,
368 sons = [ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
369 active_domid = 'resources-stats-cpu',
370 persistent_active = True,
372 main_stack.insert (tab_measurements)
374 # tab_measurements = Tabs (
376 # active_domid = 'measurements-list',
377 # outline_complete = True,
379 # title = 'Measurements',
380 # domid = 'measurements',
382 # main_stack.insert(tab_measurements)
384 # tab_measurements.insert(QueryTable(
386 # title = 'Measurements',
387 # domid = 'measurements-list',
388 # # tab's sons preferably turn this off
390 # # this is the query at the core of the slice list
391 # query = sq_measurement,
392 # # do NOT set checkboxes to False
393 # # this table being otherwise empty, it just does not fly with dataTables
395 # datatables_options = {
396 # 'iDisplayLength' : 25,
397 # 'bLengthChange' : True,
398 # 'bAutoWidth' : True,
402 # # --------------------------------------------------------------------------
403 # # MESSAGES (we use transient=False for now)
405 main_stack.insert(Messages(
407 title = "Runtime messages for slice %s"%slicename,
410 # plain messages are probably less nice for production but more reliable for development for now
412 # these make sense only in non-transient mode..
414 toggled = 'persistent',
415 outline_complete = True,
418 # variables that will get passed to the view-unfold1.html template
421 # define 'unfold_main' to the template engine - the main contents
422 template_env [ 'unfold_main' ] = main_stack.render(request)
424 # more general variables expected in the template
425 template_env [ 'title' ] = '%(slicename)s'%locals()
426 # the menu items on the top
427 template_env [ 'topmenu_items' ] = topmenu_items_live('Slice', page)
428 # so we can sho who is logged
429 template_env [ 'username' ] = the_user (request)
431 # don't forget to run the requests
432 page.expose_js_metadata()
433 # the prelude object in page contains a summary of the requirements() for all plugins
434 # define {js,css}_{files,chunks}
435 template_env.update(page.prelude_env())
437 return render_to_response ('view-unfold1.html',template_env,
438 context_instance=RequestContext(request))