ptl_test_db.py 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916
  1. # coding: utf-8
  2. # Copyright (C) 1994-2018 Altair Engineering, Inc.
  3. # For more information, contact Altair at www.altair.com.
  4. #
  5. # This file is part of the PBS Professional ("PBS Pro") software.
  6. #
  7. # Open Source License Information:
  8. #
  9. # PBS Pro is free software. You can redistribute it and/or modify it under the
  10. # terms of the GNU Affero General Public License as published by the Free
  11. # Software Foundation, either version 3 of the License, or (at your option) any
  12. # later version.
  13. #
  14. # PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
  15. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16. # FOR A PARTICULAR PURPOSE.
  17. # See the GNU Affero General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU Affero General Public License
  20. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. #
  22. # Commercial License Information:
  23. #
  24. # For a copy of the commercial license terms and conditions,
  25. # go to: (http://www.pbspro.com/UserArea/agreement.html)
  26. # or contact the Altair Legal Department.
  27. #
  28. # Altair’s dual-license business model allows companies, individuals, and
  29. # organizations to create proprietary derivative works of PBS Pro and
  30. # distribute them - whether embedded or bundled with other software -
  31. # under a commercial license agreement.
  32. #
  33. # Use of Altair’s trademarks, including but not limited to "PBS™",
  34. # "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
  35. # trademark licensing policies.
  36. import os
  37. import ptl
  38. import sys
  39. import pwd
  40. import logging
  41. import platform
  42. import traceback
  43. import time
  44. import json
  45. import ptl.utils.pbs_logutils as lu
  46. from ptl.lib.pbs_testlib import PbsTypeDuration
  47. from ptl.utils.plugins.ptl_test_tags import TAGKEY
  48. from ptl.utils.pbs_dshutils import DshUtils
  49. from ptl.utils.plugins.ptl_report_json import PTLJsonData
  50. # Following dance require because PTLTestDb().process_output() from this file
  51. # is used in pbs_loganalyzer script which is shipped with PBS package
  52. # through unsupported directory where we might not have nose installed
  53. try:
  54. from nose.util import isclass
  55. from nose.plugins.base import Plugin
  56. from nose.plugins.skip import SkipTest
  57. from ptl.utils.plugins.ptl_test_runner import TimeOut
  58. log = logging.getLogger('nose.plugins.PTLTestDb')
  59. except ImportError:
  60. class Plugin(object):
  61. pass
  62. def isclass(obj):
  63. pass
  64. class SkipTest(Exception):
  65. pass
  66. class TimeOut(Exception):
  67. pass
  68. log = logging.getLogger('PTLTestDb')
  69. # Table names
  70. _DBVER_TN = 'ptl_db_version'
  71. _TESTRESULT_TN = 'ptl_test_results'
  72. _SCHEDM_TN = 'ptl_scheduler_metrics'
  73. _SVRM_TN = 'ptl_server_metrics'
  74. _MOMM_TN = 'ptl_mom_metrics'
  75. _ACCTM_TN = 'ptl_accounting_metrics'
  76. _PROCM_TN = 'ptl_proc_metrics'
  77. _CYCLEM_TN = 'ptl_cycle_metrics'
  78. _ESTINFOSUM_TN = 'ptl_estimated_info_summary'
  79. _ESTINFO_TN = 'ptl_estimated_info'
  80. _JOBM_TN = 'ptl_job_metrics'
  81. class PTLDbError(Exception):
  82. """
  83. PTL database error class
  84. :param rv: Return value for the database error
  85. :type rv: str or None
  86. :param rc: Return code for the database error
  87. :type rc: str or None
  88. :param msg: Error message
  89. :type msg: str or None
  90. """
  91. def __init__(self, rv=None, rc=None, msg=None, post=None, *args, **kwargs):
  92. self.rv = rv
  93. self.rc = rc
  94. self.msg = msg
  95. if post is not None:
  96. post(*args, **kwargs)
  97. def __str__(self):
  98. return ('rc=' + str(self.rc) + ', rv=' + str(self.rv) +
  99. ', msg=' + str(self.msg))
  100. def __repr__(self):
  101. return (self.__class__.__name__ + '(rc=' + str(self.rc) + ', rv=' +
  102. str(self.rv) + ', msg=' + str(self.msg) + ')')
  103. class DBType(object):
  104. """
  105. Base class for each database type
  106. Any type of database must inherit from me
  107. :param dbtype: Database type
  108. :type dbtype: str
  109. :param dbpath: Path to database
  110. :type dbpath: str
  111. :param dbaccess: Path to a file that defines db options
  112. :type dbaccess: str
  113. """
  114. def __init__(self, dbtype, dbpath, dbaccess):
  115. if dbpath is None:
  116. dn = _TESTRESULT_TN + '.db'
  117. dbdir = os.getcwd()
  118. dbpath = os.path.join(dbdir, dn)
  119. elif os.path.isdir(dbpath):
  120. dn = _TESTRESULT_TN + '.db'
  121. dbdir = dbpath
  122. dbpath = os.path.join(dbdir, dn)
  123. else:
  124. dbdir = os.path.dirname(dbpath)
  125. dbpath = dbpath
  126. self.dbtype = dbtype
  127. self.dbpath = dbpath
  128. self.dbdir = dbdir
  129. self.dbaccess = dbaccess
  130. def write(self, data, logfile=None):
  131. """
  132. :param data: Data to write
  133. :param logfile: Can be one of ``server``, ``scheduler``, ``mom``,
  134. ``accounting`` or ``procs``
  135. :type logfile: str or None
  136. """
  137. _msg = 'write method must be implemented in'
  138. _msg += ' %s' % (str(self.__class__.__name__))
  139. raise PTLDbError(rc=1, rv=False, msg=_msg)
  140. def close(self, result=None):
  141. """
  142. Close the database
  143. """
  144. _msg = 'close method must be implemented in'
  145. _msg += ' %s' % (str(self.__class__.__name__))
  146. raise PTLDbError(rc=1, rv=False, msg=_msg)
  147. class PostgreSQLDb(DBType):
  148. """
  149. PostgreSQL type database
  150. """
  151. def __init__(self, dbtype, dbpath, dbaccess):
  152. DBType.__init__(self, dbtype, dbpath, dbaccess)
  153. if self.dbtype != 'pgsql':
  154. _msg = 'db type does not match with my type(file)'
  155. raise PTLDbError(rc=1, rv=False, msg=_msg)
  156. if self.dbaccess is None:
  157. _msg = 'Db access creds require!'
  158. raise PTLDbError(rc=1, rv=False, msg=_msg)
  159. try:
  160. import psycopg2
  161. except:
  162. _msg = 'psycopg2 require for %s type database!' % (self.dbtype)
  163. raise PTLDbError(rc=1, rv=False, msg=_msg)
  164. try:
  165. f = open(self.dbaccess)
  166. creds = ' '.join(map(lambda n: n.strip(), f.readlines()))
  167. f.close()
  168. self.__dbobj = psycopg2.connect(creds)
  169. except Exception, e:
  170. _msg = 'Failed to connect to database:\n%s\n' % (str(e))
  171. raise PTLDbError(rc=1, rv=False, msg=_msg)
  172. self.__username = pwd.getpwuid(os.getuid())[0]
  173. self.__platform = ' '.join(platform.uname()).strip()
  174. self.__ptlversion = str(ptl.__version__)
  175. self.__db_version = '1.0.0'
  176. self.__index = self.__create_tables()
  177. def __get_index(self, c):
  178. idxs = []
  179. stmt = 'SELECT max(id) from %s;' % (_TESTRESULT_TN)
  180. idxs.append(c.execute(stmt).fetchone()[0])
  181. stmt = 'SELECT max(id) from %s;' % (_SCHEDM_TN)
  182. idxs.append(c.execute(stmt).fetchone()[0])
  183. stmt = 'SELECT max(id) from %s;' % (_SVRM_TN)
  184. idxs.append(c.execute(stmt).fetchone()[0])
  185. stmt = 'SELECT max(id) from %s;' % (_MOMM_TN)
  186. idxs.append(c.execute(stmt).fetchone()[0])
  187. stmt = 'SELECT max(id) from %s;' % (_ACCTM_TN)
  188. idxs.append(c.execute(stmt).fetchone()[0])
  189. stmt = 'SELECT max(id) from %s;' % (_PROCM_TN)
  190. idxs.append(c.execute(stmt).fetchone()[0])
  191. stmt = 'SELECT max(id) from %s;' % (_CYCLEM_TN)
  192. idxs.append(c.execute(stmt).fetchone()[0])
  193. stmt = 'SELECT max(id) from %s;' % (_ESTINFOSUM_TN)
  194. idxs.append(c.execute(stmt).fetchone()[0])
  195. stmt = 'SELECT max(id) from %s;' % (_ESTINFO_TN)
  196. idxs.append(c.execute(stmt).fetchone()[0])
  197. stmt = 'SELECT max(id) from %s;' % (_JOBM_TN)
  198. idxs.append(c.execute(stmt).fetchone()[0])
  199. idx = max(idxs)
  200. if idx is not None:
  201. return idx
  202. else:
  203. return 1
  204. def __upgrade_db(self, version):
  205. if version == self.__db_version:
  206. return
  207. def __create_tables(self):
  208. c = self.__dbobj.cursor()
  209. try:
  210. stmt = ['CREATE TABLE %s (' % (_DBVER_TN)]
  211. stmt += ['version TEXT);']
  212. c.execute(''.join(stmt))
  213. except:
  214. stmt = 'SELECT version from %s;' % (_DBVER_TN)
  215. version = c.execute(stmt).fetchone()[0]
  216. self.__upgrade_db(version)
  217. return self.__get_index(c)
  218. stmt = ['INSERT INTO %s (version)' % (_DBVER_TN)]
  219. stmt += [' VALUES (%s);' % (self.__db_version)]
  220. c.execute(''.join(stmt))
  221. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_TESTRESULT_TN)]
  222. stmt += ['id INTEGER,']
  223. stmt += ['suite TEXT,']
  224. stmt += ['testcase TEXT,']
  225. stmt += ['testdoc TEXT,']
  226. stmt += ['start_time TEXT,']
  227. stmt += ['end_time TEXT,']
  228. stmt += ['duration TEXT,']
  229. stmt += ['pbs_version TEXT,']
  230. stmt += ['testparam TEXT,']
  231. stmt += ['username TEXT,']
  232. stmt += ['ptl_version TEXT,']
  233. stmt += ['platform TEXT,']
  234. stmt += ['status TEXT,']
  235. stmt += ['status_data TEXT,']
  236. c.execute(''.join(stmt))
  237. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SCHEDM_TN)]
  238. stmt += ['id INTEGER,']
  239. stmt += ['logname TEXT,']
  240. stmt += [lu.VER + ' TEXT,']
  241. stmt += [lu.NC + ' INTEGER,']
  242. stmt += [lu.NJR + ' INTEGER,']
  243. stmt += [lu.NJC + ' INTEGER,']
  244. stmt += [lu.NJFR + ' INTEGER,']
  245. stmt += [lu.mCD + ' TIME,']
  246. stmt += [lu.CD25 + ' TIME,']
  247. stmt += [lu.CDA + ' TIME,']
  248. stmt += [lu.CD50 + ' TIME,']
  249. stmt += [lu.CD75 + ' TIME,']
  250. stmt += [lu.MCD + ' TIME,']
  251. stmt += [lu.mCT + ' TIMESTAMP,']
  252. stmt += [lu.MCT + ' TIMESTAMP,']
  253. stmt += [lu.TTC + ' TIME,']
  254. stmt += [lu.DUR + ' TIME,']
  255. stmt += [lu.SST + ' TIME,']
  256. stmt += [lu.JRR + ' TEXT);']
  257. c.execute(''.join(stmt))
  258. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SVRM_TN)]
  259. stmt += ['id INTEGER,']
  260. stmt += ['logname TEXT,']
  261. stmt += [lu.VER + ' TEXT,']
  262. stmt += [lu.NJQ + ' INTEGER,']
  263. stmt += [lu.NJR + ' INTEGER,']
  264. stmt += [lu.NJE + ' INTEGER,']
  265. stmt += [lu.JRR + ' TEXT,']
  266. stmt += [lu.JER + ' TEXT,']
  267. stmt += [lu.JSR + ' TEXT,']
  268. stmt += [lu.NUR + ' TEXT,']
  269. stmt += [lu.JWTm + ' TIME,']
  270. stmt += [lu.JWT25 + ' TIME,']
  271. stmt += [lu.JWT50 + ' TIME,']
  272. stmt += [lu.JWTA + ' TIME,']
  273. stmt += [lu.JWT75 + ' TIME,']
  274. stmt += [lu.JWTM + ' TIME,']
  275. stmt += [lu.JRTm + ' TIME,']
  276. stmt += [lu.JRT25 + ' TIME,']
  277. stmt += [lu.JRTA + ' TIME,']
  278. stmt += [lu.JRT50 + ' TIME,']
  279. stmt += [lu.JRT75 + ' TIME,']
  280. stmt += [lu.JRTM + ' TIME);']
  281. c.execute(''.join(stmt))
  282. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_MOMM_TN)]
  283. stmt += ['id INTEGER,']
  284. stmt += ['logname TEXT,']
  285. stmt += [lu.VER + ' TEXT,']
  286. stmt += [lu.NJQ + ' INTEGER,']
  287. stmt += [lu.NJR + ' INTEGER,']
  288. stmt += [lu.NJE + ' INTEGER,']
  289. stmt += [lu.JRR + ' TEXT,']
  290. stmt += [lu.JER + ' TEXT,']
  291. stmt += [lu.JSR + ' TEXT);']
  292. c.execute(''.join(stmt))
  293. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ACCTM_TN)]
  294. stmt += ['id INTEGER,']
  295. stmt += ['logname TEXT,']
  296. stmt += [lu.DUR + ' TEXT,']
  297. stmt += [lu.NJQ + ' INTEGER,']
  298. stmt += [lu.NJR + ' INTEGER,']
  299. stmt += [lu.NJE + ' INTEGER,']
  300. stmt += [lu.JRR + ' TEXT,']
  301. stmt += [lu.JSR + ' TEXT,']
  302. stmt += [lu.JER + ' TEXT,']
  303. stmt += [lu.JWTm + ' TIME,']
  304. stmt += [lu.JWT25 + ' TIME,']
  305. stmt += [lu.JWT50 + ' TIME,']
  306. stmt += [lu.JWTA + ' TIME,']
  307. stmt += [lu.JWT75 + ' TIME,']
  308. stmt += [lu.JWTM + ' TIME,']
  309. stmt += [lu.JRTm + ' TIME,']
  310. stmt += [lu.JRT25 + ' TIME,']
  311. stmt += [lu.JRTA + ' TIME,']
  312. stmt += [lu.JRT50 + ' TIME,']
  313. stmt += [lu.JRT75 + ' TIME,']
  314. stmt += [lu.JRTM + ' TIME,']
  315. stmt += [lu.JNSm + ' INTEGER,']
  316. stmt += [lu.JNS25 + ' REAL,']
  317. stmt += [lu.JNSA + ' REAL,']
  318. stmt += [lu.JNS50 + ' REAL,']
  319. stmt += [lu.JNS75 + ' REAL,']
  320. stmt += [lu.JNSM + ' REAL,']
  321. stmt += [lu.JCSm + ' INTEGER,']
  322. stmt += [lu.JCS25 + ' REAL,']
  323. stmt += [lu.JCSA + ' REAL,']
  324. stmt += [lu.JCS50 + ' REAL,']
  325. stmt += [lu.JCS75 + ' REAL,']
  326. stmt += [lu.JCSM + ' REAL,']
  327. stmt += [lu.CPH + ' INTEGER,']
  328. stmt += [lu.NPH + ' INTEGER,']
  329. stmt += [lu.UNCPUS + ' TEXT,']
  330. stmt += [lu.UNODES + ' TEXT,']
  331. stmt += [lu.USRS + ' TEXT);']
  332. c.execute(''.join(stmt))
  333. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_PROCM_TN)]
  334. stmt += ['id INTEGER, ']
  335. stmt += ['name TEXT,']
  336. stmt += ['rss INTEGER,']
  337. stmt += ['vsz INTEGER,']
  338. stmt += ['pcpu TEXT,']
  339. stmt += ['time TEXT);']
  340. c.execute(''.join(stmt))
  341. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_CYCLEM_TN)]
  342. stmt += ['id INTEGER,']
  343. stmt += ['logname TEXT,']
  344. stmt += [lu.CST + ' TIMESTAMP,']
  345. stmt += [lu.CD + ' TIME,']
  346. stmt += [lu.QD + ' TIME,']
  347. stmt += [lu.NJC + ' INTEGER,']
  348. stmt += [lu.NJR + ' INTEGER,']
  349. stmt += [lu.NJFR + ' INTEGER,']
  350. stmt += [lu.NJCAL + ' INTEGER,']
  351. stmt += [lu.NJFP + ' INTEGER,']
  352. stmt += [lu.NJP + ' INTEGER,']
  353. stmt += [lu.TTC + ' INTEGER,']
  354. stmt += [lu.SST + ' INTEGER);']
  355. c.execute(''.join(stmt))
  356. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFOSUM_TN)]
  357. stmt += ['id INTEGER,']
  358. stmt += ['logname TEXT,']
  359. stmt += [lu.NJD + ' INTEGER,']
  360. stmt += [lu.NJND + ' INTEGER,']
  361. stmt += [lu.Ds15mn + ' INTEGER,']
  362. stmt += [lu.Ds1hr + ' INTEGER,']
  363. stmt += [lu.Ds3hr + ' INTEGER,']
  364. stmt += [lu.Do3hr + ' INTEGER,']
  365. stmt += [lu.DDm + ' INTEGER,']
  366. stmt += [lu.DDM + ' INTEGER,']
  367. stmt += [lu.DDA + ' INTEGER,']
  368. stmt += [lu.DD50 + ' INTEGER);']
  369. c.execute(''.join(stmt))
  370. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFO_TN)]
  371. stmt += ['id INTEGER,']
  372. stmt += ['logname TEXT,']
  373. stmt += [lu.JID + ' TEXT,']
  374. stmt += [lu.Eat + ' INTEGER,']
  375. stmt += [lu.JST + ' INTEGER,']
  376. stmt += [lu.ESTR + ' INTEGER,']
  377. stmt += [lu.ESTA + ' INTEGER,']
  378. stmt += [lu.NEST + ' INTEGER,']
  379. stmt += [lu.ND + ' INTEGER,']
  380. stmt += [lu.JDD + ' INTEGER);']
  381. c.execute(''.join(stmt))
  382. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_JOBM_TN)]
  383. stmt += ['id INTEGER,']
  384. stmt += ['logname TEXT,']
  385. stmt += [lu.CST + ' TIMESTAMP,']
  386. stmt += [lu.JID + ' TEXT,']
  387. stmt += [lu.T2R + ' INTEGER,']
  388. stmt += [lu.T2D + ' INTEGER,']
  389. stmt += [lu.TiS + ' INTEGER,']
  390. stmt += [lu.TTC + ' INTEGER);']
  391. c.execute(''.join(stmt))
  392. self.__dbobj.commit()
  393. return self.__get_index(c)
  394. def __write_data(self, tablename, data, logfile):
  395. keys = ['id']
  396. values = [str(self.__index)]
  397. if logfile is not None:
  398. keys.append('logname')
  399. values.append('\'' + str(logfile).replace(' ', '_') + '\'')
  400. for k, v in data.items():
  401. if k == 'id':
  402. continue
  403. keys.append(str(k))
  404. v = str(v)
  405. if v.isdigit():
  406. values.append(v)
  407. else:
  408. values.append('\'' + v + '\'')
  409. _keys = ','.join(keys)
  410. _values = ','.join(values)
  411. c = self.__dbobj.cursor()
  412. s = 'INSERT INTO %s (%s) VALUES (%s)' % (tablename, _keys, _values)
  413. c.execute(s)
  414. self.__dbobj.commit()
  415. def __write_server_data(self, data, logfile=None):
  416. self.__write_data(_SVRM_TN, data, logfile)
  417. def __write_mom_data(self, data, logfile=None):
  418. self.__write_data(_MOMM_TN, data, logfile)
  419. def __write_sched_data(self, data, logfile=None):
  420. for k, v in data.items():
  421. if k == 'summary':
  422. self.__write_data(_SCHEDM_TN, data, logfile)
  423. continue
  424. elif k == lu.EST:
  425. if lu.ESTS in v:
  426. self.__write_estinfosum_data(v[lu.ESTS], logfile)
  427. if lu.EJ in v:
  428. for j in v[lu.EJ]:
  429. if lu.EST in j:
  430. dt = map(lambda s: str(s), j[lu.Eat])
  431. j[lu.Eat] = ','.join(dt)
  432. self.__write_estsum_data(j, logfile)
  433. continue
  434. if 'jobs' in v:
  435. for j in v['jobs']:
  436. j[lu.CST] = v[lu.CST]
  437. self.__write_job_data(j, logfile)
  438. del v['jobs']
  439. self.__write_cycle_data(v, logfile)
  440. def __write_acct_data(self, data, logfile=None):
  441. self.__write_data(_ACCTM_TN, data, logfile)
  442. def __write_proc_data(self, data, logfile=None):
  443. self.__write_data(_PROCM_TN, data, None)
  444. def __write_cycle_data(self, data, logfile=None):
  445. self.__write_data(_CYCLEM_TN, data, logfile)
  446. def __write_estsum_data(self, data, logfile=None):
  447. self.__write_data(_ESTINFOSUM_TN, data, logfile)
  448. def __write_estinfosum_data(self, data, logfile=None):
  449. self.__write_data(_ESTINFO_TN, data, logfile)
  450. def __write_job_data(self, data, logfile=None):
  451. self.__write_data(_JOBM_TN, data, logfile)
  452. def __write_test_data(self, data):
  453. keys = ['id']
  454. values = [str(self.__index)]
  455. keys.append('suite')
  456. values.append(str(data['suite']))
  457. keys.append('testcase')
  458. values.append(str(data['testcase']))
  459. doc = []
  460. for l in str(data['testdoc']).strip().split('\n'):
  461. doc.append(l.strip().replace('\t', ' ').replace('\'', '\'\''))
  462. doc = ' '.join(doc)
  463. keys.append('testdoc')
  464. values.append('\'' + doc + '\'')
  465. keys.append('start_time')
  466. values.append(str(data['start_time']))
  467. keys.append('end_time')
  468. values.append(str(data['end_time']))
  469. keys.append('duration')
  470. values.append(str(data['duration']))
  471. keys.append('pbs_version')
  472. values.append(str(data['pbs_version']))
  473. keys.append('testparam')
  474. values.append(str(data['testparam']))
  475. keys.append('username')
  476. values.append(str(self.__username))
  477. keys.append('platform')
  478. values.append(str(self.__platform))
  479. keys.append('status')
  480. values.append(str(data['status']))
  481. sdata = data['status_data']
  482. sdata = sdata.replace('\'', '\'\'')
  483. keys.append('status_data')
  484. values.append('\'' + sdata + '\'')
  485. _keys = ','.join(keys)
  486. _values = ','.join(values)
  487. c = self.__dbobj.cursor()
  488. s = 'INSERT INTO %s (%s) VALUES (%s)' % (
  489. _TESTRESULT_TN, _keys, _values)
  490. c.execute(s)
  491. self.__dbobj.commit()
  492. def write(self, data, logfile=None):
  493. if len(data) == 0:
  494. return
  495. if 'testdata' in data.keys():
  496. self.__write_test_data(data['testdata'])
  497. if 'metrics_data' in data.keys():
  498. md = data['metrics_data']
  499. if 'server' in md.keys():
  500. self.__write_server_data(md['server'], logfile)
  501. if 'mom' in md.keys():
  502. self.__write_mom_data(md['mom'], logfile)
  503. if 'scheduler' in md.keys():
  504. self.__write_sched_data(md['scheduler'], logfile)
  505. if 'accounting' in md.keys():
  506. self.__write_acct_data(md['accounting'], logfile)
  507. if 'procs' in md.keys():
  508. self.__write_proc_data(md['procs'], logfile)
  509. self.__index += 1
  510. def close(self, result=None):
  511. self.__dbobj.commit()
  512. self.__dbobj.close()
  513. del self.__dbobj
  514. class SQLiteDb(DBType):
  515. """
  516. SQLite type database
  517. """
  518. def __init__(self, dbtype, dbpath, dbaccess):
  519. DBType.__init__(self, dbtype, dbpath, dbaccess)
  520. if self.dbtype != 'sqlite':
  521. _msg = 'db type does not match with my type(file)'
  522. raise PTLDbError(rc=1, rv=False, msg=_msg)
  523. if self.dbpath is None:
  524. _msg = 'Db path require!'
  525. raise PTLDbError(rc=1, rv=False, msg=_msg)
  526. try:
  527. import sqlite3 as db
  528. except:
  529. try:
  530. from pysqlite2 import dbapi2 as db
  531. except:
  532. _msg = 'Either sqlite3 or pysqlite2 module require'
  533. _msg += ' for %s type database!' % (self.dbtype)
  534. raise PTLDbError(rc=1, rv=False, msg=_msg)
  535. try:
  536. self.__dbobj = db.connect(self.dbpath)
  537. except Exception, e:
  538. _msg = 'Failed to connect to database:\n%s\n' % (str(e))
  539. raise PTLDbError(rc=1, rv=False, msg=_msg)
  540. self.__username = pwd.getpwuid(os.getuid())[0]
  541. self.__platform = ' '.join(platform.uname()).strip()
  542. self.__ptlversion = str(ptl.__version__)
  543. self.__db_version = '1.0.0'
  544. self.__index = self.__create_tables()
  545. def __get_index(self, c):
  546. idxs = []
  547. stmt = 'SELECT max(id) from %s;' % (_TESTRESULT_TN)
  548. idxs.append(c.execute(stmt).fetchone()[0])
  549. stmt = 'SELECT max(id) from %s;' % (_SCHEDM_TN)
  550. idxs.append(c.execute(stmt).fetchone()[0])
  551. stmt = 'SELECT max(id) from %s;' % (_SVRM_TN)
  552. idxs.append(c.execute(stmt).fetchone()[0])
  553. stmt = 'SELECT max(id) from %s;' % (_MOMM_TN)
  554. idxs.append(c.execute(stmt).fetchone()[0])
  555. stmt = 'SELECT max(id) from %s;' % (_ACCTM_TN)
  556. idxs.append(c.execute(stmt).fetchone()[0])
  557. stmt = 'SELECT max(id) from %s;' % (_PROCM_TN)
  558. idxs.append(c.execute(stmt).fetchone()[0])
  559. stmt = 'SELECT max(id) from %s;' % (_CYCLEM_TN)
  560. idxs.append(c.execute(stmt).fetchone()[0])
  561. stmt = 'SELECT max(id) from %s;' % (_ESTINFOSUM_TN)
  562. idxs.append(c.execute(stmt).fetchone()[0])
  563. stmt = 'SELECT max(id) from %s;' % (_ESTINFO_TN)
  564. idxs.append(c.execute(stmt).fetchone()[0])
  565. stmt = 'SELECT max(id) from %s;' % (_JOBM_TN)
  566. idxs.append(c.execute(stmt).fetchone()[0])
  567. idx = max(idxs)
  568. if idx is not None:
  569. return idx
  570. else:
  571. return 1
  572. def __upgrade_db(self, version):
  573. if version == self.__db_version:
  574. return
  575. def __create_tables(self):
  576. c = self.__dbobj.cursor()
  577. try:
  578. stmt = ['CREATE TABLE %s (' % (_DBVER_TN)]
  579. stmt += ['version TEXT);']
  580. c.execute(''.join(stmt))
  581. except:
  582. stmt = 'SELECT version from %s;' % (_DBVER_TN)
  583. version = c.execute(stmt).fetchone()[0]
  584. self.__upgrade_db(version)
  585. return self.__get_index(c)
  586. stmt = ['INSERT INTO %s (version)' % (_DBVER_TN)]
  587. stmt += [' VALUES (%s);' % (self.__db_version)]
  588. c.execute(''.join(stmt))
  589. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_TESTRESULT_TN)]
  590. stmt += ['id INTEGER,']
  591. stmt += ['suite TEXT,']
  592. stmt += ['testcase TEXT,']
  593. stmt += ['testdoc TEXT,']
  594. stmt += ['start_time TEXT,']
  595. stmt += ['end_time TEXT,']
  596. stmt += ['duration TEXT,']
  597. stmt += ['pbs_version TEXT,']
  598. stmt += ['testparam TEXT,']
  599. stmt += ['username TEXT,']
  600. stmt += ['ptl_version TEXT,']
  601. stmt += ['platform TEXT,']
  602. stmt += ['status TEXT,']
  603. stmt += ['status_data TEXT,']
  604. c.execute(''.join(stmt))
  605. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SCHEDM_TN)]
  606. stmt += ['id INTEGER,']
  607. stmt += ['logname TEXT,']
  608. stmt += [lu.VER + ' TEXT,']
  609. stmt += [lu.NC + ' INTEGER,']
  610. stmt += [lu.NJR + ' INTEGER,']
  611. stmt += [lu.NJC + ' INTEGER,']
  612. stmt += [lu.NJFR + ' INTEGER,']
  613. stmt += [lu.mCD + ' TIME,']
  614. stmt += [lu.CD25 + ' TIME,']
  615. stmt += [lu.CDA + ' TIME,']
  616. stmt += [lu.CD50 + ' TIME,']
  617. stmt += [lu.CD75 + ' TIME,']
  618. stmt += [lu.MCD + ' TIME,']
  619. stmt += [lu.mCT + ' INTEGER,']
  620. stmt += [lu.MCT + ' INTEGER,']
  621. stmt += [lu.TTC + ' TIME,']
  622. stmt += [lu.DUR + ' TIME,']
  623. stmt += [lu.SST + ' TIME,']
  624. stmt += [lu.JRR + ' TEXT);']
  625. c.execute(''.join(stmt))
  626. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_SVRM_TN)]
  627. stmt += ['id INTEGER,']
  628. stmt += ['logname TEXT,']
  629. stmt += [lu.VER + ' TEXT,']
  630. stmt += [lu.NJQ + ' INTEGER,']
  631. stmt += [lu.NJR + ' INTEGER,']
  632. stmt += [lu.NJE + ' INTEGER,']
  633. stmt += [lu.JRR + ' TEXT,']
  634. stmt += [lu.JER + ' TEXT,']
  635. stmt += [lu.JSR + ' TEXT,']
  636. stmt += [lu.NUR + ' TEXT,']
  637. stmt += [lu.JWTm + ' TIME,']
  638. stmt += [lu.JWT25 + ' TIME,']
  639. stmt += [lu.JWT50 + ' TIME,']
  640. stmt += [lu.JWTA + ' TIME,']
  641. stmt += [lu.JWT75 + ' TIME,']
  642. stmt += [lu.JWTM + ' TIME,']
  643. stmt += [lu.JRTm + ' TIME,']
  644. stmt += [lu.JRT25 + ' TIME,']
  645. stmt += [lu.JRTA + ' TIME,']
  646. stmt += [lu.JRT50 + ' TIME,']
  647. stmt += [lu.JRT75 + ' TIME,']
  648. stmt += [lu.JRTM + ' TIME);']
  649. c.execute(''.join(stmt))
  650. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_MOMM_TN)]
  651. stmt += ['id INTEGER,']
  652. stmt += ['logname TEXT,']
  653. stmt += [lu.VER + ' TEXT,']
  654. stmt += [lu.NJQ + ' INTEGER,']
  655. stmt += [lu.NJR + ' INTEGER,']
  656. stmt += [lu.NJE + ' INTEGER,']
  657. stmt += [lu.JRR + ' TEXT,']
  658. stmt += [lu.JER + ' TEXT,']
  659. stmt += [lu.JSR + ' TEXT);']
  660. c.execute(''.join(stmt))
  661. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ACCTM_TN)]
  662. stmt += ['id INTEGER,']
  663. stmt += ['logname TEXT,']
  664. stmt += [lu.DUR + ' TEXT,']
  665. stmt += [lu.NJQ + ' INTEGER,']
  666. stmt += [lu.NJR + ' INTEGER,']
  667. stmt += [lu.NJE + ' INTEGER,']
  668. stmt += [lu.JRR + ' TEXT,']
  669. stmt += [lu.JSR + ' TEXT,']
  670. stmt += [lu.JER + ' TEXT,']
  671. stmt += [lu.JWTm + ' TIME,']
  672. stmt += [lu.JWT25 + ' TIME,']
  673. stmt += [lu.JWT50 + ' TIME,']
  674. stmt += [lu.JWTA + ' TIME,']
  675. stmt += [lu.JWT75 + ' TIME,']
  676. stmt += [lu.JWTM + ' TIME,']
  677. stmt += [lu.JRTm + ' TIME,']
  678. stmt += [lu.JRT25 + ' TIME,']
  679. stmt += [lu.JRTA + ' TIME,']
  680. stmt += [lu.JRT50 + ' TIME,']
  681. stmt += [lu.JRT75 + ' TIME,']
  682. stmt += [lu.JRTM + ' TIME,']
  683. stmt += [lu.JNSm + ' INTEGER,']
  684. stmt += [lu.JNS25 + ' REAL,']
  685. stmt += [lu.JNSA + ' REAL,']
  686. stmt += [lu.JNS50 + ' REAL,']
  687. stmt += [lu.JNS75 + ' REAL,']
  688. stmt += [lu.JNSM + ' REAL,']
  689. stmt += [lu.JCSm + ' INTEGER,']
  690. stmt += [lu.JCS25 + ' REAL,']
  691. stmt += [lu.JCSA + ' REAL,']
  692. stmt += [lu.JCS50 + ' REAL,']
  693. stmt += [lu.JCS75 + ' REAL,']
  694. stmt += [lu.JCSM + ' REAL,']
  695. stmt += [lu.CPH + ' INTEGER,']
  696. stmt += [lu.NPH + ' INTEGER,']
  697. stmt += [lu.UNCPUS + ' TEXT,']
  698. stmt += [lu.UNODES + ' TEXT,']
  699. stmt += [lu.USRS + ' TEXT);']
  700. c.execute(''.join(stmt))
  701. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_PROCM_TN)]
  702. stmt += ['id INTEGER, ']
  703. stmt += ['name TEXT,']
  704. stmt += ['rss INTEGER,']
  705. stmt += ['vsz INTEGER,']
  706. stmt += ['pcpu TEXT,']
  707. stmt += ['time TEXT);']
  708. c.execute(''.join(stmt))
  709. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_CYCLEM_TN)]
  710. stmt += ['id INTEGER,']
  711. stmt += ['logname TEXT,']
  712. stmt += [lu.CST + ' INTEGER,']
  713. stmt += [lu.CD + ' TIME,']
  714. stmt += [lu.QD + ' TIME,']
  715. stmt += [lu.NJC + ' INTEGER,']
  716. stmt += [lu.NJR + ' INTEGER,']
  717. stmt += [lu.NJFR + ' INTEGER,']
  718. stmt += [lu.NJCAL + ' INTEGER,']
  719. stmt += [lu.NJFP + ' INTEGER,']
  720. stmt += [lu.NJP + ' INTEGER,']
  721. stmt += [lu.TTC + ' INTEGER,']
  722. stmt += [lu.SST + ' INTEGER);']
  723. c.execute(''.join(stmt))
  724. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFOSUM_TN)]
  725. stmt += ['id INTEGER,']
  726. stmt += ['logname TEXT,']
  727. stmt += [lu.NJD + ' INTEGER,']
  728. stmt += [lu.NJND + ' INTEGER,']
  729. stmt += [lu.Ds15mn + ' INTEGER,']
  730. stmt += [lu.Ds1hr + ' INTEGER,']
  731. stmt += [lu.Ds3hr + ' INTEGER,']
  732. stmt += [lu.Do3hr + ' INTEGER,']
  733. stmt += [lu.DDm + ' INTEGER,']
  734. stmt += [lu.DDM + ' INTEGER,']
  735. stmt += [lu.DDA + ' INTEGER,']
  736. stmt += [lu.DD50 + ' INTEGER);']
  737. c.execute(''.join(stmt))
  738. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_ESTINFO_TN)]
  739. stmt += ['id INTEGER,']
  740. stmt += ['logname TEXT,']
  741. stmt += [lu.JID + ' TEXT,']
  742. stmt += [lu.Eat + ' INTEGER,']
  743. stmt += [lu.JST + ' INTEGER,']
  744. stmt += [lu.ESTR + ' INTEGER,']
  745. stmt += [lu.ESTA + ' INTEGER,']
  746. stmt += [lu.NEST + ' INTEGER,']
  747. stmt += [lu.ND + ' INTEGER,']
  748. stmt += [lu.JDD + ' INTEGER);']
  749. c.execute(''.join(stmt))
  750. stmt = ['CREATE TABLE IF NOT EXISTS %s (' % (_JOBM_TN)]
  751. stmt += ['id INTEGER,']
  752. stmt += ['logname TEXT,']
  753. stmt += [lu.CST + ' INTEGER,']
  754. stmt += [lu.JID + ' TEXT,']
  755. stmt += [lu.T2R + ' INTEGER,']
  756. stmt += [lu.T2D + ' INTEGER,']
  757. stmt += [lu.TiS + ' INTEGER,']
  758. stmt += [lu.TTC + ' INTEGER);']
  759. c.execute(''.join(stmt))
  760. self.__dbobj.commit()
  761. return self.__get_index(c)
  762. def __write_data(self, tablename, data, logfile):
  763. keys = ['id']
  764. values = [str(self.__index)]
  765. if logfile is not None:
  766. keys.append('logfile')
  767. values.append('\'' + str(logfile).replace(' ', '_') + '\'')
  768. for k, v in data.items():
  769. if k == 'id':
  770. continue
  771. keys.append(str(k))
  772. v = str(v)
  773. if v.isdigit():
  774. values.append(v)
  775. else:
  776. values.append('\'' + v + '\'')
  777. _keys = ','.join(keys)
  778. _values = ','.join(values)
  779. c = self.__dbobj.cursor()
  780. s = 'INSERT INTO %s (%s) VALUES (%s)' % (tablename, _keys, _values)
  781. c.execute(s)
  782. self.__dbobj.commit()
  783. def __write_server_data(self, data, logfile=None):
  784. self.__write_data(_SVRM_TN, data, logfile)
  785. def __write_mom_data(self, data, logfile=None):
  786. self.__write_data(_MOMM_TN, data, logfile)
  787. def __write_sched_data(self, data, logfile=None):
  788. for k, v in data.items():
  789. if k == 'summary':
  790. self.__write_data(_SCHEDM_TN, data, logfile)
  791. continue
  792. elif k == lu.EST:
  793. if lu.ESTS in v:
  794. self.__write_estinfosum_data(v[lu.ESTS], logfile)
  795. if lu.EJ in v:
  796. for j in v[lu.EJ]:
  797. if lu.EST in j:
  798. dt = map(lambda s: str(s), j[lu.Eat])
  799. j[lu.Eat] = ','.join(dt)
  800. self.__write_estsum_data(j, logfile)
  801. continue
  802. if 'jobs' in v:
  803. for j in v['jobs']:
  804. j[lu.CST] = v[lu.CST]
  805. self.__write_job_data(j, logfile)
  806. del v['jobs']
  807. self.__write_cycle_data(v, logfile)
  808. def __write_acct_data(self, data, logfile=None):
  809. self.__write_data(_ACCTM_TN, data, logfile)
  810. def __write_proc_data(self, data, logfile=None):
  811. self.__write_data(_PROCM_TN, data, None)
  812. def __write_cycle_data(self, data, logfile=None):
  813. self.__write_data(_CYCLEM_TN, data, logfile)
  814. def __write_estsum_data(self, data, logfile=None):
  815. self.__write_data(_ESTINFOSUM_TN, data, logfile)
  816. def __write_estinfosum_data(self, data, logfile=None):
  817. self.__write_data(_ESTINFO_TN, data, logfile)
  818. def __write_job_data(self, data, logfile=None):
  819. self.__write_data(_JOBM_TN, data, logfile)
  820. def __write_test_data(self, data):
  821. keys = ['id']
  822. values = [str(self.__index)]
  823. keys.append('suite')
  824. values.append(str(data['suite']))
  825. keys.append('testcase')
  826. values.append(str(data['testcase']))
  827. doc = []
  828. for l in str(data['testdoc']).strip().split('\n'):
  829. doc.append(l.strip().replace('\t', ' ').replace('\'', '\'\''))
  830. doc = ' '.join(doc)
  831. keys.append('testdoc')
  832. values.append('\'' + doc + '\'')
  833. keys.append('start_time')
  834. values.append(str(data['start_time']))
  835. keys.append('end_time')
  836. values.append(str(data['end_time']))
  837. keys.append('duration')
  838. values.append(str(data['duration']))
  839. keys.append('pbs_version')
  840. values.append(str(data['pbs_version']))
  841. keys.append('testparam')
  842. values.append(str(data['testparam']))
  843. keys.append('username')
  844. values.append(str(self.__username))
  845. keys.append('platform')
  846. values.append(str(self.__platform))
  847. keys.append('status')
  848. values.append(str(data['status']))
  849. sdata = data['status_data']
  850. sdata = sdata.replace('\'', '\'\'')
  851. keys.append('status_data')
  852. values.append('\'' + sdata + '\'')
  853. _keys = ','.join(keys)
  854. _values = ','.join(values)
  855. c = self.__dbobj.cursor()
  856. s = 'INSERT INTO %s (%s) VALUES (%s)' % (
  857. _TESTRESULT_TN, _keys, _values)
  858. c.execute(s)
  859. self.__dbobj.commit()
  860. def write(self, data, logfile=None):
  861. if len(data) == 0:
  862. return
  863. if 'testdata' in data.keys():
  864. self.__write_test_data(data['testdata'])
  865. if 'metrics_data' in data.keys():
  866. md = data['metrics_data']
  867. if 'server' in md.keys():
  868. self.__write_server_data(md['server'], logfile)
  869. if 'mom' in md.keys():
  870. self.__write_mom_data(md['mom'], logfile)
  871. if 'scheduler' in md.keys():
  872. self.__write_sched_data(md['scheduler'], logfile)
  873. if 'accounting' in md.keys():
  874. self.__write_acct_data(md['accounting'], logfile)
  875. if 'procs' in md.keys():
  876. self.__write_proc_data(md['procs'], logfile)
  877. self.__index += 1
  878. def close(self, result=None):
  879. self.__dbobj.commit()
  880. self.__dbobj.close()
  881. del self.__dbobj
  882. class FileDb(DBType):
  883. """
  884. File type database
  885. """
  886. def __init__(self, dbtype, dbpath, dbaccess):
  887. DBType.__init__(self, dbtype, dbpath, dbaccess)
  888. if self.dbtype != 'file':
  889. _msg = 'db type does not match with my type(file)'
  890. raise PTLDbError(rc=1, rv=False, msg=_msg)
  891. if self.dbpath is None:
  892. _msg = 'Db path require!'
  893. raise PTLDbError(rc=1, rv=False, msg=_msg)
  894. self.__separator1 = '=' * 80
  895. self.__separator2 = '___m_oo_m___'
  896. self.__username = pwd.getpwuid(os.getuid())[0]
  897. self.__platform = ' '.join(platform.uname()).strip()
  898. self.__ptlversion = str(ptl.__version__)
  899. self.__dbobj = {}
  900. self.__index = 1
  901. def __write_data(self, key, data, logfile):
  902. if key not in self.__dbobj.keys():
  903. f = os.path.join(self.dbdir, key + '.db')
  904. self.__dbobj[key] = open(f, 'w+')
  905. msg = [self.__separator1]
  906. msg += ['id = %s' % (self.__index)]
  907. if logfile is not None:
  908. msg += ['logfile = %s' % (logfile)]
  909. for k, v in data.items():
  910. if k == 'id':
  911. continue
  912. msg += [str(k) + ' = ' + str(v)]
  913. msg += [self.__separator1]
  914. self.__dbobj[key].write('\n'.join(msg) + '\n')
  915. self.__dbobj[key].flush()
  916. def __write_server_data(self, data, logfile=None):
  917. self.__write_data(_SVRM_TN, data, logfile)
  918. def __write_mom_data(self, data, logfile=None):
  919. self.__write_data(_MOMM_TN, data, logfile)
  920. def __write_sched_data(self, data, logfile=None):
  921. for k, v in data.items():
  922. if k == 'summary':
  923. self.__write_data(_SCHEDM_TN, data, logfile)
  924. continue
  925. elif k == lu.EST:
  926. if lu.ESTS in v:
  927. self.__write_estinfosum_data(v[lu.ESTS], logfile)
  928. if lu.EJ in v:
  929. for j in v[lu.EJ]:
  930. if lu.EST in j:
  931. dt = map(lambda s: str(s), j[lu.Eat])
  932. j[lu.Eat] = ','.join(dt)
  933. self.__write_estsum_data(j, logfile)
  934. continue
  935. if 'jobs' in v:
  936. for j in v['jobs']:
  937. j[lu.CST] = v[lu.CST]
  938. self.__write_job_data(j, logfile)
  939. del v['jobs']
  940. self.__write_cycle_data(v, logfile)
  941. def __write_acct_data(self, data, logfile=None):
  942. self.__write_data(_ACCTM_TN, data, logfile)
  943. def __write_proc_data(self, data, logfile=None):
  944. self.__write_data(_PROCM_TN, data, None)
  945. def __write_cycle_data(self, data, logfile=None):
  946. self.__write_data(_CYCLEM_TN, data, logfile)
  947. def __write_estsum_data(self, data, logfile=None):
  948. self.__write_data(_ESTINFOSUM_TN, data, logfile)
  949. def __write_estinfosum_data(self, data, logfile=None):
  950. self.__write_data(_ESTINFO_TN, data, logfile)
  951. def __write_job_data(self, data, logfile=None):
  952. self.__write_data(_JOBM_TN, data, logfile)
  953. def __write_test_data(self, data):
  954. if _TESTRESULT_TN not in self.__dbobj.keys():
  955. self.__dbobj[_TESTRESULT_TN] = open(self.dbpath, 'w+')
  956. msg = [self.__separator1]
  957. msg += ['id = %s' % (self.__index)]
  958. msg += ['suite = %s' % (data['suite'])]
  959. msg += ['testcase = %s' % (data['testcase'])]
  960. doc = []
  961. for l in str(data['testdoc']).strip().split('\n'):
  962. doc.append(l.strip())
  963. doc = ' '.join(doc)
  964. msg += ['testdoc = %s' % (doc)]
  965. msg += ['start_time = %s' % (str(data['start_time']))]
  966. msg += ['end_time = %s' % (str(data['end_time']))]
  967. msg += ['duration = %s' % (str(data['duration']))]
  968. msg += ['pbs_version = %s' % (data['pbs_version'])]
  969. msg += ['testparam = %s' % (data['testparam'])]
  970. msg += ['username = %s' % (self.__username)]
  971. msg += ['ptl_version = %s' % (self.__ptlversion)]
  972. msg += ['platform = %s' % (self.__platform)]
  973. msg += ['status = %s' % (data['status'])]
  974. msg += ['status_data = ']
  975. msg += [self.__separator2]
  976. msg += ['%s' % (str(data['status_data']))]
  977. msg += [self.__separator2]
  978. msg += [self.__separator1]
  979. self.__dbobj[_TESTRESULT_TN].write('\n'.join(msg) + '\n')
  980. self.__dbobj[_TESTRESULT_TN].flush()
  981. def write(self, data, logfile=None):
  982. if len(data) == 0:
  983. return
  984. if 'testdata' in data.keys():
  985. self.__write_test_data(data['testdata'])
  986. if 'metrics_data' in data.keys():
  987. md = data['metrics_data']
  988. if 'server' in md.keys():
  989. self.__write_server_data(md['server'], logfile)
  990. if 'mom' in md.keys():
  991. self.__write_mom_data(md['mom'], logfile)
  992. if 'scheduler' in md.keys():
  993. self.__write_sched_data(md['scheduler'], logfile)
  994. if 'accounting' in md.keys():
  995. self.__write_acct_data(md['accounting'], logfile)
  996. if 'procs' in md.keys():
  997. self.__write_proc_data(md['procs'], logfile)
  998. self.__index += 1
  999. def close(self, result=None):
  1000. for v in self.__dbobj.values():
  1001. v.write('\n')
  1002. v.flush()
  1003. v.close()
  1004. class HTMLDb(DBType):
  1005. """
  1006. HTML type database
  1007. """
  1008. def __init__(self, dbtype, dbpath, dbaccess):
  1009. DBType.__init__(self, dbtype, dbpath, dbaccess)
  1010. if self.dbtype != 'html':
  1011. _msg = 'db type does not match with my type(html)'
  1012. raise PTLDbError(rc=1, rv=False, msg=_msg)
  1013. if self.dbpath is None:
  1014. _msg = 'Db path require!'
  1015. raise PTLDbError(rc=1, rv=False, msg=_msg)
  1016. elif not self.dbpath.endswith('.html'):
  1017. self.dbpath = self.dbpath.rstrip('.db') + '.html'
  1018. self.__cmd = [os.path.basename(sys.argv[0])]
  1019. self.__cmd += sys.argv[1:]
  1020. self.__username = pwd.getpwuid(os.getuid())[0]
  1021. self.__platform = ' '.join(platform.uname()).strip()
  1022. self.__ptlversion = str(ptl.__version__)
  1023. self.__dbobj = {}
  1024. self.__index = 1
  1025. def __write_test_html_header(self, data):
  1026. _title = 'PTL Test Report of %s' % (data['pbs_version'])
  1027. __s = []
  1028. __s += ['<!DOCTYPE html><head>']
  1029. __s += ['<title>%s</title>' % (_title)]
  1030. __s += ['<style type="text/css">']
  1031. __s += [' * {']
  1032. __s += [' font-family: verdana;']
  1033. __s += [' }']
  1034. __s += [' h1 {']
  1035. __s += [' text-align: center;']
  1036. __s += [' }']
  1037. __s += [' .data {']
  1038. __s += [' font-size: 15px;']
  1039. __s += [' font-weight: normal;']
  1040. __s += [' width: 100%;']
  1041. __s += [' }']
  1042. __s += [' .data button {']
  1043. __s += [' float: left;']
  1044. __s += [' margin-right: 4px;']
  1045. __s += [' border: 1px solid #d0d0d0;']
  1046. __s += [' font-weight: bold;']
  1047. __s += [' outline: none;']
  1048. __s += [' width: 30px;']
  1049. __s += [' height: 30px;']
  1050. __s += [' cursor: pointer;']
  1051. __s += [' background-color: #eeeeee;']
  1052. __s += [' }']
  1053. __s += [' .data div {']
  1054. __s += [' text-align: left;']
  1055. __s += [' }']
  1056. __s += [' .data table {']
  1057. __s += [' border-spacing: 0px;']
  1058. __s += [' margin-top: 6px;']
  1059. __s += [' text-align: center;']
  1060. __s += [' }']
  1061. __s += [' .data th {']
  1062. __s += [' border: 1px solid #d0d0d0;']
  1063. __s += [' border-right: 0px;']
  1064. __s += [' background-color: #eeeeee;']
  1065. __s += [' font-weight: normal;']
  1066. __s += [' width: 13%;']
  1067. __s += [' padding: 5px;']
  1068. __s += [' }']
  1069. __s += [' .data th.innert:last-child {']
  1070. __s += [' width: 100%;']
  1071. __s += [' }']
  1072. __s += [' .data th.tsname {']
  1073. __s += [' font-weight: bold;']
  1074. __s += [' width: 500px;']
  1075. __s += [' text-align: left;']
  1076. __s += [' }']
  1077. __s += [' .data th.pass {']
  1078. __s += [' color: #3c763d;']
  1079. __s += [' background-color: #dff0d8;']
  1080. __s += [' }']
  1081. __s += [' .data th.skip {']
  1082. __s += [' color: #31708f;']
  1083. __s += [' background-color: #d9edf7;']
  1084. __s += [' }']
  1085. __s += [' .data th.fail,th.error,th.timedout {']
  1086. __s += [' color: #a94442;']
  1087. __s += [' background-color: #f2dede;']
  1088. __s += [' }']
  1089. __s += [' .data table th:last-child {']
  1090. __s += [' border: 1px solid #d0d0d0;']
  1091. __s += [' }']
  1092. __s += [' .data td {']
  1093. __s += [' border: 1px solid #d0d0d0;']
  1094. __s += [' border-top: 0px;']
  1095. __s += [' border-right: 0px;']
  1096. __s += [' padding: 5px;']
  1097. __s += [' }']
  1098. __s += [' .data td.pass_td {']
  1099. __s += [' background-color: #dff0d8;']
  1100. __s += [' color: #3c763d;']
  1101. __s += [' }']
  1102. __s += [' .data td.skip_td {']
  1103. __s += [' background-color: #d9edf7;']
  1104. __s += [' color: #31708f;']
  1105. __s += [' }']
  1106. __s += [' .data td.fail_td,td.error_td,td.timedout_td {']
  1107. __s += [' color: #a94442;']
  1108. __s += [' background-color: #f2dede;']
  1109. __s += [' }']
  1110. __s += [' .data tr td:last-child {']
  1111. __s += [' border: 1px solid #d0d0d0;']
  1112. __s += [' border-top: 0px;']
  1113. __s += [' text-align: left;']
  1114. __s += [' word-break: break-all;']
  1115. __s += [' white-space: pre-wrap;']
  1116. __s += [' }']
  1117. __s += [' .flt td {']
  1118. __s += [' padding-right: 25px;']
  1119. __s += [' padding-bottom: 10px;']
  1120. __s += [' font-size: 14px;']
  1121. __s += [' }']
  1122. __s += ['</style><script type="text/javascript">']
  1123. __s += ['function toggle(id) {']
  1124. __s += [' var b = document.getElementById(id);']
  1125. __s += [' if (b == null) {']
  1126. __s += [' return;']
  1127. __s += [' }']
  1128. __s += [' b.textContent = b.textContent == "+" ? "-" : "+";']
  1129. __s += [' if (b.textContent == "-") {']
  1130. __s += [' var table = document.getElementById(id + "_t");']
  1131. __s += [' table.style.display = "";']
  1132. __s += [' var i = b.offsetLeft + b.offsetWidth;']
  1133. __s += [' i = i - b.clientLeft - 1;']
  1134. __s += [' table.style.marginLeft = i.toString() + "px";']
  1135. __s += [' sessionStorage.setItem(id, "");']
  1136. __s += [' } else {']
  1137. __s += [' var table = document.getElementById(id + "_t");']
  1138. __s += [' table.style.display = "none";']
  1139. __s += [' sessionStorage.removeItem(id);']
  1140. __s += [' }']
  1141. __s += ['}']
  1142. __s += ['function add_ts(tsn, n) {']
  1143. __s += [' sum = 0;']
  1144. __s += [' if (tsn == "Summary")']
  1145. __s += [' sum = 1;']
  1146. __s += [' if (document.getElementById(tsn + "_d") != null) {']
  1147. __s += [' return;']
  1148. __s += [' }']
  1149. __s += [' var div = document.createElement("div");']
  1150. __s += [' div.setAttribute("class", "data");']
  1151. __s += [' div.setAttribute("id", tsn + "_d");']
  1152. __s += [' if (sum == 1) {']
  1153. __s += [' div.setAttribute("style", "margin-bottom: 15px;");']
  1154. __s += [' }']
  1155. __s += [' document.body.appendChild(div);']
  1156. __s += [' if (n != null) {']
  1157. __s += [' return;']
  1158. __s += [' }']
  1159. __s += [' var btn = document.createElement("button");']
  1160. __s += [' btn.appendChild(document.createTextNode("+"));']
  1161. __s += [' div.appendChild(btn);']
  1162. __s += [' btn.setAttribute("id", tsn);']
  1163. __s += [' var t = "toggle(\\"" + tsn + "\\")";']
  1164. __s += [' btn.setAttribute("onclick", t);']
  1165. __s += [' if (sum == 1) {']
  1166. __s += [' btn.setAttribute("style", "visibility: hidden;");']
  1167. __s += [' }']
  1168. __s += [' var table = document.createElement("table");']
  1169. __s += [' div.appendChild(table);']
  1170. __s += [' table.setAttribute("id", tsn + "_i");']
  1171. __s += [' var th = document.createElement("th");']
  1172. __s += [' th.setAttribute("class", "tsname");']
  1173. __s += [' if (sum == 1) {']
  1174. __s += [' th.setAttribute("style", "text-align: center;");']
  1175. __s += [' }']
  1176. __s += [' th.appendChild(document.createTextNode(tsn));']
  1177. __s += [' table.appendChild(th);']
  1178. __s += [' var th = document.createElement("th");']
  1179. __s += [' th.setAttribute("class", "run");']
  1180. __s += [' if (sum == 1) {']
  1181. __s += [' th.setAttribute("style", "font-weight: bold;");']
  1182. __s += [' }']
  1183. __s += [' table.appendChild(th);']
  1184. __s += [' var th = document.createElement("th");']
  1185. __s += [' th.setAttribute("class", "pass");']
  1186. __s += [' if (sum == 1) {']
  1187. __s += [' th.setAttribute("style", "font-weight: bold;");']
  1188. __s += [' }']
  1189. __s += [' table.appendChild(th);']
  1190. __s += [' f = document.createElement("font");']
  1191. __s += [' f.setAttribute("style", "color: #ade4ad");']
  1192. __s += [' th.appendChild(f);']
  1193. __s += [' tsn = document.createTextNode("Passed: 0");']
  1194. __s += [' f.appendChild(tsn);']
  1195. __s += [' var th = document.createElement("th");']
  1196. __s += [' th.setAttribute("class", "skip");']
  1197. __s += [' if (sum == 1) {']
  1198. __s += [' th.setAttribute("style", "font-weight: bold;");']
  1199. __s += [' }']
  1200. __s += [' table.appendChild(th);']
  1201. __s += [' f = document.createElement("font");']
  1202. __s += [' f.setAttribute("style", "color: #b5d7f3");']
  1203. __s += [' th.appendChild(f);']
  1204. __s += [' tsn = document.createTextNode("Skipped: 0");']
  1205. __s += [' f.appendChild(tsn);']
  1206. __s += [' var th = document.createElement("th");']
  1207. __s += [' th.setAttribute("class", "fail");']
  1208. __s += [' if (sum == 1) {']
  1209. __s += [' th.setAttribute("style", "font-weight: bold;");']
  1210. __s += [' }']
  1211. __s += [' table.appendChild(th);']
  1212. __s += [' f = document.createElement("font");']
  1213. __s += [' f.setAttribute("style", "color: #efc0bf");']
  1214. __s += [' th.appendChild(f);']
  1215. __s += [' tsn = document.createTextNode("Failed: 0");']
  1216. __s += [' f.appendChild(tsn);']
  1217. __s += [' var th = document.createElement("th");']
  1218. __s += [' th.setAttribute("class", "error");']
  1219. __s += [' if (sum == 1) {']
  1220. __s += [' th.setAttribute("style", "font-weight: bold;");']
  1221. __s += [' }']
  1222. __s += [' table.appendChild(th);']
  1223. __s += [' f = document.createElement("font");']
  1224. __s += [' f.setAttribute("style", "color: #efc0bf");']
  1225. __s += [' th.appendChild(f);']
  1226. __s += [' tsn = document.createTextNode("Error: 0");']
  1227. __s += [' f.appendChild(tsn);']
  1228. __s += [' var th = document.createElement("th");']
  1229. __s += [' th.setAttribute("class", "timedout");']
  1230. __s += [' if (sum == 1) {']
  1231. __s += [' th.setAttribute("style", "font-weight: bold;");']
  1232. __s += [' }']
  1233. __s += [' table.appendChild(th);']
  1234. __s += [' f = document.createElement("font");']
  1235. __s += [' f.setAttribute("style", "color: #efc0bf");']
  1236. __s += [' th.appendChild(f);']
  1237. __s += [' tsn = document.createTextNode("TimedOut: 0");']
  1238. __s += [' f.appendChild(tsn);']
  1239. __s += ['}']
  1240. __s += ['function add_th(tsn) {']
  1241. __s += [' if (document.getElementById(tsn + "_t") != null) {']
  1242. __s += [' return;']
  1243. __s += [' }']
  1244. __s += [' var div = document.getElementById(tsn + "_d");']
  1245. __s += [' var table = document.createElement("table");']
  1246. __s += [' table.setAttribute("id", tsn + "_t");']
  1247. __s += [' table.setAttribute("style", "display: none");']
  1248. __s += [' div.appendChild(table);']
  1249. __s += [' var tr = document.createElement("tr");']
  1250. __s += [' table.appendChild(tr);']
  1251. __s += [' var lenh = datah.length;']
  1252. __s += [' for (var i = 0; i < lenh; i++) {']
  1253. __s += [' var th = document.createElement("th");']
  1254. __s += [' if (i < (lenh-1)) {']
  1255. __s += [' th.setAttribute("style", "border-right: 0px");']
  1256. __s += [' }']
  1257. __s += [' th.setAttribute("class", "innert");']
  1258. __s += [' var txt = document.createTextNode(datah[i]);']
  1259. __s += [' th.appendChild(txt);']
  1260. __s += [' tr.appendChild(th);']
  1261. __s += [' }']
  1262. __s += ['}']
  1263. __s += ['function restore(tc) {']
  1264. __s += [' var tco = document.getElementById(tc + "_o");']
  1265. __s += [' tco.removeAttribute("style");']
  1266. __s += [' tco.removeAttribute("id");']
  1267. __s += [' var tc = document.getElementById(tc);']
  1268. __s += [' tc.parentNode.removeChild(tc);']
  1269. __s += ['}']
  1270. __s += ['function add_row(d, sel) {']
  1271. __s += [' var s = d.status.toLowerCase();']
  1272. __s += [' if (s != sel && sel != "all") {']
  1273. __s += [' return;']
  1274. __s += [' }']
  1275. __s += [' if (sel == "all") {']
  1276. __s += [' sel = d.suite;']
  1277. __s += [' }']
  1278. __s += [' var table = document.getElementById(sel + "_t");']
  1279. __s += [' var tr = document.createElement("tr");']
  1280. __s += [' table.appendChild(tr);']
  1281. __s += [' var td = document.createElement("td");']
  1282. __s += [' td.setAttribute("class", s + "_td");']
  1283. __s += [' var tc = d.suite + "." + d.testcase']
  1284. __s += [' td.appendChild(document.createTextNode(tc));']
  1285. __s += [' tr.appendChild(td);']
  1286. __s += [' var td = document.createElement("td");']
  1287. __s += [' td.setAttribute("class", s + "_td");']
  1288. __s += [' var txt = document.createTextNode(d.duration);']
  1289. __s += [' td.appendChild(txt);']
  1290. __s += [' tr.appendChild(td);']
  1291. __s += [' var td = document.createElement("td");']
  1292. __s += [' td.setAttribute("class", s + "_td");']
  1293. __s += [' td.appendChild(document.createTextNode(d.status));']
  1294. __s += [' tr.appendChild(td);']
  1295. __s += [' tr.setAttribute("class", s);']
  1296. __s += [' var td = document.createElement("td");']
  1297. __s += [' td.setAttribute("class", s + "_td");']
  1298. __s += [' var lines = d.status_data.split("\\n");']
  1299. __s += [' var llen = lines.length;']
  1300. __s += [' if (llen > 10) {']
  1301. __s += [' var fl = lines.slice(0, 3).join("\\n");']
  1302. __s += [' td.appendChild(document.createTextNode(fl));']
  1303. __s += [' var a = document.createElement("a");']
  1304. __s += [' var scr = "javascript:restore(\\"" + tc + "\\")";']
  1305. __s += [' a.setAttribute("href", scr);']
  1306. __s += [' var txt = document.createTextNode("\\n...\\n\\n");']
  1307. __s += [' a.appendChild(txt);']
  1308. __s += [' td.setAttribute("id", tc);']
  1309. __s += [' td.appendChild(a);']
  1310. __s += [' lines = lines.slice(llen - 4, llen).join("\\n");']
  1311. __s += [' td.appendChild(document.createTextNode(lines));']
  1312. __s += [' var tdo = document.createElement("td");']
  1313. __s += [' tdo.setAttribute("class", s + "_td");']
  1314. __s += [' tdo.setAttribute("id", tc + "_o");']
  1315. __s += [' tdo.setAttribute("style", "display: none");']
  1316. __s += [' tr.appendChild(tdo);']
  1317. __s += [' var txt = document.createTextNode(d.status_data);']
  1318. __s += [' tdo.appendChild(txt);']
  1319. __s += [' } else {']
  1320. __s += [' var txt = document.createTextNode(d.status_data);']
  1321. __s += [' td.appendChild(txt);']
  1322. __s += [' }']
  1323. __s += [' tr.appendChild(td);']
  1324. __s += [' var tc = document.getElementById(sel + "_i");']
  1325. __s += [' if (tc == null) {']
  1326. __s += [' return;']
  1327. __s += [' }']
  1328. __s += [' var tt = tc.getElementsByClassName(s)[0];']
  1329. __s += [' var t = tt.textContent.split(" ");']
  1330. __s += [' var i = parseInt(t[1]) + 1;']
  1331. __s += [' tt.textContent = t[0] + " " + i;']
  1332. __s += [' var tt = tc.getElementsByClassName("run")[0]']
  1333. __s += [' if (tt.textContent == "") {']
  1334. __s += [' tt.textContent = "Run: 1";']
  1335. __s += [' } else {']
  1336. __s += [' var t = tt.textContent.split(" ");']
  1337. __s += [' var i = parseInt(t[1]) + 1;']
  1338. __s += [' tt.textContent = t[0] + " " + i;']
  1339. __s += [' }']
  1340. __s += [' var tc = document.getElementById("Summary_i");']
  1341. __s += [' if (tc == null) {']
  1342. __s += [' return;']
  1343. __s += [' }']
  1344. __s += [' var tt = tc.getElementsByClassName(s)[0];']
  1345. __s += [' var t = tt.textContent.split(" ");']
  1346. __s += [' var i = parseInt(t[1]) + 1;']
  1347. __s += [' tt.textContent = t[0] + " " + i;']
  1348. __s += [' var tt = tc.getElementsByClassName("run")[0]']
  1349. __s += [' if (tt.textContent == "") {']
  1350. __s += [' tt.textContent = "Run: 1";']
  1351. __s += [' } else {']
  1352. __s += [' var t = tt.textContent.split(" ");']
  1353. __s += [' var i = parseInt(t[1]) + 1;']
  1354. __s += [' tt.textContent = t[0] + " " + i;']
  1355. __s += [' }']
  1356. __s += ['}']
  1357. __s += ['function add_dt(sel) {']
  1358. __s += [' var len = data.length;']
  1359. __s += [' for (i = 0; i < len; i++) {']
  1360. __s += [' var d = data[i];']
  1361. __s += [' if (sel == "all") {']
  1362. __s += [' add_ts("Summary");']
  1363. __s += [' add_ts(d.suite);']
  1364. __s += [' add_th(d.suite);']
  1365. __s += [' } else {']
  1366. __s += [' add_ts(sel, 1);']
  1367. __s += [' add_th(sel, 1);']
  1368. __s += [' }']
  1369. __s += [' add_row(d, sel);']
  1370. __s += [' }']
  1371. __s += [' var size = "40px";']
  1372. __s += [' if (len > 0) {']
  1373. __s += [' var b = document.getElementById(data[0].suite);']
  1374. __s += [' if (b != null) {']
  1375. __s += [' var i = b.offsetLeft + b.offsetWidth;']
  1376. __s += [' i = i - b.clientLeft - 1;']
  1377. __s += [' size = i.toString() + "px";']
  1378. __s += [' }']
  1379. __s += [' }']
  1380. __s += [' var t = document.getElementById("flt");']
  1381. __s += [' t.style.marginLeft = size;']
  1382. __s += [' if (sel != "all") {']
  1383. __s += [' t = document.getElementById(sel + "_t");']
  1384. __s += [' t.style.display = "";']
  1385. __s += [' t.style.marginLeft = size;']
  1386. __s += [' }']
  1387. __s += [' sessionStorage.removeItem("_filter_");']
  1388. __s += [' for (i = 0; i < sessionStorage.length; i++) {']
  1389. __s += [' toggle(sessionStorage.key(i));']
  1390. __s += [' }']
  1391. __s += [' sessionStorage.setItem("_filter_", sel);']
  1392. __s += ['}']
  1393. __s += ['function filter(n) {']
  1394. __s += [' var sf = sessionStorage.getItem("_filter_");']
  1395. __s += [' if (sf == null)']
  1396. __s += [' sf = "all";']
  1397. __s += [' var map = [sf, "all", "pass", "skip", "fail", "error",']
  1398. __s += [' "timedout"];']
  1399. __s += [' var sel = map[n];']
  1400. __s += [' var rbs = document.getElementsByTagName("input");']
  1401. __s += [' for (i = 0; i < rbs.length; i++) {']
  1402. __s += [' if (rbs[i].name == sel) {']
  1403. __s += [' rbs[i].checked = true;']
  1404. __s += [' } else {']
  1405. __s += [' rbs[i].checked = false;']
  1406. __s += [' }']
  1407. __s += [' }']
  1408. __s += [' var els = document.getElementsByClassName("data");']
  1409. __s += [' while (els.length > 0) {']
  1410. __s += [' els[0].parentNode.removeChild(els[0]);']
  1411. __s += [' }']
  1412. __s += [' add_dt(sel);']
  1413. __s += ['}']
  1414. __s += ['document.addEventListener("keydown", function(event) {']
  1415. __s += [' if (event.shiftKey || event.ctrlKey || event.altKey']
  1416. __s += [' || event.metaKey) {']
  1417. __s += [' return;']
  1418. __s += [' }']
  1419. __s += [' // a, p, s, f, e, t']
  1420. __s += [' var map = [-1, 65, 80, 83, 70, 69, 84]']
  1421. __s += [' if (map.indexOf(event.keyCode) != -1) {']
  1422. __s += [' filter(map.indexOf(event.keyCode));']
  1423. __s += [' }']
  1424. __s += ['});']
  1425. __s += ['</script></head><body onload="filter(0)">']
  1426. __s += ['<h1>%s</h1>' % (_title)]
  1427. _s = 'margin: 30px;margin-bottom: 15px;text-align: left;'
  1428. __s += ['<div style="%s"><table>' % (_s)]
  1429. _s = '<tr><th>%s:</th><td>%s</td></tr>'
  1430. __s += [_s % ('Command', ' '.join(self.__cmd))]
  1431. __s += [_s % ('TestParm', data['testparam'])]
  1432. __s += [_s % ('User', self.__username)]
  1433. __s += [_s % ('PTL Version', self.__ptlversion)]
  1434. __s += [_s % ('Platform', self.__platform)]
  1435. __s += ['</table></div><div id="flt"><table class="flt"><tr>']
  1436. _s = '<td><input name="%s" type="radio" onclick="filter(%d);"/>%s</td>'
  1437. __s += [_s % ('all', 1, 'Show All')]
  1438. __s += [_s % ('pass', 2, 'Show only "Passed"')]
  1439. __s += [_s % ('skip', 3, 'Show only "Skipped"')]
  1440. __s += [_s % ('fail', 4, 'Show only "Failed"')]
  1441. __s += [_s % ('error', 5, 'Show only "Error"')]
  1442. __s += [_s % ('timedout', 6, 'Show only "TimedOut"')]
  1443. __s += ['</tr></table></div><script type="text/javascript">']
  1444. __s += ['datah = ["TestCase", "Duration", "Status", "Status Data"];']
  1445. __s += ['data = [']
  1446. __s += ['];</script></body></html>']
  1447. self.__dbobj[_TESTRESULT_TN].write('\n'.join(__s))
  1448. self.__dbobj[_TESTRESULT_TN].flush()
  1449. def __write_test_data(self, data):
  1450. if _TESTRESULT_TN not in self.__dbobj.keys():
  1451. self.__dbobj[_TESTRESULT_TN] = open(self.dbpath, 'w+')
  1452. self.__write_test_html_header(data)
  1453. d = {}
  1454. d['suite'] = data['suite']
  1455. d['testcase'] = data['testcase']
  1456. d['status'] = data['status']
  1457. d['status_data'] = data['status_data']
  1458. d['duration'] = str(data['duration'])
  1459. self.__dbobj[_TESTRESULT_TN].seek(-27, os.SEEK_END)
  1460. t = self.__dbobj[_TESTRESULT_TN].readline().strip()
  1461. line = ''
  1462. if t != '[':
  1463. line += ',\n'
  1464. else:
  1465. line += '\n'
  1466. line += str(d) + '\n];</script></body></html>'
  1467. self.__dbobj[_TESTRESULT_TN].seek(-26, os.SEEK_END)
  1468. self.__dbobj[_TESTRESULT_TN].write(line)
  1469. self.__dbobj[_TESTRESULT_TN].flush()
  1470. self.__index += 1
  1471. def write(self, data, logfile=None):
  1472. if len(data) == 0:
  1473. return
  1474. if 'testdata' in data.keys():
  1475. self.__write_test_data(data['testdata'])
  1476. def close(self, result=None):
  1477. for v in self.__dbobj.values():
  1478. v.write('\n')
  1479. v.flush()
  1480. v.close()
  1481. class JSONDb(DBType):
  1482. """
  1483. JSON type database
  1484. """
  1485. def __init__(self, dbtype, dbpath, dbaccess):
  1486. super(JSONDb, self).__init__(dbtype, dbpath, dbaccess)
  1487. if self.dbtype != 'json':
  1488. _msg = 'db type does not match with my type(json)'
  1489. raise PTLDbError(rc=1, rv=False, msg=_msg)
  1490. if not self.dbpath:
  1491. _msg = 'Db path require!'
  1492. raise PTLDbError(rc=1, rv=False, msg=_msg)
  1493. elif not self.dbpath.endswith('.json'):
  1494. self.dbpath = self.dbpath.rstrip('.db') + '.json'
  1495. self.__dbobj = {}
  1496. self.__cmd = [os.path.basename(sys.argv[0])]
  1497. self.__cmd += sys.argv[1:]
  1498. self.__cmd = ' '.join(self.__cmd)
  1499. self.res_data = PTLJsonData(command=self.__cmd)
  1500. def __write_test_data(self, data):
  1501. jdata = None
  1502. if _TESTRESULT_TN not in self.__dbobj.keys():
  1503. self.__dbobj[_TESTRESULT_TN] = open(self.dbpath, 'w+')
  1504. else:
  1505. self.__dbobj[_TESTRESULT_TN].seek(0)
  1506. jdata = json.load(self.__dbobj[_TESTRESULT_TN])
  1507. jsondata = self.res_data.get_json(data=data, prev_data=jdata)
  1508. self.__dbobj[_TESTRESULT_TN].seek(0)
  1509. json.dump(jsondata, self.__dbobj[_TESTRESULT_TN], indent=2)
  1510. def write(self, data, logfile=None):
  1511. if len(data) == 0:
  1512. return
  1513. if 'testdata' in data.keys():
  1514. self.__write_test_data(data['testdata'])
  1515. def close(self, result=None):
  1516. if result is not None:
  1517. self.__dbobj[_TESTRESULT_TN].seek(0)
  1518. df = json.load(self.__dbobj[_TESTRESULT_TN])
  1519. dur = str(result.stop - result.start)
  1520. df['test_summary']['test_duration'] = dur
  1521. self.__dbobj[_TESTRESULT_TN].seek(0)
  1522. json.dump(df, self.__dbobj[_TESTRESULT_TN], indent=2)
  1523. for v in self.__dbobj.values():
  1524. v.write('\n')
  1525. v.flush()
  1526. v.close()
  1527. class PTLTestDb(Plugin):
  1528. """
  1529. PTL Test Database Plugin
  1530. """
  1531. name = 'PTLTestDb'
  1532. score = sys.maxint - 5
  1533. logger = logging.getLogger(__name__)
  1534. def __init__(self):
  1535. Plugin.__init__(self)
  1536. self.__dbconn = None
  1537. self.__dbtype = 'JSONDb'
  1538. self.__dbpath = None
  1539. self.__dbaccess = None
  1540. self.__dbmapping = {'file': FileDb,
  1541. 'html': HTMLDb,
  1542. 'json': JSONDb,
  1543. 'sqlite': SQLiteDb,
  1544. 'pgsql': PostgreSQLDb}
  1545. self.__du = DshUtils()
  1546. def options(self, parser, env):
  1547. """
  1548. Register command line options
  1549. """
  1550. pass
  1551. def set_data(self, dbtype, dbpath, dbaccess):
  1552. """
  1553. Set the data
  1554. """
  1555. self.__dbtype = dbtype
  1556. self.__dbpath = dbpath
  1557. self.__dbaccess = dbaccess
  1558. def configure(self, options, config):
  1559. """
  1560. Configure the plugin and system, based on selected options
  1561. :param options: Configuration options for ``plugin`` and ``system``
  1562. """
  1563. if self.__dbconn is not None:
  1564. return
  1565. if self.__dbtype is None:
  1566. self.__dbtype = 'json'
  1567. if self.__dbtype not in self.__dbmapping.keys():
  1568. self.logger.error('Invalid db type: %s' % self.__dbtype)
  1569. sys.exit(1)
  1570. try:
  1571. self.__dbconn = self.__dbmapping[self.__dbtype](self.__dbtype,
  1572. self.__dbpath,
  1573. self.__dbaccess)
  1574. except PTLDbError, e:
  1575. self.logger.error(str(e) + '\n')
  1576. sys.exit(1)
  1577. self.enabled = True
  1578. def __create_data(self, test, err=None, status=None):
  1579. if hasattr(test, 'test'):
  1580. _test = test.test
  1581. sn = _test.__class__.__name__
  1582. elif hasattr(test, 'context'):
  1583. test = _test = test.context
  1584. sn = test.__name__
  1585. else:
  1586. return {}
  1587. testdata = {}
  1588. data = {}
  1589. if (hasattr(_test, 'server') and
  1590. (getattr(_test, 'server', None) is not None)):
  1591. testdata['pbs_version'] = _test.server.attributes['pbs_version']
  1592. testdata['hostname'] = _test.server.hostname
  1593. else:
  1594. testdata['pbs_version'] = 'unknown'
  1595. testdata['hostname'] = 'unknown'
  1596. testdata['machinfo'] = self.__get_machine_info(_test)
  1597. testdata['testparam'] = getattr(_test, 'param', None)
  1598. testdata['suite'] = sn
  1599. testdata['suitedoc'] = str(_test.__class__.__doc__)
  1600. testdata['file'] = _test.__module__.replace('.', '/') + '.py'
  1601. testdata['module'] = _test.__module__
  1602. testdata['testcase'] = getattr(_test, '_testMethodName', '<unknown>')
  1603. testdata['testdoc'] = getattr(_test, '_testMethodDoc', '<unknown>')
  1604. testdata['start_time'] = getattr(test, 'start_time', 0)
  1605. testdata['end_time'] = getattr(test, 'end_time', 0)
  1606. testdata['duration'] = getattr(test, 'duration', 0)
  1607. testdata['tags'] = getattr(_test, TAGKEY, [])
  1608. measurements_dic = getattr(_test, 'measurements', {})
  1609. if measurements_dic:
  1610. testdata['measurements'] = measurements_dic
  1611. additional_data_dic = getattr(_test, 'additional_data', {})
  1612. if additional_data_dic:
  1613. testdata['additional_data'] = additional_data_dic
  1614. if err is not None:
  1615. if isclass(err[0]) and issubclass(err[0], SkipTest):
  1616. testdata['status'] = 'SKIP'
  1617. testdata['status_data'] = 'Reason = %s' % (err[1])
  1618. else:
  1619. if isclass(err[0]) and issubclass(err[0], TimeOut):
  1620. status = 'TIMEDOUT'
  1621. testdata['status'] = status
  1622. testdata['status_data'] = getattr(test, 'err_in_string',
  1623. '<unknown>')
  1624. else:
  1625. testdata['status'] = status
  1626. testdata['status_data'] = ''
  1627. data['testdata'] = testdata
  1628. md = getattr(_test, 'metrics_data', {})
  1629. if len(md) > 0:
  1630. data['metrics_data'] = md
  1631. return data
  1632. def __get_machine_info(self, test):
  1633. """
  1634. Helper function to return machines dictionary with details
  1635. :param: test
  1636. :test type: object
  1637. returns dictionary with machines information
  1638. """
  1639. mpinfo = {
  1640. 'servers': [],
  1641. 'moms': [],
  1642. 'comms': [],
  1643. 'clients': []
  1644. }
  1645. minstall_type = {
  1646. 'servers': 'server',
  1647. 'moms': 'execution',
  1648. 'comms': 'communication',
  1649. 'clients': 'client'
  1650. }
  1651. for name in mpinfo:
  1652. mlist = None
  1653. if (hasattr(test, name) and
  1654. (getattr(test, name, None) is not None)):
  1655. mlist = getattr(test, name).values()
  1656. if mlist:
  1657. for mc in mlist:
  1658. mpinfo[name].append(mc.hostname)
  1659. machines = {}
  1660. for k, v in mpinfo.items():
  1661. for hst in v:
  1662. if hst not in machines:
  1663. machines[hst] = {}
  1664. mshort = machines[hst]
  1665. mshort['platform'] = self.__du.get_uname(hostname=hst)
  1666. mshort['os_info'] = self.__du.get_os_info(hostname=hst)
  1667. machines[hst]['pbs_install_type'] = minstall_type[k]
  1668. if ((k == 'moms' or k == 'comms') and
  1669. hst in mpinfo['servers']):
  1670. machines[hst]['pbs_install_type'] = 'server'
  1671. return machines
  1672. def addError(self, test, err):
  1673. self.__dbconn.write(self.__create_data(test, err, 'ERROR'))
  1674. def addFailure(self, test, err):
  1675. self.__dbconn.write(self.__create_data(test, err, 'FAIL'))
  1676. def addSuccess(self, test):
  1677. self.__dbconn.write(self.__create_data(test, None, 'PASS'))
  1678. def finalize(self, result):
  1679. self.__dbconn.close(result)
  1680. self.__dbconn = None
  1681. self.__dbaccess = None
  1682. def process_output(self, info={}, dbout=None, dbtype=None, dbaccess=None,
  1683. name=None, logtype=None, summary=False):
  1684. """
  1685. Send analyzed log information to either the screen or to a database
  1686. file.
  1687. :param info: A dictionary of log analysis metrics.
  1688. :type info: Dictionary
  1689. :param dbout: The name of the database file to send output to
  1690. :type dbout: str or None
  1691. :param dbtype: Type of database
  1692. :param dbaccess: Path to a file that defines db options
  1693. (PostreSQL only)
  1694. :param name: The name of the log file being analyzed
  1695. :type name: str or None
  1696. :param logtype: The log type, one of ``accounting``, ``schedsummary``,
  1697. ``scheduler``, ``server``, or ``mom``
  1698. :param summary: If True output summary only
  1699. """
  1700. if dbout is not None:
  1701. try:
  1702. self.set_data(dbtype, dbout, dbaccess)
  1703. self.configure(None, None)
  1704. data = {'metrics_data': {logtype: info}}
  1705. self.__dbconn.write(data, os.path.basename(name))
  1706. self.finalize(None)
  1707. except Exception, e:
  1708. traceback.print_exc()
  1709. sys.stderr.write('Error processing output ' + str(e))
  1710. return
  1711. if lu.CFC in info:
  1712. freq_info = info[lu.CFC]
  1713. elif 'summary' in info and lu.CFC in info['summary']:
  1714. freq_info = info['summary'][lu.CFC]
  1715. else:
  1716. freq_info = None
  1717. if 'matches' in info:
  1718. for m in info['matches']:
  1719. print m,
  1720. del info['matches']
  1721. if freq_info is not None:
  1722. for ((l, m), n) in freq_info:
  1723. b = time.strftime("%m/%d/%y %H:%M:%S", time.localtime(l))
  1724. e = time.strftime("%m/%d/%y %H:%M:%S", time.localtime(m))
  1725. print(b + ' -'),
  1726. if b[:8] != e[:8]:
  1727. print(e),
  1728. else:
  1729. print(e[9:]),
  1730. print(': ' + str(n))
  1731. return
  1732. if lu.EST in info:
  1733. einfo = info[lu.EST]
  1734. m = []
  1735. for j in einfo[lu.EJ]:
  1736. m.append('Job ' + j[lu.JID] + '\n\testimated:')
  1737. if lu.Eat in j:
  1738. for estimate in j[lu.Eat]:
  1739. m.append('\t\t' + str(time.ctime(estimate)))
  1740. if lu.JST in j:
  1741. m.append('\tstarted:\n')
  1742. m.append('\t\t' + str(time.ctime(j[lu.JST])))
  1743. m.append('\testimate range: ' + str(j[lu.ESTR]))
  1744. m.append('\tstart to estimated: ' + str(j[lu.ESTA]))
  1745. if lu.NEST in j:
  1746. m.append('\tnumber of estimates: ' + str(j[lu.NEST]))
  1747. if lu.NJD in j:
  1748. m.append('\tnumber of drifts: ' + str(j[lu.NJD]))
  1749. if lu.JDD in j:
  1750. m.append('\tdrift duration: ' + str(j[lu.JDD]))
  1751. m.append('\n')
  1752. if lu.ESTS in einfo:
  1753. m.append('\nsummary: ')
  1754. for k, v in sorted(einfo[lu.ESTS].items()):
  1755. if 'duration' in k:
  1756. m.append('\t' + k + ': ' +
  1757. str(PbsTypeDuration(int(v))))
  1758. else:
  1759. m.append('\t' + k + ': ' + str(v))
  1760. print "\n".join(m)
  1761. return
  1762. sorted_info = sorted(info.items())
  1763. for (k, v) in sorted_info:
  1764. if summary and k != 'summary':
  1765. continue
  1766. print str(k) + ": ",
  1767. if isinstance(v, dict):
  1768. sorted_v = sorted(v.items())
  1769. for (k, val) in sorted_v:
  1770. print str(k) + '=' + str(val) + ' '
  1771. print
  1772. else:
  1773. print str(v)
  1774. print ''