summaryrefslogtreecommitdiffstats
path: root/src/lib/Server/Reports/reports
diff options
context:
space:
mode:
authorSol Jerome <sol.jerome@gmail.com>2012-03-24 11:20:07 -0500
committerSol Jerome <sol.jerome@gmail.com>2012-03-24 11:20:07 -0500
commitdab1d03d81c538966d03fb9318a4588a9e803b44 (patch)
treef51e27fa55887e9fb961766805fe43f0da56c5b9 /src/lib/Server/Reports/reports
parent5cd6238df496a3cea178e4596ecd87967cce1ce6 (diff)
downloadbcfg2-dab1d03d81c538966d03fb9318a4588a9e803b44.tar.gz
bcfg2-dab1d03d81c538966d03fb9318a4588a9e803b44.tar.bz2
bcfg2-dab1d03d81c538966d03fb9318a4588a9e803b44.zip
Allow to run directly from a git checkout (#1037)
Signed-off-by: Sol Jerome <sol.jerome@gmail.com>
Diffstat (limited to 'src/lib/Server/Reports/reports')
-rw-r--r--src/lib/Server/Reports/reports/__init__.py1
-rw-r--r--src/lib/Server/Reports/reports/fixtures/initial_version.xml39
-rw-r--r--src/lib/Server/Reports/reports/models.py343
-rw-r--r--src/lib/Server/Reports/reports/sql/client.sql9
-rw-r--r--src/lib/Server/Reports/reports/templates/404.html8
-rw-r--r--src/lib/Server/Reports/reports/templates/base-timeview.html25
-rw-r--r--src/lib/Server/Reports/reports/templates/base.html95
-rw-r--r--src/lib/Server/Reports/reports/templates/clients/detail.html127
-rw-r--r--src/lib/Server/Reports/reports/templates/clients/detailed-list.html46
-rw-r--r--src/lib/Server/Reports/reports/templates/clients/history.html20
-rw-r--r--src/lib/Server/Reports/reports/templates/clients/index.html34
-rw-r--r--src/lib/Server/Reports/reports/templates/clients/manage.html45
-rw-r--r--src/lib/Server/Reports/reports/templates/config_items/item.html115
-rw-r--r--src/lib/Server/Reports/reports/templates/config_items/listing.html33
-rw-r--r--src/lib/Server/Reports/reports/templates/displays/summary.html42
-rw-r--r--src/lib/Server/Reports/reports/templates/displays/timing.html38
-rw-r--r--src/lib/Server/Reports/reports/templates/widgets/filter_bar.html13
-rw-r--r--src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc38
-rw-r--r--src/lib/Server/Reports/reports/templates/widgets/page_bar.html23
-rw-r--r--src/lib/Server/Reports/reports/templatetags/__init__.py0
-rw-r--r--src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py276
-rw-r--r--src/lib/Server/Reports/reports/templatetags/syntax_coloring.py49
-rw-r--r--src/lib/Server/Reports/reports/urls.py55
-rw-r--r--src/lib/Server/Reports/reports/views.py415
24 files changed, 0 insertions, 1889 deletions
diff --git a/src/lib/Server/Reports/reports/__init__.py b/src/lib/Server/Reports/reports/__init__.py
deleted file mode 100644
index ccdce8943..000000000
--- a/src/lib/Server/Reports/reports/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__all__ = ['templatetags']
diff --git a/src/lib/Server/Reports/reports/fixtures/initial_version.xml b/src/lib/Server/Reports/reports/fixtures/initial_version.xml
deleted file mode 100644
index 919265d48..000000000
--- a/src/lib/Server/Reports/reports/fixtures/initial_version.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version='1.0' encoding='utf-8' ?>
-<django-objects version="1.0">
- <object pk="1" model="reports.internaldatabaseversion">
- <field type="IntegerField" name="version">0</field>
- <field type="DateTimeField" name="updated">2008-08-05 11:03:50</field>
- </object>
- <object pk="2" model="reports.internaldatabaseversion">
- <field type="IntegerField" name="version">1</field>
- <field type="DateTimeField" name="updated">2008-08-05 11:04:10</field>
- </object>
- <object pk="3" model="reports.internaldatabaseversion">
- <field type="IntegerField" name="version">2</field>
- <field type="DateTimeField" name="updated">2008-08-05 13:37:19</field>
- </object>
- <object pk="4" model="reports.internaldatabaseversion">
- <field type='IntegerField' name='version'>3</field>
- <field type='DateTimeField' name='updated'>2008-08-11 08:44:36</field>
- </object>
- <object pk="5" model="reports.internaldatabaseversion">
- <field type='IntegerField' name='version'>10</field>
- <field type='DateTimeField' name='updated'>2008-08-22 11:28:50</field>
- </object>
- <object pk="5" model="reports.internaldatabaseversion">
- <field type='IntegerField' name='version'>11</field>
- <field type='DateTimeField' name='updated'>2009-01-13 12:26:10</field>
- </object>
- <object pk="6" model="reports.internaldatabaseversion">
- <field type='IntegerField' name='version'>16</field>
- <field type='DateTimeField' name='updated'>2010-06-01 12:26:10</field>
- </object>
- <object pk="7" model="reports.internaldatabaseversion">
- <field type='IntegerField' name='version'>17</field>
- <field type='DateTimeField' name='updated'>2010-07-02 00:00:00</field>
- </object>
- <object pk="8" model="reports.internaldatabaseversion">
- <field type='IntegerField' name='version'>18</field>
- <field type='DateTimeField' name='updated'>2011-06-30 00:00:00</field>
- </object>
-</django-objects>
diff --git a/src/lib/Server/Reports/reports/models.py b/src/lib/Server/Reports/reports/models.py
deleted file mode 100644
index 870239641..000000000
--- a/src/lib/Server/Reports/reports/models.py
+++ /dev/null
@@ -1,343 +0,0 @@
-"""Django models for Bcfg2 reports."""
-from django.db import models
-from django.db import connection, transaction
-from django.db.models import Q
-from datetime import datetime, timedelta
-from time import strptime
-
-KIND_CHOICES = (
- #These are the kinds of config elements
- ('Package', 'Package'),
- ('Path', 'directory'),
- ('Path', 'file'),
- ('Path', 'permissions'),
- ('Path', 'symlink'),
- ('Service', 'Service'),
-)
-PING_CHOICES = (
- #These are possible ping states
- ('Up (Y)', 'Y'),
- ('Down (N)', 'N')
-)
-TYPE_BAD = 1
-TYPE_MODIFIED = 2
-TYPE_EXTRA = 3
-
-TYPE_CHOICES = (
- (TYPE_BAD, 'Bad'),
- (TYPE_MODIFIED, 'Modified'),
- (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:
- if e_name.lower() == type_name.lower():
- 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."""
-
- if timestamp == None:
- timestamp = datetime.now()
- elif not isinstance(timestamp, datetime):
- raise ValueError('Expected a datetime object')
- else:
- try:
- 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)
-
-
-class Client(models.Model):
- """Object representing every client we have seen stats for."""
- creation = models.DateTimeField(auto_now_add=True)
- name = models.CharField(max_length=128,)
- current_interaction = models.ForeignKey('Interaction',
- 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
-
- class Meta:
- get_latest_by = 'endtime'
-
-
-class InteractiveManager(models.Manager):
- """Manages interactions objects."""
-
- def recent_interactions_dict(self, maxdate=None, active_only=True):
- """
- Return the most recent interactions for clients as of a date.
-
- This method uses aggregated queries to return a ValuesQueryDict object.
- Faster then raw sql since this is executed as a single query.
- """
-
- 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))
-
- 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()
- cfilter = "expiration is null"
-
- 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')
- sql = sql + " where timestamp <= '%s' " % 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:
- sql = sql + " and x.client_id in (select id from reports_client where %s)" % \
- cfilter
- try:
- cursor.execute(sql)
- return [item[0] for item in cursor.fetchall()]
- except:
- '''FIXME - really need some error hadling'''
- 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
- bad_entries = models.IntegerField(default=-1)
- modified_entries = models.IntegerField(default=-1)
- extra_entries = models.IntegerField(default=-1)
-
- def __str__(self):
- return "With " + self.client.name + " @ " + self.timestamp.isoformat()
-
- def percentgood(self):
- if not self.totalcount == 0:
- 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
- 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)):
- return True
- else:
- return False
- else:
- #Search for subsequent Interaction for this client
- #Check if it happened more than 25 hrs ago.
- if (self.client.interactions.filter(timestamp__gt=self.timestamp)
- .order_by('timestamp')[0].timestamp -
- self.timestamp > timedelta(hours=25)):
- return True
- else:
- return False
-
- def save(self):
- super(Interaction, self).save() # call the real save...
- self.client.current_interaction = self.client.interactions.latest()
- self.client.save() # save again post update
-
- def delete(self):
- '''Override the default delete. Allows us to remove Performance items'''
- pitems = list(self.performance_items.all())
- super(Interaction, self).delete()
- for perf in pitems:
- if perf.interaction.count() == 0:
- perf.delete()
-
- def badcount(self):
- return self.totalcount - self.goodcount
-
- def bad(self):
- return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_BAD)
-
- def bad_entry_count(self):
- """Number of bad entries. Store the count in the interation field to save db queries."""
- if self.bad_entries < 0:
- self.bad_entries = Entries_interactions.objects.filter(interaction=self, type=TYPE_BAD).count()
- self.save()
- return self.bad_entries
-
- def modified(self):
- return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_MODIFIED)
-
- def modified_entry_count(self):
- """Number of modified entries. Store the count in the interation field to save db queries."""
- if self.modified_entries < 0:
- self.modified_entries = Entries_interactions.objects.filter(interaction=self, type=TYPE_MODIFIED).count()
- self.save()
- return self.modified_entries
-
- def extra(self):
- return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_EXTRA)
-
- def extra_entry_count(self):
- """Number of extra entries. Store the count in the interation field to save db queries."""
- if self.extra_entries < 0:
- 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
- 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)
- 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_diff = models.TextField(max_length=1280, blank=True)
- is_binary = models.BooleanField(default=False)
- is_sensitive = models.BooleanField(default=False)
-
- def _str_(self):
- return "Reason"
-
- @staticmethod
- @transaction.commit_on_success
- def prune_orphans():
- '''Prune oprhaned rows... no good way to use the ORM'''
- 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."""
- name = models.CharField(max_length=128, db_index=True)
- kind = models.CharField(max_length=16, choices=KIND_CHOICES, db_index=True)
-
- def __str__(self):
- return self.name
-
- @staticmethod
- @transaction.commit_on_success
- def prune_orphans():
- '''Prune oprhaned rows... no good way to use the ORM'''
- 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
-
- @staticmethod
- @transaction.commit_on_success
- def prune_orphans():
- '''Prune oprhaned rows... no good way to use the ORM'''
- 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()
- updated = models.DateTimeField(auto_now_add=True)
-
- def __str__(self):
- return "version %d updated the %s" % (self.version, self.updated.isoformat())
diff --git a/src/lib/Server/Reports/reports/sql/client.sql b/src/lib/Server/Reports/reports/sql/client.sql
deleted file mode 100644
index 8c63754c9..000000000
--- a/src/lib/Server/Reports/reports/sql/client.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-CREATE VIEW reports_current_interactions AS SELECT x.client_id AS client_id, reports_interaction.id AS interaction_id FROM (select client_id, MAX(timestamp) as timer FROM reports_interaction GROUP BY client_id) x, reports_interaction WHERE reports_interaction.client_id = x.client_id AND reports_interaction.timestamp = x.timer;
-
-create index reports_interaction_client_id on reports_interaction (client_id);
-create index reports_extra_interactions_client_id on reports_extra_interactions(interaction_id);
-create index reports_modified_interactions_client_id on reports_modified_interactions(interaction_id);
-create index reports_client_current_interaction_id on reports_client (current_interaction_id);
-create index reports_performance_interaction_performance_id on reports_performance_interaction (performance_id);
-create index reports_interaction_timestamp on reports_interaction (timestamp);
-create index reports_performance_interation_interaction_id on reports_performance_interaction (interaction_id); \ No newline at end of file
diff --git a/src/lib/Server/Reports/reports/templates/404.html b/src/lib/Server/Reports/reports/templates/404.html
deleted file mode 100644
index 168bd9fec..000000000
--- a/src/lib/Server/Reports/reports/templates/404.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% extends 'base.html' %}
-{% block title %}Bcfg2 - Page not found{% endblock %}
-{% block fullcontent %}
-<h2>Page not found</h2>
-<p>
-The page or object requested could not be found.
-</p>
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/base-timeview.html b/src/lib/Server/Reports/reports/templates/base-timeview.html
deleted file mode 100644
index 842de36f0..000000000
--- a/src/lib/Server/Reports/reports/templates/base-timeview.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% extends "base.html" %}
-
-{% block timepiece %}
-<script type="text/javascript">
-function showCalendar() {
- var cal = new CalendarPopup("calendar_div");
- cal.showYearNavigation();
- cal.select(document.forms['cal_form'].cal_date,'cal_link',
- 'yyyy/MM/dd' {% if timestamp %}, '{{ timestamp|date:"Y/m/d" }}'{% endif %} );
- return false;
-}
-function bcfg2_check_date() {
- var new_date = document.getElementById('cal_date').value;
- if(new_date) {
- document.cal_form.submit();
- }
-}
-document.write(getCalendarStyles());
-</script>
-{% if not timestamp %}Rendered at {% now "Y-m-d H:i" %} | {% else %}View as of {{ timestamp|date:"Y-m-d H:i" }} | {% endif %}{% spaceless %}
- <a id='cal_link' name='cal_link' href='#' onclick='showCalendar(); return false;'
- >[change]</a>
- <form method='post' action='{{ path }}' id='cal_form' name='cal_form'><input id='cal_date' name='cal_date' type='hidden' value=''/></form>
-{% endspaceless %}
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/base.html b/src/lib/Server/Reports/reports/templates/base.html
deleted file mode 100644
index f541c0d2b..000000000
--- a/src/lib/Server/Reports/reports/templates/base.html
+++ /dev/null
@@ -1,95 +0,0 @@
-{% load bcfg2_tags %}
-
-<?xml version="1.0"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<title>{% block title %}Bcfg2 Reporting System{% endblock %}</title>
-
-<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-<meta http-equiv="Content-language" content="en" />
-<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
-<meta name="robots" content="noindex, nofollow" />
-<meta http-equiv="cache-control" content="no-cache" />
-
-<link rel="stylesheet" type="text/css" href="{% to_media_url bcfg2_base.css %}" media="all" />
-<script type="text/javascript" src="{% to_media_url bcfg2.js %}"></script>
-<script type="text/javascript" src="{% to_media_url date.js %}"></script>
-<script type="text/javascript" src="{% to_media_url AnchorPosition.js %}"></script>
-<script type="text/javascript" src="{% to_media_url CalendarPopup.js %}"></script>
-<script type="text/javascript" src="{% to_media_url PopupWindow.js %}"></script>
-{% block extra_header_info %}{% endblock %}
-
-</head>
-<body onload="{% block body_onload %}{% endblock %}">
-
- <div id="header">
- <a href="http://bcfg2.org"><img src='{% to_media_url bcfg2_logo.png %}'
- height='115' width='300' alt='Bcfg2' style='float:left; height: 115px' /></a>
- </div>
-
-<div id="document">
- <div id="content"><div id="contentwrapper">
- {% block fullcontent %}
- <div class='page_name'>
- <h1>{% block pagebanner %}Page Banner{% endblock %}</h1>
- <div id="timepiece">{% block timepiece %}Rendered at {% now "Y-m-d H:i" %}{% endblock %}</div>
- </div>
- <div class='detail_wrapper'>
- {% block content %}{% endblock %}
- </div>
- {% endblock %}
- </div></div><!-- content -->
- <div id="sidemenucontainer"><div id="sidemenu">
- {% block sidemenu %}
- <ul class='menu-level1'>
- <li>Overview</li>
- </ul>
- <ul class='menu-level2'>
- <li><a href="{% url reports_summary %}">Summary</a></li>
- <li><a href="{% url reports_history %}">Recent Interactions</a></li>
- <li><a href="{% url reports_timing %}">Timing</a></li>
- </ul>
- <ul class='menu-level1'>
- <li>Clients</li>
- </ul>
- <ul class='menu-level2'>
- <li><a href="{% url reports_grid_view %}">Grid View</a></li>
- <li><a href="{% url reports_detailed_list %}">Detailed List</a></li>
- <li><a href="{% url reports_client_manage %}">Manage</a></li>
- </ul>
- <ul class='menu-level1'>
- <li>Entries Configured</li>
- </ul>
- <ul class='menu-level2'>
- <li><a href="{% url reports_item_list "bad" %}">Bad</a></li>
- <li><a href="{% url reports_item_list "modified" %}">Modified</a></li>
- <li><a href="{% url reports_item_list "extra" %}">Extra</a></li>
- </ul>
-{% comment %}
- TODO
- <ul class='menu-level1'>
- <li>Entry Types</li>
- </ul>
- <ul class='menu-level2'>
- <li><a href="#">Action</a></li>
- <li><a href="#">Package</a></li>
- <li><a href="#">Path</a></li>
- <li><a href="#">Service</a></li>
- </ul>
-{% endcomment %}
- <ul class='menu-level1'>
- <li><a href="http://bcfg2.org">Homepage</a></li>
- <li><a href="http://docs.bcfg2.org">Documentation</a></li>
- </ul>
- {% endblock %}
- </div></div><!-- sidemenu -->
- <div style='clear:both'></div>
-</div><!-- document -->
- <div id="footer">
- <span>Bcfg2 Version 1.2.2</span>
- </div>
-
-<div id="calendar_div" style='position:absolute; visibility:hidden; background-color:white; layer-background-color:white;'></div>
-</body>
-</html>
diff --git a/src/lib/Server/Reports/reports/templates/clients/detail.html b/src/lib/Server/Reports/reports/templates/clients/detail.html
deleted file mode 100644
index dd4295f21..000000000
--- a/src/lib/Server/Reports/reports/templates/clients/detail.html
+++ /dev/null
@@ -1,127 +0,0 @@
-{% extends "base.html" %}
-{% load bcfg2_tags %}
-
-{% block title %}Bcfg2 - Client {{client.name}}{% endblock %}
-
-{% block extra_header_info %}
-<style type="text/css">
-.node_data {
- border: 1px solid #98DBCC;
- margin: 10px;
- padding-left: 18px;
-}
-.node_data td {
- padding: 1px 20px 1px 2px;
-}
-span.history_links {
- font-size: 90%;
- margin-left: 50px;
-}
-span.history_links a {
- font-size: 90%;
-}
-</style>
-{% endblock %}
-
-{% block body_onload %}javascript:clientdetailload(){% endblock %}
-
-{% block pagebanner %}Client Details{% endblock %}
-
-{% block content %}
- <div class='detail_header'>
- <h2>{{client.name}}</h2>
- <a href='{% url reports_client_manage %}#{{ client.name }}'>[manage]</a>
- <span class='history_links'><a href="{% url reports_client_history client.name %}">View History</a> | Jump to&nbsp;
- <select id="quick" name="quick" onchange="javascript:pageJump('quick');">
- <option value="" selected="selected">--- Time ---</option>
- {% for i in client.interactions.all|slice:":25" %}
- <option value="{% url reports_client_detail_pk hostname=client.name, pk=i.id %}">{{i.timestamp}}</option>
- {% endfor %}
- </select></span>
- </div>
-
- {% if interaction.isstale %}
- <div class="warningbox">
- This node did not run within the last 24 hours &#8212; it may be out of date.
- </div>
- {% endif %}
- <table class='node_data'>
- <tr><td>Timestamp</td><td>{{interaction.timestamp}}</td></tr>
- {% if interaction.server %}
- <tr><td>Served by</td><td>{{interaction.server}}</td></tr>
- {% endif %}
- {% if interaction.repo_rev_code %}
- <tr><td>Revision</td><td>{{interaction.repo_rev_code}}</td></tr>
- {% endif %}
- <tr><td>State</td><td class='{{interaction.state}}-lineitem'>{{interaction.state|capfirst}}</td></tr>
- <tr><td>Managed entries</td><td>{{interaction.totalcount}}</td></tr>
- {% if not interaction.isclean %}
- <tr><td>Deviation</td><td>{{interaction.percentbad|floatformat:"3"}}%</td></tr>
- {% endif %}
- </table>
-
- {% if interaction.bad_entry_count %}
- <div class='entry_list'>
- <div class='entry_list_head dirty-lineitem' onclick='javascript:toggleMe("bad_table");'>
- <h3>Bad Entries &#8212; {{ interaction.bad_entry_count }}</h3>
- <div class='entry_expand_tab' id='plusminus_bad_table'>[+]</div>
- </div>
- <table id='bad_table' class='entry_list'>
- {% for e in interaction.bad|sortwell %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td class='entry_list_type'>{{e.entry.kind}}:</td>
- <td><a href="{% url reports_item "bad",e.id %}">
- {{e.entry.name}}</a></td>
- </tr>
- {% endfor %}
- </table>
- </div>
- {% endif %}
-
- {% if interaction.modified_entry_count %}
- <div class='entry_list'>
- <div class='entry_list_head modified-lineitem' onclick='javascript:toggleMe("modified_table");'>
- <h3>Modified Entries &#8212; {{ interaction.modified_entry_count }}</h3>
- <div class='entry_expand_tab' id='plusminus_modified_table'>[+]</div>
- </div>
- <table id='modified_table' class='entry_list'>
- {% for e in interaction.modified|sortwell %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td class='entry_list_type'>{{e.entry.kind}}:</td>
- <td><a href="{% url reports_item "modified",e.id %}">
- {{e.entry.name}}</a></td>
- </tr>
- {% endfor %}
- </table>
- </div>
- {% endif %}
-
- {% if interaction.extra_entry_count %}
- <div class='entry_list'>
- <div class='entry_list_head extra-lineitem' onclick='javascript:toggleMe("extra_table");'>
- <h3>Extra Entries &#8212; {{ interaction.extra_entry_count }}</h3>
- <div class='entry_expand_tab' id='plusminus_extra_table'>[+]</div>
- </div>
- <table id='extra_table' class='entry_list'>
- {% for e in interaction.extra|sortwell %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td class='entry_list_type'>{{e.entry.kind}}:</td>
- <td><a href="{% url reports_item "extra",e.id %}">{{e.entry.name}}</a></td>
- </tr>
- {% endfor %}
- </table>
- </div>
- {% endif %}
-
- {% if entry_list %}
- <div class="entry_list recent_history_wrapper">
- <div class="entry_list_head" style="border-bottom: 2px solid #98DBCC;">
- <h4 style="display: inline"><a href="{% url reports_client_history client.name %}">Recent Interactions</a></h4>
- </div>
- <div class='recent_history_box'>
- {% include "widgets/interaction_list.inc" %}
- <div style='padding-left: 5px'><a href="{% url reports_client_history client.name %}">more...</a></div>
- </div>
- </div>
- {% endif %}
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/clients/detailed-list.html b/src/lib/Server/Reports/reports/templates/clients/detailed-list.html
deleted file mode 100644
index 0c1fae8d5..000000000
--- a/src/lib/Server/Reports/reports/templates/clients/detailed-list.html
+++ /dev/null
@@ -1,46 +0,0 @@
-{% extends "base-timeview.html" %}
-{% load bcfg2_tags %}
-
-{% block title %}Bcfg2 - Detailed Client Listing{% endblock %}
-{% block pagebanner %}Clients - Detailed View{% endblock %}
-
-{% block content %}
-<div class='client_list_box'>
-{% if entry_list %}
- {% filter_navigator %}
- <table cellpadding="3">
- <tr id='table_list_header' class='listview'>
- <td class='left_column'>Node</td>
- <td class='right_column' style='width:75px'>State</td>
- <td class='right_column_narrow'>Good</td>
- <td class='right_column_narrow'>Bad</td>
- <td class='right_column_narrow'>Modified</td>
- <td class='right_column_narrow'>Extra</td>
- <td class='right_column'>Last Run</td>
- <td class='right_column_wide'>Server</td>
- </tr>
- {% for entry in entry_list %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td class='left_column'><a href='{% url Bcfg2.Server.Reports.reports.views.client_detail hostname=entry.client.name, pk=entry.id %}'>{{ entry.client.name }}</a></td>
- <td class='right_column' style='width:75px'><a href='{% add_url_filter state=entry.state %}'
- {% ifequal entry.state 'dirty' %}class='dirty-lineitem'{% endifequal %}>{{ entry.state }}</a></td>
- <td class='right_column_narrow'>{{ entry.goodcount }}</td>
- <td class='right_column_narrow'>{{ entry.bad_entry_count }}</td>
- <td class='right_column_narrow'>{{ entry.modified_entry_count }}</td>
- <td class='right_column_narrow'>{{ entry.extra_entry_count }}</td>
- <td class='right_column'><span {% if entry.timestamp|isstale:entry_max %}class='dirty-lineitem'{% endif %}>{{ entry.timestamp|date:"Y-m-d\&\n\b\s\p\;H:i"|safe }}</span></td>
- <td class='right_column_wide'>
- {% if entry.server %}
- <a href='{% add_url_filter server=entry.server %}'>{{ entry.server }}</a>
- {% else %}
- &nbsp;
- {% endif %}
- </td>
- </tr>
- {% endfor %}
- </table>
-{% else %}
- <p>No client records are available.</p>
-{% endif %}
-</div>
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/clients/history.html b/src/lib/Server/Reports/reports/templates/clients/history.html
deleted file mode 100644
index 01d4ec2f4..000000000
--- a/src/lib/Server/Reports/reports/templates/clients/history.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "base.html" %}
-{% load bcfg2_tags %}
-
-{% block title %}Bcfg2 - Interaction History{% endblock %}
-{% block pagebanner %}Interaction history{% if client %} for {{ client.name }}{% endif %}{% endblock %}
-
-{% block extra_header_info %}
-{% endblock %}
-
-{% block content %}
-<div class='client_list_box'>
-{% if entry_list %}
- {% filter_navigator %}
- {% include "widgets/interaction_list.inc" %}
-{% else %}
- <p>No client records are available.</p>
-{% endif %}
-</div>
-{% page_navigator %}
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/clients/index.html b/src/lib/Server/Reports/reports/templates/clients/index.html
deleted file mode 100644
index e0c0d2d7a..000000000
--- a/src/lib/Server/Reports/reports/templates/clients/index.html
+++ /dev/null
@@ -1,34 +0,0 @@
-{% extends "base-timeview.html" %}
-
-{% block extra_header_info %}
-{% endblock%}
-
-{% block title %}Bcfg2 - Client Grid View{% endblock %}
-
-{% block pagebanner %}Clients - Grid View{% endblock %}
-
-{% block content %}
-
-{% if inter_list %}
- <table class='grid-view' align='center'>
- {% for inter in inter_list %}
- {% if forloop.first %}<tr>{% endif %}
- <td class="{{inter.state}}-lineitem">
- <a href="{% spaceless %}{% if not timestamp %}
- {% url reports_client_detail inter.client.name %}
- {% else %}
- {% url reports_client_detail_pk inter.client.name,inter.id %}
- {% endif %}
- {% endspaceless %}">{{ inter.client.name }}</a>
- </td>
- {% if forloop.last %}
- </tr>
- {% else %}
- {% if forloop.counter|divisibleby:"4" %}</tr><tr>{% endif %}
- {% endif %}
- {% endfor %}
- </table>
-{% else %}
- <p>No client records are available.</p>
-{% endif %}
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/clients/manage.html b/src/lib/Server/Reports/reports/templates/clients/manage.html
deleted file mode 100644
index 5725ae577..000000000
--- a/src/lib/Server/Reports/reports/templates/clients/manage.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% extends "base.html" %}
-
-{% block extra_header_info %}
-{% endblock%}
-
-{% block title %}Bcfg2 - Manage Clients{% endblock %}
-
-{% block pagebanner %}Clients - Manage{% endblock %}
-
-{% block content %}
-<div class='client_list_box'>
- {% if message %}
- <div class="warningbox">{{ message }}</div>
- {% endif %}
-{% if clients %}
- <table cellpadding="3">
- <tr id='table_list_header' class='listview'>
- <td class='left_column'>Node</td>
- <td class='right_column'>Expiration</td>
- <td class='right_column_narrow'>Manage</td>
- </tr>
- {% for client in clients %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td><span id="{{ client.name }}"> </span>
- <span id="ttag-{{ client.name }}"> </span>
- <span id="s-ttag-{{ client.name }}"> </span>
- <a href="{% url reports_client_detail client.name %}">{{ client.name }}</a></td>
- <td>{% firstof client.expiration 'Active' %}</td>
- <td>
- <form method="post" action="{% url reports_client_manage %}">
- <div> {# here for no reason other then to validate #}
- <input type="hidden" name="client_name" value="{{ client.name }}" />
- <input type="hidden" name="client_action" value="{% if client.expiration %}unexpire{% else %}expire{% endif %}" />
- <input type="submit" value="{% if client.expiration %}Activate{% else %}Expire Now{% endif %}" />
- </div>
- </form>
- </td>
- </tr>
- {% endfor %}
- </table>
- </div>
-{% else %}
- <p>No client records are available.</p>
-{% endif %}
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/config_items/item.html b/src/lib/Server/Reports/reports/templates/config_items/item.html
deleted file mode 100644
index cc99ef503..000000000
--- a/src/lib/Server/Reports/reports/templates/config_items/item.html
+++ /dev/null
@@ -1,115 +0,0 @@
-{% extends "base.html" %}
-{% load syntax_coloring %}
-
-
-{% block title %}Bcfg2 - Element Details{% endblock %}
-
-
-{% block extra_header_info %}
-<style type="text/css">
-#table_list_header {
- font-size: 100%;
-}
-table.entry_list {
- width: auto;
-}
-div.information_wrapper {
- margin: 15px;
-}
-div.diff_wrapper {
- overflow: auto;
-}
-div.entry_list h3 {
- font-size: 90%;
- padding: 5px;
-}
-</style>
-{% endblock%}
-
-{% block pagebanner %}Element Details{% endblock %}
-
-{% block content %}
- <div class='detail_header'>
- <h3>{{mod_or_bad|capfirst}} {{item.entry.kind}}: {{item.entry.name}}</h3>
- </div>
-
- <div class="information_wrapper">
-
- {% if isextra %}
- <p>This item exists on the host but is not defined in the configuration.</p>
- {% endif %}
-
- {% if not item.reason.current_exists %}
- <div class="warning">This item does not currently exist on the host but is specified to exist in the configuration.</div>
- {% endif %}
-
- {% if item.reason.current_owner or item.reason.current_group or item.reason.current_perms or item.reason.current_status or item.reason.current_status or item.reason.current_to or item.reason.current_version %}
- <table class='entry_list'>
- <tr id='table_list_header'>
- <td style='text-align: right;'>Problem Type</td><td>Expected</td><td style='border-bottom: 1px solid #98DBCC;'>Found</td></tr>
- {% if item.reason.current_owner %}
- <tr><td style='text-align: right'><b>Owner</b></td><td>{{item.reason.owner}}</td>
- <td>{{item.reason.current_owner}}</td></tr>
- {% endif %}
- {% if item.reason.current_group %}
- <tr><td style='text-align: right'><b>Group</b></td><td>{{item.reason.group}}</td>
- <td>{{item.reason.current_group}}</td></tr>
- {% endif %}
- {% if item.reason.current_perms %}
- <tr><td style='text-align: right'><b>Permissions</b></td><td>{{item.reason.perms}}</td>
- <td>{{item.reason.current_perms}}</td></tr>
- {% endif %}
- {% if item.reason.current_status %}
- <tr><td style='text-align: right'><b>Status</b></td><td>{{item.reason.status}}</td>
- <td>{{item.reason.current_status}}</td></tr>
- {% endif %}
- {% if item.reason.current_to %}
- <tr><td style='text-align: right'><b>Symlink Target</b></td><td>{{item.reason.to}}</td>
- <td>{{item.reason.current_to}}</td></tr>
- {% endif %}
- {% if item.reason.current_version %}
- <tr><td style='text-align: right'><b>Package Version</b></td><td>{{item.reason.version|cut:"("|cut:")"}}</td>
- <td>{{item.reason.current_version|cut:"("|cut:")"}}</td></tr>
- {% endif %}
- </table>
- {% endif %}
-
- {% if item.reason.current_diff or item.reason.is_sensitive %}
- <div class='entry_list'>
- <div class='entry_list_head'>
- {% if item.reason.is_sensitive %}
- <h3>File contents unavailable, as they might contain sensitive data.</h3>
- {% else %}
- <h3>Incorrect file contents</h3>
- {% endif %}
- </div>
- {% if not item.reason.is_sensitive %}
- <div class='diff_wrapper'>
- {{ item.reason.current_diff|syntaxhilight }}
- </div>
- {% endif %}
- </div>
- {% endif %}
-
-
- <div class='entry_list'>
- <div class='entry_list_head'>
- <h3>Occurences on {{ timestamp|date:"Y-m-d" }}</h3>
- </div>
- {% if associated_list %}
- <table class="entry_list" cellpadding="3">
- {% for inter in associated_list %}
- <tr><td><a href="{% url reports_client_detail inter.client.name %}"
- >{{inter.client.name}}</a></td>
- <td><a href="{% url reports_client_detail_pk hostname=inter.client.name,pk=inter.id %}"
- >{{inter.timestamp}}</a></td>
- </tr>
- {% endfor %}
- </table>
- {% else %}
- <p>Missing client list</p>
- {% endif %}
- </div>
-
- </div><!-- information_wrapper -->
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/config_items/listing.html b/src/lib/Server/Reports/reports/templates/config_items/listing.html
deleted file mode 100644
index 9b1026a08..000000000
--- a/src/lib/Server/Reports/reports/templates/config_items/listing.html
+++ /dev/null
@@ -1,33 +0,0 @@
-{% extends "base-timeview.html" %}
-{% load bcfg2_tags %}
-
-{% block title %}Bcfg2 - Element Listing{% endblock %}
-
-{% block extra_header_info %}
-{% endblock%}
-
-{% block pagebanner %}{{mod_or_bad|capfirst}} Element Listing{% endblock %}
-
-{% block content %}
-{% if item_list_dict %}
- {% for kind, entries in item_list_dict.items %}
-
- <div class='entry_list'>
- <div class='entry_list_head element_list_head' onclick='javascript:toggleMe("table_{{ kind }}");'>
- <h3>{{ kind }} &#8212; {{ entries|length }}</h3>
- <div class='entry_expand_tab' id='plusminus_table_{{ kind }}'>[&ndash;]</div>
- </div>
-
- <table id='table_{{ kind }}' class='entry_list'>
- {% for e in entries %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td><a href="{% url reports_item type=mod_or_bad,pk=e.id %}">{{e.entry.name}}</a></td>
- </tr>
- {% endfor %}
- </table>
- </div>
- {% endfor %}
-{% else %}
- <p>There are currently no inconsistent configuration entries.</p>
-{% endif %}
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/displays/summary.html b/src/lib/Server/Reports/reports/templates/displays/summary.html
deleted file mode 100644
index b9847cf96..000000000
--- a/src/lib/Server/Reports/reports/templates/displays/summary.html
+++ /dev/null
@@ -1,42 +0,0 @@
-{% extends "base-timeview.html" %}
-{% load bcfg2_tags %}
-
-{% block title %}Bcfg2 - Client Summary{% endblock %}
-{% block pagebanner %}Clients - Summary{% endblock %}
-
-{% block body_onload %}javascript:hide_table_array(hide_tables){% endblock %}
-
-{% block extra_header_info %}
-<script type="text/javascript">
-var hide_tables = new Array({{ summary_data|length }});
-{% for summary in summary_data %}
-hide_tables[{{ forloop.counter0 }}] = "table_{{ summary.name }}";
-{% endfor %}
-</script>
-{% endblock%}
-
-{% block content %}
- <div class='detail_header'>
- <h2>{{ node_count }} nodes reporting in</h2>
- </div>
-{% if summary_data %}
- {% for summary in summary_data %}
- <div class='entry_list'>
- <div class='entry_list_head element_list_head' onclick='javascript:toggleMe("table_{{ summary.name }}");'>
- <h3>{{ summary.nodes|length }} {{ summary.label }}</h3>
- <div class='entry_expand_tab' id='plusminus_table_{{ summary.name }}'>[+]</div>
- </div>
-
- <table id='table_{{ summary.name }}' class='entry_list'>
- {% for node in summary.nodes|sort_interactions_by_name %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td><a href="{% url reports_client_detail_pk hostname=node.client.name,pk=node.id %}">{{ node.client.name }}</a></td>
- </tr>
- {% endfor %}
- </table>
- </div>
- {% endfor %}
-{% else %}
- <p>No data to report on</p>
-{% endif %}
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/displays/timing.html b/src/lib/Server/Reports/reports/templates/displays/timing.html
deleted file mode 100644
index 47accb2cb..000000000
--- a/src/lib/Server/Reports/reports/templates/displays/timing.html
+++ /dev/null
@@ -1,38 +0,0 @@
-{% extends "base-timeview.html" %}
-{% load bcfg2_tags %}
-
-{% block title %}Bcfg2 - Performance Metrics{% endblock %}
-{% block pagebanner %}Performance Metrics{% endblock %}
-
-
-{% block extra_header_info %}
-{% endblock%}
-
-{% block content %}
-<div class='client_list_box'>
- {% if metrics %}
- <table cellpadding="3">
- <tr id='table_list_header' class='listview'>
- <td>Name</td>
- <td>Parse</td>
- <td>Probe</td>
- <td>Inventory</td>
- <td>Install</td>
- <td>Config</td>
- <td>Total</td>
- </tr>
- {% for metric in metrics|dictsort:"name" %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td><a style='font-size: 100%'
- href="{% url reports_client_detail hostname=metric.name %}">{{ metric.name }}</a></td>
- {% for mitem in metric|build_metric_list %}
- <td>{{ mitem }}</td>
- {% endfor %}
- </tr>
- {% endfor %}
- </table>
- {% else %}
- <p>No metric data available</p>
- {% endif %}
-</div>
-{% endblock %}
diff --git a/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html b/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html
deleted file mode 100644
index 6b57baf6a..000000000
--- a/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% spaceless %}
-{% if filters %}
-{% for filter, filter_url in filters %}
- {% if forloop.first %}
- <div class="filter_bar">Active filters (click to remove):
- {% endif %}
- <a href='{{ filter_url }}'>{{ filter|capfirst }}</a>{% if not forloop.last %}, {% endif %}
- {% if forloop.last %}
- </div>
- {% endif %}
-{% endfor %}
-{% endif %}
-{% endspaceless %}
diff --git a/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc b/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc
deleted file mode 100644
index 8f2dec1dc..000000000
--- a/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc
+++ /dev/null
@@ -1,38 +0,0 @@
-{% load bcfg2_tags %}
-<div class='interaction_history_widget'>
- <table cellpadding="3">
- <tr id='table_list_header' class='listview'>
- <td class='left_column'>Timestamp</td>
- {% if not client %}
- <td class='right_column_wide'>Client</td>
- {% endif %}
- <td class='right_column' style='width:75px'>State</td>
- <td class='right_column_narrow'>Good</td>
- <td class='right_column_narrow'>Bad</td>
- <td class='right_column_narrow'>Modified</td>
- <td class='right_column_narrow'>Extra</td>
- <td class='right_column_wide'>Server</td>
- </tr>
- {% for entry in entry_list %}
- <tr class='{% cycle listview,listview_alt %}'>
- <td class='left_column'><a href='{% url reports_client_detail_pk hostname=entry.client.name, pk=entry.id %}'>{{ entry.timestamp|date:"Y-m-d\&\n\b\s\p\;H:i"|safe }}</a></td>
- {% if not client %}
- <td class='right_column_wide'><a href='{% add_url_filter hostname=entry.client.name %}'>{{ entry.client.name }}</a></td>
- {% endif %}
- <td class='right_column' style='width:75px'><a href='{% add_url_filter state=entry.state %}'
- {% ifequal entry.state 'dirty' %}class='dirty-lineitem'{% endifequal %}>{{ entry.state }}</a></td>
- <td class='right_column_narrow'>{{ entry.goodcount }}</td>
- <td class='right_column_narrow'>{{ entry.bad_entry_count }}</td>
- <td class='right_column_narrow'>{{ entry.modified_entry_count }}</td>
- <td class='right_column_narrow'>{{ entry.extra_entry_count }}</td>
- <td class='right_column_wide'>
- {% if entry.server %}
- <a href='{% add_url_filter server=entry.server %}'>{{ entry.server }}</a>
- {% else %}
- &nbsp;
- {% endif %}
- </td>
- </tr>
- {% endfor %}
- </table>
-</div>
diff --git a/src/lib/Server/Reports/reports/templates/widgets/page_bar.html b/src/lib/Server/Reports/reports/templates/widgets/page_bar.html
deleted file mode 100644
index aa0def83e..000000000
--- a/src/lib/Server/Reports/reports/templates/widgets/page_bar.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{% spaceless %}
-{% for page, page_url in pager %}
- {% if forloop.first %}
- <div class="page_bar">
- {% if prev_page %}<a href="{{ prev_page }}">&lt; Prev</a><span>&nbsp;</span>{% endif %}
- {% if first_page %}<a href="{{ first_page }}">1</a><span>&nbsp;...&nbsp;</span>{% endif %}
- {% endif %}
- {% ifequal page current_page %}
- <span class='nav_bar_current'>{{ page }}</span>
- {% else %}
- <a href="{{ page_url }}">{{ page }}</a>
- {% endifequal %}
- {% if forloop.last %}
- {% if last_page %}<span>&nbsp;...&nbsp;</span><a href="{{ last_page }}">{{ total_pages }}</a><span>&nbsp;</span>{% endif %}
- {% if next_page %}<a href="{{ next_page }}">Next &gt;</a><span>&nbsp;</span>{% endif %}
- |{% for limit, limit_url in page_limits %}&nbsp;<a href="{{ limit_url }}">{{ limit }}</a>{% endfor %}
- </div>
- {% else %}
- <span>&nbsp;</span>
- {% endif %}
-{% endfor %}
-{% endspaceless %}
-<!-- {{ path }} -->
diff --git a/src/lib/Server/Reports/reports/templatetags/__init__.py b/src/lib/Server/Reports/reports/templatetags/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/src/lib/Server/Reports/reports/templatetags/__init__.py
+++ /dev/null
diff --git a/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py b/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py
deleted file mode 100644
index 629984f26..000000000
--- a/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py
+++ /dev/null
@@ -1,276 +0,0 @@
-from django import template
-from django.core.urlresolvers import resolve, reverse, Resolver404, NoReverseMatch
-from django.utils.encoding import smart_unicode, smart_str
-from datetime import datetime, timedelta
-from Bcfg2.Server.Reports.utils import filter_list
-
-register = template.Library()
-
-__PAGE_NAV_LIMITS__ = (10, 25, 50, 100)
-
-@register.inclusion_tag('widgets/page_bar.html', takes_context=True)
-def page_navigator(context):
- """
- Creates paginated links.
-
- Expects the context to be a RequestContext and views.prepare_paginated_list()
- to have populated page information.
- """
- fragment = dict()
- try:
- path = context['request'].META['PATH_INFO']
- total_pages = int(context['total_pages'])
- records_per_page = int(context['records_per_page'])
- except KeyError:
- return fragment
- except ValueError:
- return fragment
-
- if total_pages < 2:
- return {}
-
- try:
- view, args, kwargs = resolve(path)
- current_page = int(kwargs.get('page_number',1))
- fragment['current_page'] = current_page
- fragment['page_number'] = current_page
- fragment['total_pages'] = total_pages
- fragment['records_per_page'] = records_per_page
- if current_page > 1:
- kwargs['page_number'] = current_page - 1
- fragment['prev_page'] = reverse(view, args=args, kwargs=kwargs)
- if current_page < total_pages:
- kwargs['page_number'] = current_page + 1
- fragment['next_page'] = reverse(view, args=args, kwargs=kwargs)
-
- view_range = 5
- if total_pages > view_range:
- pager_start = current_page - 2
- pager_end = current_page + 2
- if pager_start < 1:
- pager_end += (1 - pager_start)
- pager_start = 1
- if pager_end > total_pages:
- pager_start -= (pager_end - total_pages)
- pager_end = total_pages
- else:
- pager_start = 1
- pager_end = total_pages
-
- if pager_start > 1:
- kwargs['page_number'] = 1
- fragment['first_page'] = reverse(view, args=args, kwargs=kwargs)
- if pager_end < total_pages:
- kwargs['page_number'] = total_pages
- fragment['last_page'] = reverse(view, args=args, kwargs=kwargs)
-
- pager = []
- for page in range(pager_start, int(pager_end) + 1):
- kwargs['page_number'] = page
- pager.append( (page, reverse(view, args=args, kwargs=kwargs)) )
-
- kwargs['page_number'] = 1
- page_limits = []
- for limit in __PAGE_NAV_LIMITS__:
- kwargs['page_limit'] = limit
- page_limits.append( (limit, reverse(view, args=args, kwargs=kwargs)) )
- # resolver doesn't like this
- del kwargs['page_number']
- del kwargs['page_limit']
- page_limits.append( ('all', reverse(view, args=args, kwargs=kwargs) + "|all") )
-
- fragment['pager'] = pager
- fragment['page_limits'] = page_limits
-
- except Resolver404:
- path = "404"
- except NoReverseMatch:
- nr = sys.exc_info()[1]
- path = "NoReverseMatch: %s" % nr
- except ValueError:
- path = "ValueError"
- #FIXME - Handle these
-
- fragment['path'] = path
- return fragment
-
-@register.inclusion_tag('widgets/filter_bar.html', takes_context=True)
-def filter_navigator(context):
- try:
- path = context['request'].META['PATH_INFO']
- view, args, kwargs = resolve(path)
-
- # Strip any page limits and numbers
- if 'page_number' in kwargs:
- del kwargs['page_number']
- if 'page_limit' in kwargs:
- del kwargs['page_limit']
-
- filters = []
- for filter in filter_list:
- if filter in kwargs:
- myargs = kwargs.copy()
- del myargs[filter]
- filters.append( (filter, reverse(view, args=args, kwargs=myargs) ) )
- filters.sort(lambda x,y: cmp(x[0], y[0]))
- return { 'filters': filters }
- except (Resolver404, NoReverseMatch, ValueError, KeyError):
- pass
- return dict()
-
-def _subtract_or_na(mdict, x, y):
- """
- Shortcut for build_metric_list
- """
- try:
- return round(mdict[x] - mdict[y], 4)
- except:
- return "n/a"
-
-@register.filter
-def build_metric_list(mdict):
- """
- Create a list of metric table entries
-
- Moving this here it simplify the view. Should really handle the case where these
- are missing...
- """
- td_list = []
- # parse
- td_list.append( _subtract_or_na(mdict, 'config_parse', 'config_download'))
- #probe
- td_list.append( _subtract_or_na(mdict, 'probe_upload', 'start'))
- #inventory
- td_list.append( _subtract_or_na(mdict, 'inventory', 'initialization'))
- #install
- td_list.append( _subtract_or_na(mdict, 'install', 'inventory'))
- #cfg download & parse
- td_list.append( _subtract_or_na(mdict, 'config_parse', 'probe_upload'))
- #total
- td_list.append( _subtract_or_na(mdict, 'finished', 'start'))
- return td_list
-
-@register.filter
-def isstale(timestamp, entry_max=None):
- """
- Check for a stale timestamp
-
- Compares two timestamps and returns True if the
- difference is greater then 24 hours.
- """
- if not entry_max:
- entry_max = datetime.now()
- return entry_max - timestamp > timedelta(hours=24)
-
-@register.filter
-def sort_interactions_by_name(value):
- """
- Sort an interaction list by client name
- """
- inters = list(value)
- inters.sort(lambda a,b: cmp(a.client.name, b.client.name))
- return inters
-
-class AddUrlFilter(template.Node):
- def __init__(self, filter_name, filter_value):
- self.filter_name = filter_name
- self.filter_value = filter_value
- self.fallback_view = 'Bcfg2.Server.Reports.reports.views.render_history_view'
-
- def render(self, context):
- link = '#'
- try:
- path = context['request'].META['PATH_INFO']
- view, args, kwargs = resolve(path)
- filter_value = self.filter_value.resolve(context, True)
- if filter_value:
- filter_name = smart_str(self.filter_name)
- filter_value = smart_unicode(filter_value)
- kwargs[filter_name] = filter_value
- # These two don't make sense
- if filter_name == 'server' and 'hostname' in kwargs:
- del kwargs['hostname']
- elif filter_name == 'hostname' and 'server' in kwargs:
- del kwargs['server']
- try:
- link = reverse(view, args=args, kwargs=kwargs)
- except NoReverseMatch:
- link = reverse(self.fallback_view, args=None,
- kwargs={ filter_name: filter_value })
- except NoReverseMatch:
- rm = sys.exc_info()[1]
- raise rm
- except (Resolver404, ValueError):
- pass
- return link
-
-@register.tag
-def add_url_filter(parser, token):
- """
- Return a url with the filter added to the current view.
-
- Takes a new filter and resolves the current view with the new filter
- applied. Resolves to Bcfg2.Server.Reports.reports.views.client_history
- by default.
-
- {% add_url_filter server=interaction.server %}
- """
- try:
- tag_name, filter_pair = token.split_contents()
- filter_name, filter_value = filter_pair.split('=', 1)
- 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])
- if not filter_name or not filter_value:
- raise template.TemplateSyntaxError("argument should be a filter=value pair")
-
- return AddUrlFilter(filter_name, filter_value)
-
-@register.filter
-def sortwell(value):
- """
- Sorts a list(or evaluates queryset to list) of bad, extra, or modified items in the best
- way for presentation
- """
-
- configItems = list(value)
- configItems.sort(lambda x,y: cmp(x.entry.name, y.entry.name))
- configItems.sort(lambda x,y: cmp(x.entry.kind, y.entry.kind))
- return configItems
-
-class MediaTag(template.Node):
- def __init__(self, filter_value):
- self.filter_value = filter_value
-
- def render(self, context):
- base = context['MEDIA_URL']
- try:
- request = context['request']
- try:
- base = request.environ['bcfg2.media_url']
- except:
- if request.path != request.META['PATH_INFO']:
- offset = request.path.find(request.META['PATH_INFO'])
- if offset > 0:
- base = "%s/%s" % (request.path[:offset], \
- context['MEDIA_URL'].strip('/'))
- except:
- pass
- return "%s/%s" % (base, self.filter_value)
-
-@register.tag
-def to_media_url(parser, token):
- """
- Return a url relative to the media_url.
-
- {% to_media_url /bcfg2.css %}
- """
- try:
- 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])
-
- 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
deleted file mode 100644
index 2e30125f9..000000000
--- a/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import sys
-from django import template
-from django.utils.encoding import smart_unicode, smart_str
-from django.utils.html import conditional_escape
-from django.utils.safestring import mark_safe
-
-register = template.Library()
-
-try:
- from pygments import highlight
- from pygments.lexers import get_lexer_by_name
- from pygments.formatters import HtmlFormatter
- colorize = True
-
-except:
- colorize = False
-
-# py3k compatibility
-def u_str(string):
- if sys.hexversion >= 0x03000000:
- return string
- else:
- return unicode(string)
-
-@register.filter
-def syntaxhilight(value, arg="diff", autoescape=None):
- """
- Returns a syntax-hilighted version of Code; requires code/language arguments
- """
-
- if autoescape:
- value = conditional_escape(value)
- arg = conditional_escape(arg)
-
- if colorize:
- try:
- output = u_str('<style type="text/css">') \
- + smart_unicode(HtmlFormatter().get_style_defs('.highlight')) \
- + u_str('</style>')
-
- lexer = get_lexer_by_name(arg)
- output += highlight(value, lexer, HtmlFormatter())
- return mark_safe(output)
- except:
- return value
- else:
- 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/urls.py b/src/lib/Server/Reports/reports/urls.py
deleted file mode 100644
index 434ce07b7..000000000
--- a/src/lib/Server/Reports/reports/urls.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from django.conf.urls.defaults import *
-from django.core.urlresolvers import reverse, NoReverseMatch
-from django.http import HttpResponsePermanentRedirect
-from Bcfg2.Server.Reports.utils import filteredUrls, paginatedUrls, timeviewUrls
-
-def newRoot(request):
- try:
- grid_view = reverse('reports_grid_view')
- except NoReverseMatch:
- grid_view = '/grid'
- return HttpResponsePermanentRedirect(grid_view)
-
-urlpatterns = patterns('Bcfg2.Server.Reports.reports',
- (r'^$', newRoot),
-
- url(r'^manage/?$', 'views.client_manage', name='reports_client_manage'),
- url(r'^client/(?P<hostname>[^/]+)/(?P<pk>\d+)/?$', 'views.client_detail', name='reports_client_detail_pk'),
- url(r'^client/(?P<hostname>[^/]+)/?$', 'views.client_detail', name='reports_client_detail'),
- url(r'^elements/(?P<type>\w+)/(?P<pk>\d+)/?$', 'views.config_item', name='reports_item'),
-)
-
-urlpatterns += patterns('Bcfg2.Server.Reports.reports',
- *timeviewUrls(
- (r'^grid/?$', 'views.client_index', None, 'reports_grid_view'),
- (r'^summary/?$', 'views.display_summary', None, 'reports_summary'),
- (r'^timing/?$', 'views.display_timing', None, 'reports_timing'),
- (r'^elements/(?P<type>\w+)/?$', 'views.config_item_list', None, 'reports_item_list'),
-))
-
-urlpatterns += patterns('Bcfg2.Server.Reports.reports',
- *filteredUrls(*timeviewUrls(
- (r'^detailed/?$',
- 'views.client_detailed_list', None, 'reports_detailed_list')
-)))
-
-urlpatterns += patterns('Bcfg2.Server.Reports.reports',
- *paginatedUrls( *filteredUrls(
- (r'^history/?$',
- 'views.render_history_view', None, 'reports_history'),
- (r'^history/(?P<hostname>[^/|]+)/?$',
- 'views.render_history_view', None, 'reports_client_history'),
-)))
-
- # Uncomment this for admin:
- #(r'^admin/', include('django.contrib.admin.urls')),
-
-
-## Uncomment this section if using authentication
-#urlpatterns += patterns('',
-# (r'^login/$', 'django.contrib.auth.views.login',
-# {'template_name': 'auth/login.html'}),
-# (r'^logout/$', 'django.contrib.auth.views.logout',
-# {'template_name': 'auth/logout.html'})
-# )
-
diff --git a/src/lib/Server/Reports/reports/views.py b/src/lib/Server/Reports/reports/views.py
deleted file mode 100644
index ccd71a60e..000000000
--- a/src/lib/Server/Reports/reports/views.py
+++ /dev/null
@@ -1,415 +0,0 @@
-"""
-Report views
-
-Functions to handle all of the reporting views.
-"""
-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.db import connection
-
-from Bcfg2.Server.Reports.reports.models import *
-
-
-class PaginationError(Exception):
- """This error is raised when pagination cannot be completed."""
- pass
-
-
-def server_error(request):
- """
- 500 error handler.
-
- For now always return the debug response. Mailing isn't appropriate here.
-
- """
- from django.views import debug
- return debug.technical_500_response(request, *sys.exc_info())
-
-
-def timeview(fn):
- """
- Setup a timeview view
-
- Handles backend posts from the calendar and converts date pieces
- into a 'timestamp' parameter
-
- """
- def _handle_timeview(request, **kwargs):
- """Send any posts back."""
- if request.method == 'POST':
- cal_date = request.POST['cal_date']
- try:
- fmt = "%Y/%m/%d"
- if cal_date.find(' ') > -1:
- fmt += " %H:%M"
- timestamp = datetime(*strptime(cal_date, fmt)[0:6])
- view, args, kw = resolve(request.META['PATH_INFO'])
- kw['year'] = "%0.4d" % timestamp.year
- kw['month'] = "%02.d" % timestamp.month
- kw['day'] = "%02.d" % timestamp.day
- if cal_date.find(' ') > -1:
- kw['hour'] = timestamp.hour
- kw['minute'] = timestamp.minute
- 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')),
- int(kwargs.pop('day')), int(kwargs.pop('hour', 0)),
- int(kwargs.pop('minute', 0)), 0)
- kwargs['timestamp'] = timestamp
- except KeyError:
- pass
- except:
- raise
- return fn(request, **kwargs)
-
- return _handle_timeview
-
-
-def config_item(request, pk, type="bad"):
- """
- Display a single entry.
-
- Dispalys information about a single entry.
-
- """
- 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')])
-
- associated_list = Interaction.objects.filter(id__in=[x['interaction']\
- for x in shared_entries.values('interaction')])\
- .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))
-
-
-@timeview
-def config_item_list(request, type, timestamp=None):
- """Render a listing of affected elements"""
- mod_or_bad = type.lower()
- 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():
- if (x.entry, x.reason) in seen:
- continue
- seen[(x.entry, x.reason)] = 1
- if item_list_dict.get(x.entry.kind, None):
- item_list_dict[x.entry.kind].append(x)
- else:
- 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))
-
- 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):
- """
- Render a grid view of active clients.
-
- Keyword parameters:
- timestamp -- datetime objectto render from
-
- """
- list = Interaction.objects.interaction_per_client(timestamp).select_related()\
- .order_by("client__name").all()
-
- return render_to_response('clients/index.html',
- {'inter_list': list,
- 'timestamp': timestamp},
- context_instance=RequestContext(request))
-
-
-@timeview
-def client_detailed_list(request, timestamp=None, **kwargs):
- """
- Provides a more detailed list view of the clients. Allows for extra
- filters to be passed in.
-
- """
-
- kwargs['interaction_base'] = Interaction.objects.interaction_per_client(timestamp).select_related()
- kwargs['orderby'] = "client__name"
- kwargs['page_limit'] = 0
- return render_history_view(request, 'clients/detailed-list.html', **kwargs)
-
-
-def client_detail(request, hostname=None, pk=None):
- context = dict()
- client = get_object_or_404(Client, name=hostname)
- if(pk == None):
- context['interaction'] = client.current_interaction
- return render_history_view(request, 'clients/detail.html', page_limit=5,
- client=client, context=context)
- else:
- context['interaction'] = client.interactions.get(pk=pk)
- 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 = ''
- if request.method == 'POST':
- try:
- client_name = request.POST.get('client_name', None)
- client_action = request.POST.get('client_action', None)
- client = Client.objects.get(name=client_name)
- if client_action == 'expire':
- 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.save()
- message = "%s is now active." % client_name
- else:
- message = "Missing action"
- except Client.DoesNotExist:
- if not client_name:
- client_name = "<none>"
- message = "Couldn't find client \"%s\"" % client_name
-
- return render_to_response('clients/manage.html',
- {'clients': Client.objects.order_by('name').all(), 'message': message},
- context_instance=RequestContext(request))
-
-
-@timeview
-def display_summary(request, timestamp=None):
- """
- Display a summary of the bcfg2 world
- """
- query = Interaction.objects.interaction_per_client(timestamp).select_related()
- node_count = query.count()
- recent_data = query.all()
- if not timestamp:
- timestamp = datetime.now()
-
- 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)
- # If stale check for uptime
- try:
- if node.client.pings.latest().status == 'N':
- collected_data['pings'].append(node)
- except Ping.DoesNotExist:
- collected_data['pings'].append(node)
- continue
- if node.bad_entry_count() > 0:
- collected_data['bad'].append(node)
- else:
- collected_data['clean'].append(node)
- if node.modified_entry_count() > 0:
- collected_data['modified'].append(node)
- if node.extra_entry_count() > 0:
- collected_data['extra'].append(node)
-
- # label, header_text, node_list
- summary_data = []
- 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.'))
- if len(collected_data['bad']) > 0:
- summary_data.append(get_dict('bad',
- 'nodes are bad.'))
- if len(collected_data['modified']) > 0:
- 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.'))
- if len(collected_data['stale']) > 0:
- 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.'))
-
- 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=list(mdict.keys())).all():
- for i in metric.interaction.all():
- mdict[i][metric.metric] = metric.value
- return render_to_response('displays/timing.html',
- {'metrics': list(mdict.values()),
- 'timestamp': timestamp},
- context_instance=RequestContext(request))
-
-
-def render_history_view(request, template='clients/history.html', **kwargs):
- """
- Provides a detailed history of a clients interactions.
-
- Renders a detailed history of a clients interactions. Allows for various
- filters and settings. Automatically sets pagination data into the context.
-
- Keyword arguments:
- interaction_base -- Interaction QuerySet to build on
- (default Interaction.objects)
- context -- Additional context data to render with
- page_number -- Page to display (default 1)
- page_limit -- Number of results per page, if 0 show all (default 25)
- client -- Client object to render
- hostname -- Client hostname to lookup and render. Returns a 404 if
- not found
- server -- Filter interactions by server
- state -- Filter interactions by state
- entry_max -- Most recent interaction to display
- orderby -- Sort results using this field
-
- """
-
- context = kwargs.get('context', dict())
- max_results = int(kwargs.get('page_limit', 25))
- page = int(kwargs.get('page_number', 1))
-
- client = kwargs.get('client', None)
- if not client and 'hostname' in kwargs:
- client = get_object_or_404(Client, name=kwargs['hostname'])
- if client:
- context['client'] = client
-
- entry_max = kwargs.get('maxdate', None)
- context['entry_max'] = entry_max
-
- # Either filter by client or limit by clients
- iquery = kwargs.get('interaction_base', Interaction.objects)
- if client:
- iquery = iquery.filter(client__exact=client).select_related()
-
- if 'orderby' in kwargs and kwargs['orderby']:
- iquery = iquery.order_by(kwargs['orderby'])
-
- if 'state' in kwargs and kwargs['state']:
- iquery = iquery.filter(state__exact=kwargs['state'])
- if 'server' in kwargs and kwargs['server']:
- iquery = iquery.filter(server__exact=kwargs['server'])
-
- if entry_max:
- iquery = iquery.filter(timestamp__lte=entry_max)
-
- if max_results < 0:
- max_results = 1
- entry_list = []
- if max_results > 0:
- try:
- 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)
- context['entry_list'] = iquery.all()[rec_start:rec_end]
- else:
- context['entry_list'] = iquery.all()
-
- 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")
- if paged_list == None:
- 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
- except:
- total_pages = 1
- if page > total_pages:
- # If we passed beyond the end send back
- try:
- view, args, kwargs = resolve(request.META['PATH_INFO'])
- kwargs['page_number'] = total_pages
- 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))