pbs_qsub_remove_files.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 TestQsub_remove_files(TestFunctional):
  38. """
  39. validate qsub remove file option.
  40. """
  41. def test_remove_file_when_job_succeeds(self):
  42. """
  43. submit a sleep job and make sure that the std_files
  44. are getting deleted when remove_files option is used.
  45. """
  46. j = Job(TEST_USER, attrs={ATTR_R: 'oe'})
  47. j.set_sleep_time(1)
  48. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  49. jid = self.server.submit(j, submit_dir=sub_dir)
  50. self.server.expect(JOB, {ATTR_R: 'oe'}, id=jid)
  51. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  52. file_count = len([name for name in os.listdir(
  53. sub_dir) if os.path.isfile(os.path.join(sub_dir, name))])
  54. self.assertEqual(0, file_count)
  55. def test_remove_file_sandbox_private(self):
  56. """
  57. submit a sleep job and make sure that the std_files
  58. are getting deleted when remove_files option is used
  59. and job is submitted with -Wsandbox=private.
  60. """
  61. j = Job(TEST_USER, attrs={ATTR_R: 'oe', ATTR_sandbox: 'private'})
  62. j.set_sleep_time(1)
  63. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  64. jid = self.server.submit(j, submit_dir=sub_dir)
  65. self.server.expect(JOB, {ATTR_R: 'oe'}, id=jid)
  66. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  67. file_count = len([name for name in os.listdir(
  68. sub_dir) if os.path.isfile(os.path.join(sub_dir, name))])
  69. self.assertEqual(0, file_count)
  70. def test_remove_files_output_file(self):
  71. """
  72. submit a job with -Ro option and make sure the output file
  73. gets deleted after job finishes
  74. """
  75. j = Job(TEST_USER, attrs={ATTR_R: 'o'})
  76. j.set_sleep_time(1)
  77. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  78. jid = self.server.submit(j, submit_dir=sub_dir)
  79. self.server.expect(JOB, {ATTR_R: 'o'}, id=jid)
  80. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  81. for name in os.listdir(sub_dir):
  82. p = re.search('STDIN.e*', name)
  83. if p:
  84. self.logger.info('Match found: ' + p.group())
  85. else:
  86. self.assertTrue(False)
  87. file_count = len([name for name in os.listdir(
  88. sub_dir) if os.path.isfile(os.path.join(sub_dir, name))])
  89. self.assertEqual(1, file_count)
  90. def test_remove_files_error_file(self):
  91. """
  92. submit a job with -Re option and make sure the error file
  93. gets deleted after job finishes and works with direct_write
  94. """
  95. j = Job(TEST_USER, attrs={ATTR_k: 'de', ATTR_R: 'e'})
  96. j.set_sleep_time(1)
  97. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  98. mapping_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  99. self.mom.add_config(
  100. {'$usecp': self.server.hostname + ':' + sub_dir
  101. + ' ' + mapping_dir})
  102. self.mom.restart()
  103. jid = self.server.submit(j, submit_dir=sub_dir)
  104. self.server.expect(JOB, {ATTR_R: 'e'}, id=jid)
  105. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  106. for name in os.listdir(mapping_dir):
  107. p = re.search('STDIN.o*', name)
  108. if p:
  109. self.logger.info('Match found: ' + p.group())
  110. else:
  111. self.assertTrue(False)
  112. file_count = len([name for name in os.listdir(
  113. mapping_dir) if os.path.isfile(os.path.join(mapping_dir, name))])
  114. self.assertEqual(1, file_count)
  115. def test_remove_files_error_custom_path(self):
  116. """
  117. submit a sleep job and make sure that the files
  118. are getting deleted from custom path provided in
  119. -e and -o option when -Roe is set.
  120. """
  121. tmp_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  122. err_file = os.path.join(tmp_dir, 'error_file')
  123. out_file = os.path.join(tmp_dir, 'output_file')
  124. a = {ATTR_e: err_file, ATTR_o: out_file, ATTR_R: 'oe'}
  125. j = Job(TEST_USER, attrs=a)
  126. j.set_sleep_time(1)
  127. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  128. jid = self.server.submit(j, submit_dir=sub_dir)
  129. self.server.expect(JOB, {ATTR_R: 'oe'}, id=jid)
  130. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  131. file_count = len([name for name in os.listdir(
  132. tmp_dir) if os.path.isfile(os.path.join(tmp_dir, name))])
  133. self.assertEqual(0, file_count)
  134. def test_remove_files_error_custom_dir(self):
  135. """
  136. submit a sleep job and make sure that the files
  137. are getting deleted from custom directory path
  138. provided in -e and -o option when -Roe is set.
  139. """
  140. tmp_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  141. a = {ATTR_e: tmp_dir, ATTR_o: tmp_dir, ATTR_R: 'oe'}
  142. j = Job(TEST_USER, attrs=a)
  143. j.set_sleep_time(1)
  144. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  145. jid = self.server.submit(j, submit_dir=sub_dir)
  146. self.server.expect(JOB, {ATTR_R: 'oe'}, id=jid)
  147. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  148. file_count = len([name for name in os.listdir(
  149. tmp_dir) if os.path.isfile(os.path.join(tmp_dir, name))])
  150. self.assertEqual(0, file_count)
  151. def test_remove_files_default_qsub_arguments(self):
  152. """
  153. submit a sleep job and make sure that the std_files
  154. are removed after the job finishes from submission
  155. directory when default_qsub_arguments is set to -Roe.
  156. """
  157. j = Job(TEST_USER)
  158. j.set_sleep_time(1)
  159. self.server.manager(MGR_CMD_SET, SERVER, {
  160. 'default_qsub_arguments': '-Roe'})
  161. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  162. jid = self.server.submit(j, submit_dir=sub_dir)
  163. self.server.expect(JOB, {ATTR_R: 'oe'}, id=jid)
  164. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  165. file_count = len([name for name in os.listdir(
  166. sub_dir) if os.path.isfile(os.path.join(sub_dir, name))])
  167. self.assertEqual(0, file_count)
  168. def test_remove_file_when_job_fails(self):
  169. """
  170. submit a job using unavailable binary and make sure
  171. that the std_files are available when remove_files
  172. option is used.
  173. """
  174. j = Job(TEST_USER, attrs={ATTR_R: 'oe'})
  175. j.set_execargs('sleep', 1)
  176. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  177. jid = self.server.submit(j, submit_dir=sub_dir)
  178. self.server.expect(JOB, 'job_state', op=UNSET, id=jid)
  179. file_count = len([name for name in os.listdir(
  180. sub_dir) if os.path.isfile(os.path.join(sub_dir, name))])
  181. self.assertEqual(2, file_count)
  182. def test_qalter_remove_files(self):
  183. """
  184. submit a job and make sure that it in queued state.
  185. alter the job with -Roe and check whether it is
  186. reflecting in qstat -f output.
  187. """
  188. mydate = int(time.time()) + 60
  189. j = Job(TEST_USER)
  190. attribs = {
  191. ATTR_a: time.strftime(
  192. '%m%d%H%M',
  193. time.localtime(
  194. float(mydate)))}
  195. j.set_attributes(attribs)
  196. jid = self.server.submit(j)
  197. attribs = {ATTR_R: 'oe'}
  198. try:
  199. self.server.alterjob(jid, attribs)
  200. if self.server.expect(JOB, {'job_state': 'W'},
  201. id=jid):
  202. self.server.expect(JOB, attribs,
  203. id=jid)
  204. except PbsAlterError as e:
  205. print str(e)
  206. def test_qalter_direct_write_error(self):
  207. """
  208. submit a job and after it starts running alter
  209. the job with -Roe and check whether expected
  210. error message appears
  211. """
  212. j = Job(TEST_USER)
  213. jid = self.server.submit(j)
  214. attribs = {ATTR_R: 'oe'}
  215. self.server.expect(JOB, {'job_state': 'R'})
  216. try:
  217. self.server.alterjob(jid, attribs)
  218. except PbsAlterError as e:
  219. self.assertTrue(
  220. 'Cannot modify attribute while job'
  221. ' running Remove_Files' in e.msg[0])
  222. def test_remove_file_job_array(self):
  223. """
  224. submit job array script that makes subjobs to exit with 0 except for
  225. subjob[2] and make sure that the std_files for only subjob[2] are
  226. available when remove_files option is used.
  227. """
  228. script = \
  229. "#!/bin/sh\n"\
  230. "/bin/sleep 3;\n"\
  231. "if [ $PBS_ARRAY_INDEX -eq 2 ]; then\n"\
  232. "exit 1; fi; exit 0;"
  233. j = Job(TEST_USER, attrs={ATTR_R: 'oe', ATTR_J: '1-3'},
  234. jobname='JOB_NAME')
  235. j.create_script(script)
  236. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  237. jid = self.server.submit(j, submit_dir=sub_dir)
  238. self.server.expect(JOB, {ATTR_state: 'B'}, id=jid)
  239. self.server.expect(JOB, ATTR_state, op=UNSET, id=jid)
  240. file_list = [name for name in os.listdir(
  241. sub_dir) if os.path.isfile(os.path.join(sub_dir, name))]
  242. self.assertEqual(2, len(file_list), "expected 2 std files")
  243. idn = jid[:jid.find('[]')]
  244. std_files = ['JOB_NAME.o' + idn + '.2', 'JOB_NAME.e' + idn + '.2']
  245. for f_name in std_files:
  246. if f_name not in file_list:
  247. raise self.failureException("std file " + f_name
  248. + " not found")
  249. def test_remove_file_custom_path_job_array(self):
  250. """
  251. submit job array script that makes subjobs to exit with 0 except for
  252. subjob[2] and make sure that the std_files for only subjob[2] are
  253. available in custom directory when remove_files option is used with
  254. -o and -e options.
  255. """
  256. script = \
  257. "#!/bin/sh\n"\
  258. "/bin/sleep 3;\n"\
  259. "if [ $PBS_ARRAY_INDEX -eq 2 ]; then\n"\
  260. "exit 1; fi; exit 0;"
  261. tmp_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  262. j = Job(TEST_USER, attrs={ATTR_e: tmp_dir, ATTR_o: tmp_dir,
  263. ATTR_R: 'oe', ATTR_J: '1-3'})
  264. j.create_script(script)
  265. sub_dir = self.du.mkdtemp(uid=TEST_USER.uid)
  266. jid = self.server.submit(j, submit_dir=sub_dir)
  267. self.server.expect(JOB, {ATTR_state: 'B'}, id=jid)
  268. self.server.expect(JOB, ATTR_state, op=UNSET, id=jid)
  269. file_list = [name for name in os.listdir(
  270. tmp_dir) if os.path.isfile(os.path.join(tmp_dir, name))]
  271. self.assertEqual(2, len(file_list), "expected 2 std files")
  272. subj2_id = j.create_subjob_id(jid, 2)
  273. std_files = [subj2_id + '.OU', subj2_id + '.ER']
  274. for f_name in std_files:
  275. if f_name not in file_list:
  276. raise self.failureException("std file " + f_name
  277. + " not found")