pbs_stf.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  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 TestSTF(TestFunctional):
  38. """
  39. The goal for this test suite is to contain basic STF tests that use
  40. the following timed events that cause the STF job to shrink its walltime:
  41. - dedicated time
  42. - primetime (with backfill_prime)
  43. - reservations
  44. """
  45. def setUp(self):
  46. TestFunctional.setUp(self)
  47. a = {'resources_available.ncpus': 1}
  48. self.server.manager(MGR_CMD_SET, NODE, a, id=self.mom.shortname)
  49. def set_primetime(self, ptime_start, ptime_end):
  50. """
  51. Set primttime to start at ptime_start and end at ptime_end.
  52. Remove all default holidays because will cause a test to fail on
  53. a holiday
  54. """
  55. # Delete all entries in the holidays file
  56. self.scheduler.holidays_delete_entry('a')
  57. # Without the YEAR entry primetime is considered to be 24 hours.
  58. p_yy = time.strftime('%Y', time.localtime(ptime_start))
  59. self.scheduler.holidays_set_year(p_yy)
  60. p_day = 'weekday'
  61. p_hhmm = time.strftime('%H%M', time.localtime(ptime_start))
  62. np_hhmm = time.strftime('%H%M', time.localtime(ptime_end))
  63. self.scheduler.holidays_set_day(p_day, p_hhmm, np_hhmm)
  64. p_day = 'saturday'
  65. self.scheduler.holidays_set_day(p_day, p_hhmm, np_hhmm)
  66. p_day = 'sunday'
  67. self.scheduler.holidays_set_day(p_day, p_hhmm, np_hhmm)
  68. def submit_resv(self, resv_start, ncpus, resv_dur):
  69. """
  70. Submit a reservation and expect it to be confirmed
  71. """
  72. a = {'Resource_List.select': '1:ncpus=%d' % ncpus,
  73. 'Resource_List.place': 'free',
  74. 'reserve_start': int(resv_start),
  75. 'reserve_duration': int(resv_dur)
  76. }
  77. r = Reservation(TEST_USER, attrs=a)
  78. rid = self.server.submit(r)
  79. a = {'reserve_state': (MATCH_RE, 'RESV_CONFIRMED|2')}
  80. self.server.expect(RESV, a, id=rid)
  81. def submit_jq(self, ncpus):
  82. """
  83. Submit a job and expect it to stay queued
  84. """
  85. a = {'Resource_List.select': '1:ncpus=%d' % ncpus,
  86. 'Resource_List.place': 'free',
  87. 'Resource_List.walltime': '01:00:00'
  88. }
  89. j = Job(TEST_USER, attrs=a)
  90. jid = self.server.submit(j)
  91. self.server.expect(JOB, ATTR_comment, op=SET)
  92. self.server.expect(JOB, {ATTR_state: 'Q'}, id=jid)
  93. def test_t_4_1_3(self):
  94. """
  95. Test shrink to fit by setting a dedicated time that started 20 minutes
  96. ago with a duration of 2 hours. Submit a job that can run for as
  97. short as 1 minute and as long as 20 hours. Submit a second job to the
  98. dedicated time queue. Expect the first job to be in Q state and the
  99. second job in R state with a walltime that's less than or equal to
  100. 1 hr 40 mins and greater than or equal to 1 min.
  101. """
  102. qname = 'ded_time'
  103. a = {'queue_type': 'execution', 'enabled': 'True', 'started': 'True'}
  104. self.server.manager(MGR_CMD_CREATE, QUEUE, a, qname)
  105. now = int(time.time())
  106. self.scheduler.add_dedicated_time(start=now - 1200, end=now + 6000)
  107. j = Job(TEST_USER)
  108. a = {'Resource_List.max_walltime': '20:00:00',
  109. 'Resource_List.min_walltime': '00:01:00'}
  110. j.set_attributes(a)
  111. jid = self.server.submit(j)
  112. self.server.expect(JOB, {'job_state': 'Q'}, id=jid)
  113. a = {'queue': 'ded_time',
  114. 'Resource_List.max_walltime': '20:00:00',
  115. 'Resource_List.min_walltime': '00:01:00'}
  116. j = Job(TEST_USER, attrs=a)
  117. j2id = self.server.submit(j)
  118. self.server.expect(JOB, {'job_state': 'R'}, id=j2id)
  119. self.server.expect(JOB, {'job_state': 'Q'}, id=jid)
  120. attr = {'Resource_List.walltime': (LE, '01:40:00')}
  121. self.server.expect(JOB, attr, id=j2id)
  122. attr = {'Resource_List.walltime': (GE, '00:01:00')}
  123. self.server.expect(JOB, attr, id=j2id)
  124. sw = self.server.status(JOB, 'Resource_List.walltime', id=j2id)
  125. wt = sw[0]['Resource_List.walltime']
  126. wt2 = wt
  127. # Make walltime given by qstat to agree with format in sched_logs.
  128. # A leading '0' is removed in the hour string.
  129. hh = wt.split(':')[0]
  130. if len(hh) == 2 and hh[0] == '0':
  131. wt2 = wt[1:]
  132. msg = "Job;%s;Job will run for duration=[%s|%s]" % (j2id, wt, wt2)
  133. self.scheduler.log_match(msg, regexp=True, max_attempts=5, interval=2)
  134. def test_t_4_1_1(self):
  135. """
  136. Test shrink to fit by setting a dedicated time that starts 1 hour
  137. from now for 1 hour Submit a job that can run for as low as 10 minutes
  138. and as long as 10 hours. Expect the job in R state with a walltime
  139. that is less than or equal to 1 hour and greater than or equal to
  140. 10 minutes.
  141. """
  142. now = int(time.time())
  143. self.scheduler.add_dedicated_time(start=now + 3600, end=now + 7200)
  144. a = {'Resource_List.max_walltime': '10:00:00',
  145. 'Resource_List.min_walltime': '00:10:00'}
  146. j = Job(TEST_USER, attrs=a)
  147. jid = self.server.submit(j)
  148. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  149. attr = {'Resource_List.walltime': (LE, '01:00:00')}
  150. self.server.expect(JOB, attr, id=jid)
  151. attr = {'Resource_List.walltime': (GE, '00:10:00')}
  152. self.server.expect(JOB, attr, id=jid)
  153. def test_t_4_2_1(self):
  154. """
  155. Test shrink to fit by setting primetime that starts 4 hours from now
  156. and ends 12 hours from now and scheduler's backfill_prime is true.
  157. A regular job is submitted which goes into Q state. Then a STF job
  158. with a max_walltime of 10:00:00 is able to run with a shrunk walltime
  159. of less than or equal to 4:00:00.
  160. """
  161. now = time.time()
  162. ptime_start = now + 14400
  163. ptime_end = now + 43200
  164. self.set_primetime(ptime_start, ptime_end)
  165. self.scheduler.set_sched_config({'backfill_prime': 'True'})
  166. a = {'Resource_List.ncpus': '1'}
  167. j = Job(TEST_USER, attrs=a)
  168. jid = self.server.submit(j)
  169. self.server.expect(JOB, {'job_state': 'Q'}, id=jid)
  170. a2 = {'Resource_List.max_walltime': '10:00:00',
  171. 'Resource_List.min_walltime': '00:10:00'}
  172. j = Job(TEST_USER, attrs=a2)
  173. j2id = self.server.submit(j)
  174. self.server.expect(JOB, {'job_state': 'R'}, id=j2id)
  175. self.server.expect(JOB, {'job_state': 'Q'}, id=jid)
  176. attr = {'Resource_List.walltime': (LE, '04:00:00')}
  177. self.server.expect(JOB, attr, id=j2id)
  178. attr = {'Resource_List.walltime': (GE, '00:10:00')}
  179. self.server.expect(JOB, attr, id=j2id)
  180. def test_t_4_2_3(self):
  181. """
  182. Test shrink to fit by setting primetime that starts 4 hours from now
  183. and ends 12 hours from now and scheduler's backfill_prime is true and
  184. prime_spill is 1 hour. A STF job with a min_walltime of 00:10:00 and
  185. with a max_walltime of 10:00:00 gets queued with a shrunk walltime
  186. of less than or equal to 05:00:00.
  187. """
  188. now = time.time()
  189. ptime_start = now + 14400
  190. ptime_end = now + 43200
  191. self.set_primetime(ptime_start, ptime_end)
  192. self.scheduler.set_sched_config({'backfill_prime': 'True',
  193. 'prime_spill': '01:00:00'})
  194. a2 = {'Resource_List.max_walltime': '10:00:00',
  195. 'Resource_List.min_walltime': '00:10:00'}
  196. j = Job(TEST_USER, attrs=a2)
  197. jid = self.server.submit(j)
  198. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  199. attr = {'Resource_List.walltime': (LE, '05:00:00')}
  200. self.server.expect(JOB, attr, id=jid)
  201. attr = {'Resource_List.walltime': (GE, '00:10:00')}
  202. self.server.expect(JOB, attr, id=jid)
  203. def test_t_4_2_4(self):
  204. """
  205. Test shrink to fit by setting primetime that started 22 minutes ago
  206. and ends 5:38 hours from now and scheduler's backfill_prime is true and
  207. prime_spill is 1 hour. A STF job with a min_walltime of 00:01:00 and
  208. with a max_walltime of 20:00:00 gets queued with a shrunk walltime
  209. of less than or equal to 06:38:00.
  210. """
  211. now = time.time()
  212. ptime_start = now - 1320
  213. ptime_end = now + 20280
  214. self.set_primetime(ptime_start, ptime_end)
  215. self.scheduler.set_sched_config({'backfill_prime': 'True',
  216. 'prime_spill': '01:00:00'})
  217. a = {'Resource_List.max_walltime': '20:00:00',
  218. 'Resource_List.min_walltime': '00:01:00'}
  219. j = Job(TEST_USER, attrs=a)
  220. jid = self.server.submit(j)
  221. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  222. attr = {'Resource_List.walltime': (LE, '06:38:00')}
  223. self.server.expect(JOB, attr, id=jid)
  224. attr = {'Resource_List.walltime': (GE, '00:01:00')}
  225. self.server.expect(JOB, attr, id=jid)
  226. def test_t_4_3_1(self):
  227. """
  228. Test shrink to fit by creating 16 reservations, say from R110 to R125,
  229. with R117, R121, R124 having ncpus=3, all others having ncpus=2.
  230. Duration of 10 min with 30 min difference between consecutive
  231. reservation. A STF job will shrink its walltime to less than or
  232. equal to 4 hours.
  233. """
  234. a = {'resources_available.ncpus': 3}
  235. self.server.manager(MGR_CMD_SET, NODE, a, id=self.mom.shortname)
  236. now = int(time.time())
  237. resv_dur = 600
  238. for i in range(1, 8):
  239. resv_start = now + i * 1800
  240. self.submit_resv(resv_start, 2, resv_dur)
  241. resv_start = now + 8 * 1800
  242. self.submit_resv(resv_start, 3, resv_dur)
  243. for i in range(9, 12):
  244. resv_start = now + i * 1800
  245. self.submit_resv(resv_start, 2, resv_dur)
  246. resv_start = now + 12 * 1800
  247. self.submit_resv(resv_start, 3, resv_dur)
  248. for i in range(13, 15):
  249. resv_start = now + i * 1800
  250. self.submit_resv(resv_start, 2, resv_dur)
  251. resv_start = now + 15 * 1800
  252. self.submit_resv(resv_start, 3, resv_dur)
  253. resv_start = now + 16 * 1800
  254. self.submit_resv(resv_start, 2, resv_dur)
  255. a = {'Resource_List.max_walltime': '10:00:00',
  256. 'Resource_List.min_walltime': '00:10:00'}
  257. j = Job(TEST_USER, attrs=a)
  258. jid = self.server.submit(j)
  259. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  260. attr = {'Resource_List.walltime': (LE, '04:00:00')}
  261. self.server.expect(JOB, attr, id=jid)
  262. attr = {'Resource_List.walltime': (GE, '00:10:00')}
  263. self.server.expect(JOB, attr, id=jid)
  264. def test_t_4_3_6(self):
  265. """
  266. Test shrink to fit by creating one reservation having ncpus=1,
  267. starting in 3 min. with a duration of two hours. A preempted STF job
  268. with min_walltime of 2 min. and max_walltime of 2 hours will stay
  269. suspended after higher priority job goes away if its
  270. min_walltime can't be satisfied.
  271. """
  272. self.skip_test('Skipping test due to PP-1049')
  273. qname = 'highp'
  274. a = {'queue_type': 'execution', 'enabled': 'True', 'started': 'True',
  275. 'priority': '150'}
  276. self.server.manager(MGR_CMD_CREATE, QUEUE, a, qname)
  277. now = int(time.time())
  278. resv_dur = 7200
  279. resv_start = now + 180
  280. d = self.submit_resv(resv_start, 1, resv_dur)
  281. self.assertTrue(d)
  282. a = {'Resource_List.max_walltime': '02:00:00',
  283. 'Resource_List.min_walltime': '00:02:00'}
  284. j = Job(TEST_USER, attrs=a)
  285. jid = self.server.submit(j)
  286. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  287. attr = {'Resource_List.walltime': (LE, '00:03:00')}
  288. self.server.expect(JOB, attr, id=jid)
  289. attr = {'Resource_List.walltime': (GE, '00:02:00')}
  290. self.server.expect(JOB, attr, id=jid)
  291. # The sleep below will leave less than 2 minutes window for jid
  292. # after j2id is deleted. The min_walltime of jid can't be
  293. # satisfied and jid will stay in S state.
  294. self.logger.info("Sleeping 65s to leave less than 2m before resv")
  295. time.sleep(65)
  296. a = {'queue': 'highp', 'Resource_List.select': '1:ncpus=1',
  297. 'Resource_List.walltime': '00:01:00'}
  298. j = Job(TEST_USER, attrs=a)
  299. j2id = self.server.submit(j)
  300. self.server.expect(JOB, {'job_state': 'R'}, id=j2id)
  301. self.server.expect(JOB, {'job_state': 'S'}, id=jid)
  302. self.server.delete(j2id)
  303. t = int(time.time())
  304. a = {'scheduling': 'True'}
  305. self.server.manager(MGR_CMD_SET, SERVER, a)
  306. self.scheduler.log_match("Leaving Scheduling Cycle", starttime=t,
  307. max_attempts=5)
  308. self.server.expect(JOB, {'job_state': 'S'}, id=jid)
  309. def test_t_4_3_8(self):
  310. """
  311. Test shrink to fit by submitting a STF job and then creating a
  312. reservation having ncpus=1 that overlaps with the job. The
  313. reservation is denied.
  314. """
  315. a = {'Resource_List.max_walltime': '02:00:00',
  316. 'Resource_List.min_walltime': '00:02:00'}
  317. j = Job(TEST_USER, attrs=a)
  318. jid = self.server.submit(j)
  319. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  320. now = int(time.time())
  321. resv_start = now + 300
  322. resv_dur = 7200
  323. a = {'Resource_List.select': '1:ncpus=1',
  324. 'Resource_List.place': 'free',
  325. 'reserve_start': resv_start,
  326. 'reserve_duration': resv_dur
  327. }
  328. r = Reservation(TEST_USER, attrs=a)
  329. rid1 = self.server.submit(r)
  330. self.server.log_match(rid1 + ";reservation deleted", max_attempts=10)
  331. self.server.delete(jid, wait=True)
  332. a = {'Resource_List.select': '1:ncpus=1'}
  333. j = Job(TEST_USER, attrs=a)
  334. j2id = self.server.submit(j)
  335. self.server.expect(JOB, {'job_state': 'R'}, id=j2id)
  336. resv_start = now + 300
  337. resv_dur = 7200
  338. a = {'Resource_List.select': '1:ncpus=1',
  339. 'Resource_List.place': 'free',
  340. 'reserve_start': resv_start,
  341. 'reserve_duration': resv_dur
  342. }
  343. r = Reservation(TEST_USER, attrs=a)
  344. rid2 = self.server.submit(r)
  345. self.server.log_match(rid2 + ";reservation deleted", max_attempts=10)
  346. def test_t_4_4_1(self):
  347. """
  348. Test shrink to fit by submitting top jobs as barrier.
  349. A STF job will shrink its walltime relative to top jobs
  350. """
  351. a = {'resources_available.ncpus': 3}
  352. self.server.manager(MGR_CMD_SET, NODE, a, id=self.mom.shortname)
  353. a = {'strict_ordering': 'true ALL', 'backfill': 'true ALL'}
  354. self.scheduler.set_sched_config(a)
  355. a = {'backfill_depth': '20'}
  356. self.server.manager(MGR_CMD_SET, SERVER, a, expect=True)
  357. a = {'Resource_List.select': '1:ncpus=2',
  358. 'Resource_List.place': 'free',
  359. 'Resource_List.walltime': '01:00:00'}
  360. j = Job(TEST_USER, attrs=a)
  361. jid = self.server.submit(j)
  362. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  363. for _ in range(1, 5):
  364. self.submit_jq(2)
  365. self.submit_jq(3)
  366. for _ in range(6, 8):
  367. self.submit_jq(2)
  368. self.submit_jq(3)
  369. for _ in range(9, 12):
  370. self.submit_jq(2)
  371. self.submit_jq(3)
  372. for _ in range(13, 16):
  373. self.submit_jq(2)
  374. a = {'Resource_List.max_walltime': '10:00:00',
  375. 'Resource_List.min_walltime': '00:10:00',
  376. 'Resource_List.select': '1:ncpus=1'}
  377. j = Job(TEST_USER, attrs=a)
  378. jid = self.server.submit(j)
  379. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  380. attr = {'Resource_List.walltime': (LE, '05:00:00')}
  381. self.server.expect(JOB, attr, id=jid)
  382. def test_t_4_5_1(self):
  383. """
  384. Test shrink to fit by setting primetime that started 45 minutes ago
  385. and ends 2:45 hours from now and dedicated time starting in 5 minutes
  386. ending in 1:45 hours. A STF job with a min_walltime of 00:01:00 and
  387. with a max_walltime of 20:00:00 gets queued with a shrunk walltime
  388. of less than or equal to 00:05:00.
  389. """
  390. now = int(time.time())
  391. ptime_start = now - 2700
  392. ptime_end = now + 9900
  393. p_day = 'weekday'
  394. p_hhmm = time.strftime('%H%M', time.localtime(ptime_start))
  395. np_hhmm = time.strftime('%H%M', time.localtime(ptime_end))
  396. self.scheduler.holidays_set_day(p_day, p_hhmm, np_hhmm)
  397. p_day = 'saturday'
  398. self.scheduler.holidays_set_day(p_day, p_hhmm, np_hhmm)
  399. p_day = 'sunday'
  400. self.scheduler.holidays_set_day(p_day, p_hhmm, np_hhmm)
  401. self.scheduler.add_dedicated_time(start=now + 300, end=now + 6300)
  402. a = {'Resource_List.max_walltime': '20:00:00',
  403. 'Resource_List.min_walltime': '00:01:00'}
  404. j = Job(TEST_USER, attrs=a)
  405. j2id = self.server.submit(j)
  406. self.server.expect(JOB, {'job_state': 'R'}, id=j2id)
  407. attr = {'Resource_List.walltime': (LE, '00:05:00')}
  408. self.server.expect(JOB, attr, id=j2id)
  409. def test_t_4_6_1(self):
  410. """
  411. Test shrink to fit by submitting a reservation and top jobs as
  412. barriers. A STF job will shrink its walltime relative to top jobs
  413. and reservations.
  414. """
  415. a = {'resources_available.ncpus': 3}
  416. self.server.manager(MGR_CMD_SET, NODE, a, id=self.mom.shortname)
  417. self.scheduler.set_sched_config({'strict_ordering': 'True ALL'})
  418. now = int(time.time())
  419. resv_start = now + 4200
  420. resv_dur = 900
  421. self.submit_resv(resv_start, 3, resv_dur)
  422. a = {'Resource_List.select': '1:ncpus=2',
  423. 'Resource_List.place': 'free',
  424. 'Resource_List.walltime': '00:15:00'}
  425. j = Job(TEST_USER, attrs=a)
  426. jid = self.server.submit(j)
  427. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  428. a = {'Resource_List.select': '1:ncpus=3',
  429. 'Resource_List.place': 'free',
  430. 'Resource_List.walltime': '00:15:00'}
  431. j = Job(TEST_USER, attrs=a)
  432. jid2 = self.server.submit(j)
  433. self.server.expect(JOB, {'job_state': 'Q'}, id=jid2)
  434. a = {'Resource_List.max_walltime': '02:00:00',
  435. 'Resource_List.min_walltime': '00:01:00',
  436. 'Resource_List.select': '1:ncpus=1'}
  437. j = Job(TEST_USER, attrs=a)
  438. jid3 = self.server.submit(j)
  439. self.server.expect(JOB, {'job_state': 'R'}, id=jid3)
  440. attr = {'Resource_List.walltime': (LE, '00:01:00')}
  441. self.server.expect(JOB, attr, id=jid3)
  442. def test_t_5_1_1(self):
  443. """
  444. STF job's min/max_walltime relative to resources_min/max.walltime
  445. setting on queue.
  446. """
  447. a = {'resources_min.walltime': '00:10:00',
  448. 'resources_max.walltime': '10:00:00'}
  449. self.server.manager(MGR_CMD_SET, QUEUE, a, id="workq", expect=True)
  450. a = {'Resource_List.max_walltime': '10:00:00',
  451. 'Resource_List.min_walltime': '00:09:00'}
  452. j = Job(TEST_USER, attrs=a)
  453. error_msg = 'Job violates queue and/or server resource limits'
  454. try:
  455. jid = self.server.submit(j)
  456. except PbsSubmitError as e:
  457. self.assertTrue(error_msg in e.msg[0])
  458. a = {'Resource_List.max_walltime': '00:09:00',
  459. 'Resource_List.min_walltime': '00:09:00'}
  460. j = Job(TEST_USER, attrs=a)
  461. try:
  462. jid = self.server.submit(j)
  463. except PbsSubmitError as e:
  464. self.assertTrue(error_msg in e.msg[0])
  465. a = {'Resource_List.max_walltime': '11:00:00',
  466. 'Resource_List.min_walltime': '00:10:00'}
  467. j = Job(TEST_USER, attrs=a)
  468. try:
  469. jid = self.server.submit(j)
  470. except PbsSubmitError as e:
  471. self.assertTrue(error_msg in e.msg[0])
  472. a = {'Resource_List.max_walltime': '11:00:00',
  473. 'Resource_List.min_walltime': '11:00:00'}
  474. j = Job(TEST_USER, attrs=a)
  475. try:
  476. jid = self.server.submit(j)
  477. except PbsSubmitError as e:
  478. self.assertTrue(error_msg in e.msg[0])
  479. a = {'Resource_List.max_walltime': '10:00:00',
  480. 'Resource_List.min_walltime': '00:10:00'}
  481. j = Job(TEST_USER, attrs=a)
  482. jid = self.server.submit(j)
  483. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  484. self.server.delete(jid)
  485. a = {'Resource_List.max_walltime': '00:10:00',
  486. 'Resource_List.min_walltime': '00:10:00'}
  487. j = Job(TEST_USER, attrs=a)
  488. jid = self.server.submit(j)
  489. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  490. self.server.delete(jid)
  491. a = {'Resource_List.max_walltime': '10:00:00',
  492. 'Resource_List.min_walltime': '10:00:00'}
  493. j = Job(TEST_USER, attrs=a)
  494. jid = self.server.submit(j)
  495. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  496. self.server.delete(jid)
  497. a = {'Resource_List.max_walltime': '09:00:00',
  498. 'Resource_List.min_walltime': '00:11:00'}
  499. j = Job(TEST_USER, attrs=a)
  500. jid = self.server.submit(j)
  501. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  502. def test_t_5_1_2(self):
  503. """
  504. STF job's max_walltime relative to resources_max.walltime
  505. setting on server.
  506. """
  507. a = {'resources_max.walltime': '15:00:00'}
  508. self.server.manager(MGR_CMD_SET, SERVER, a)
  509. a = {'Resource_List.max_walltime': '16:00:00',
  510. 'Resource_List.min_walltime': '00:20:00'}
  511. j = Job(TEST_USER, attrs=a)
  512. error_msg = 'Job violates queue and/or server resource limits'
  513. try:
  514. jid = self.server.submit(j)
  515. except PbsSubmitError as e:
  516. self.assertTrue(error_msg in e.msg[0])
  517. a = {'Resource_List.max_walltime': '16:00:00',
  518. 'Resource_List.min_walltime': '16:00:00'}
  519. j = Job(TEST_USER, attrs=a)
  520. try:
  521. jid = self.server.submit(j)
  522. except PbsSubmitError as e:
  523. self.assertTrue(error_msg in e.msg[0])
  524. a = {'Resource_List.max_walltime': '15:00:00',
  525. 'Resource_List.min_walltime': '15:00:00'}
  526. j = Job(TEST_USER, attrs=a)
  527. jid = self.server.submit(j)
  528. self.server.expect(JOB, {'job_state': 'R'}, id=jid)
  529. def test_t_5_2_1(self):
  530. """
  531. Setting resources_max.min_walltime on a queue.
  532. """
  533. a = {'resources_max.min_walltime': '10:00:00'}
  534. try:
  535. self.server.manager(MGR_CMD_SET, QUEUE, a, id="workq")
  536. except PbsManagerError as e:
  537. self.assertTrue('Resource limits can not be set for the resource'
  538. in e.msg[0])
  539. def test_t_5_2_2(self):
  540. """
  541. Setting resources_max.min_walltime on the server.
  542. """
  543. a = {'resources_max.min_walltime': '10:00:00'}
  544. try:
  545. self.server.manager(MGR_CMD_SET, SERVER, a)
  546. except PbsManagerError as e:
  547. self.assertTrue('Resource limits can not be set for the resource'
  548. in e.msg[0])
  549. def test_t_6(self):
  550. """
  551. Test to see that the min_walltime is not unset if the max_walltime
  552. is attempted to be set less than the min.
  553. """
  554. self.server.manager(MGR_CMD_SET, SERVER, {'scheduling': 'False'})
  555. a = {'Resource_List.min_walltime': 9, 'Resource_List.max_walltime': 60}
  556. J = Job(TEST_USER, attrs=a)
  557. jid = self.server.submit(J)
  558. try:
  559. self.server.alterjob(jid, {'Resource_List.max_walltime': 3})
  560. except PbsAlterError as e:
  561. self.assertTrue('\"min_walltime\" can not be greater'
  562. ' than \"max_walltime\"' in e.msg[0])
  563. self.server.expect(JOB, 'Resource_List.min_walltime', op=SET)
  564. self.server.expect(JOB, 'Resource_List.max_walltime', op=SET)
  565. try:
  566. self.server.alterjob(jid, {'Resource_List.min_walltime': 180})
  567. except PbsAlterError as e:
  568. self.assertTrue('\"min_walltime\" can not be greater'
  569. ' than \"max_walltime\"' in e.msg[0])
  570. self.server.expect(JOB, 'Resource_List.min_walltime', op=SET)
  571. self.server.expect(JOB, 'Resource_List.max_walltime', op=SET)
  572. try:
  573. a = {'Resource_List.min_walltime': 60,
  574. 'Resource_List.max_walltime': 30}
  575. self.server.alterjob(jid, a)
  576. except PbsAlterError as e:
  577. self.assertTrue('\"min_walltime\" can not be greater'
  578. ' than \"max_walltime\"' in e.msg[0])
  579. self.server.expect(JOB, 'Resource_List.min_walltime', op=SET)
  580. self.server.expect(JOB, 'Resource_List.max_walltime', op=SET)