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.config import Config
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"))
60 page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
62 page.expose_js_metadata()
64 metadata = page.get_metadata()
65 resource_md = metadata.details_by_object('resource')
66 resource_fields = [column['name'] for column in resource_md['column']]
68 user_md = metadata.details_by_object('user')
69 user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
71 # TODO The query to run is embedded in the URL
72 main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
75 #'resource.hrn', 'resource.urn',
76 'resource.hostname', 'resource.type',
77 'resource.network_hrn',
80 #'application.measurement_point.counter'
82 # for internal use in the querytable plugin;
83 # needs to be a unique column present for each returned record
84 main_query_init_key = 'hostname'
86 query_resource_all = Query.get('resource').select(resource_fields)
88 aq = AnalyzedQuery(main_query, metadata=metadata)
89 page.enqueue_query(main_query, analyzed_query=aq)
90 page.enqueue_query(query_resource_all)
92 # Required: the user must have an authority in its user.config
93 # XXX Temporary solution
94 user_query = Query().get('local:user').select('config','email')
95 user_details = execute_query(self.request, user_query)
97 # not always found in user_details...
99 # for user_detail in user_details:
100 # #email = user_detail['email']
101 # if user_detail['config']:
102 # config = json.loads(user_detail['config'])
103 # user_detail['authority'] = config.get('authority',"Unknown Authority")
105 # if user_detail['authority'] is not None:
106 # sub_authority = user_detail['authority'].split('.')
107 # root_authority = sub_authority[0]
108 # query_user_all = Query.get(root_authority+':user').select(user_fields)
110 # # XXX TODO this filter doesn't work - to be improved in Manifold
111 # #.filter_by('authority.authority_hrn', '=', user_detail['authority'])
113 # page.enqueue_query(query_user_all)
115 # print "authority of the user is not in local:user db"
116 query_user_all = Query.get('user').select(user_fields)
117 # query_user_all = None
119 # ... and for the relations
120 # XXX Let's hardcode resources for now
121 sq_resource = aq.subquery('resource')
122 sq_user = aq.subquery('user')
123 sq_lease = aq.subquery('lease')
124 sq_measurement = aq.subquery('measurement')
127 # Prepare the display according to all metadata
128 # (some parts will be pending, others can be triggered by users).
130 # For example slice measurements will not be requested by default...
132 # Create the base layout (Stack)...
135 title="Slice %s"%slicename,
139 # ... responsible for the slice properties...
146 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
149 # --------------------------------------------------------------------------
150 # QueryUpdater (Pending Operations)
152 main_stack.insert(QueryUpdater(
154 title = 'Pending operations',
157 # start turned off, it will open up itself when stuff comes in
160 outline_complete = True,
163 # --------------------------------------------------------------------------
166 # turn off for now -- see above
167 # filter_query_editor = QueryEditor(
169 # query = sq_resource,
170 # query_all = query_resource_all,
171 # title = "Select Columns",
172 # domid = 'select-columns',
174 filter_active_filters = ActiveFilters(
177 title = "Active Filters",
179 filters_area = Stack(
181 title = 'Filter Resources',
183 sons = [# filter_query_editor,
184 filter_active_filters],
186 toggled = 'persistent',
187 outline_complete = True,
189 main_stack.insert (filters_area)
191 # --------------------------------------------------------------------------
193 # the resources part is made of a Tabs (Geographic, List),
195 resources_as_gmap = GoogleMap(
197 title = 'Geographic view',
198 domid = 'resources-map',
199 # tab's sons preferably turn this off
202 query_all = query_resource_all,
203 # this key is the one issued by google
204 googlemap_api_key = Config().googlemap_api_key(),
205 # the key to use at init-time
206 init_key = main_query_init_key,
214 resources_as_3dmap = SensLabMap(
217 domid = 'senslabmap',
219 query_all = query_resource_all,
222 resources_as_list = QueryTable(
224 domid = 'resources-list',
226 # this is the query at the core of the slice list
228 query_all = query_resource_all,
229 # use 'hrn' as the internal unique key for this plugin
230 init_key = main_query_init_key,
232 datatables_options = {
233 'iDisplayLength': 25,
234 'bLengthChange' : True,
240 resources_as_grid = QueryGrid(
242 domid = 'resources-grid',
244 # this is the query at the core of the slice list
246 query_all = query_resource_all,
247 # use 'hrn' as the internal unique key for this plugin
248 # xxx todo on querygrid as well
249 # init_key = main_query_init_key,
254 resources_as_scheduler = Scheduler(
259 query_all_resources = query_resource_all,
260 query_lease = sq_lease,
263 # with the new 'Filter' stuff on top, no need for anything but the querytable
264 resources_as_list_area = resources_as_list
269 resources_as_scheduler,
270 resources_as_list_area,
271 ] if do_query_leases else [
274 resources_as_list_area,
277 resources_sons.append(resources_as_grid)
279 resources_area = Tabs ( page=page,
283 outline_complete=True,
284 sons= resources_sons,
285 active_domid = 'resources-map',
286 persistent_active=True,
288 main_stack.insert (resources_area)
290 # --------------------------------------------------------------------------
293 if do_query_users and query_user_all is not None:
297 outline_complete = True,
300 active_domid = 'users-list',
302 main_stack.insert(tab_users)
304 tab_users.insert(QueryTable(
306 title = 'Users List',
307 domid = 'users-list',
308 # tab's sons preferably turn this off
310 # this is the query at the core of the slice list
312 query_all = query_user_all,
314 datatables_options = {
315 'iDisplayLength' : 25,
316 'bLengthChange' : True,
322 # --------------------------------------------------------------------------
324 measurements_stats_cpu = SliceStat(
326 domid = 'resources-stats-cpu',
331 slicename = slicename,
335 measurements_stats_mem = SliceStat(
336 title = "Memory Usage",
337 domid = 'resources-stats-mem',
342 slicename = slicename,
346 measurements_stats_asb = SliceStat(
347 title = "Traffic Sent",
348 domid = 'resources-stats-asb',
353 slicename = slicename,
357 measurements_stats_arb = SliceStat(
358 title = "Traffic Received",
359 domid = 'resources-stats-arb',
364 slicename = slicename,
368 tab_measurements = Tabs ( page=page,
369 domid="measurements",
372 title="Measurements",
373 outline_complete=True,
374 sons=[ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
375 active_domid = 'measurements_stats_cpu',
377 main_stack.insert (tab_measurements)
379 # tab_measurements = Tabs (
381 # active_domid = 'measurements-list',
382 # outline_complete = True,
384 # title = 'Measurements',
385 # domid = 'measurements',
387 # main_stack.insert(tab_measurements)
389 # tab_measurements.insert(QueryTable(
391 # title = 'Measurements',
392 # domid = 'measurements-list',
393 # # tab's sons preferably turn this off
395 # # this is the query at the core of the slice list
396 # query = sq_measurement,
397 # # do NOT set checkboxes to False
398 # # this table being otherwise empty, it just does not fly with dataTables
400 # datatables_options = {
401 # 'iDisplayLength' : 25,
402 # 'bLengthChange' : True,
403 # 'bAutoWidth' : True,
407 # # --------------------------------------------------------------------------
408 # # MESSAGES (we use transient=False for now)
410 main_stack.insert(Messages(
412 title = "Runtime messages for slice %s"%slicename,
415 # plain messages are probably less nice for production but more reliable for development for now
417 # these make sense only in non-transient mode..
419 toggled = 'persistent',
420 outline_complete = True,
423 # variables that will get passed to the view-unfold1.html template
426 # define 'unfold_main' to the template engine - the main contents
427 template_env [ 'unfold_main' ] = main_stack.render(request)
429 # more general variables expected in the template
430 template_env [ 'title' ] = '%(slicename)s'%locals()
431 # the menu items on the top
432 template_env [ 'topmenu_items' ] = topmenu_items_live('Slice', page)
433 # so we can sho who is logged
434 template_env [ 'username' ] = the_user (request)
436 # don't forget to run the requests
437 page.expose_queries ()
439 # xxx create another plugin with the same query and a different layout (with_datatables)
440 # show that it worls as expected, one single api call to backend and 2 refreshed views
442 # the prelude object in page contains a summary of the requirements() for all plugins
443 # define {js,css}_{files,chunks}
444 prelude_env = page.prelude_env()
445 template_env.update(prelude_env)
446 result=render_to_response ('view-unfold1.html',template_env,
447 context_instance=RequestContext(request))