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 manifoldapi.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 from myslice.theme import ThemeView
36 tmp_default_slice='ple.upmc.myslicedemo'
38 # temporary : turn off the users part to speed things up
51 class SliceView (LoginRequiredAutoLogoutView, ThemeView):
53 def get (self,request, slicename=tmp_default_slice):
56 page.add_css_files ('css/slice-view.css')
57 page.add_js_files ( [ "js/common.functions.js" ] )
58 page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
59 page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
60 page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
61 page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(ConfigEngine().manifold_url()))
63 metadata = page.get_metadata()
64 resource_md = metadata.details_by_object('resource')
65 resource_fields = [column['name'] for column in resource_md['column']]
67 user_md = metadata.details_by_object('user')
68 user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
70 # TODO The query to run is embedded in the URL
71 main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
74 #'resource.hrn', 'resource.urn',
75 'resource.hostname', 'resource.type',
76 'resource.network_hrn',
79 #'application.measurement_point.counter'
81 # for internal use in the querytable plugin;
82 # needs to be a unique column present for each returned record
83 main_query_init_key = 'hostname'
85 query_resource_all = Query.get('resource').select(resource_fields)
87 aq = AnalyzedQuery(main_query, metadata=metadata)
88 page.enqueue_query(main_query, analyzed_query=aq)
89 page.enqueue_query(query_resource_all)
91 # Required: the user must have an authority in its user.config
92 # XXX Temporary solution
93 user_query = Query().get('local:user').select('config','email')
94 user_details = execute_query(self.request, user_query)
96 # not always found in user_details...
98 # for user_detail in user_details:
99 # #email = user_detail['email']
100 # if user_detail['config']:
101 # config = json.loads(user_detail['config'])
102 # user_detail['authority'] = config.get('authority',"Unknown Authority")
104 # if user_detail['authority'] is not None:
105 # sub_authority = user_detail['authority'].split('.')
106 # root_authority = sub_authority[0]
107 # query_user_all = Query.get(root_authority+':user').select(user_fields)
109 # # XXX TODO this filter doesn't work - to be improved in Manifold
110 # #.filter_by('authority.authority_hrn', '=', user_detail['authority'])
112 # page.enqueue_query(query_user_all)
114 # print "authority of the user is not in local:user db"
115 query_user_all = Query.get('user').select(user_fields)
116 # query_user_all = None
118 # ... and for the relations
119 # XXX Let's hardcode resources for now
120 sq_resource = aq.subquery('resource')
121 sq_user = aq.subquery('user')
122 sq_lease = aq.subquery('lease')
123 sq_measurement = aq.subquery('measurement')
126 # Prepare the display according to all metadata
127 # (some parts will be pending, others can be triggered by users).
129 # For example slice measurements will not be requested by default...
131 # Create the base layout (Stack)...
134 title="Slice %s"%slicename,
138 # ... responsible for the slice properties...
145 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
148 # --------------------------------------------------------------------------
149 # QueryUpdater (Pending Operations)
151 main_stack.insert(QueryUpdater(
153 title = 'Pending operations',
156 # start turned off, it will open up itself when stuff comes in
159 outline_complete = True,
162 # --------------------------------------------------------------------------
165 # turn off for now -- see above
166 filter_query_editor = QueryEditor(
169 query_all = query_resource_all,
170 title = "Select Columns",
171 domid = 'select-columns',
173 filter_active_filters = ActiveFilters(
176 title = "Active Filters",
178 filters_area = Stack(
180 title = 'Filter Resources',
182 sons = [filter_query_editor,
183 filter_active_filters],
185 toggled = 'persistent',
186 outline_complete = True,
188 main_stack.insert (filters_area)
190 # --------------------------------------------------------------------------
192 # the resources part is made of a Tabs (Geographic, List),
194 resources_as_gmap = GoogleMap(
196 title = 'Geographic view',
197 domid = 'resources-map',
198 # tab's sons preferably turn this off
201 query_all = query_resource_all,
202 # this key is the one issued by google
203 googlemap_api_key = ConfigEngine().googlemap_api_key(),
204 # the key to use at init-time
205 init_key = main_query_init_key,
213 resources_as_3dmap = SensLabMap(
216 domid = 'senslabmap',
218 query_all = query_resource_all,
221 resources_as_list = QueryTable(
223 domid = 'resources-list',
225 # this is the query at the core of the slice list
227 query_all = query_resource_all,
228 init_key = main_query_init_key,
230 datatables_options = {
231 'iDisplayLength': 25,
232 'bLengthChange' : True,
238 resources_as_grid = QueryGrid(
240 domid = 'resources-grid',
242 # this is the query at the core of the slice list
244 query_all = query_resource_all,
245 init_key = main_query_init_key,
250 resources_as_scheduler = Scheduler(
255 query_all_resources = query_resource_all,
256 query_lease = sq_lease,
259 # with the new 'Filter' stuff on top, no need for anything but the querytable
260 resources_as_list_area = resources_as_list
265 resources_as_scheduler,
266 resources_as_list_area,
267 ] if do_query_leases else [
270 resources_as_list_area,
273 resources_sons.append(resources_as_grid)
275 resources_area = Tabs ( page=page,
279 outline_complete=True,
280 sons= resources_sons,
281 active_domid = 'resources-map',
282 persistent_active=True,
284 main_stack.insert (resources_area)
286 # --------------------------------------------------------------------------
289 if do_query_users and query_user_all is not None:
293 outline_complete = True,
296 active_domid = 'users-list',
298 main_stack.insert(tab_users)
300 tab_users.insert(QueryTable(
302 title = 'Users List',
303 domid = 'users-list',
304 # tab's sons preferably turn this off
306 # this is the query at the core of the slice list
308 query_all = query_user_all,
310 datatables_options = {
311 'iDisplayLength' : 25,
312 'bLengthChange' : True,
318 # --------------------------------------------------------------------------
320 measurements_stats_cpu = SliceStat(
322 domid = 'resources-stats-cpu',
327 slicename = slicename,
331 measurements_stats_mem = SliceStat(
332 title = "Memory Usage",
333 domid = 'resources-stats-mem',
338 slicename = slicename,
342 measurements_stats_asb = SliceStat(
343 title = "Traffic Sent",
344 domid = 'resources-stats-asb',
349 slicename = slicename,
353 measurements_stats_arb = SliceStat(
354 title = "Traffic Received",
355 domid = 'resources-stats-arb',
360 slicename = slicename,
364 tab_measurements = Tabs ( page=page,
365 domid = "measurements",
367 toggled = 'persistent',
368 title = "Measurements",
369 outline_complete=True,
370 sons = [ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
371 active_domid = 'resources-stats-cpu',
372 persistent_active = True,
374 main_stack.insert (tab_measurements)
376 # tab_measurements = Tabs (
378 # active_domid = 'measurements-list',
379 # outline_complete = True,
381 # title = 'Measurements',
382 # domid = 'measurements',
384 # main_stack.insert(tab_measurements)
386 # tab_measurements.insert(QueryTable(
388 # title = 'Measurements',
389 # domid = 'measurements-list',
390 # # tab's sons preferably turn this off
392 # # this is the query at the core of the slice list
393 # query = sq_measurement,
394 # # do NOT set checkboxes to False
395 # # this table being otherwise empty, it just does not fly with dataTables
397 # datatables_options = {
398 # 'iDisplayLength' : 25,
399 # 'bLengthChange' : True,
400 # 'bAutoWidth' : True,
404 # # --------------------------------------------------------------------------
405 # # MESSAGES (we use transient=False for now)
407 main_stack.insert(Messages(
409 title = "Runtime messages for slice %s"%slicename,
412 # plain messages are probably less nice for production but more reliable for development for now
414 # these make sense only in non-transient mode..
416 toggled = 'persistent',
417 outline_complete = True,
420 # variables that will get passed to the view-unfold1.html template
423 # define 'unfold_main' to the template engine - the main contents
424 template_env [ 'unfold_main' ] = main_stack.render(request)
426 # more general variables expected in the template
427 template_env [ 'title' ] = '%(slicename)s'%locals()
428 # the menu items on the top
429 template_env [ 'topmenu_items' ] = topmenu_items_live('Slice', page)
430 # so we can sho who is logged
431 template_env [ 'username' ] = the_user (request)
433 template_env ['theme'] = self.theme
435 # don't forget to run the requests
436 page.expose_js_metadata()
437 # the prelude object in page contains a summary of the requirements() for all plugins
438 # define {js,css}_{files,chunks}
439 template_env.update(page.prelude_env())
441 return render_to_response ('view-unfold1.html',template_env,
442 context_instance=RequestContext(request))