# coding: utf-8
# Copyright (C) 1994-2018 Altair Engineering, Inc.
# For more information, contact Altair at www.altair.com.
#
# This file is part of the PBS Professional ("PBS Pro") software.
#
# Open Source License Information:
#
# PBS Pro is free software. You can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#
# Commercial License Information:
#
# For a copy of the commercial license terms and conditions,
# go to: (http://www.pbspro.com/UserArea/agreement.html)
# or contact the Altair Legal Department.
#
# Altair’s dual-license business model allows companies, individuals, and
# organizations to create proprietary derivative works of PBS Pro and
# distribute them - whether embedded or bundled with other software -
# under a commercial license agreement.
#
# Use of Altair’s trademarks, including but not limited to "PBS™",
# "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
# trademark licensing policies.
import os
import ptl
import sys
import pwd
import logging
import platform
import traceback
import time
import json
import ptl.utils.pbs_logutils as lu
from ptl.lib.pbs_testlib import PbsTypeDuration
from ptl.utils.plugins.ptl_test_tags import TAGKEY
from ptl.utils.pbs_dshutils import DshUtils
from ptl.utils.plugins.ptl_report_json import PTLJsonData
# Following dance require because PTLTestDb().process_output() from this file
# is used in pbs_loganalyzer script which is shipped with PBS package
# through unsupported directory where we might not have nose installed
try:
from nose.util import isclass
from nose.plugins.base import Plugin
from nose.plugins.skip import SkipTest
from ptl.utils.plugins.ptl_test_runner import TimeOut
log = logging.getLogger('nose.plugins.PTLTestDb')
except ImportError:
class Plugin(object):
pass
def isclass(obj):
pass
class SkipTest(Exception):
pass
class TimeOut(Exception):
pass
log = logging.getLogger('PTLTestDb')
# Table names
_DBVER_TN = 'ptl_db_version'
_TESTRESULT_TN = 'ptl_test_results'
_SCHEDM_TN = 'ptl_scheduler_metrics'
_SVRM_TN = 'ptl_server_metrics'
_MOMM_TN = 'ptl_mom_metrics'
_ACCTM_TN = 'ptl_accounting_metrics'
_PROCM_TN = 'ptl_proc_metrics'
_CYCLEM_TN = 'ptl_cycle_metrics'
_ESTINFOSUM_TN = 'ptl_estimated_info_summary'
_ESTINFO_TN = 'ptl_estimated_info'
_JOBM_TN = 'ptl_job_metrics'
class PTLDbError(Exception):
"""
PTL database error class
:param rv: Return value for the database error
:type rv: str or None
:param rc: Return code for the database error
:type rc: str or None
:param msg: Error message
:type msg: str or None
"""
def __init__(self, rv=None, rc=None, msg=None, post=None, *args, **kwargs):
self.rv = rv
self.rc = rc
self.msg = msg
if post is not None:
post(*args, **kwargs)
def __str__(self):
return ('rc=' + str(self.rc) + ', rv=' + str(self.rv) +
', msg=' + str(self.msg))
def __repr__(self):
return (self.__class__.__name__ + '(rc=' + str(self.rc) + ', rv=' +
str(self.rv) + ', msg=' + str(self.msg) + ')')
class DBType(object):
"""
Base class for each database type
Any type of database must inherit from me
:param dbtype: Database type
:type dbtype: str
:param dbpath: Path to database
:type dbpath: str
:param dbaccess: Path to a file that defines db options
:type dbaccess: str
"""
def __init__(self, dbtype, dbpath, dbaccess):
if dbpath is None:
dn = _TESTRESULT_TN + '.db'
dbdir = os.getcwd()
dbpath = os.path.join(dbdir, dn)
elif os.path.isdir(dbpath):
dn = _TESTRESULT_TN + '.db'
dbdir = dbpath
dbpath = os.path.join(dbdir, dn)
else:
dbdir = os.path.dirname(dbpath)
dbpath = dbpath
self.dbtype = dbtype
self.dbpath = dbpath
self.dbdir = dbdir
self.dbaccess = dbaccess
def write(self, data, logfile=None):
"""
:param data: Data to write
:param logfile: Can be one of ``server``, ``scheduler``, ``mom``,
``accounting`` or ``procs``
:type logfile: str or None
"""
_msg = 'write method must be implemented in'
_msg += ' %s' % (str(self.__class__.__name__))
raise PTLDbError(rc=1, rv=False, msg=_msg)
def close(self, result=None):
"""
Close the database
"""
_msg = 'close method must be implemented in'
_msg += ' %s' % (str(self.__class__.__name__))
raise PTLDbError(rc=1, rv=False, msg=_msg)
class PostgreSQLDb(DBType):
"""
PostgreSQL type database
"""
def __init__(self, dbtype, dbpath, dbaccess):
DBType.__init__(self, dbtype, dbpath, dbaccess)
if self.dbtype != 'pgsql':
_msg = 'db type does not match with my type(file)'
raise PTLDbError(rc=1, rv=False, msg=_msg)
if self.dbaccess is None:
_msg = 'Db access creds require!'
raise PTLDbError(rc=1, rv=False, msg=_msg)
try:
import psycopg2
except:
_msg = 'psycopg2 require for %s type database!' % (self.dbtype)
raise PTLDbError(rc=1, rv=False, msg=_msg)
try:
f = open(self.dbaccess)
creds = ' '.join(map(lambda n: n.strip(), f.readlines()))
f.close()
self.__dbobj = psycopg2.connect(creds)
except Exception, e:
_msg = 'Failed to connect to database:\n%s\n' % (str(e))
raise PTLDbError(rc=1, rv=False, msg=_msg)
self.__username = pwd.getpwuid(os.getuid())[0]
self.__platform = ' '.join(platform.uname()).strip()
self.__ptlversion = str(ptl.__version__)
self.__db_version = '1.0.0'
self.__index = self.__create_tables()
def __get_index(self, c):
idxs = []
stmt = 'SELECT max(id) from %s;' % (_TESTRESULT_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_SCHEDM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_SVRM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_MOMM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_ACCTM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_PROCM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_CYCLEM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_ESTINFOSUM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_ESTINFO_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_JOBM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
idx = max(idxs)
if idx is not None:
return idx
else:
return 1
def __upgrade_db(self, version):
if version == self.__db_version:
return
def __create_tables(self):
c = self.__dbobj.cursor()
try:
stmt = ['CREATE TABLE %s (' % (_DBVER_TN)]
stmt += ['version TEXT);']
c.execute(''.join(stmt))
except:
stmt = 'SELECT version from %s;' % (_DBVER_TN)
version = c.execute(stmt).fetchone()[0]
self.__upgrade_db(version)
return self.__get_index(c)
stmt = ['INSERT INTO %s (version)' % (_DBVER_TN)]
stmt += [' VALUES (%s);' % (self.__db_version)]
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_TESTRESULT_TN)]
stmt += ['id INTEGER,']
stmt += ['suite TEXT,']
stmt += ['testcase TEXT,']
stmt += ['testdoc TEXT,']
stmt += ['start_time TEXT,']
stmt += ['end_time TEXT,']
stmt += ['duration TEXT,']
stmt += ['pbs_version TEXT,']
stmt += ['testparam TEXT,']
stmt += ['username TEXT,']
stmt += ['ptl_version TEXT,']
stmt += ['platform TEXT,']
stmt += ['status TEXT,']
stmt += ['status_data TEXT,']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SCHEDM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.VER + ' TEXT,']
stmt += [lu.NC + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJC + ' INTEGER,']
stmt += [lu.NJFR + ' INTEGER,']
stmt += [lu.mCD + ' TIME,']
stmt += [lu.CD25 + ' TIME,']
stmt += [lu.CDA + ' TIME,']
stmt += [lu.CD50 + ' TIME,']
stmt += [lu.CD75 + ' TIME,']
stmt += [lu.MCD + ' TIME,']
stmt += [lu.mCT + ' TIMESTAMP,']
stmt += [lu.MCT + ' TIMESTAMP,']
stmt += [lu.TTC + ' TIME,']
stmt += [lu.DUR + ' TIME,']
stmt += [lu.SST + ' TIME,']
stmt += [lu.JRR + ' TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SVRM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.VER + ' TEXT,']
stmt += [lu.NJQ + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJE + ' INTEGER,']
stmt += [lu.JRR + ' TEXT,']
stmt += [lu.JER + ' TEXT,']
stmt += [lu.JSR + ' TEXT,']
stmt += [lu.NUR + ' TEXT,']
stmt += [lu.JWTm + ' TIME,']
stmt += [lu.JWT25 + ' TIME,']
stmt += [lu.JWT50 + ' TIME,']
stmt += [lu.JWTA + ' TIME,']
stmt += [lu.JWT75 + ' TIME,']
stmt += [lu.JWTM + ' TIME,']
stmt += [lu.JRTm + ' TIME,']
stmt += [lu.JRT25 + ' TIME,']
stmt += [lu.JRTA + ' TIME,']
stmt += [lu.JRT50 + ' TIME,']
stmt += [lu.JRT75 + ' TIME,']
stmt += [lu.JRTM + ' TIME);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_MOMM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.VER + ' TEXT,']
stmt += [lu.NJQ + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJE + ' INTEGER,']
stmt += [lu.JRR + ' TEXT,']
stmt += [lu.JER + ' TEXT,']
stmt += [lu.JSR + ' TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ACCTM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.DUR + ' TEXT,']
stmt += [lu.NJQ + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJE + ' INTEGER,']
stmt += [lu.JRR + ' TEXT,']
stmt += [lu.JSR + ' TEXT,']
stmt += [lu.JER + ' TEXT,']
stmt += [lu.JWTm + ' TIME,']
stmt += [lu.JWT25 + ' TIME,']
stmt += [lu.JWT50 + ' TIME,']
stmt += [lu.JWTA + ' TIME,']
stmt += [lu.JWT75 + ' TIME,']
stmt += [lu.JWTM + ' TIME,']
stmt += [lu.JRTm + ' TIME,']
stmt += [lu.JRT25 + ' TIME,']
stmt += [lu.JRTA + ' TIME,']
stmt += [lu.JRT50 + ' TIME,']
stmt += [lu.JRT75 + ' TIME,']
stmt += [lu.JRTM + ' TIME,']
stmt += [lu.JNSm + ' INTEGER,']
stmt += [lu.JNS25 + ' REAL,']
stmt += [lu.JNSA + ' REAL,']
stmt += [lu.JNS50 + ' REAL,']
stmt += [lu.JNS75 + ' REAL,']
stmt += [lu.JNSM + ' REAL,']
stmt += [lu.JCSm + ' INTEGER,']
stmt += [lu.JCS25 + ' REAL,']
stmt += [lu.JCSA + ' REAL,']
stmt += [lu.JCS50 + ' REAL,']
stmt += [lu.JCS75 + ' REAL,']
stmt += [lu.JCSM + ' REAL,']
stmt += [lu.CPH + ' INTEGER,']
stmt += [lu.NPH + ' INTEGER,']
stmt += [lu.UNCPUS + ' TEXT,']
stmt += [lu.UNODES + ' TEXT,']
stmt += [lu.USRS + ' TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_PROCM_TN)]
stmt += ['id INTEGER, ']
stmt += ['name TEXT,']
stmt += ['rss INTEGER,']
stmt += ['vsz INTEGER,']
stmt += ['pcpu TEXT,']
stmt += ['time TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_CYCLEM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.CST + ' TIMESTAMP,']
stmt += [lu.CD + ' TIME,']
stmt += [lu.QD + ' TIME,']
stmt += [lu.NJC + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJFR + ' INTEGER,']
stmt += [lu.NJCAL + ' INTEGER,']
stmt += [lu.NJFP + ' INTEGER,']
stmt += [lu.NJP + ' INTEGER,']
stmt += [lu.TTC + ' INTEGER,']
stmt += [lu.SST + ' INTEGER);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFOSUM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.NJD + ' INTEGER,']
stmt += [lu.NJND + ' INTEGER,']
stmt += [lu.Ds15mn + ' INTEGER,']
stmt += [lu.Ds1hr + ' INTEGER,']
stmt += [lu.Ds3hr + ' INTEGER,']
stmt += [lu.Do3hr + ' INTEGER,']
stmt += [lu.DDm + ' INTEGER,']
stmt += [lu.DDM + ' INTEGER,']
stmt += [lu.DDA + ' INTEGER,']
stmt += [lu.DD50 + ' INTEGER);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFO_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.JID + ' TEXT,']
stmt += [lu.Eat + ' INTEGER,']
stmt += [lu.JST + ' INTEGER,']
stmt += [lu.ESTR + ' INTEGER,']
stmt += [lu.ESTA + ' INTEGER,']
stmt += [lu.NEST + ' INTEGER,']
stmt += [lu.ND + ' INTEGER,']
stmt += [lu.JDD + ' INTEGER);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_JOBM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.CST + ' TIMESTAMP,']
stmt += [lu.JID + ' TEXT,']
stmt += [lu.T2R + ' INTEGER,']
stmt += [lu.T2D + ' INTEGER,']
stmt += [lu.TiS + ' INTEGER,']
stmt += [lu.TTC + ' INTEGER);']
c.execute(''.join(stmt))
self.__dbobj.commit()
return self.__get_index(c)
def __write_data(self, tablename, data, logfile):
keys = ['id']
values = [str(self.__index)]
if logfile is not None:
keys.append('logname')
values.append('\'' + str(logfile).replace(' ', '_') + '\'')
for k, v in data.items():
if k == 'id':
continue
keys.append(str(k))
v = str(v)
if v.isdigit():
values.append(v)
else:
values.append('\'' + v + '\'')
_keys = ','.join(keys)
_values = ','.join(values)
c = self.__dbobj.cursor()
s = 'INSERT INTO %s (%s) VALUES (%s)' % (tablename, _keys, _values)
c.execute(s)
self.__dbobj.commit()
def __write_server_data(self, data, logfile=None):
self.__write_data(_SVRM_TN, data, logfile)
def __write_mom_data(self, data, logfile=None):
self.__write_data(_MOMM_TN, data, logfile)
def __write_sched_data(self, data, logfile=None):
for k, v in data.items():
if k == 'summary':
self.__write_data(_SCHEDM_TN, data, logfile)
continue
elif k == lu.EST:
if lu.ESTS in v:
self.__write_estinfosum_data(v[lu.ESTS], logfile)
if lu.EJ in v:
for j in v[lu.EJ]:
if lu.EST in j:
dt = map(lambda s: str(s), j[lu.Eat])
j[lu.Eat] = ','.join(dt)
self.__write_estsum_data(j, logfile)
continue
if 'jobs' in v:
for j in v['jobs']:
j[lu.CST] = v[lu.CST]
self.__write_job_data(j, logfile)
del v['jobs']
self.__write_cycle_data(v, logfile)
def __write_acct_data(self, data, logfile=None):
self.__write_data(_ACCTM_TN, data, logfile)
def __write_proc_data(self, data, logfile=None):
self.__write_data(_PROCM_TN, data, None)
def __write_cycle_data(self, data, logfile=None):
self.__write_data(_CYCLEM_TN, data, logfile)
def __write_estsum_data(self, data, logfile=None):
self.__write_data(_ESTINFOSUM_TN, data, logfile)
def __write_estinfosum_data(self, data, logfile=None):
self.__write_data(_ESTINFO_TN, data, logfile)
def __write_job_data(self, data, logfile=None):
self.__write_data(_JOBM_TN, data, logfile)
def __write_test_data(self, data):
keys = ['id']
values = [str(self.__index)]
keys.append('suite')
values.append(str(data['suite']))
keys.append('testcase')
values.append(str(data['testcase']))
doc = []
for l in str(data['testdoc']).strip().split('\n'):
doc.append(l.strip().replace('\t', ' ').replace('\'', '\'\''))
doc = ' '.join(doc)
keys.append('testdoc')
values.append('\'' + doc + '\'')
keys.append('start_time')
values.append(str(data['start_time']))
keys.append('end_time')
values.append(str(data['end_time']))
keys.append('duration')
values.append(str(data['duration']))
keys.append('pbs_version')
values.append(str(data['pbs_version']))
keys.append('testparam')
values.append(str(data['testparam']))
keys.append('username')
values.append(str(self.__username))
keys.append('platform')
values.append(str(self.__platform))
keys.append('status')
values.append(str(data['status']))
sdata = data['status_data']
sdata = sdata.replace('\'', '\'\'')
keys.append('status_data')
values.append('\'' + sdata + '\'')
_keys = ','.join(keys)
_values = ','.join(values)
c = self.__dbobj.cursor()
s = 'INSERT INTO %s (%s) VALUES (%s)' % (
_TESTRESULT_TN, _keys, _values)
c.execute(s)
self.__dbobj.commit()
def write(self, data, logfile=None):
if len(data) == 0:
return
if 'testdata' in data.keys():
self.__write_test_data(data['testdata'])
if 'metrics_data' in data.keys():
md = data['metrics_data']
if 'server' in md.keys():
self.__write_server_data(md['server'], logfile)
if 'mom' in md.keys():
self.__write_mom_data(md['mom'], logfile)
if 'scheduler' in md.keys():
self.__write_sched_data(md['scheduler'], logfile)
if 'accounting' in md.keys():
self.__write_acct_data(md['accounting'], logfile)
if 'procs' in md.keys():
self.__write_proc_data(md['procs'], logfile)
self.__index += 1
def close(self, result=None):
self.__dbobj.commit()
self.__dbobj.close()
del self.__dbobj
class SQLiteDb(DBType):
"""
SQLite type database
"""
def __init__(self, dbtype, dbpath, dbaccess):
DBType.__init__(self, dbtype, dbpath, dbaccess)
if self.dbtype != 'sqlite':
_msg = 'db type does not match with my type(file)'
raise PTLDbError(rc=1, rv=False, msg=_msg)
if self.dbpath is None:
_msg = 'Db path require!'
raise PTLDbError(rc=1, rv=False, msg=_msg)
try:
import sqlite3 as db
except:
try:
from pysqlite2 import dbapi2 as db
except:
_msg = 'Either sqlite3 or pysqlite2 module require'
_msg += ' for %s type database!' % (self.dbtype)
raise PTLDbError(rc=1, rv=False, msg=_msg)
try:
self.__dbobj = db.connect(self.dbpath)
except Exception, e:
_msg = 'Failed to connect to database:\n%s\n' % (str(e))
raise PTLDbError(rc=1, rv=False, msg=_msg)
self.__username = pwd.getpwuid(os.getuid())[0]
self.__platform = ' '.join(platform.uname()).strip()
self.__ptlversion = str(ptl.__version__)
self.__db_version = '1.0.0'
self.__index = self.__create_tables()
def __get_index(self, c):
idxs = []
stmt = 'SELECT max(id) from %s;' % (_TESTRESULT_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_SCHEDM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_SVRM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_MOMM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_ACCTM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_PROCM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_CYCLEM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_ESTINFOSUM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_ESTINFO_TN)
idxs.append(c.execute(stmt).fetchone()[0])
stmt = 'SELECT max(id) from %s;' % (_JOBM_TN)
idxs.append(c.execute(stmt).fetchone()[0])
idx = max(idxs)
if idx is not None:
return idx
else:
return 1
def __upgrade_db(self, version):
if version == self.__db_version:
return
def __create_tables(self):
c = self.__dbobj.cursor()
try:
stmt = ['CREATE TABLE %s (' % (_DBVER_TN)]
stmt += ['version TEXT);']
c.execute(''.join(stmt))
except:
stmt = 'SELECT version from %s;' % (_DBVER_TN)
version = c.execute(stmt).fetchone()[0]
self.__upgrade_db(version)
return self.__get_index(c)
stmt = ['INSERT INTO %s (version)' % (_DBVER_TN)]
stmt += [' VALUES (%s);' % (self.__db_version)]
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_TESTRESULT_TN)]
stmt += ['id INTEGER,']
stmt += ['suite TEXT,']
stmt += ['testcase TEXT,']
stmt += ['testdoc TEXT,']
stmt += ['start_time TEXT,']
stmt += ['end_time TEXT,']
stmt += ['duration TEXT,']
stmt += ['pbs_version TEXT,']
stmt += ['testparam TEXT,']
stmt += ['username TEXT,']
stmt += ['ptl_version TEXT,']
stmt += ['platform TEXT,']
stmt += ['status TEXT,']
stmt += ['status_data TEXT,']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SCHEDM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.VER + ' TEXT,']
stmt += [lu.NC + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJC + ' INTEGER,']
stmt += [lu.NJFR + ' INTEGER,']
stmt += [lu.mCD + ' TIME,']
stmt += [lu.CD25 + ' TIME,']
stmt += [lu.CDA + ' TIME,']
stmt += [lu.CD50 + ' TIME,']
stmt += [lu.CD75 + ' TIME,']
stmt += [lu.MCD + ' TIME,']
stmt += [lu.mCT + ' INTEGER,']
stmt += [lu.MCT + ' INTEGER,']
stmt += [lu.TTC + ' TIME,']
stmt += [lu.DUR + ' TIME,']
stmt += [lu.SST + ' TIME,']
stmt += [lu.JRR + ' TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SVRM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.VER + ' TEXT,']
stmt += [lu.NJQ + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJE + ' INTEGER,']
stmt += [lu.JRR + ' TEXT,']
stmt += [lu.JER + ' TEXT,']
stmt += [lu.JSR + ' TEXT,']
stmt += [lu.NUR + ' TEXT,']
stmt += [lu.JWTm + ' TIME,']
stmt += [lu.JWT25 + ' TIME,']
stmt += [lu.JWT50 + ' TIME,']
stmt += [lu.JWTA + ' TIME,']
stmt += [lu.JWT75 + ' TIME,']
stmt += [lu.JWTM + ' TIME,']
stmt += [lu.JRTm + ' TIME,']
stmt += [lu.JRT25 + ' TIME,']
stmt += [lu.JRTA + ' TIME,']
stmt += [lu.JRT50 + ' TIME,']
stmt += [lu.JRT75 + ' TIME,']
stmt += [lu.JRTM + ' TIME);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_MOMM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.VER + ' TEXT,']
stmt += [lu.NJQ + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJE + ' INTEGER,']
stmt += [lu.JRR + ' TEXT,']
stmt += [lu.JER + ' TEXT,']
stmt += [lu.JSR + ' TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ACCTM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.DUR + ' TEXT,']
stmt += [lu.NJQ + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJE + ' INTEGER,']
stmt += [lu.JRR + ' TEXT,']
stmt += [lu.JSR + ' TEXT,']
stmt += [lu.JER + ' TEXT,']
stmt += [lu.JWTm + ' TIME,']
stmt += [lu.JWT25 + ' TIME,']
stmt += [lu.JWT50 + ' TIME,']
stmt += [lu.JWTA + ' TIME,']
stmt += [lu.JWT75 + ' TIME,']
stmt += [lu.JWTM + ' TIME,']
stmt += [lu.JRTm + ' TIME,']
stmt += [lu.JRT25 + ' TIME,']
stmt += [lu.JRTA + ' TIME,']
stmt += [lu.JRT50 + ' TIME,']
stmt += [lu.JRT75 + ' TIME,']
stmt += [lu.JRTM + ' TIME,']
stmt += [lu.JNSm + ' INTEGER,']
stmt += [lu.JNS25 + ' REAL,']
stmt += [lu.JNSA + ' REAL,']
stmt += [lu.JNS50 + ' REAL,']
stmt += [lu.JNS75 + ' REAL,']
stmt += [lu.JNSM + ' REAL,']
stmt += [lu.JCSm + ' INTEGER,']
stmt += [lu.JCS25 + ' REAL,']
stmt += [lu.JCSA + ' REAL,']
stmt += [lu.JCS50 + ' REAL,']
stmt += [lu.JCS75 + ' REAL,']
stmt += [lu.JCSM + ' REAL,']
stmt += [lu.CPH + ' INTEGER,']
stmt += [lu.NPH + ' INTEGER,']
stmt += [lu.UNCPUS + ' TEXT,']
stmt += [lu.UNODES + ' TEXT,']
stmt += [lu.USRS + ' TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_PROCM_TN)]
stmt += ['id INTEGER, ']
stmt += ['name TEXT,']
stmt += ['rss INTEGER,']
stmt += ['vsz INTEGER,']
stmt += ['pcpu TEXT,']
stmt += ['time TEXT);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_CYCLEM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.CST + ' INTEGER,']
stmt += [lu.CD + ' TIME,']
stmt += [lu.QD + ' TIME,']
stmt += [lu.NJC + ' INTEGER,']
stmt += [lu.NJR + ' INTEGER,']
stmt += [lu.NJFR + ' INTEGER,']
stmt += [lu.NJCAL + ' INTEGER,']
stmt += [lu.NJFP + ' INTEGER,']
stmt += [lu.NJP + ' INTEGER,']
stmt += [lu.TTC + ' INTEGER,']
stmt += [lu.SST + ' INTEGER);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFOSUM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.NJD + ' INTEGER,']
stmt += [lu.NJND + ' INTEGER,']
stmt += [lu.Ds15mn + ' INTEGER,']
stmt += [lu.Ds1hr + ' INTEGER,']
stmt += [lu.Ds3hr + ' INTEGER,']
stmt += [lu.Do3hr + ' INTEGER,']
stmt += [lu.DDm + ' INTEGER,']
stmt += [lu.DDM + ' INTEGER,']
stmt += [lu.DDA + ' INTEGER,']
stmt += [lu.DD50 + ' INTEGER);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFO_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.JID + ' TEXT,']
stmt += [lu.Eat + ' INTEGER,']
stmt += [lu.JST + ' INTEGER,']
stmt += [lu.ESTR + ' INTEGER,']
stmt += [lu.ESTA + ' INTEGER,']
stmt += [lu.NEST + ' INTEGER,']
stmt += [lu.ND + ' INTEGER,']
stmt += [lu.JDD + ' INTEGER);']
c.execute(''.join(stmt))
stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_JOBM_TN)]
stmt += ['id INTEGER,']
stmt += ['logname TEXT,']
stmt += [lu.CST + ' INTEGER,']
stmt += [lu.JID + ' TEXT,']
stmt += [lu.T2R + ' INTEGER,']
stmt += [lu.T2D + ' INTEGER,']
stmt += [lu.TiS + ' INTEGER,']
stmt += [lu.TTC + ' INTEGER);']
c.execute(''.join(stmt))
self.__dbobj.commit()
return self.__get_index(c)
def __write_data(self, tablename, data, logfile):
keys = ['id']
values = [str(self.__index)]
if logfile is not None:
keys.append('logfile')
values.append('\'' + str(logfile).replace(' ', '_') + '\'')
for k, v in data.items():
if k == 'id':
continue
keys.append(str(k))
v = str(v)
if v.isdigit():
values.append(v)
else:
values.append('\'' + v + '\'')
_keys = ','.join(keys)
_values = ','.join(values)
c = self.__dbobj.cursor()
s = 'INSERT INTO %s (%s) VALUES (%s)' % (tablename, _keys, _values)
c.execute(s)
self.__dbobj.commit()
def __write_server_data(self, data, logfile=None):
self.__write_data(_SVRM_TN, data, logfile)
def __write_mom_data(self, data, logfile=None):
self.__write_data(_MOMM_TN, data, logfile)
def __write_sched_data(self, data, logfile=None):
for k, v in data.items():
if k == 'summary':
self.__write_data(_SCHEDM_TN, data, logfile)
continue
elif k == lu.EST:
if lu.ESTS in v:
self.__write_estinfosum_data(v[lu.ESTS], logfile)
if lu.EJ in v:
for j in v[lu.EJ]:
if lu.EST in j:
dt = map(lambda s: str(s), j[lu.Eat])
j[lu.Eat] = ','.join(dt)
self.__write_estsum_data(j, logfile)
continue
if 'jobs' in v:
for j in v['jobs']:
j[lu.CST] = v[lu.CST]
self.__write_job_data(j, logfile)
del v['jobs']
self.__write_cycle_data(v, logfile)
def __write_acct_data(self, data, logfile=None):
self.__write_data(_ACCTM_TN, data, logfile)
def __write_proc_data(self, data, logfile=None):
self.__write_data(_PROCM_TN, data, None)
def __write_cycle_data(self, data, logfile=None):
self.__write_data(_CYCLEM_TN, data, logfile)
def __write_estsum_data(self, data, logfile=None):
self.__write_data(_ESTINFOSUM_TN, data, logfile)
def __write_estinfosum_data(self, data, logfile=None):
self.__write_data(_ESTINFO_TN, data, logfile)
def __write_job_data(self, data, logfile=None):
self.__write_data(_JOBM_TN, data, logfile)
def __write_test_data(self, data):
keys = ['id']
values = [str(self.__index)]
keys.append('suite')
values.append(str(data['suite']))
keys.append('testcase')
values.append(str(data['testcase']))
doc = []
for l in str(data['testdoc']).strip().split('\n'):
doc.append(l.strip().replace('\t', ' ').replace('\'', '\'\''))
doc = ' '.join(doc)
keys.append('testdoc')
values.append('\'' + doc + '\'')
keys.append('start_time')
values.append(str(data['start_time']))
keys.append('end_time')
values.append(str(data['end_time']))
keys.append('duration')
values.append(str(data['duration']))
keys.append('pbs_version')
values.append(str(data['pbs_version']))
keys.append('testparam')
values.append(str(data['testparam']))
keys.append('username')
values.append(str(self.__username))
keys.append('platform')
values.append(str(self.__platform))
keys.append('status')
values.append(str(data['status']))
sdata = data['status_data']
sdata = sdata.replace('\'', '\'\'')
keys.append('status_data')
values.append('\'' + sdata + '\'')
_keys = ','.join(keys)
_values = ','.join(values)
c = self.__dbobj.cursor()
s = 'INSERT INTO %s (%s) VALUES (%s)' % (
_TESTRESULT_TN, _keys, _values)
c.execute(s)
self.__dbobj.commit()
def write(self, data, logfile=None):
if len(data) == 0:
return
if 'testdata' in data.keys():
self.__write_test_data(data['testdata'])
if 'metrics_data' in data.keys():
md = data['metrics_data']
if 'server' in md.keys():
self.__write_server_data(md['server'], logfile)
if 'mom' in md.keys():
self.__write_mom_data(md['mom'], logfile)
if 'scheduler' in md.keys():
self.__write_sched_data(md['scheduler'], logfile)
if 'accounting' in md.keys():
self.__write_acct_data(md['accounting'], logfile)
if 'procs' in md.keys():
self.__write_proc_data(md['procs'], logfile)
self.__index += 1
def close(self, result=None):
self.__dbobj.commit()
self.__dbobj.close()
del self.__dbobj
class FileDb(DBType):
"""
File type database
"""
def __init__(self, dbtype, dbpath, dbaccess):
DBType.__init__(self, dbtype, dbpath, dbaccess)
if self.dbtype != 'file':
_msg = 'db type does not match with my type(file)'
raise PTLDbError(rc=1, rv=False, msg=_msg)
if self.dbpath is None:
_msg = 'Db path require!'
raise PTLDbError(rc=1, rv=False, msg=_msg)
self.__separator1 = '=' * 80
self.__separator2 = '___m_oo_m___'
self.__username = pwd.getpwuid(os.getuid())[0]
self.__platform = ' '.join(platform.uname()).strip()
self.__ptlversion = str(ptl.__version__)
self.__dbobj = {}
self.__index = 1
def __write_data(self, key, data, logfile):
if key not in self.__dbobj.keys():
f = os.path.join(self.dbdir, key + '.db')
self.__dbobj[key] = open(f, 'w+')
msg = [self.__separator1]
msg += ['id = %s' % (self.__index)]
if logfile is not None:
msg += ['logfile = %s' % (logfile)]
for k, v in data.items():
if k == 'id':
continue
msg += [str(k) + ' = ' + str(v)]
msg += [self.__separator1]
self.__dbobj[key].write('\n'.join(msg) + '\n')
self.__dbobj[key].flush()
def __write_server_data(self, data, logfile=None):
self.__write_data(_SVRM_TN, data, logfile)
def __write_mom_data(self, data, logfile=None):
self.__write_data(_MOMM_TN, data, logfile)
def __write_sched_data(self, data, logfile=None):
for k, v in data.items():
if k == 'summary':
self.__write_data(_SCHEDM_TN, data, logfile)
continue
elif k == lu.EST:
if lu.ESTS in v:
self.__write_estinfosum_data(v[lu.ESTS], logfile)
if lu.EJ in v:
for j in v[lu.EJ]:
if lu.EST in j:
dt = map(lambda s: str(s), j[lu.Eat])
j[lu.Eat] = ','.join(dt)
self.__write_estsum_data(j, logfile)
continue
if 'jobs' in v:
for j in v['jobs']:
j[lu.CST] = v[lu.CST]
self.__write_job_data(j, logfile)
del v['jobs']
self.__write_cycle_data(v, logfile)
def __write_acct_data(self, data, logfile=None):
self.__write_data(_ACCTM_TN, data, logfile)
def __write_proc_data(self, data, logfile=None):
self.__write_data(_PROCM_TN, data, None)
def __write_cycle_data(self, data, logfile=None):
self.__write_data(_CYCLEM_TN, data, logfile)
def __write_estsum_data(self, data, logfile=None):
self.__write_data(_ESTINFOSUM_TN, data, logfile)
def __write_estinfosum_data(self, data, logfile=None):
self.__write_data(_ESTINFO_TN, data, logfile)
def __write_job_data(self, data, logfile=None):
self.__write_data(_JOBM_TN, data, logfile)
def __write_test_data(self, data):
if _TESTRESULT_TN not in self.__dbobj.keys():
self.__dbobj[_TESTRESULT_TN] = open(self.dbpath, 'w+')
msg = [self.__separator1]
msg += ['id = %s' % (self.__index)]
msg += ['suite = %s' % (data['suite'])]
msg += ['testcase = %s' % (data['testcase'])]
doc = []
for l in str(data['testdoc']).strip().split('\n'):
doc.append(l.strip())
doc = ' '.join(doc)
msg += ['testdoc = %s' % (doc)]
msg += ['start_time = %s' % (str(data['start_time']))]
msg += ['end_time = %s' % (str(data['end_time']))]
msg += ['duration = %s' % (str(data['duration']))]
msg += ['pbs_version = %s' % (data['pbs_version'])]
msg += ['testparam = %s' % (data['testparam'])]
msg += ['username = %s' % (self.__username)]
msg += ['ptl_version = %s' % (self.__ptlversion)]
msg += ['platform = %s' % (self.__platform)]
msg += ['status = %s' % (data['status'])]
msg += ['status_data = ']
msg += [self.__separator2]
msg += ['%s' % (str(data['status_data']))]
msg += [self.__separator2]
msg += [self.__separator1]
self.__dbobj[_TESTRESULT_TN].write('\n'.join(msg) + '\n')
self.__dbobj[_TESTRESULT_TN].flush()
def write(self, data, logfile=None):
if len(data) == 0:
return
if 'testdata' in data.keys():
self.__write_test_data(data['testdata'])
if 'metrics_data' in data.keys():
md = data['metrics_data']
if 'server' in md.keys():
self.__write_server_data(md['server'], logfile)
if 'mom' in md.keys():
self.__write_mom_data(md['mom'], logfile)
if 'scheduler' in md.keys():
self.__write_sched_data(md['scheduler'], logfile)
if 'accounting' in md.keys():
self.__write_acct_data(md['accounting'], logfile)
if 'procs' in md.keys():
self.__write_proc_data(md['procs'], logfile)
self.__index += 1
def close(self, result=None):
for v in self.__dbobj.values():
v.write('\n')
v.flush()
v.close()
class HTMLDb(DBType):
"""
HTML type database
"""
def __init__(self, dbtype, dbpath, dbaccess):
DBType.__init__(self, dbtype, dbpath, dbaccess)
if self.dbtype != 'html':
_msg = 'db type does not match with my type(html)'
raise PTLDbError(rc=1, rv=False, msg=_msg)
if self.dbpath is None:
_msg = 'Db path require!'
raise PTLDbError(rc=1, rv=False, msg=_msg)
elif not self.dbpath.endswith('.html'):
self.dbpath = self.dbpath.rstrip('.db') + '.html'
self.__cmd = [os.path.basename(sys.argv[0])]
self.__cmd += sys.argv[1:]
self.__username = pwd.getpwuid(os.getuid())[0]
self.__platform = ' '.join(platform.uname()).strip()
self.__ptlversion = str(ptl.__version__)
self.__dbobj = {}
self.__index = 1
def __write_test_html_header(self, data):
_title = 'PTL Test Report of %s' % (data['pbs_version'])
__s = []
__s += ['
']
__s += ['%s' % (_title)]
__s += ['']
__s += ['%s
' % (_title)]
_s = 'margin: 30px;margin-bottom: 15px;text-align: left;'
__s += ['' % (_s)]
_s = '%s: | %s |
'
__s += [_s % ('Command', ' '.join(self.__cmd))]
__s += [_s % ('TestParm', data['testparam'])]
__s += [_s % ('User', self.__username)]
__s += [_s % ('PTL Version', self.__ptlversion)]
__s += [_s % ('Platform', self.__platform)]
__s += ['
']
_s = '%s | '
__s += [_s % ('all', 1, 'Show All')]
__s += [_s % ('pass', 2, 'Show only "Passed"')]
__s += [_s % ('skip', 3, 'Show only "Skipped"')]
__s += [_s % ('fail', 4, 'Show only "Failed"')]
__s += [_s % ('error', 5, 'Show only "Error"')]
__s += [_s % ('timedout', 6, 'Show only "TimedOut"')]
__s += ['