|
|
95ec45 |
commit 004d8a3e46fe4c56b0ea4db27c2c618b86b54f76
|
|
|
95ec45 |
Author: Nathan Scott <nathans@redhat.com>
|
|
|
95ec45 |
Date: Mon Feb 3 17:13:12 2014 +1100
|
|
|
95ec45 |
|
|
|
95ec45 |
Fix and test python wrappers for pmLocaltime and pmCtime
|
|
|
95ec45 |
|
|
|
95ec45 |
Several problems uncovered in the time-processing wrappers
|
|
|
95ec45 |
of the python PMAPI module after attempting to use 'em for
|
|
|
95ec45 |
the first time:
|
|
|
95ec45 |
- size of 'struct tm' did not match modern reality (missing
|
|
|
95ec45 |
the final two fields for Linux and BSD - sigsegv results);
|
|
|
95ec45 |
- system time.mktime python method does not take 9 arguments
|
|
|
95ec45 |
just one - fix the string-printing method for struct tm;
|
|
|
95ec45 |
- system time.mktime takes year field as an actual year, and
|
|
|
95ec45 |
not the number of years since 1900 - code didn't cater for
|
|
|
95ec45 |
this difference to struct tm form returned from localtime.
|
|
|
95ec45 |
- definition of the pmLocaltime return code was not correct;
|
|
|
95ec45 |
- definition of first pmCtime parameter was not correct;
|
|
|
95ec45 |
- code didn't cope with numeric input being passed in either
|
|
|
95ec45 |
float/integer format - pythonic time-in-seconds is float.
|
|
|
95ec45 |
- no memory allocated to hold the struct tm that pmLocaltime
|
|
|
95ec45 |
returns - pointer passed in pointing off into lala-land;
|
|
|
95ec45 |
- need to ensure a pointer to a ctypes c_long is passed into
|
|
|
95ec45 |
both of these routines - caller might well pass int (e.g.
|
|
|
95ec45 |
from a pmResult timestamp (struct timeval, tv_sec field).
|
|
|
95ec45 |
|
|
|
95ec45 |
Fixed the above and added qa test (boeing) 737 to verify it.
|
|
|
95ec45 |
Some small cleanups as well, in the affected code - fixed a
|
|
|
95ec45 |
couple of typos in comments, and removed an unused import
|
|
|
95ec45 |
of struct_time from the system time module.
|
|
|
95ec45 |
|
|
|
95ec45 |
diff --git a/qa/737 b/qa/737
|
|
|
95ec45 |
new file mode 100755
|
|
|
95ec45 |
index 0000000..17d6c18
|
|
|
95ec45 |
--- /dev/null
|
|
|
95ec45 |
+++ b/qa/737
|
|
|
95ec45 |
@@ -0,0 +1,29 @@
|
|
|
95ec45 |
+#!/bin/sh
|
|
|
95ec45 |
+# PCP QA Test No. 737
|
|
|
95ec45 |
+# Exercise time interfaces in python PMAPI wrapper module.
|
|
|
95ec45 |
+#
|
|
|
95ec45 |
+# Copyright (c) Red Hat.
|
|
|
95ec45 |
+#
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+seq=`basename $0`
|
|
|
95ec45 |
+echo "QA output created by $seq"
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+# get standard environment, filters and checks
|
|
|
95ec45 |
+. ./common.product
|
|
|
95ec45 |
+. ./common.filter
|
|
|
95ec45 |
+. ./common.check
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+python -c "from pcp import pmda" >/dev/null 2>&1
|
|
|
95ec45 |
+[ $? -eq 0 ] || _notrun "python pcp pmda module not installed"
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+status=1 # failure is the default!
|
|
|
95ec45 |
+$sudo rm -rf $tmp.* $seq.full
|
|
|
95ec45 |
+trap "rm -rf $tmp.*; exit \$status" 0 1 2 3 15
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+# real QA test starts here
|
|
|
95ec45 |
+python src/test_pcp_time.python
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+# success, all done
|
|
|
95ec45 |
+status=0
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+exit
|
|
|
95ec45 |
diff --git a/qa/737.out b/qa/737.out
|
|
|
95ec45 |
new file mode 100644
|
|
|
95ec45 |
index 0000000..6a12e50
|
|
|
95ec45 |
--- /dev/null
|
|
|
95ec45 |
+++ b/qa/737.out
|
|
|
95ec45 |
@@ -0,0 +1,5 @@
|
|
|
95ec45 |
+QA output created by 737
|
|
|
95ec45 |
+pmLocaltime from int: 1388763979.0 (2014, 1, 3, 15, 46, 19, 1, 33, 0)
|
|
|
95ec45 |
+pmLocaltime from float: 1388763979.0 (2014, 1, 3, 15, 46, 19, 1, 33, 0)
|
|
|
95ec45 |
+pmCtime from int: Mon Feb 3 15:46:19 2014
|
|
|
95ec45 |
+pmCtime from float: Mon Feb 3 15:46:19 2014
|
|
|
95ec45 |
diff --git a/qa/group b/qa/group
|
|
|
95ec45 |
index 077b83c..bb752f1 100644
|
|
|
95ec45 |
--- a/qa/group
|
|
|
95ec45 |
+++ b/qa/group
|
|
|
95ec45 |
@@ -883,6 +883,7 @@ avahi
|
|
|
95ec45 |
733 pmie pmval pmdumplog local oss
|
|
|
95ec45 |
735 pmda.proc local oss
|
|
|
95ec45 |
736 pmlogrewrite local oss
|
|
|
95ec45 |
+737 python local oss
|
|
|
95ec45 |
740 pmda.sample pmstore secure local oss
|
|
|
95ec45 |
748 pmlogrewrite pmda.mysql local oss
|
|
|
95ec45 |
749 pmcd local oss
|
|
|
95ec45 |
diff --git a/qa/src/GNUlocaldefs b/qa/src/GNUlocaldefs
|
|
|
95ec45 |
index b4382ce..0cf7971 100644
|
|
|
95ec45 |
--- a/qa/src/GNUlocaldefs
|
|
|
95ec45 |
+++ b/qa/src/GNUlocaldefs
|
|
|
95ec45 |
@@ -154,7 +154,8 @@ PLFILES = $(shell echo $(PERLFILES) | sed -e 's/\.perl/.pl/g')
|
|
|
95ec45 |
PYTHONFILES = \
|
|
|
95ec45 |
test_pcp.python test_pmcc.python \
|
|
|
95ec45 |
test_pmi.python check_import.python \
|
|
|
95ec45 |
- test_mmv.python test_webapi.python
|
|
|
95ec45 |
+ test_mmv.python test_webapi.python \
|
|
|
95ec45 |
+ test_pcp_time.python
|
|
|
95ec45 |
# not installed:
|
|
|
95ec45 |
PYFILES = $(shell echo $(PYTHONFILES) | sed -e 's/\.python/.py/g')
|
|
|
95ec45 |
|
|
|
95ec45 |
diff --git a/qa/src/test_pcp_time.python b/qa/src/test_pcp_time.python
|
|
|
95ec45 |
new file mode 100755
|
|
|
95ec45 |
index 0000000..674686b
|
|
|
95ec45 |
--- /dev/null
|
|
|
95ec45 |
+++ b/qa/src/test_pcp_time.python
|
|
|
95ec45 |
@@ -0,0 +1,32 @@
|
|
|
95ec45 |
+#!/usr/bin/python
|
|
|
95ec45 |
+#
|
|
|
95ec45 |
+# Copyright (C) 2014 Red Hat.
|
|
|
95ec45 |
+#
|
|
|
95ec45 |
+# This program is free software; you can redistribute it and/or modify it
|
|
|
95ec45 |
+# under the terms of the GNU General Public License as published by the
|
|
|
95ec45 |
+# Free Software Foundation; either version 2 of the License, or (at your
|
|
|
95ec45 |
+# option) any later version.
|
|
|
95ec45 |
+#
|
|
|
95ec45 |
+# This program is distributed in the hope that it will be useful, but
|
|
|
95ec45 |
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
95ec45 |
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
95ec45 |
+# for more details.
|
|
|
95ec45 |
+#
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+""" Exercise the pmCtime and pmLocaltime interfaces """
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+from pcp import pmapi
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+""" Create a live PMAPI context, set as UTC and report time """
|
|
|
95ec45 |
+context = pmapi.pmContext()
|
|
|
95ec45 |
+context.pmNewZone("UTC")
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+# seconds-since-epoch for: "Mon Feb 3 15:46:19 2014 UTC"
|
|
|
95ec45 |
+sample_time_i = 1391402779 # integer
|
|
|
95ec45 |
+sample_time_f = 1391402779.0 # float
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+print "pmLocaltime from int: ", context.pmLocaltime(sample_time_i)
|
|
|
95ec45 |
+print "pmLocaltime from float: ", context.pmLocaltime(sample_time_f)
|
|
|
95ec45 |
+
|
|
|
95ec45 |
+print "pmCtime from int: ", context.pmCtime(sample_time_i),
|
|
|
95ec45 |
+print "pmCtime from float: ", context.pmCtime(sample_time_f),
|
|
|
95ec45 |
diff --git a/src/python/pcp/pmapi.py b/src/python/pcp/pmapi.py
|
|
|
95ec45 |
index 527a1f3..72302b4 100644
|
|
|
95ec45 |
--- a/src/python/pcp/pmapi.py
|
|
|
95ec45 |
+++ b/src/python/pcp/pmapi.py
|
|
|
95ec45 |
@@ -56,7 +56,7 @@
|
|
|
95ec45 |
# Is this the kernel.all.load id?
|
|
|
95ec45 |
if (results.contents.get_pmid(i) != metric_ids[1]):
|
|
|
95ec45 |
continue
|
|
|
95ec45 |
- # Extrace the kernal.all.load instance
|
|
|
95ec45 |
+ # Extract the kernel.all.load instance
|
|
|
95ec45 |
for j in xrange(results.contents.get_numval(i) - 1):
|
|
|
95ec45 |
atom = context.pmExtractValue(results.contents.get_valfmt(i),
|
|
|
95ec45 |
results.contents.get_vlist(i, j),
|
|
|
95ec45 |
@@ -69,8 +69,8 @@
|
|
|
95ec45 |
print "load average 5=",atom.f
|
|
|
95ec45 |
"""
|
|
|
95ec45 |
|
|
|
95ec45 |
-# for dereferencing times from pmLocaltime function (struct tm)
|
|
|
95ec45 |
-from time import struct_time, mktime
|
|
|
95ec45 |
+# for reporting on times from pmLocaltime function
|
|
|
95ec45 |
+from time import mktime
|
|
|
95ec45 |
|
|
|
95ec45 |
# constants adapted from C header file <pcp/pmapi.h>
|
|
|
95ec45 |
import cpmapi as c_api
|
|
|
95ec45 |
@@ -148,13 +148,20 @@ class tm(Structure):
|
|
|
95ec45 |
("tm_year", c_int),
|
|
|
95ec45 |
("tm_wday", c_int),
|
|
|
95ec45 |
("tm_yday", c_int),
|
|
|
95ec45 |
- ("tm_isdst", c_int)]
|
|
|
95ec45 |
+ ("tm_isdst", c_int),
|
|
|
95ec45 |
+ ("tm_gmtoff", c_long), # glibc/bsd extension
|
|
|
95ec45 |
+ ("tm_zone", c_char_p)] # glibc/bsd extension
|
|
|
95ec45 |
|
|
|
95ec45 |
def __str__(self):
|
|
|
95ec45 |
- tmp = mktime(self.tm_year, self.tm_mon, self.tm_mday, self.tm_hour,
|
|
|
95ec45 |
- self.tm_min, self.tm_sec, self.tm_wday, self.tm_yday,
|
|
|
95ec45 |
- self.tm_isdst)
|
|
|
95ec45 |
- return "%s" % tmp.__str__()
|
|
|
95ec45 |
+ timetuple = (self.tm_year+1900, self.tm_mon, self.tm_mday,
|
|
|
95ec45 |
+ self.tm_hour, self.tm_min, self.tm_sec,
|
|
|
95ec45 |
+ self.tm_wday, self.tm_yday, self.tm_isdst)
|
|
|
95ec45 |
+ inseconds = 0.0
|
|
|
95ec45 |
+ try:
|
|
|
95ec45 |
+ inseconds = mktime(timetuple)
|
|
|
95ec45 |
+ except:
|
|
|
95ec45 |
+ pass
|
|
|
95ec45 |
+ return "%s %s" % (inseconds.__str__(), timetuple)
|
|
|
95ec45 |
|
|
|
95ec45 |
class pmAtomValue(Union):
|
|
|
95ec45 |
"""Union used for unpacking metric values according to type
|
|
|
95ec45 |
@@ -512,11 +519,11 @@ LIBPCP.pmUseZone.argtypes = [c_int]
|
|
|
95ec45 |
LIBPCP.pmWhichZone.restype = c_int
|
|
|
95ec45 |
LIBPCP.pmWhichZone.argtypes = [POINTER(c_char_p)]
|
|
|
95ec45 |
|
|
|
95ec45 |
-LIBPCP.pmLocaltime.restype = tm
|
|
|
95ec45 |
+LIBPCP.pmLocaltime.restype = POINTER(tm)
|
|
|
95ec45 |
LIBPCP.pmLocaltime.argtypes = [POINTER(c_long), POINTER(tm)]
|
|
|
95ec45 |
|
|
|
95ec45 |
LIBPCP.pmCtime.restype = c_char_p
|
|
|
95ec45 |
-LIBPCP.pmCtime.argtypes = [c_long, c_char_p]
|
|
|
95ec45 |
+LIBPCP.pmCtime.argtypes = [POINTER(c_long), c_char_p]
|
|
|
95ec45 |
|
|
|
95ec45 |
|
|
|
95ec45 |
##
|
|
|
95ec45 |
@@ -689,7 +696,7 @@ class pmContext(object):
|
|
|
95ec45 |
status = LIBPCP.pmUseContext(self.ctx)
|
|
|
95ec45 |
if status < 0:
|
|
|
95ec45 |
raise pmErr, status
|
|
|
95ec45 |
- status = LIBPCP.pmGetChildren(name, byref( offspring))
|
|
|
95ec45 |
+ status = LIBPCP.pmGetChildren(name, byref(offspring))
|
|
|
95ec45 |
if status < 0:
|
|
|
95ec45 |
raise pmErr, status
|
|
|
95ec45 |
if status > 0:
|
|
|
95ec45 |
@@ -1148,16 +1155,20 @@ class pmContext(object):
|
|
|
95ec45 |
status = LIBPCP.pmUseContext(self.ctx)
|
|
|
95ec45 |
if status < 0:
|
|
|
95ec45 |
raise pmErr, status
|
|
|
95ec45 |
- result = POINTER(tm)()
|
|
|
95ec45 |
- return LIBPCP.pmLocaltime(seconds, byref(result))
|
|
|
95ec45 |
+ result = (tm)()
|
|
|
95ec45 |
+ timetp = c_long(int(seconds))
|
|
|
95ec45 |
+ LIBPCP.pmLocaltime(byref(timetp), byref(result))
|
|
|
95ec45 |
+ return result
|
|
|
95ec45 |
|
|
|
95ec45 |
def pmCtime(self, seconds):
|
|
|
95ec45 |
"""PMAPI - format the date and time for a reporting timezone """
|
|
|
95ec45 |
status = LIBPCP.pmUseContext(self.ctx)
|
|
|
95ec45 |
if status < 0:
|
|
|
95ec45 |
raise pmErr, status
|
|
|
95ec45 |
- result = (c_char * 32)()
|
|
|
95ec45 |
- return LIBPCP.pmCtime(seconds, byref(result))
|
|
|
95ec45 |
+ result = ctypes.create_string_buffer(32)
|
|
|
95ec45 |
+ timetp = c_long(int(seconds))
|
|
|
95ec45 |
+ LIBPCP.pmCtime(byref(timetp), result)
|
|
|
95ec45 |
+ return str(result.value)
|
|
|
95ec45 |
|
|
|
95ec45 |
##
|
|
|
95ec45 |
# PMAPI Metrics Services
|