| #!/usr/bin/python |
| # |
| |
| # Copyright (C) 2012 Google Inc. |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: |
| # |
| # 1. Redistributions of source code must retain the above copyright notice, |
| # this list of conditions and the following disclaimer. |
| # |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
| # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| |
| """Script for testing ganeti.client.gnt_job""" |
| |
| import unittest |
| import optparse |
| |
| from ganeti.client import gnt_job |
| from ganeti import utils |
| from ganeti import errors |
| from ganeti import query |
| from ganeti import qlang |
| from ganeti import objects |
| from ganeti import compat |
| from ganeti import constants |
| |
| import testutils |
| |
| |
| class _ClientForCancelJob: |
| def __init__(self, cancel_cb, query_cb): |
| self.cancelled = [] |
| self._cancel_cb = cancel_cb |
| self._query_cb = query_cb |
| |
| def CancelJob(self, job_id): |
| self.cancelled.append(job_id) |
| return self._cancel_cb(job_id) |
| |
| def Query(self, kind, selected, qfilter): |
| assert kind == constants.QR_JOB |
| assert selected == ["id", "status", "summary"] |
| |
| fields = query.GetAllFields(query._GetQueryFields(query.JOB_FIELDS, |
| selected)) |
| |
| return objects.QueryResponse(data=self._query_cb(qfilter), |
| fields=fields) |
| |
| |
| class TestCancelJob(unittest.TestCase): |
| def setUp(self): |
| unittest.TestCase.setUp(self) |
| self.stdout = [] |
| |
| def _ToStdout(self, line): |
| self.stdout.append(line) |
| |
| def _Ask(self, answer, question): |
| self.assertTrue(question.endswith("?")) |
| return answer |
| |
| def testStatusFilterAndArguments(self): |
| opts = optparse.Values(dict(status_filter=frozenset())) |
| try: |
| gnt_job.CancelJobs(opts, ["a"], cl=NotImplemented, |
| _stdout_fn=NotImplemented, _ask_fn=NotImplemented) |
| except errors.OpPrereqError, err: |
| self.assertEqual(err.args[1], errors.ECODE_INVAL) |
| else: |
| self.fail("Did not raise exception") |
| |
| def _TestArguments(self, force): |
| opts = optparse.Values(dict(status_filter=None, force=force)) |
| |
| def _CancelCb(job_id): |
| self.assertTrue(job_id in ("24185", "3252")) |
| return (True, "%s will be cancelled" % job_id) |
| |
| cl = _ClientForCancelJob(_CancelCb, NotImplemented) |
| self.assertEqual(gnt_job.CancelJobs(opts, ["24185", "3252"], cl=cl, |
| _stdout_fn=self._ToStdout, |
| _ask_fn=NotImplemented), |
| constants.EXIT_SUCCESS) |
| self.assertEqual(cl.cancelled, ["24185", "3252"]) |
| self.assertEqual(self.stdout, [ |
| "24185 will be cancelled", |
| "3252 will be cancelled", |
| ]) |
| |
| def testArgumentsWithForce(self): |
| self._TestArguments(True) |
| |
| def testArgumentsNoForce(self): |
| self._TestArguments(False) |
| |
| def testArgumentsWithError(self): |
| opts = optparse.Values(dict(status_filter=None, force=True)) |
| |
| def _CancelCb(job_id): |
| if job_id == "10788": |
| return (False, "error %s" % job_id) |
| else: |
| return (True, "%s will be cancelled" % job_id) |
| |
| cl = _ClientForCancelJob(_CancelCb, NotImplemented) |
| self.assertEqual(gnt_job.CancelJobs(opts, ["203", "10788", "30801"], cl=cl, |
| _stdout_fn=self._ToStdout, |
| _ask_fn=NotImplemented), |
| constants.EXIT_FAILURE) |
| self.assertEqual(cl.cancelled, ["203", "10788", "30801"]) |
| self.assertEqual(self.stdout, [ |
| "203 will be cancelled", |
| "error 10788", |
| "30801 will be cancelled", |
| ]) |
| |
| def testFilterPending(self): |
| opts = optparse.Values(dict(status_filter=constants.JOBS_PENDING, |
| force=False)) |
| |
| def _Query(qfilter): |
| # Need to sort as constants.JOBS_PENDING has no stable order |
| assert isinstance(constants.JOBS_PENDING, frozenset) |
| self.assertEqual(sorted(qfilter), |
| sorted(qlang.MakeSimpleFilter("status", |
| constants.JOBS_PENDING))) |
| |
| return [ |
| [(constants.RS_UNAVAIL, None), |
| (constants.RS_UNAVAIL, None), |
| (constants.RS_UNAVAIL, None)], |
| [(constants.RS_NORMAL, 32532), |
| (constants.RS_NORMAL, constants.JOB_STATUS_QUEUED), |
| (constants.RS_NORMAL, ["op1", "op2", "op3"])], |
| ] |
| |
| cl = _ClientForCancelJob(NotImplemented, _Query) |
| |
| result = gnt_job.CancelJobs(opts, [], cl=cl, |
| _stdout_fn=self._ToStdout, |
| _ask_fn=compat.partial(self._Ask, False)) |
| self.assertEqual(result, constants.EXIT_CONFIRMATION) |
| |
| |
| if __name__ == "__main__": |
| testutils.GanetiTestProgram() |