pbs_eligible_time.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. from ptl.utils.pbs_logutils import PBSLogUtils
  38. class TestEligibleTime(TestFunctional):
  39. """
  40. Test suite for eligible time tests
  41. """
  42. def setUp(self):
  43. TestFunctional.setUp(self)
  44. a = {'eligible_time_enable': 'True'}
  45. self.server.manager(MGR_CMD_SET, SERVER, a)
  46. def test_qsub_a(self):
  47. """
  48. Test that jobs requsting qsub -a <time> do not accrue
  49. eligible time until <time> is reached
  50. """
  51. a = {'scheduling': 'False'}
  52. self.server.manager(MGR_CMD_SET, SERVER, a)
  53. now = int(time.time())
  54. now += 120
  55. s = time.strftime("%H%M.%S", time.localtime(now))
  56. J1 = Job(TEST_USER, attrs={ATTR_a: s})
  57. jid = self.server.submit(J1)
  58. self.server.expect(JOB, {ATTR_state: 'W'}, id=jid)
  59. self.logger.info("Sleeping 120s till job is out of 'W' state")
  60. time.sleep(120)
  61. self.server.expect(JOB, {ATTR_state: 'Q'}, id=jid)
  62. # eligible_time should really be 0, but just incase there is some
  63. # lag on some slow systems, add a little leeway.
  64. self.server.expect(JOB, {'eligible_time': 10}, op=LT)
  65. def test_job_array(self):
  66. """
  67. Test that a job array switches from accruing eligible time
  68. to ineligible time when its last subjob starts running
  69. """
  70. logutils = PBSLogUtils()
  71. a = {'resources_available.ncpus': 2}
  72. self.server.manager(MGR_CMD_SET, NODE, a, id=self.mom.shortname)
  73. a = {'log_events': 2047}
  74. self.server.manager(MGR_CMD_SET, SERVER, a)
  75. J1 = Job(TEST_USER, attrs={ATTR_J: '1-3'})
  76. J1.set_sleep_time(20)
  77. jid = self.server.submit(J1)
  78. jid_short = jid.split('[')[0]
  79. sjid1 = jid_short + '[1]'
  80. sjid2 = jid_short + '[2]'
  81. sjid3 = jid_short + '[3]'
  82. # Capture the time stamp when subjob 1 starts run. Accrue type changes
  83. # to eligible time
  84. msg1 = J1.create_subjob_id(jid, 1) + ";Job Run at request of Scheduler"
  85. m1 = self.server.log_match(msg1)
  86. t1 = logutils.convert_date_time(m1[1].split(';')[0])
  87. self.server.expect(JOB, {ATTR_state: 'R'}, id=sjid1, extend='t')
  88. self.server.expect(JOB, {ATTR_state: 'R'}, id=sjid2, extend='t')
  89. self.server.expect(JOB, {ATTR_state: 'Q'}, id=sjid3, extend='t')
  90. # accrue_type = 2 is eligible_time
  91. self.server.expect(JOB, {'accrue_type': 2}, id=jid)
  92. self.logger.info("subjobs 1 and 2 finished; subjob 3 must run now")
  93. self.server.expect(JOB, {ATTR_state: 'R'}, id=sjid3,
  94. extend='t', offset=20)
  95. self.server.expect(JOB, {'accrue_type': 1}, id=jid)
  96. # Capture the time stamp when subjob 3 starts run. Accrue type changes
  97. # to ineligible time. eligible_time calculation is completed.
  98. msg2 = J1.create_subjob_id(jid, 3) + ";Job Run at request of Scheduler"
  99. m2 = self.server.log_match(msg2)
  100. t2 = logutils.convert_date_time(m2[1].split(';')[0])
  101. eligible_time = t2 - t1
  102. m1 = jid + ";Accrue type has changed to ineligible_time, "
  103. m1 += "previous accrue type was eligible_time"
  104. m2 = m1 + " for %d secs, " % eligible_time
  105. # Format timedelta object as it does not print a preceding 0 for
  106. # hours in HH:MM:SS
  107. m2 += "total eligible_time={:0>8}".format(
  108. datetime.timedelta(seconds=eligible_time))
  109. try:
  110. self.server.log_match(m2)
  111. except PtlLogMatchError as e:
  112. # In some slow machines, there is a delay observed between
  113. # job run and accrue type change.
  114. # Checking if log_match failed because eligible_time
  115. # value was off only by a few seconds(5 seconds).
  116. # This is done to acommodate differences in the eligible
  117. # time calculated by the test and the eligible time
  118. # calculated by PBS.
  119. # If the eligible_time value was off by > 5 seconds, test fails.
  120. match = self.server.log_match(m1)
  121. e_time = re.search('(\d+) secs', match[1])
  122. if e_time:
  123. self.logger.info("Checking if log_match failed because "
  124. "the eligible_time value was off by "
  125. "a few seconds, but within the allowed "
  126. "range (5 secs). Expected %d secs Got: %s"
  127. % (eligible_time, e_time.group(1)))
  128. if int(e_time.group(1)) - eligible_time > 5:
  129. raise PtlLogMatchError(rc=1, rv=False, msg=e.msg)
  130. else:
  131. raise PtlLogMatchError(rc=1, rv=False, msg=e.msg)