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'
68 query_resource_all = Query.get('resource').select(resource_fields)
70 query_user_all = Query.get('user').select(user_fields)
72 aq = AnalyzedQuery(main_query, metadata=metadata)
73 page.enqueue_query(main_query, analyzed_query=aq)
74 page.enqueue_query(query_resource_all)
76 page.enqueue_query(query_user_all)
78 # ... and for the relations
79 # XXX Let's hardcode resources for now
80 sq_resource = aq.subquery('resource')
81 sq_user = aq.subquery('user')
82 sq_lease = aq.subquery('lease')
83 sq_measurement = aq.subquery('measurement')
86 # Prepare the display according to all metadata
87 # (some parts will be pending, others can be triggered by users).
89 # For example slice measurements will not be requested by default...
91 # Create the base layout (Stack)...
94 title="Slice %s"%slicename,
98 # ... responsible for the slice properties...
105 html="<h2 class='well well-lg'> Slice %s</h2>"%slicename)
108 # --------------------------------------------------------------------------
109 # QueryUpdater (Pending Operations)
111 main_stack.insert(QueryUpdater(
113 title = 'Pending operations',
116 # start turned off, it will open up itself when stuff comes in
119 outline_complete = True,
122 # --------------------------------------------------------------------------
125 filter_query_editor = QueryEditor(
128 query_all = query_resource_all,
129 title = "Select Columns",
130 domid = 'select-columns',
132 filter_active_filters = ActiveFilters(
135 title = "Active Filters",
137 filters_area = Stack(
139 title = 'Filter Resources',
141 sons = [filter_query_editor, filter_active_filters],
143 toggled = 'persistent',
144 outline_complete = True,
146 main_stack.insert (filters_area)
148 # --------------------------------------------------------------------------
150 # the resources part is made of a Tabs (Geographic, List),
152 resources_as_gmap = GoogleMap(
154 title = 'Geographic view',
155 domid = 'resources-map',
156 # tab's sons preferably turn this off
159 query_all = query_resource_all,
160 googlemap_api_key = Config().googlemap_api_key(),
168 resources_as_3dmap = SensLabMap(
171 domid = 'senslabmap',
173 query_all = query_resource_all,
176 resources_as_list = QueryTable(
178 domid = 'resources-list',
180 # this is the query at the core of the slice list
182 query_all = query_resource_all,
184 datatables_options = {
185 'iDisplayLength': 25,
186 'bLengthChange' : True,
191 resources_as_scheduler = Scheduler(
196 query_all_resources = query_resource_all,
197 query_lease = sq_lease,
200 # with the new 'Filter' stuff on top, no need for anything but the querytable
201 resources_as_list_area = resources_as_list
203 resources_area = Tabs ( page=page,
207 outline_complete=True,
209 resources_as_scheduler,
212 resources_as_list_area, ],
213 active_domid = 'resources-map',
215 main_stack.insert (resources_area)
217 # --------------------------------------------------------------------------
224 outline_complete = True,
227 active_domid = 'users-list',
229 main_stack.insert(tab_users)
231 tab_users.insert(QueryTable(
233 title = 'Users List',
234 domid = 'users-list',
235 # tab's sons preferably turn this off
237 # this is the query at the core of the slice list
239 query_all = query_user_all,
241 datatables_options = {
242 'iDisplayLength' : 25,
243 'bLengthChange' : True,
249 # --------------------------------------------------------------------------
251 measurements_stats_cpu = SliceStat(
253 domid = 'resources-stats-cpu',
258 slicename = slicename,
262 measurements_stats_mem = SliceStat(
263 title = "Memory Usage",
264 domid = 'resources-stats-mem',
269 slicename = slicename,
273 measurements_stats_asb = SliceStat(
274 title = "Traffic Sent",
275 domid = 'resources-stats-asb',
280 slicename = slicename,
284 measurements_stats_arb = SliceStat(
285 title = "Traffic Received",
286 domid = 'resources-stats-arb',
291 slicename = slicename,
295 tab_measurements = Tabs ( page=page,
296 domid="measurements",
299 title="Measurements",
300 outline_complete=True,
301 sons=[ measurements_stats_cpu, measurements_stats_mem, measurements_stats_asb, measurements_stats_arb ],
302 active_domid = 'measurements_stats_cpu',
304 main_stack.insert (tab_measurements)
306 # tab_measurements = Tabs (
308 # active_domid = 'measurements-list',
309 # outline_complete = True,
311 # title = 'Measurements',
312 # domid = 'measurements',
314 # main_stack.insert(tab_measurements)
316 # tab_measurements.insert(QueryTable(
318 # title = 'Measurements',
319 # domid = 'measurements-list',
320 # # tab's sons preferably turn this off
322 # # this is the query at the core of the slice list
323 # query = sq_measurement,
324 # # do NOT set checkboxes to False
325 # # this table being otherwise empty, it just does not fly with dataTables
327 # datatables_options = {
328 # 'iDisplayLength' : 25,
329 # 'bLengthChange' : True,
330 # 'bAutoWidth' : True,
334 # # --------------------------------------------------------------------------
335 # # MESSAGES (we use transient=False for now)
337 main_stack.insert(Messages(
339 title = "Runtime messages for slice %s"%slicename,
342 # plain messages are probably less nice for production but more reliable for development for now
344 # these make sense only in non-transient mode..
346 toggled = 'persistent',
347 outline_complete = True,
351 # variables that will get passed to the view-unfold1.html template
354 # define 'unfold_main' to the template engine - the main contents
355 template_env [ 'unfold_main' ] = main_stack.render(request)
357 # more general variables expected in the template
358 template_env [ 'title' ] = '%(slicename)s'%locals()
359 # the menu items on the top
360 template_env [ 'topmenu_items' ] = topmenu_items('Slice', request)
361 # so we can sho who is logged
362 template_env [ 'username' ] = the_user (request)
364 # don't forget to run the requests
365 page.expose_queries ()
367 # xxx create another plugin with the same query and a different layout (with_datatables)
368 # show that it worls as expected, one single api call to backend and 2 refreshed views
370 # the prelude object in page contains a summary of the requirements() for all plugins
371 # define {js,css}_{files,chunks}
372 prelude_env = page.prelude_env()
373 template_env.update(prelude_env)
374 result=render_to_response ('view-unfold1.html',template_env,
375 context_instance=RequestContext(request))