diff options
Diffstat (limited to 'src/lib/Server/Reports/reports')
-rw-r--r-- | src/lib/Server/Reports/reports/models.py | 108 | ||||
-rw-r--r-- | src/lib/Server/Reports/reports/templates/base.html | 2 | ||||
-rw-r--r-- | src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py | 20 | ||||
-rw-r--r-- | src/lib/Server/Reports/reports/templatetags/syntax_coloring.py | 13 | ||||
-rw-r--r-- | src/lib/Server/Reports/reports/views.py | 168 |
5 files changed, 185 insertions, 126 deletions
diff --git a/src/lib/Server/Reports/reports/models.py b/src/lib/Server/Reports/reports/models.py index 1963a9090..d94b2e1ba 100644 --- a/src/lib/Server/Reports/reports/models.py +++ b/src/lib/Server/Reports/reports/models.py @@ -29,6 +29,7 @@ TYPE_CHOICES = ( (TYPE_EXTRA, 'Extra'), ) + def convert_entry_type_to_id(type_name): """Convert a entry type to its entry id""" for e_id, e_name in TYPE_CHOICES: @@ -36,23 +37,25 @@ def convert_entry_type_to_id(type_name): return e_id return -1 + class ClientManager(models.Manager): """Extended client manager functions.""" def active(self, timestamp=None): - """returns a set of clients that have been created and have not yet been - expired as of optional timestmamp argument. Timestamp should be a - datetime object.""" - + """returns a set of clients that have been created and have not + yet been expired as of optional timestmamp argument. Timestamp + should be a datetime object.""" + if timestamp == None: timestamp = datetime.now() elif not isinstance(timestamp, datetime): - raise ValueError, 'Expected a datetime object' + raise ValueError('Expected a datetime object') else: try: - timestamp = datetime(*strptime(timestamp, "%Y-%m-%d %H:%M:%S")[0:6]) + timestamp = datetime(*strptime(timestamp, + "%Y-%m-%d %H:%M:%S")[0:6]) except ValueError: return self.none() - + return self.filter(Q(expiration__gt=timestamp) | Q(expiration__isnull=True), creation__lt=timestamp) @@ -65,25 +68,27 @@ class Client(models.Model): null=True, blank=True, related_name="parent_client") expiration = models.DateTimeField(blank=True, null=True) - + def __str__(self): return self.name objects = ClientManager() - + class Admin: pass + class Ping(models.Model): """Represents a ping of a client (sparsely).""" client = models.ForeignKey(Client, related_name="pings") starttime = models.DateTimeField() endtime = models.DateTimeField() - status = models.CharField(max_length=4, choices=PING_CHOICES)#up/down + status = models.CharField(max_length=4, choices=PING_CHOICES) # up/down class Meta: get_latest_by = 'endtime' - + + class InteractiveManager(models.Manager): """Manages interactions objects.""" @@ -94,31 +99,31 @@ class InteractiveManager(models.Manager): This method uses aggregated queries to return a ValuesQueryDict object. Faster then raw sql since this is executed as a single query. """ - - return self.values('client').annotate(max_timestamp=Max('timestamp')).values() - def interaction_per_client(self, maxdate = None, active_only=True): + return list(self.values('client').annotate(max_timestamp=Max('timestamp')).values()) + + def interaction_per_client(self, maxdate=None, active_only=True): """ Returns the most recent interactions for clients as of a date Arguments: maxdate -- datetime object. Most recent date to pull. (dafault None) active_only -- Include only active clients (default True) - + """ - if maxdate and not isinstance(maxdate,datetime): - raise ValueError, 'Expected a datetime object' - return self.filter(id__in = self.get_interaction_per_client_ids(maxdate, active_only)) + if maxdate and not isinstance(maxdate, datetime): + raise ValueError('Expected a datetime object') + return self.filter(id__in=self.get_interaction_per_client_ids(maxdate, active_only)) - def get_interaction_per_client_ids(self, maxdate = None, active_only=True): + def get_interaction_per_client_ids(self, maxdate=None, active_only=True): """ Returns the ids of most recent interactions for clients as of a date. Arguments: maxdate -- datetime object. Most recent date to pull. (dafault None) active_only -- Include only active clients (default True) - + """ from django.db import connection cursor = connection.cursor() @@ -127,10 +132,10 @@ class InteractiveManager(models.Manager): sql = 'select reports_interaction.id, x.client_id from (select client_id, MAX(timestamp) ' + \ 'as timer from reports_interaction' if maxdate: - if not isinstance(maxdate,datetime): - raise ValueError, 'Expected a datetime object' + if not isinstance(maxdate, datetime): + raise ValueError('Expected a datetime object') sql = sql + " where timestamp <= '%s' " % maxdate - cfilter = "(expiration is null or expiration > '%s') and creation <= '%s'" % (maxdate,maxdate) + cfilter = "(expiration is null or expiration > '%s') and creation <= '%s'" % (maxdate, maxdate) sql = sql + ' GROUP BY client_id) x, reports_interaction where ' + \ 'reports_interaction.client_id = x.client_id AND reports_interaction.timestamp = x.timer' if active_only: @@ -144,16 +149,17 @@ class InteractiveManager(models.Manager): pass return [] + class Interaction(models.Model): """Models each reconfiguration operation interaction between client and server.""" client = models.ForeignKey(Client, related_name="interactions",) - timestamp = models.DateTimeField()#Timestamp for this record - state = models.CharField(max_length=32)#good/bad/modified/etc - repo_rev_code = models.CharField(max_length=64)#repo revision at time of interaction - client_version = models.CharField(max_length=32)#Client Version - goodcount = models.IntegerField()#of good config-items - totalcount = models.IntegerField()#of total config-items - server = models.CharField(max_length=256) # Name of the server used for the interaction + timestamp = models.DateTimeField() # Timestamp for this record + state = models.CharField(max_length=32) # good/bad/modified/etc + repo_rev_code = models.CharField(max_length=64) # repo revision at time of interaction + client_version = models.CharField(max_length=32) # Client Version + goodcount = models.IntegerField() # of good config-items + totalcount = models.IntegerField() # of total config-items + server = models.CharField(max_length=256) # Name of the server used for the interaction bad_entries = models.IntegerField(default=-1) modified_entries = models.IntegerField(default=-1) extra_entries = models.IntegerField(default=-1) @@ -163,25 +169,25 @@ class Interaction(models.Model): def percentgood(self): if not self.totalcount == 0: - return (self.goodcount/float(self.totalcount))*100 + return (self.goodcount / float(self.totalcount)) * 100 else: return 0 def percentbad(self): if not self.totalcount == 0: - return ((self.totalcount-self.goodcount)/(float(self.totalcount)))*100 + return ((self.totalcount - self.goodcount) / (float(self.totalcount))) * 100 else: return 0 - + def isclean(self): if (self.bad_entry_count() == 0 and self.goodcount == self.totalcount): return True else: return False - + def isstale(self): - if (self == self.client.current_interaction):#Is Mostrecent - if(datetime.now()-self.timestamp > timedelta(hours=25) ): + if (self == self.client.current_interaction): # Is Mostrecent + if(datetime.now() - self.timestamp > timedelta(hours=25)): return True else: return False @@ -194,10 +200,11 @@ class Interaction(models.Model): return True else: return False + def save(self): - super(Interaction, self).save() #call the real save... + super(Interaction, self).save() # call the real save... self.client.current_interaction = self.client.interactions.latest() - self.client.save()#save again post update + self.client.save() # save again post update def delete(self): '''Override the default delete. Allows us to remove Performance items''' @@ -239,35 +246,38 @@ class Interaction(models.Model): self.extra_entries = Entries_interactions.objects.filter(interaction=self, type=TYPE_EXTRA).count() self.save() return self.extra_entries - + objects = InteractiveManager() class Admin: list_display = ('client', 'timestamp', 'state') list_filter = ['client', 'timestamp'] pass + class Meta: get_latest_by = 'timestamp' ordering = ['-timestamp'] unique_together = ("client", "timestamp") + class Reason(models.Model): """reason why modified or bad entry did not verify, or changed.""" owner = models.TextField(max_length=128, blank=True) current_owner = models.TextField(max_length=128, blank=True) group = models.TextField(max_length=128, blank=True) current_group = models.TextField(max_length=128, blank=True) - perms = models.TextField(max_length=4, blank=True)#txt fixes typing issue + perms = models.TextField(max_length=4, blank=True) # txt fixes typing issue current_perms = models.TextField(max_length=4, blank=True) - status = models.TextField(max_length=3, blank=True)#on/off/(None) - current_status = models.TextField(max_length=1, blank=True)#on/off/(None) + status = models.TextField(max_length=3, blank=True) # on/off/(None) + current_status = models.TextField(max_length=1, blank=True) # on/off/(None) to = models.TextField(max_length=256, blank=True) current_to = models.TextField(max_length=256, blank=True) version = models.TextField(max_length=128, blank=True) current_version = models.TextField(max_length=128, blank=True) - current_exists = models.BooleanField()#False means its missing. Default True + current_exists = models.BooleanField() # False means its missing. Default True current_diff = models.TextField(max_length=1280, blank=True) is_binary = models.BooleanField(default=False) + def _str_(self): return "Reason" @@ -278,7 +288,7 @@ class Reason(models.Model): cursor = connection.cursor() cursor.execute('delete from reports_reason where not exists (select rei.id from reports_entries_interactions rei where rei.reason_id = reports_reason.id)') transaction.set_dirty() - + class Entries(models.Model): """Contains all the entries feed by the client.""" @@ -295,19 +305,22 @@ class Entries(models.Model): cursor = connection.cursor() cursor.execute('delete from reports_entries where not exists (select rei.id from reports_entries_interactions rei where rei.entry_id = reports_entries.id)') transaction.set_dirty() - + + class Entries_interactions(models.Model): """Define the relation between the reason, the interaction and the entry.""" entry = models.ForeignKey(Entries) reason = models.ForeignKey(Reason) interaction = models.ForeignKey(Interaction) type = models.IntegerField(choices=TYPE_CHOICES) - + + class Performance(models.Model): """Object representing performance data for any interaction.""" interaction = models.ManyToManyField(Interaction, related_name="performance_items") metric = models.CharField(max_length=128) value = models.DecimalField(max_digits=32, decimal_places=16) + def __str__(self): return self.metric @@ -318,7 +331,8 @@ class Performance(models.Model): cursor = connection.cursor() cursor.execute('delete from reports_performance where not exists (select ri.id from reports_performance_interaction ri where ri.performance_id = reports_performance.id)') transaction.set_dirty() - + + class InternalDatabaseVersion(models.Model): """Object that tell us to witch version is the database.""" version = models.IntegerField() diff --git a/src/lib/Server/Reports/reports/templates/base.html b/src/lib/Server/Reports/reports/templates/base.html index a64f1c76a..6ef4c9aff 100644 --- a/src/lib/Server/Reports/reports/templates/base.html +++ b/src/lib/Server/Reports/reports/templates/base.html @@ -87,7 +87,7 @@ <div style='clear:both'></div> </div><!-- document --> <div id="footer"> - <span>Bcfg2 Version 1.2.0pre1</span> + <span>Bcfg2 Version 1.2.0pre2</span> </div> <div id="calendar_div" style='position:absolute; visibility:hidden; background-color:white; layer-background-color:white;'></div> diff --git a/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py b/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py index 7fffe289d..629984f26 100644 --- a/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py +++ b/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py @@ -21,9 +21,9 @@ def page_navigator(context): path = context['request'].META['PATH_INFO'] total_pages = int(context['total_pages']) records_per_page = int(context['records_per_page']) - except KeyError, e: + except KeyError: return fragment - except ValueError, e: + except ValueError: return fragment if total_pages < 2: @@ -84,7 +84,8 @@ def page_navigator(context): except Resolver404: path = "404" - except NoReverseMatch, nr: + except NoReverseMatch: + nr = sys.exc_info()[1] path = "NoReverseMatch: %s" % nr except ValueError: path = "ValueError" @@ -193,12 +194,13 @@ class AddUrlFilter(template.Node): del kwargs['server'] try: link = reverse(view, args=args, kwargs=kwargs) - except NoReverseMatch, rm: + except NoReverseMatch: link = reverse(self.fallback_view, args=None, kwargs={ filter_name: filter_value }) - except NoReverseMatch, rm: + except NoReverseMatch: + rm = sys.exc_info()[1] raise rm - except (Resolver404, ValueError), e: + except (Resolver404, ValueError): pass return link @@ -219,9 +221,9 @@ def add_url_filter(parser, token): filter_name = filter_name.strip() filter_value = parser.compile_filter(filter_value) except ValueError: - raise template.TemplateSyntaxError, "%r tag requires exactly one argument" % token.contents.split()[0] + raise template.TemplateSyntaxError("%r tag requires exactly one argument" % token.contents.split()[0]) if not filter_name or not filter_value: - raise template.TemplateSyntaxError, "argument should be a filter=value pair" + raise template.TemplateSyntaxError("argument should be a filter=value pair") return AddUrlFilter(filter_name, filter_value) @@ -268,7 +270,7 @@ def to_media_url(parser, token): tag_name, filter_value = token.split_contents() filter_value = parser.compile_filter(filter_value) except ValueError: - raise template.TemplateSyntaxError, "%r tag requires exactly one argument" % token.contents.split()[0] + raise template.TemplateSyntaxError("%r tag requires exactly one argument" % token.contents.split()[0]) return MediaTag(filter_value) diff --git a/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py b/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py index 43dafb262..291528e2e 100644 --- a/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py +++ b/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py @@ -1,3 +1,4 @@ +import sys from django import template from django.utils.encoding import smart_unicode, smart_str from django.utils.html import conditional_escape @@ -14,6 +15,12 @@ try: except: colorize = False +def u_str(string): + if sys.hexversion >= 0x03000000: + return string + else: + return unicode(string) + @register.filter def syntaxhilight(value, arg="diff", autoescape=None): """ @@ -26,9 +33,9 @@ def syntaxhilight(value, arg="diff", autoescape=None): if colorize: try: - output = u'<style type="text/css">' \ + output = u_str('<style type="text/css">') \ + smart_unicode(HtmlFormatter().get_style_defs('.highlight')) \ - + u'</style>' + + u_str('</style>') lexer = get_lexer_by_name(arg) output += highlight(value, lexer, HtmlFormatter()) @@ -36,6 +43,6 @@ def syntaxhilight(value, arg="diff", autoescape=None): except: return value else: - return mark_safe(u'<div class="note-box">Tip: Install pygments for highlighting</div><pre>%s</pre>' % value) + return mark_safe(u_str('<div class="note-box">Tip: Install pygments for highlighting</div><pre>%s</pre>') % value) syntaxhilight.needs_autoescape = True diff --git a/src/lib/Server/Reports/reports/views.py b/src/lib/Server/Reports/reports/views.py index 00d35c092..ccd71a60e 100644 --- a/src/lib/Server/Reports/reports/views.py +++ b/src/lib/Server/Reports/reports/views.py @@ -3,22 +3,26 @@ Report views Functions to handle all of the reporting views. """ -from django.template import Context, RequestContext, loader -from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError, Http404 +from datetime import datetime, timedelta +import sys +from time import strptime + +from django.template import Context, RequestContext +from django.http import \ + HttpResponse, HttpResponseRedirect, HttpResponseServerError, Http404 from django.shortcuts import render_to_response, get_object_or_404 -from django.core.urlresolvers import resolve, reverse, Resolver404, NoReverseMatch +from django.core.urlresolvers import \ + resolve, reverse, Resolver404, NoReverseMatch from django.db import connection -from django.db.backends import util from Bcfg2.Server.Reports.reports.models import * -from datetime import datetime, timedelta -from time import strptime -import sys + class PaginationError(Exception): """This error is raised when pagination cannot be completed.""" pass + def server_error(request): """ 500 error handler. @@ -29,6 +33,7 @@ def server_error(request): from django.views import debug return debug.technical_500_response(request, *sys.exc_info()) + def timeview(fn): """ Setup a timeview view @@ -53,28 +58,32 @@ def timeview(fn): if cal_date.find(' ') > -1: kw['hour'] = timestamp.hour kw['minute'] = timestamp.minute - return HttpResponseRedirect(reverse(view, args=args, kwargs=kw)) + return HttpResponseRedirect(reverse(view, + args=args, + kwargs=kw)) except KeyError: pass except: pass # FIXME - Handle this - + """Extract timestamp from args.""" timestamp = None try: - timestamp = datetime(int(kwargs.pop('year')), int(kwargs.pop('month')), + timestamp = datetime(int(kwargs.pop('year')), + int(kwargs.pop('month')), int(kwargs.pop('day')), int(kwargs.pop('hour', 0)), int(kwargs.pop('minute', 0)), 0) kwargs['timestamp'] = timestamp except KeyError: pass - except: + except: raise return fn(request, **kwargs) return _handle_timeview - + + def config_item(request, pk, type="bad"): """ Display a single entry. @@ -83,30 +92,33 @@ def config_item(request, pk, type="bad"): """ item = get_object_or_404(Entries_interactions, id=pk) - timestamp=item.interaction.timestamp - time_start=item.interaction.timestamp.replace(\ - hour=0, minute=0, second=0, microsecond=0) - time_end=time_start + timedelta(days=1) - - todays_data = Interaction.objects.filter(\ - timestamp__gte=time_start,\ - timestamp__lt=time_end) - shared_entries = Entries_interactions.objects.filter(entry=item.entry,\ - reason=item.reason, type=item.type, - interaction__in=[x['id']\ - for x in todays_data.values('id')]) + timestamp = item.interaction.timestamp + time_start = item.interaction.timestamp.replace(hour=0, + minute=0, + second=0, + microsecond=0) + time_end = time_start + timedelta(days=1) + + todays_data = Interaction.objects.filter(timestamp__gte=time_start, + timestamp__lt=time_end) + shared_entries = Entries_interactions.objects.filter(entry=item.entry, + reason=item.reason, + type=item.type, + interaction__in=[x['id']\ + for x in todays_data.values('id')]) associated_list = Interaction.objects.filter(id__in=[x['interaction']\ for x in shared_entries.values('interaction')])\ - .order_by('client__name','timestamp').select_related().all() + .order_by('client__name', 'timestamp').select_related().all() return render_to_response('config_items/item.html', - {'item':item, - 'isextra': item.type == TYPE_EXTRA, - 'mod_or_bad': type, - 'associated_list':associated_list, - 'timestamp' : timestamp}, - context_instance=RequestContext(request)) + {'item': item, + 'isextra': item.type == TYPE_EXTRA, + 'mod_or_bad': type, + 'associated_list': associated_list, + 'timestamp': timestamp}, + context_instance=RequestContext(request)) + @timeview def config_item_list(request, type, timestamp=None): @@ -115,11 +127,12 @@ def config_item_list(request, type, timestamp=None): type = convert_entry_type_to_id(type) if type < 0: raise Http404 - + current_clients = Interaction.objects.get_interaction_per_client_ids(timestamp) item_list_dict = {} seen = dict() - for x in Entries_interactions.objects.filter(interaction__in=current_clients, type=type).select_related(): + for x in Entries_interactions.objects.filter(interaction__in=current_clients, + type=type).select_related(): if (x.entry, x.reason) in seen: continue seen[(x.entry, x.reason)] = 1 @@ -129,13 +142,15 @@ def config_item_list(request, type, timestamp=None): item_list_dict[x.entry.kind] = [x] for kind in item_list_dict: - item_list_dict[kind].sort(lambda a,b: cmp(a.entry.name, b.entry.name)) + item_list_dict[kind].sort(lambda a, b: cmp(a.entry.name, b.entry.name)) - return render_to_response('config_items/listing.html', {'item_list_dict':item_list_dict, - 'mod_or_bad':mod_or_bad, - 'timestamp' : timestamp}, + return render_to_response('config_items/listing.html', + {'item_list_dict': item_list_dict, + 'mod_or_bad': mod_or_bad, + 'timestamp': timestamp}, context_instance=RequestContext(request)) + @timeview def client_index(request, timestamp=None): """ @@ -149,8 +164,10 @@ def client_index(request, timestamp=None): .order_by("client__name").all() return render_to_response('clients/index.html', - { 'inter_list': list, 'timestamp' : timestamp}, - context_instance=RequestContext(request)) + {'inter_list': list, + 'timestamp': timestamp}, + context_instance=RequestContext(request)) + @timeview def client_detailed_list(request, timestamp=None, **kwargs): @@ -165,7 +182,8 @@ def client_detailed_list(request, timestamp=None, **kwargs): kwargs['page_limit'] = 0 return render_history_view(request, 'clients/detailed-list.html', **kwargs) -def client_detail(request, hostname = None, pk = None): + +def client_detail(request, hostname=None, pk=None): context = dict() client = get_object_or_404(Client, name=hostname) if(pk == None): @@ -177,6 +195,7 @@ def client_detail(request, hostname = None, pk = None): return render_history_view(request, 'clients/detail.html', page_limit=5, client=client, maxdate=context['interaction'].timestamp, context=context) + def client_manage(request): """Manage client expiration""" message = '' @@ -186,12 +205,12 @@ def client_manage(request): client_action = request.POST.get('client_action', None) client = Client.objects.get(name=client_name) if client_action == 'expire': - client.expiration = datetime.now(); + client.expiration = datetime.now() client.save() message = "Expiration for %s set to %s." % \ (client_name, client.expiration.strftime("%Y-%m-%d %H:%M:%S")) elif client_action == 'unexpire': - client.expiration = None; + client.expiration = None client.save() message = "%s is now active." % client_name else: @@ -205,6 +224,7 @@ def client_manage(request): {'clients': Client.objects.order_by('name').all(), 'message': message}, context_instance=RequestContext(request)) + @timeview def display_summary(request, timestamp=None): """ @@ -216,7 +236,12 @@ def display_summary(request, timestamp=None): if not timestamp: timestamp = datetime.now() - collected_data = dict(clean=[],bad=[],modified=[],extra=[],stale=[],pings=[]) + collected_data = dict(clean=[], + bad=[], + modified=[], + extra=[], + stale=[], + pings=[]) for node in recent_data: if timestamp - node.timestamp > timedelta(hours=24): collected_data['stale'].append(node) @@ -238,42 +263,47 @@ def display_summary(request, timestamp=None): # label, header_text, node_list summary_data = [] - get_dict = lambda name, label: { 'name': name, - 'nodes': collected_data[name], - 'label': label } + get_dict = lambda name, label: {'name': name, + 'nodes': collected_data[name], + 'label': label} if len(collected_data['clean']) > 0: - summary_data.append( get_dict('clean', 'nodes are clean.') ) + summary_data.append(get_dict('clean', + 'nodes are clean.')) if len(collected_data['bad']) > 0: - summary_data.append( get_dict('bad', 'nodes are bad.') ) + summary_data.append(get_dict('bad', + 'nodes are bad.')) if len(collected_data['modified']) > 0: - summary_data.append( get_dict('modified', 'nodes were modified.') ) + summary_data.append(get_dict('modified', + 'nodes were modified.')) if len(collected_data['extra']) > 0: - summary_data.append( get_dict('extra', - 'nodes have extra configurations.') ) + summary_data.append(get_dict('extra', + 'nodes have extra configurations.')) if len(collected_data['stale']) > 0: - summary_data.append( get_dict('stale', - 'nodes did not run within the last 24 hours.') ) + summary_data.append(get_dict('stale', + 'nodes did not run within the last 24 hours.')) if len(collected_data['pings']) > 0: - summary_data.append( get_dict('pings', - 'are down.') ) + summary_data.append(get_dict('pings', + 'are down.')) return render_to_response('displays/summary.html', {'summary_data': summary_data, 'node_count': node_count, 'timestamp': timestamp}, context_instance=RequestContext(request)) + @timeview def display_timing(request, timestamp=None): mdict = dict() inters = Interaction.objects.interaction_per_client(timestamp).select_related().all() [mdict.__setitem__(inter, {'name': inter.client.name}) \ for inter in inters] - for metric in Performance.objects.filter(interaction__in=mdict.keys()).all(): + for metric in Performance.objects.filter(interaction__in=list(mdict.keys())).all(): for i in metric.interaction.all(): mdict[i][metric.metric] = metric.value return render_to_response('displays/timing.html', - {'metrics': mdict.values(), 'timestamp': timestamp}, - context_instance=RequestContext(request)) + {'metrics': list(mdict.values()), + 'timestamp': timestamp}, + context_instance=RequestContext(request)) def render_history_view(request, template='clients/history.html', **kwargs): @@ -303,7 +333,7 @@ def render_history_view(request, template='clients/history.html', **kwargs): max_results = int(kwargs.get('page_limit', 25)) page = int(kwargs.get('page_number', 1)) - client=kwargs.get('client', None) + client = kwargs.get('client', None) if not client and 'hostname' in kwargs: client = get_object_or_404(Client, name=kwargs['hostname']) if client: @@ -333,8 +363,13 @@ def render_history_view(request, template='clients/history.html', **kwargs): entry_list = [] if max_results > 0: try: - rec_start, rec_end = prepare_paginated_list(request, context, iquery, page, max_results) - except PaginationError, page_error: + rec_start, rec_end = prepare_paginated_list(request, + context, + iquery, + page, + max_results) + except PaginationError: + page_error = sys.exc_info()[1] if isinstance(page_error[0], HttpResponse): return page_error[0] return HttpResponseServerError(page_error) @@ -345,20 +380,21 @@ def render_history_view(request, template='clients/history.html', **kwargs): return render_to_response(template, context, context_instance=RequestContext(request)) + def prepare_paginated_list(request, context, paged_list, page=1, max_results=25): """ Prepare context and slice an object for pagination. """ if max_results < 1: - raise PaginationError, "Max results less then 1" + raise PaginationError("Max results less then 1") if paged_list == None: - raise PaginationError, "Invalid object" + raise PaginationError("Invalid object") try: nitems = paged_list.count() except TypeError: nitems = len(paged_list) - + rec_start = (page - 1) * int(max_results) try: total_pages = (nitems / int(max_results)) + 1 @@ -369,11 +405,11 @@ def prepare_paginated_list(request, context, paged_list, page=1, max_results=25) try: view, args, kwargs = resolve(request.META['PATH_INFO']) kwargs['page_number'] = total_pages - raise PaginationError, HttpResponseRedirect( reverse(view, kwargs=kwargs) ) + raise PaginationError(HttpResponseRedirect(reverse(view, + kwards=kwargs))) except (Resolver404, NoReverseMatch, ValueError): raise "Accessing beyond last page. Unable to resolve redirect." context['total_pages'] = total_pages context['records_per_page'] = max_results return (rec_start, rec_start + int(max_results)) - |