summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSol Jerome <solj@ices.utexas.edu>2009-11-09 23:51:56 +0000
committerSol Jerome <solj@ices.utexas.edu>2009-11-09 23:51:56 +0000
commitd14eef57303c4b9cef33fa97b71e12aa25e6bd0a (patch)
tree2779f16fc948fcceecc3fe73aac741e4f92ea797
parentd7e21c89c1b2e37ff45b40d14680a74ffc4974a5 (diff)
downloadbcfg2-d14eef57303c4b9cef33fa97b71e12aa25e6bd0a.tar.gz
bcfg2-d14eef57303c4b9cef33fa97b71e12aa25e6bd0a.tar.bz2
bcfg2-d14eef57303c4b9cef33fa97b71e12aa25e6bd0a.zip
Reports: Detailed Client List view from Tim Laszlo
This commit adds a new view for the reporting system submitted by Tim Laszlo. It gives detailed information about clients in a table format with State, Good/Bad/Extra entry counts, time of last run, and server client last communicated with. Signed-off-by: Sol Jerome <solj@ices.utexas.edu> git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@5563 ce84e21b-d406-0410-9b95-82705330c041
-rw-r--r--reports/site_media/boxypastel.css1
-rw-r--r--src/lib/Server/Reports/reports/models_new.py3
-rw-r--r--src/lib/Server/Reports/reports/models_old.py3
-rw-r--r--src/lib/Server/Reports/reports/templates/base.html5
-rw-r--r--src/lib/Server/Reports/reports/templates/clients/detailed-list.html97
-rw-r--r--src/lib/Server/Reports/reports/views.py47
-rw-r--r--src/lib/Server/Reports/urls.py6
7 files changed, 159 insertions, 3 deletions
diff --git a/reports/site_media/boxypastel.css b/reports/site_media/boxypastel.css
index f4e34eea4..4824270a5 100644
--- a/reports/site_media/boxypastel.css
+++ b/reports/site_media/boxypastel.css
@@ -145,7 +145,6 @@ span.nodelisttitle {
}
span.mini-date {
font-size: 10px;
- position: absolute;
right: 65px;
}
diff --git a/src/lib/Server/Reports/reports/models_new.py b/src/lib/Server/Reports/reports/models_new.py
index c8f649089..01e34de55 100644
--- a/src/lib/Server/Reports/reports/models_new.py
+++ b/src/lib/Server/Reports/reports/models_new.py
@@ -159,6 +159,9 @@ class Interaction(models.Model):
self.client.current_interaction = self.client.interactions.latest()
self.client.save()#save again post update
+ def badcount(self):
+ return self.totalcount - self.goodcount
+
def bad(self):
return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_BAD)
diff --git a/src/lib/Server/Reports/reports/models_old.py b/src/lib/Server/Reports/reports/models_old.py
index aee66fd7d..575ed0921 100644
--- a/src/lib/Server/Reports/reports/models_old.py
+++ b/src/lib/Server/Reports/reports/models_old.py
@@ -159,6 +159,9 @@ class Interaction(models.Model):
self.client.current_interaction = self.client.interactions.latest()
self.client.save()#save again post update
+ def badcount(self):
+ return self.totalcount - self.goodcount
+
def bad(self):
return Entries_interactions.objects.select_related().filter(interaction=self, type=TYPE_BAD)
diff --git a/src/lib/Server/Reports/reports/templates/base.html b/src/lib/Server/Reports/reports/templates/base.html
index d733e5563..81886ba75 100644
--- a/src/lib/Server/Reports/reports/templates/base.html
+++ b/src/lib/Server/Reports/reports/templates/base.html
@@ -21,6 +21,9 @@
<ul class="sidebar">
<li><a href="{% url Bcfg2.Server.Reports.reports.views.client_index %}../" class="sidebar">Home</a></li>
<li><a href="{% url Bcfg2.Server.Reports.reports.views.client_index %}" class="sidebar">Clients</a></li>
+ <ul class="sidebar-level2">
+ <li><a href="{% url Bcfg2.Server.Reports.reports.views.client_detailed_list %}" class="sidebar">Detailed List</a></li>
+ </ul>
<li>
<a href="{% url Bcfg2.Server.Reports.reports.views.display_index %}" class="sidebar">Displays</a>
<ul class="sidebar-level2">
@@ -48,4 +51,4 @@
</div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/src/lib/Server/Reports/reports/templates/clients/detailed-list.html b/src/lib/Server/Reports/reports/templates/clients/detailed-list.html
new file mode 100644
index 000000000..139c22780
--- /dev/null
+++ b/src/lib/Server/Reports/reports/templates/clients/detailed-list.html
@@ -0,0 +1,97 @@
+{% extends "base.html" %}
+
+{% block title %}Detailed Client Listing{% endblock %}
+
+{% block extra_header_info %}
+<script type="text/javascript" src="{% url Bcfg2.Server.Reports.reports.views.client_index %}../site_media/CalendarPopup.js"></script>
+<script type="text/javascript">var cal = new CalendarPopup();</script>
+<style type="text/css">
+#client_list_header {
+ font-weight: bold;
+ border-bottom:1px solid;
+ /*color: #333366;*/
+}
+/*#client_list_box {
+ min-width:875px;
+}*/
+.listview {
+ padding-top:3px;
+ padding-bottom:3px;
+}
+.listview_alt {
+ background:#f1ffc9;
+ padding-top:3px;
+ padding-bottom:3px;
+}
+</style>
+{% endblock%}
+
+{% block pagebanner %}
+ <div class="header">
+ <h1>Detailed Client List</h1>
+ </div>
+ <br/>
+{% endblock %}
+
+{% block content %}
+<div>
+<form name="timestamp-select" action='{{ path }}' method='get'>
+<span class="mini-date">
+<b>Enter date or use calendar popup: </b>
+<input type="text" name="date1" value="{{timestamp_date}}" size="10" />@
+<input type="text" name="time" value="{{timestamp_time}}" size="8" />
+<a href=""onclick="cal.select(document.forms['timestamp-select'].date1,'anchor1','yyyy-MM-dd'); return false;"
+ name="anchor1" id="anchor1">Calendar</a>
+<input type="button" value="Go" onclick="document.forms['timestamp-select'].submit();"/>
+ | <input type="button" name="now" value="Now" onclick="location.href='{{ path }}';"/>
+</span><br/><br/>
+</form>
+</div>
+
+<div id='client_list_box'>
+{% if entry_list %}
+ <table cellpadding="3">
+ <tr id='client_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'>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=
+ {% if server %}
+ '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list server=server,state=entry.state %}{{ qsa }}'
+ {% else %}
+ '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list state=entry.state %}{{ qsa }}'
+ {% endif %}
+ {% ifequal entry.state 'dirty' %}style='background:#FF6A6A'{% endifequal %}>{{ entry.state }}</a></td>
+ <td class='right_column_narrow'>{{ entry.goodcount }}</td>
+ <td class='right_column_narrow'>{{ entry.badcount }}</td>
+ <td class='right_column_narrow'>{{ entry.extra|length }}</td>
+ <td class='right_column'><span {% if entry.isstale %}style='background:#FF6A6A'{% endif %}>{{ entry.timestamp|date:"Y-m-d H:i" }}</span></td>
+ <td class='right_column_wide'>
+ {% if entry.server %}
+ <a href=
+ {% if state %}
+ '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list server=entry.server,state=state %}{{ qsa }}'
+ {% else %}
+ '{% url Bcfg2.Server.Reports.reports.views.client_detailed_list server=entry.server %}{{ qsa }}'
+ {% endif %}
+ >{{ 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/views.py b/src/lib/Server/Reports/reports/views.py
index 7a092c7d2..03a97e523 100644
--- a/src/lib/Server/Reports/reports/views.py
+++ b/src/lib/Server/Reports/reports/views.py
@@ -102,6 +102,53 @@ def client_index(request, timestamp = 'now'):
'timestamp_date' : timestamp[:10],
'timestamp_time' : timestamp[11:19]})
+def client_detailed_list(request, **kwargs):
+ '''
+ Provides a more detailed list view of the clients. Allows for extra
+ filters to be passed in. Somewhat clunky now that dates are allowed.
+ '''
+ context = dict(path=request.path)
+ timestamp = 'now'
+ entry_max = None
+ if request.GET:
+ context['qsa']='?%s' % request.GET.urlencode()
+ if request.GET.has_key('date1') and request.GET.has_key('time'):
+ timestamp = "%s %s" % (request.GET['date1'],request.GET['time'])
+ entry_max = datetime(*strptime(timestamp, "%Y-%m-%d %H:%M:%S")[0:6])
+ client_list = Client.objects.active(timestamp).order_by('name')
+ if timestamp == 'now':
+ timestamp = datetime.now().isoformat('@')
+ context['timestamp_date'] = timestamp[:10]
+ context['timestamp_time'] = timestamp[11:19]
+
+ if 'server' in kwargs and kwargs['server']:
+ context['server'] = kwargs['server']
+ if 'state' in kwargs and kwargs['state']:
+ context['state'] = kwargs['state']
+
+ # build the entry list from available clients
+ entry_list = []
+ if entry_max:
+ for client in client_list:
+ try:
+ e = interaction.objects.filter(client=client).filter(timestamp__lt=entry_max).order_by('-timestamp')[0]
+ if 'server' in context and e.server != context['server']:
+ continue
+ if 'state' in context and e.state != context['state']:
+ continue
+ entry_list.append(e)
+ except IndexError:
+ # Should never see this.. but skip clients with no data
+ pass
+ else:
+ if 'server' in context:
+ client_list = client_list.filter(current_interaction__server__exact=kwargs['server'])
+ if 'state' in context:
+ client_list = client_list.filter(current_interaction__state__exact=kwargs['state'])
+ [ entry_list.append(x.current_interaction) for x in client_list ]
+ context['entry_list'] = entry_list
+ return render_to_response('clients/detailed-list.html', context)
+
def client_detail(request, hostname = None, pk = None):
#SETUP error pages for when you specify a client or interaction that doesn't exist
client = get_object_or_404(Client, name=hostname)
diff --git a/src/lib/Server/Reports/urls.py b/src/lib/Server/Reports/urls.py
index 836808c7e..63c119d14 100644
--- a/src/lib/Server/Reports/urls.py
+++ b/src/lib/Server/Reports/urls.py
@@ -19,7 +19,11 @@ urlpatterns = patterns('',
# (r'^%sBcfg2.Server.Reports/' % web_prefix, include('Bcfg2.Server.Reports.apps.foo.urls.foo')),
(r'^%s*$' % web_prefix_root,'Bcfg2.Server.Reports.reports.views.index'),
- (r'^%sclients/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_index'),
+ (r'^%sclients-detailed/state/(?P<state>\w+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'),
+ (r'^%sclients-detailed/server/(?P<server>[\w\-\.]+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'),
+ (r'^%sclients-detailed/server/(?P<server>[\w\-\.]+)/(?P<state>[A-Za-z]+)/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'),
+ (r'^%sclients-detailed/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_detailed_list'),
+ (r'^%sclients/(?P<timestamp>(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])@([01][0-9]|2[0-3]):([0-5][0-9]|60):([0-5][0-9]|60))/$' % web_prefix,'Bcfg2.Server.Reports.reports.views.client_index'),
(r'^%sclients/(?P<hostname>\S+)/(?P<pk>\d+)/$' % web_prefix, 'Bcfg2.Server.Reports.reports.views.client_detail'),
(r'^%sclients/(?P<hostname>\S+)/manage/$' % web_prefix, 'Bcfg2.Server.Reports.reports.views.client_manage'),
(r'^%sclients/(?P<hostname>\S+)/$' % web_prefix, 'Bcfg2.Server.Reports.reports.views.client_detail'),