pbs_test_entity_limits.py 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  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. from tests.functional import *
  37. class TestEntityLimits(TestFunctional):
  38. """
  39. This test suite tests working of queued_jobs_threshold, max_queued,
  40. queued_jobs_threshold_res and max_queued_res.
  41. PBS supports entity limits at queue and server level. And these limits
  42. can be applied for a user, group, project or overall.
  43. This test suite iterates over all the entities.
  44. """
  45. limit = 10
  46. def setUp(self):
  47. TestFunctional.setUp(self)
  48. a = {'resources_available.ncpus': 1}
  49. self.server.manager(MGR_CMD_SET, NODE, a, self.mom.shortname,
  50. expect=True)
  51. def common_limit_test(self, server, entstr, job_attr={}, queued=False,
  52. exp_err=''):
  53. if not server:
  54. qname = self.server.default_queue
  55. self.server.manager(MGR_CMD_SET, QUEUE, entstr, qname)
  56. else:
  57. self.server.manager(MGR_CMD_SET, SERVER, entstr)
  58. if queued:
  59. j = Job(TST_USR, job_attr)
  60. jid = self.server.submit(j)
  61. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  62. for _ in range(self.limit):
  63. j = Job(TST_USR, job_attr)
  64. self.server.submit(j)
  65. try:
  66. j = Job(TST_USR, job_attr)
  67. self.server.submit(j)
  68. except PbsSubmitError as e:
  69. if e.msg[0] != exp_err:
  70. raise self.failureException("rcvd unexpected err message: "
  71. + e.msg[0])
  72. else:
  73. self.assertFalse(True, "Job violating limits got submitted.")
  74. self.server.cleanup_jobs()
  75. try:
  76. jval = "1-" + str(self.limit + 1)
  77. job_attr[ATTR_J] = jval
  78. j = Job(TST_USR, job_attr)
  79. jid = self.server.submit(j)
  80. except PbsSubmitError as e:
  81. if e.msg[0] != exp_err:
  82. raise self.failureException("rcvd unexpected err message: "
  83. + e.msg[0])
  84. else:
  85. self.assertFalse(True, "Array Job violating limits got submitted.")
  86. jval = "1-" + str(self.limit)
  87. job_attr[ATTR_J] = jval
  88. j = Job(TST_USR, job_attr)
  89. jid = self.server.submit(j)
  90. self.server.expect(JOB, {'job_state': 'B'}, id=jid)
  91. del job_attr[ATTR_J]
  92. if queued:
  93. j = Job(TST_USR, job_attr)
  94. self.server.submit(j)
  95. try:
  96. j = Job(TST_USR, job_attr)
  97. self.server.submit(j)
  98. except PbsSubmitError:
  99. if e.msg[0] != exp_err:
  100. raise self.failureException("rcvd unexpected err message: "
  101. + e.msg[0])
  102. else:
  103. self.assertFalse(True, "Job violating limits got submitted.")
  104. self.server.restart()
  105. try:
  106. self.server.submit(j)
  107. except PbsSubmitError:
  108. if e.msg[0] != exp_err:
  109. raise self.failureException("rcvd unexpected err message: "
  110. + e.msg[0])
  111. else:
  112. self.assertFalse(True, "Job violating limits got submitted after "
  113. + "server restart.")
  114. def test_server_generic_user_limits_queued(self):
  115. """
  116. Test queued_jobs_threshold for any user at the server level.
  117. """
  118. a = {"queued_jobs_threshold":
  119. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  120. m = "qsub: would exceed complex's per-user limit of jobs in 'Q' state"
  121. self.common_limit_test(True, a, queued=True, exp_err=m)
  122. def test_server_user_limits_queued(self):
  123. """
  124. Test queued_jobs_threshold for user TST_USR at the server level.
  125. """
  126. a = {"queued_jobs_threshold":
  127. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  128. errmsg = "qsub: Maximum number of jobs in 'Q' state for user " + \
  129. str(TST_USR) + ' already in complex'
  130. self.common_limit_test(True, a, queued=True, exp_err=errmsg)
  131. def test_server_project_limits_queued(self):
  132. """
  133. Test queued_jobs_threshold for project p1 at the server level.
  134. """
  135. a = {"queued_jobs_threshold": "[p:p1=" + str(self.limit) + "]"}
  136. attrs = {ATTR_project: 'p1'}
  137. errmsg = "qsub: Maximum number of jobs in 'Q' state for project p1 " \
  138. + "already in complex"
  139. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  140. def test_server_generic_project_limits_queued(self):
  141. """
  142. Test queued_jobs_threshold for any project at the server level.
  143. """
  144. a = {"queued_jobs_threshold":
  145. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  146. errmsg = "qsub: would exceed complex's per-project limit of jobs in " \
  147. + "'Q' state"
  148. self.common_limit_test(True, a, queued=True, exp_err=errmsg)
  149. def test_server_group_limits_queued(self):
  150. """
  151. Test queued_jobs_threshold for group TSTGRP0 at the server level.
  152. """
  153. a = {"queued_jobs_threshold":
  154. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  155. errmsg = "qsub: Maximum number of jobs in 'Q' state for group " + \
  156. str(TSTGRP0) + ' already in complex'
  157. self.common_limit_test(True, a, queued=True, exp_err=errmsg)
  158. def test_server_generic_group_limits_queued(self):
  159. """
  160. Test queued_jobs_threshold for any group at the server level.
  161. """
  162. a = {"queued_jobs_threshold":
  163. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  164. m = "qsub: would exceed complex's per-group limit of jobs in 'Q' state"
  165. self.common_limit_test(True, a, queued=True, exp_err=m)
  166. def test_server_overall_limits_queued(self):
  167. """
  168. Test queued_jobs_threshold for any entity at the server level.
  169. """
  170. a = {"queued_jobs_threshold": "[o:PBS_ALL=" + str(self.limit) + "]"}
  171. errmsg = "qsub: Maximum number of jobs in 'Q' state already in complex"
  172. self.common_limit_test(True, a, queued=True, exp_err=errmsg)
  173. def test_queue_generic_user_limits_queued(self):
  174. """
  175. Test queued_jobs_threshold for any user for the default queue.
  176. """
  177. a = {"queued_jobs_threshold":
  178. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  179. attrs = {ATTR_queue: self.server.default_queue}
  180. errmsg = "qsub: would exceed queue generic's per-user limit of " \
  181. + "jobs in 'Q' state"
  182. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  183. def test_queue_user_limits_queued(self):
  184. """
  185. Test queued_jobs_threshold for user pbsuser1 for the default queue.
  186. """
  187. a = {"queued_jobs_threshold":
  188. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  189. attrs = {ATTR_queue: self.server.default_queue}
  190. errmsg = "qsub: Maximum number of jobs in 'Q' state for user " + \
  191. str(TST_USR) + ' already in queue ' + self.server.default_queue
  192. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  193. def test_queue_group_limits_queued(self):
  194. """
  195. Test queued_jobs_threshold for group TSTGRP0 for the default queue.
  196. """
  197. a = {"queued_jobs_threshold":
  198. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  199. attrs = {ATTR_queue: self.server.default_queue}
  200. errmsg = "qsub: Maximum number of jobs in 'Q' state for group " + \
  201. str(TSTGRP0) + ' already in queue ' + self.server.default_queue
  202. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  203. def test_queue_project_limits_queued(self):
  204. """
  205. Test queued_jobs_threshold for project p1 for the default queue.
  206. """
  207. a = {"queued_jobs_threshold": "[p:p1=" + str(self.limit) + "]"}
  208. attrs = {ATTR_queue: self.server.default_queue, ATTR_project: 'p1'}
  209. errmsg = "qsub: Maximum number of jobs in 'Q' state for project p1 " \
  210. 'already in queue ' + self.server.default_queue
  211. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  212. def test_queue_generic_project_limits_queued(self):
  213. """
  214. Test queued_jobs_threshold for any project for the default queue.
  215. """
  216. a = {"queued_jobs_threshold":
  217. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  218. attrs = {ATTR_queue: self.server.default_queue}
  219. errmsg = 'qsub: would exceed queue ' + self.server.default_queue + \
  220. "'s per-project limit of jobs in 'Q' state"
  221. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  222. def test_queue_generic_group_limits_queued(self):
  223. """
  224. Test queued_jobs_threshold for any group for the default queue.
  225. """
  226. a = {"queued_jobs_threshold":
  227. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  228. attrs = {ATTR_queue: self.server.default_queue}
  229. errmsg = 'qsub: would exceed queue ' + self.server.default_queue + \
  230. "'s per-group limit of jobs in 'Q' state"
  231. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  232. def test_queue_overall_limits_queued(self):
  233. """
  234. Test queued_jobs_threshold for all entities for the default queue.
  235. """
  236. a = {"queued_jobs_threshold": "[o:PBS_ALL=" + str(self.limit) + "]"}
  237. attrs = {ATTR_queue: self.server.default_queue}
  238. emsg = "qsub: Maximum number of jobs in 'Q' state already in queue " \
  239. + self.server.default_queue
  240. self.common_limit_test(False, a, attrs, queued=True, exp_err=emsg)
  241. def test_server_generic_user_limits_res_queued(self):
  242. """
  243. Test queued_jobs_threshold_res for any user at the server level.
  244. """
  245. a = {"queued_jobs_threshold_res.ncpus":
  246. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  247. attrs = {'Resource_List.select': '1:ncpus=1'}
  248. errmsg = 'qsub: would exceed per-user limit on resource ncpus in ' \
  249. + "complex for jobs in 'Q' state"
  250. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  251. def test_server_user_limits_res_queued(self):
  252. """
  253. Test queued_jobs_threshold_res for user pbsuser1 at the server level.
  254. """
  255. a = {"queued_jobs_threshold_res.ncpus":
  256. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  257. attrs = {'Resource_List.select': '1:ncpus=1'}
  258. errmsg = 'qsub: would exceed user ' + str(TST_USR) + \
  259. "'s limit on resource ncpus in complex for jobs in 'Q' state"
  260. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  261. def test_server_generic_group_limits_res_queued(self):
  262. """
  263. Test queued_jobs_threshold_res for any group at the server level.
  264. """
  265. a = {"queued_jobs_threshold_res.ncpus":
  266. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  267. attrs = {'Resource_List.select': '1:ncpus=1'}
  268. errmsg = 'qsub: would exceed per-group limit on resource ncpus in '\
  269. + "complex for jobs in 'Q' state"
  270. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  271. def test_server_project_limits_res_queued(self):
  272. """
  273. Test queued_jobs_threshold_res for project p1 at the server level.
  274. """
  275. a = {"queued_jobs_threshold_res.ncpus":
  276. "[p:p1=" + str(self.limit) + "]"}
  277. attrs = {ATTR_project: 'p1', 'Resource_List.select': '1:ncpus=1'}
  278. errmsg = "qsub: would exceed project p1's limit on resource ncpus in" \
  279. + " complex for jobs in 'Q' state"
  280. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  281. def test_server_generic_project_limits_res_queued(self):
  282. """
  283. Test queued_jobs_threshold_res for any project at the server level.
  284. """
  285. a = {"queued_jobs_threshold_res.ncpus":
  286. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  287. attrs = {'Resource_List.select': '1:ncpus=1'}
  288. errmsg = 'qsub: would exceed per-project limit on resource ncpus in ' \
  289. + "complex for jobs in 'Q' state"
  290. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  291. def test_server_group_limits_res_queued(self):
  292. """
  293. Test queued_jobs_threshold_res for group pbsuser1 at the server level.
  294. """
  295. a = {"queued_jobs_threshold_res.ncpus":
  296. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  297. attrs = {'Resource_List.select': '1:ncpus=1'}
  298. errmsg = 'qsub: would exceed group ' + str(TSTGRP0) + \
  299. "'s limit on resource ncpus in complex for jobs in 'Q' state"
  300. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  301. def test_server_overall_limits_res_queued(self):
  302. """
  303. Test queued_jobs_threshold_res for all entities at the server level.
  304. """
  305. a = {"queued_jobs_threshold_res.ncpus":
  306. "[o:PBS_ALL=" + str(self.limit) + "]"}
  307. attrs = {'Resource_List.select': '1:ncpus=1'}
  308. errmsg = 'qsub: would exceed limit on resource ncpus in complex for '\
  309. + "jobs in 'Q' state"
  310. self.common_limit_test(True, a, attrs, queued=True, exp_err=errmsg)
  311. def test_queue_generic_user_limits_res_queued(self):
  312. """
  313. Test queued_jobs_threshold_res for all users for the default queue.
  314. """
  315. a = {"queued_jobs_threshold_res.ncpus":
  316. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  317. attrs = {ATTR_queue: self.server.default_queue,
  318. 'Resource_List.select': '1:ncpus=1'}
  319. emsg = 'qsub: would exceed per-user limit on resource ncpus in queue '\
  320. + self.server.default_queue + " for jobs in 'Q' state"
  321. self.common_limit_test(False, a, attrs, queued=True, exp_err=emsg)
  322. def test_queue_user_limits_res_queued(self):
  323. """
  324. Test queued_jobs_threshold_res for user pbsuser1 for the default queue.
  325. """
  326. a = {"queued_jobs_threshold_res.ncpus":
  327. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  328. attrs = {ATTR_queue: self.server.default_queue,
  329. 'Resource_List.select': '1:ncpus=1'}
  330. errmsg = 'qsub: would exceed user ' + str(TST_USR) + \
  331. "'s limit on resource ncpus in queue " + \
  332. self.server.default_queue + " for jobs in 'Q' state"
  333. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  334. def test_queue_group_limits_res_queued(self):
  335. """
  336. Test queued_jobs_threshold_res for group pbsuser1 for the default queue
  337. """
  338. a = {"queued_jobs_threshold_res.ncpus":
  339. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  340. attrs = {ATTR_queue: self.server.default_queue,
  341. 'Resource_List.select': '1:ncpus=1'}
  342. errmsg = 'qsub: would exceed group ' + str(TSTGRP0) + \
  343. "'s limit on resource ncpus in queue " + \
  344. self.server.default_queue + " for jobs in 'Q' state"
  345. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  346. def test_queue_generic_group_limits_res_queued(self):
  347. """
  348. Test queued_jobs_threshold_res for any group for the default queue.
  349. """
  350. a = {"queued_jobs_threshold_res.ncpus":
  351. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  352. attrs = {ATTR_queue: self.server.default_queue,
  353. 'Resource_List.select': '1:ncpus=1'}
  354. errmsg = 'qsub: would exceed per-group limit on resource ncpus in ' \
  355. + 'queue ' + self.server.default_queue + " for jobs in 'Q' state"
  356. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  357. def test_queue_project_limits_res_queued(self):
  358. """
  359. Test queued_jobs_threshold_res for project p1 for the default queue.
  360. """
  361. a = {"queued_jobs_threshold_res.ncpus":
  362. "[p:p1=" + str(self.limit) + "]"}
  363. attrs = {ATTR_queue: self.server.default_queue,
  364. ATTR_project: 'p1', 'Resource_List.select': '1:ncpus=1'}
  365. errmsg = "qsub: would exceed project p1's limit on resource ncpus " + \
  366. 'in queue ' + self.server.default_queue + " for jobs in 'Q' state"
  367. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  368. def test_queue_generic_project_limits_res_queued(self):
  369. """
  370. Test queued_jobs_threshold_res for any project for the default queue.
  371. """
  372. a = {"queued_jobs_threshold_res.ncpus":
  373. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  374. attrs = {ATTR_queue: self.server.default_queue,
  375. 'Resource_List.select': '1:ncpus=1'}
  376. errmsg = 'qsub: would exceed per-project limit on resource ncpus in' \
  377. + ' queue ' + self.server.default_queue + " for jobs in 'Q' state"
  378. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  379. def test_queue_overall_limits_res_queued(self):
  380. """
  381. Test queued_jobs_threshold_res for any entity for the default queue.
  382. """
  383. a = {"queued_jobs_threshold_res.ncpus":
  384. "[o:PBS_ALL=" + str(self.limit) + "]"}
  385. attrs = {ATTR_queue: self.server.default_queue,
  386. 'Resource_List.select': '1:ncpus=1'}
  387. errmsg = 'qsub: would exceed limit on resource ncpus in queue ' + \
  388. self.server.default_queue + " for jobs in 'Q' state"
  389. self.common_limit_test(False, a, attrs, queued=True, exp_err=errmsg)
  390. def test_server_generic_user_limits_max(self):
  391. """
  392. Test max_queued for any user at the server level.
  393. """
  394. a = {"max_queued":
  395. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  396. errmsg = "qsub: would exceed complex's per-user limit"
  397. self.common_limit_test(True, a, exp_err=errmsg)
  398. def test_server_user_limits_max(self):
  399. """
  400. Test max_queued for user pbsuser1 at the server level.
  401. """
  402. a = {"max_queued":
  403. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  404. errmsg = 'qsub: Maximum number of jobs for user ' + str(TST_USR) + \
  405. ' already in complex'
  406. self.common_limit_test(True, a, exp_err=errmsg)
  407. def test_server_project_limits_max(self):
  408. """
  409. Test max_queued for project p1 at the server level.
  410. """
  411. a = {"max_queued": "[p:p1=" + str(self.limit) + "]"}
  412. attrs = {ATTR_project: 'p1'}
  413. msg = 'qsub: Maximum number of jobs for project p1 already in complex'
  414. self.common_limit_test(True, a, attrs, exp_err=msg)
  415. def test_server_generic_project_limits_max(self):
  416. """
  417. Test max_queued for any project at the server level.
  418. """
  419. a = {"max_queued":
  420. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  421. errmsg = "qsub: would exceed complex's per-project limit"
  422. self.common_limit_test(True, a, exp_err=errmsg)
  423. def test_server_group_limits_max(self):
  424. """
  425. Test max_queued for group pbsuser1 at the server level.
  426. """
  427. a = {"max_queued":
  428. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  429. errmsg = 'qsub: Maximum number of jobs for group ' + str(TSTGRP0) + \
  430. ' already in complex'
  431. self.common_limit_test(True, a, exp_err=errmsg)
  432. def test_server_generic_group_limits_max(self):
  433. """
  434. Test max_queued for any group at the server level.
  435. """
  436. a = {"max_queued":
  437. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  438. errmsg = "qsub: would exceed complex's per-group limit"
  439. self.common_limit_test(True, a, exp_err=errmsg)
  440. def test_server_overall_limits_max(self):
  441. """
  442. Test max_queued for any entity at the server level.
  443. """
  444. a = {"max_queued": "[o:PBS_ALL=" + str(self.limit) + "]"}
  445. errmsg = 'qsub: Maximum number of jobs already in complex'
  446. self.common_limit_test(True, a, exp_err=errmsg)
  447. def test_queue_generic_user_limits_max(self):
  448. """
  449. Test max_queued for any user for the default queue.
  450. """
  451. a = {"max_queued":
  452. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  453. attrs = {ATTR_queue: self.server.default_queue}
  454. errmsg = "qsub: would exceed queue generic's per-user limit"
  455. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  456. def test_queue_user_limits_max(self):
  457. """
  458. Test max_queued for user pbsuser1 for the default queue.
  459. """
  460. a = {"max_queued":
  461. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  462. attrs = {ATTR_queue: self.server.default_queue}
  463. errmsg = 'qsub: Maximum number of jobs for user ' + str(TST_USR) + \
  464. ' already in queue ' + self.server.default_queue
  465. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  466. def test_queue_group_limits_max(self):
  467. """
  468. Test max_queued for group pbsuser1 for the default queue.
  469. """
  470. a = {"max_queued":
  471. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  472. attrs = {ATTR_queue: self.server.default_queue}
  473. errmsg = 'qsub: Maximum number of jobs for group ' + str(TSTGRP0) + \
  474. ' already in queue ' + self.server.default_queue
  475. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  476. def test_queue_project_limits_max(self):
  477. """
  478. Test max_queued for project p1 for the default queue.
  479. """
  480. a = {"max_queued": "[p:p1=" + str(self.limit) + "]"}
  481. attrs = {ATTR_queue: self.server.default_queue, ATTR_project: 'p1'}
  482. msg = 'qsub: Maximum number of jobs for project p1 already in queue '\
  483. + self.server.default_queue
  484. self.common_limit_test(False, a, attrs, exp_err=msg)
  485. def test_queue_generic_project_limits_max(self):
  486. """
  487. Test max_queued for any project for the default queue.
  488. """
  489. a = {"max_queued":
  490. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  491. attrs = {ATTR_queue: self.server.default_queue}
  492. errmsg = 'qsub: would exceed queue ' + self.server.default_queue + \
  493. "'s per-project limit"
  494. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  495. def test_queue_generic_group_limits_max(self):
  496. """
  497. Test max_queued for any group for the default queue.
  498. """
  499. a = {"max_queued":
  500. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  501. attrs = {ATTR_queue: self.server.default_queue}
  502. errmsg = 'qsub: would exceed queue ' + self.server.default_queue + \
  503. "'s per-group limit"
  504. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  505. def test_queue_overall_limits_max(self):
  506. """
  507. Test max_queued for all entities for the default queue.
  508. """
  509. a = {"max_queued": "[o:PBS_ALL=" + str(self.limit) + "]"}
  510. attrs = {ATTR_queue: self.server.default_queue}
  511. errmsg = 'qsub: Maximum number of jobs already in queue ' + \
  512. self.server.default_queue
  513. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  514. def test_server_generic_user_limits_res_max(self):
  515. """
  516. Test max_queued_res for any user at the server level.
  517. """
  518. a = {"max_queued_res.ncpus":
  519. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  520. attrs = {'Resource_List.select': '1:ncpus=1'}
  521. emsg = 'qsub: would exceed per-user limit on resource ncpus in complex'
  522. self.common_limit_test(True, a, attrs, exp_err=emsg)
  523. def test_server_user_limits_res_max(self):
  524. """
  525. Test max_queued_res for user pbsuser1 at the server level.
  526. """
  527. a = {"max_queued_res.ncpus":
  528. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  529. attrs = {'Resource_List.select': '1:ncpus=1'}
  530. errmsg = 'qsub: would exceed user ' + str(TST_USR) + \
  531. "'s limit on resource ncpus in complex"
  532. self.common_limit_test(True, a, attrs, exp_err=errmsg)
  533. def test_server_generic_group_limits_res_max(self):
  534. """
  535. Test max_queued_res for any group at the server level.
  536. """
  537. a = {"max_queued_res.ncpus":
  538. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  539. attrs = {'Resource_List.select': '1:ncpus=1'}
  540. msg = 'qsub: would exceed per-group limit on resource ncpus in complex'
  541. self.common_limit_test(True, a, attrs, exp_err=msg)
  542. def test_server_project_limits_res_max(self):
  543. """
  544. Test max_queued_res for project p1 at the server level.
  545. """
  546. a = {"max_queued_res.ncpus":
  547. "[p:p1=" + str(self.limit) + "]"}
  548. attrs = {ATTR_project: 'p1', 'Resource_List.select': '1:ncpus=1'}
  549. errmsg = "qsub: would exceed project p1's limit on resource ncpus in" \
  550. + " complex"
  551. self.common_limit_test(True, a, attrs, exp_err=errmsg)
  552. def test_server_generic_project_limits_res_max(self):
  553. """
  554. Test max_queued_res for any project at the server level.
  555. """
  556. a = {"max_queued_res.ncpus":
  557. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  558. attrs = {'Resource_List.select': '1:ncpus=1'}
  559. m = 'qsub: would exceed per-project limit on resource ncpus in complex'
  560. self.common_limit_test(True, a, attrs, exp_err=m)
  561. def test_server_group_limits_res_max(self):
  562. """
  563. Test max_queued_res for group pbsuser1 at the server level.
  564. """
  565. a = {"max_queued_res.ncpus":
  566. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  567. attrs = {'Resource_List.select': '1:ncpus=1'}
  568. errmsg = 'qsub: would exceed group ' + str(TSTGRP0) + \
  569. "'s limit on resource ncpus in complex"
  570. self.common_limit_test(True, a, attrs, exp_err=errmsg)
  571. def test_server_overall_limits_res_max(self):
  572. """
  573. Test max_queued_res for all entities at the server level.
  574. """
  575. a = {"max_queued_res.ncpus":
  576. "[o:PBS_ALL=" + str(self.limit) + "]"}
  577. attrs = {'Resource_List.select': '1:ncpus=1'}
  578. errmsg = 'qsub: would exceed limit on resource ncpus in complex'
  579. self.common_limit_test(True, a, attrs, exp_err=errmsg)
  580. def test_queue_generic_user_limits_res_max(self):
  581. """
  582. Test max_queued_res for all users for the default queue.
  583. """
  584. a = {"max_queued_res.ncpus":
  585. "[u:PBS_GENERIC=" + str(self.limit) + "]"}
  586. attrs = {ATTR_queue: self.server.default_queue,
  587. 'Resource_List.select': '1:ncpus=1'}
  588. errmsg = 'qsub: would exceed per-user limit on resource ncpus in' \
  589. + ' queue ' + self.server.default_queue
  590. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  591. def test_queue_user_limits_res_max(self):
  592. """
  593. Test max_queued_res for user pbsuser1 for the default queue.
  594. """
  595. a = {"max_queued_res.ncpus":
  596. "[u:" + str(TST_USR) + "=" + str(self.limit) + "]"}
  597. attrs = {ATTR_queue: self.server.default_queue,
  598. 'Resource_List.select': '1:ncpus=1'}
  599. errmsg = 'qsub: would exceed user ' + str(TST_USR) + \
  600. "'s limit on resource ncpus in queue " + \
  601. self.server.default_queue
  602. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  603. def test_queue_group_limits_res_max(self):
  604. """
  605. Test max_queued_res for group pbsuser1 for the default queue
  606. """
  607. a = {"max_queued_res.ncpus":
  608. "[g:" + str(TSTGRP0) + "=" + str(self.limit) + "]"}
  609. attrs = {ATTR_queue: self.server.default_queue,
  610. 'Resource_List.select': '1:ncpus=1'}
  611. errmsg = 'qsub: would exceed group ' + str(TSTGRP0) + \
  612. "'s limit on resource ncpus in queue " + self.server.default_queue
  613. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  614. def test_queue_generic_group_limits_res_max(self):
  615. """
  616. Test max_queued_res for any group for the default queue.
  617. """
  618. a = {"max_queued_res.ncpus":
  619. "[g:PBS_GENERIC=" + str(self.limit) + "]"}
  620. attrs = {ATTR_queue: self.server.default_queue,
  621. 'Resource_List.select': '1:ncpus=1'}
  622. errmsg = 'qsub: would exceed per-group limit on resource ncpus in' \
  623. + ' queue ' + self.server.default_queue
  624. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  625. def test_queue_project_limits_res_max(self):
  626. """
  627. Test max_queued_res for project p1 for the default queue.
  628. """
  629. a = {"max_queued_res.ncpus":
  630. "[p:p1=" + str(self.limit) + "]"}
  631. attrs = {ATTR_queue: self.server.default_queue,
  632. ATTR_project: 'p1', 'Resource_List.select': '1:ncpus=1'}
  633. errmsg = "qsub: would exceed project p1's limit on resource ncpus" + \
  634. ' in queue ' + self.server.default_queue
  635. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  636. def test_queue_generic_project_limits_res_max(self):
  637. """
  638. Test max_queued_res for any project for the default queue.
  639. """
  640. a = {"max_queued_res.ncpus":
  641. "[p:PBS_GENERIC=" + str(self.limit) + "]"}
  642. attrs = {ATTR_queue: self.server.default_queue,
  643. 'Resource_List.select': '1:ncpus=1'}
  644. errmsg = 'qsub: would exceed per-project limit on resource ncpus in' \
  645. + ' queue ' + self.server.default_queue
  646. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  647. def test_queue_overall_limits_res_max(self):
  648. """
  649. Test max_queued_res for any entity for the default queue.
  650. """
  651. a = {"max_queued_res.ncpus":
  652. "[o:PBS_ALL=" + str(self.limit) + "]"}
  653. attrs = {ATTR_queue: self.server.default_queue,
  654. 'Resource_List.select': '1:ncpus=1'}
  655. errmsg = 'qsub: would exceed limit on resource ncpus in queue ' \
  656. + self.server.default_queue
  657. self.common_limit_test(False, a, attrs, exp_err=errmsg)
  658. def test_qalter_resource(self):
  659. """
  660. Test that qaltering a job's resource list is accounted
  661. """
  662. res_name = 'res_long'
  663. res_attr = {ATTR_RESC_TYPE: 'long', ATTR_RESC_FLAG: 'q'}
  664. rc = self.server.manager(MGR_CMD_CREATE, RSC, res_attr, id=res_name)
  665. a = {"max_queued_res." + res_name:
  666. "[o:PBS_ALL=" + str(self.limit) + "]"}
  667. qname = self.server.default_queue
  668. self.server.manager(MGR_CMD_SET, QUEUE, a, qname)
  669. self.server.manager(MGR_CMD_SET, SERVER, {ATTR_scheduling: 'False'})
  670. attrs = {ATTR_queue: qname, 'Resource_List.' + res_name: 9}
  671. j_1 = Job(TST_USR, attrs)
  672. J_1_id = self.server.submit(j_1)
  673. try:
  674. attrs = {ATTR_queue: qname, 'Resource_List.' + res_name: 2}
  675. j_2 = Job(TST_USR, attrs)
  676. self.server.submit(j_2)
  677. except PbsSubmitError as e:
  678. exp_err = 'qsub: would exceed limit on resource ' + res_name + \
  679. ' in queue ' + qname
  680. if e.msg[0] != exp_err:
  681. raise self.failureException("rcvd unexpected err message: "
  682. + e.msg[0])
  683. attribs = {'Resource_List.' + res_name: 8}
  684. self.server.alterjob(J_1_id, attribs)
  685. self.server.expect(JOB, attribs, id=J_1_id)
  686. self.server.submit(j_2)
  687. try:
  688. attrs = {ATTR_queue: qname, 'Resource_List.' + res_name: 1}
  689. j_3 = Job(TST_USR, attrs)
  690. self.server.submit(j_3)
  691. except PbsSubmitError as e:
  692. exp_err = 'qsub: would exceed limit on resource ' + res_name + \
  693. ' in queue ' + qname
  694. if e.msg[0] != exp_err:
  695. raise self.failureException("rcvd unexpected err message: "
  696. + e.msg[0])
  697. def test_multiple_queued_limits(self):
  698. defqname = self.server.default_queue
  699. q2name = 'q2'
  700. a = OrderedDict()
  701. a['queue_type'] = 'execution'
  702. a['enabled'] = 'True'
  703. a['started'] = 'True'
  704. self.server.manager(MGR_CMD_CREATE, QUEUE, a, id=q2name)
  705. a = {"queued_jobs_threshold":
  706. "[u:PBS_GENERIC=10]"}
  707. self.server.manager(MGR_CMD_SET, SERVER, a)
  708. a = {"queued_jobs_threshold":
  709. "[u:PBS_GENERIC=5]"}
  710. self.server.manager(MGR_CMD_SET, QUEUE, a, defqname)
  711. jd = Job(TST_USR, {ATTR_queue: defqname})
  712. j2 = Job(TST_USR, {ATTR_queue: q2name})
  713. jid = self.server.submit(jd)
  714. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  715. for _ in range(5):
  716. jd = Job(TST_USR, {ATTR_queue: defqname})
  717. self.server.submit(jd)
  718. try:
  719. self.server.submit(jd)
  720. except PbsSubmitError as e:
  721. exp_err = "qsub: would exceed queue generic's per-user limit " + \
  722. "of jobs in 'Q' state"
  723. if e.msg[0] != exp_err:
  724. raise self.failureException("rcvd unexpected err message: "
  725. + e.msg[0])
  726. else:
  727. self.assertFalse(True, "Job violating limits got submitted.")
  728. for _ in range(5):
  729. self.server.submit(j2)
  730. try:
  731. self.server.submit(j2)
  732. except PbsSubmitError as e:
  733. exp_err = "qsub: would exceed complex's per-user limit of " + \
  734. "jobs in 'Q' state"
  735. if e.msg[0] != exp_err:
  736. raise self.failureException("rcvd unexpected err message: "
  737. + e.msg[0])
  738. else:
  739. self.assertFalse(True, "Job violating limits got submitted.")