1 from django.template import RequestContext
2 from django.shortcuts import render_to_response
4 from unfold.loginrequired import LoginRequiredAutoLogoutView
6 from unfold.page import Page
7 from manifold.core.query import Query, AnalyzedQuery
9 from ui.topmenu import topmenu_items, the_user
11 from plugins.raw import Raw
12 from plugins.stack import Stack
13 from plugins.tabs import Tabs
14 from plugins.querytable import QueryTable
15 from plugins.queryupdater import QueryUpdater
16 from plugins.googlemap import GoogleMap
17 from plugins.senslabmap import SensLabMap
18 from plugins.scheduler import Scheduler
19 from plugins.querycode import QueryCode
20 from plugins.query_editor import QueryEditor
21 from plugins.active_filters import ActiveFilters
22 from plugins.quickfilter import QuickFilter
23 from plugins.messages import Messages
24 from plugins.slicestat import SliceStat
26 from myslice.config import Config
28 tmp_default_slice='ple.upmc.myslicedemo'
30 # temporary : turn off the users part to speed things up
37 class SliceView (LoginRequiredAutoLogoutView):
39 def get (self,request, slicename=tmp_default_slice):
42 page.add_css_files ('css/slice-view.css')
43 page.add_js_files ( [ "js/common.functions.js" ] )
44 page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
45 page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
47 page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
48 page.expose_js_metadata()
50 metadata = page.get_metadata()
51 resource_md = metadata.details_by_object('resource')
52 resource_fields = [column['name'] for column in resource_md['column']]
54 user_md = metadata.details_by_object('user')
55 user_fields = ['user_hrn'] # [column['name'] for column in user_md['column']]
57 # TODO The query to run is embedded in the URL
58 main_query = Query.get('slice').filter_by('slice_hrn', '=', slicename)
61 'resource.hrn', 'resource.hostname', 'resource.type',
62 'resource.network_hrn',
65 #'application.measurement_point.counter'
67 # for internal use in the querytable plugin;
68 # needs to be a unique column present for each returned record
69 main_query_key = 'hrn'
71 query_resource_all = Query.get('resource').select(resource_fields)
73 query_user_all = Query.get('user').select(user_fields)
75 aq = AnalyzedQuery(main_query, metadata=metadata)
76 page.enqueue_query(main_query, analyzed_query=aq)
77 page.enqueue_query(query_resource_all)
79 page.enqueue_query(query_user_all)
81 # ... and for the relations
82 # XXX Let's hardcode resources for now
83 sq_resource = aq.subquery('resource')
84 sq_user = aq.subquery('user')
85 sq_lease = aq.subquery('lease')
86 sq_measurement = aq.subquery('measurement')
89 # Prepare the display according to all metadata
90 # (some parts will be pending, others can be triggered by users).
92 # For example slice measurements will not be requested by default...
94 # Create the base layout (Stack)...
97 title="Slice %s"%slicename,
101 # ... responsible for the slice properties...
108 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
111 # --------------------------------------------------------------------------
112 # QueryUpdater (Pending Operations)
114 main_stack.insert(QueryUpdater(
116 title = 'Pending operations',
119 # start turned off, it will open up itself when stuff comes in
122 outline_complete = True,
125 # --------------------------------------------------------------------------
128 filter_query_editor = QueryEditor(
131 query_all = query_resource_all,
132 title = "Select Columns",
133 domid = 'select-columns',
135 filter_active_filters = ActiveFilters(
138 title = "Active Filters",
140 filters_area = Stack(
142 title = 'Filter Resources',
144 sons = [filter_query_editor, filter_active_filters],
146 toggled = 'persistent',
147 outline_complete = True,
149 main_stack.insert (filters_area)
151 # --------------------------------------------------------------------------
153 # the resources part is made of a Tabs (Geographic, List),
155 resources_as_gmap = GoogleMap(
157 title = 'Geographic view',
158 domid = 'resources-map',
159 # tab's sons preferably turn this off
162 query_all = query_resource_all,
163 googlemap_api_key = Config().googlemap_api_key(),
171 resources_as_3dmap = SensLabMap(
174 domid = 'senslabmap',
176 query_all = query_resource_all,
179 resources_as_list = QueryTable(
181 domid = 'resources-list',
183 # this is the query at the core of the slice list
185 query_all = query_resource_all,
186 # safer to use 'hrn' as the internal unique key for this plugin
187 id_key = main_query_key,
189 datatables_options = {
190 'iDisplayLength': 25,
191 'bLengthChange' : True,
196 resources_as_scheduler = Scheduler(
201 query_all_resources = query_resource_all,
202 query_lease = sq_lease,
205 # with the new 'Filter' stuff on top, no need for anything but the querytable
206 resources_as_list_area = resources_as_list
208 resources_area = Tabs ( page=page,
212 outline_complete=True,
216 resources_as_scheduler,
217 resources_as_list_area, ],
218 active_domid = 'resources-map',
219 persistent_active=True,
221 main_stack.insert (resources_area)
223 # --------------------------------------------------------------------------
230 outline_complete = True,
233 active_domid = 'users-list',
235 main_stack.insert(tab_users)
237 tab_users.insert(QueryTable(
239 title = 'Users List',
240 domid = 'users-list',
241 # tab's sons preferably turn this off
243 # this is the query at the core of the slice list
245 query_all = query_user_all,
247 datatables_options = {
248 'iDisplayLength' : 25,
249 'bLengthChange' : True,
255 # --------------------------------------------------------------------------
257 measurements_stats_cpu = SliceStat(
259 domid = 'resources-stats-cpu',
264 slicename = slicename,
268 measurements_stats_mem = SliceStat(
269 title = "Memory Usage",
270 domid = 'resources-stats-mem',
275 slicename = slicename,
279 measurements_stats_asb = SliceStat(
280 title = "Traffic Sent",
281 domid = 'resources-stats-asb',
286 slicename = slicename,
290 measurements_stats_arb = SliceStat(
291 title = "Traffic Received",
292 domid = 'resources-stats-arb',
297 slicename = slicename,
301 tab_measurements = Tabs ( page=page,
302 domid="measurements",
305 title="Measurements",
306 outline_complete=True,
307 sons=[ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
308 active_domid = 'measurements_stats_cpu',
310 main_stack.insert (tab_measurements)
312 # tab_measurements = Tabs (
314 # active_domid = 'measurements-list',
315 # outline_complete = True,
317 # title = 'Measurements',
318 # domid = 'measurements',
320 # main_stack.insert(tab_measurements)
322 # tab_measurements.insert(QueryTable(
324 # title = 'Measurements',
325 # domid = 'measurements-list',
326 # # tab's sons preferably turn this off
328 # # this is the query at the core of the slice list
329 # query = sq_measurement,
330 # # do NOT set checkboxes to False
331 # # this table being otherwise empty, it just does not fly with dataTables
333 # datatables_options = {
334 # 'iDisplayLength' : 25,
335 # 'bLengthChange' : True,
336 # 'bAutoWidth' : True,
340 # # --------------------------------------------------------------------------
341 # # MESSAGES (we use transient=False for now)
343 main_stack.insert(Messages(
345 title = "Runtime messages for slice %s"%slicename,
348 # plain messages are probably less nice for production but more reliable for development for now
350 # these make sense only in non-transient mode..
352 toggled = 'persistent',
353 outline_complete = True,
357 # variables that will get passed to the view-unfold1.html template
360 # define 'unfold_main' to the template engine - the main contents
361 template_env [ 'unfold_main' ] = main_stack.render(request)
363 # more general variables expected in the template
364 template_env [ 'title' ] = '%(slicename)s'%locals()
365 # the menu items on the top
366 template_env [ 'topmenu_items' ] = topmenu_items('Slice', request)
367 # so we can sho who is logged
368 template_env [ 'username' ] = the_user (request)
370 # don't forget to run the requests
371 page.expose_queries ()
373 # xxx create another plugin with the same query and a different layout (with_datatables)
374 # show that it worls as expected, one single api call to backend and 2 refreshed views
376 # the prelude object in page contains a summary of the requirements() for all plugins
377 # define {js,css}_{files,chunks}
378 prelude_env = page.prelude_env()
379 template_env.update(prelude_env)
380 result=render_to_response ('view-unfold1.html',template_env,
381 context_instance=RequestContext(request))