Statistics
| Branch: | Tag: | Revision:

root / qa / qa_job.py @ 31d3b918

History | View | Annotate | Download (4.3 kB)

1 09470dd8 Michael Hanselmann
#
2 09470dd8 Michael Hanselmann
#
3 09470dd8 Michael Hanselmann
4 66cb789f Hrvoje Ribicic
# Copyright (C) 2012, 2014 Google Inc.
5 09470dd8 Michael Hanselmann
#
6 09470dd8 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 09470dd8 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 09470dd8 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 09470dd8 Michael Hanselmann
# (at your option) any later version.
10 09470dd8 Michael Hanselmann
#
11 09470dd8 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 09470dd8 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 09470dd8 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 09470dd8 Michael Hanselmann
# General Public License for more details.
15 09470dd8 Michael Hanselmann
#
16 09470dd8 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 09470dd8 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 09470dd8 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 09470dd8 Michael Hanselmann
# 02110-1301, USA.
20 09470dd8 Michael Hanselmann
21 09470dd8 Michael Hanselmann
22 09470dd8 Michael Hanselmann
"""Job-related QA tests.
23 09470dd8 Michael Hanselmann

24 09470dd8 Michael Hanselmann
"""
25 09470dd8 Michael Hanselmann
26 e4f485cc Hrvoje Ribicic
from ganeti.utils import retry
27 66cb789f Hrvoje Ribicic
from ganeti import constants
28 09470dd8 Michael Hanselmann
from ganeti import query
29 09470dd8 Michael Hanselmann
30 e4f485cc Hrvoje Ribicic
import functools
31 66cb789f Hrvoje Ribicic
import re
32 66cb789f Hrvoje Ribicic
33 66cb789f Hrvoje Ribicic
import qa_config
34 66cb789f Hrvoje Ribicic
import qa_error
35 09470dd8 Michael Hanselmann
import qa_utils
36 09470dd8 Michael Hanselmann
37 66cb789f Hrvoje Ribicic
from qa_utils import AssertCommand, GetCommandOutput
38 66cb789f Hrvoje Ribicic
39 09470dd8 Michael Hanselmann
40 09470dd8 Michael Hanselmann
def TestJobList():
41 09470dd8 Michael Hanselmann
  """gnt-job list"""
42 6d1e4845 Michael Hanselmann
  qa_utils.GenericQueryTest("gnt-job", query.JOB_FIELDS.keys(),
43 6d1e4845 Michael Hanselmann
                            namefield="id", test_unknown=False)
44 09470dd8 Michael Hanselmann
45 09470dd8 Michael Hanselmann
46 09470dd8 Michael Hanselmann
def TestJobListFields():
47 09470dd8 Michael Hanselmann
  """gnt-node list-fields"""
48 09470dd8 Michael Hanselmann
  qa_utils.GenericQueryFieldsTest("gnt-job", query.JOB_FIELDS.keys())
49 66cb789f Hrvoje Ribicic
50 66cb789f Hrvoje Ribicic
51 66cb789f Hrvoje Ribicic
def _GetJobStatuses():
52 66cb789f Hrvoje Ribicic
  """ Invokes gnt-job list and extracts an id to status dictionary.
53 66cb789f Hrvoje Ribicic

54 66cb789f Hrvoje Ribicic
  @rtype: dict of string to string
55 66cb789f Hrvoje Ribicic
  @return: A dictionary mapping job ids to matching statuses
56 66cb789f Hrvoje Ribicic

57 66cb789f Hrvoje Ribicic
  """
58 66cb789f Hrvoje Ribicic
  master = qa_config.GetMasterNode()
59 66cb789f Hrvoje Ribicic
  list_output = GetCommandOutput(
60 66cb789f Hrvoje Ribicic
    master.primary, "gnt-job list --no-headers --output=id,status"
61 66cb789f Hrvoje Ribicic
  )
62 66cb789f Hrvoje Ribicic
  return dict(map(lambda s: s.split(), list_output.splitlines()))
63 66cb789f Hrvoje Ribicic
64 66cb789f Hrvoje Ribicic
65 e4f485cc Hrvoje Ribicic
def _GetJobStatus(job_id):
66 e4f485cc Hrvoje Ribicic
  """ Retrieves the status of a job.
67 e4f485cc Hrvoje Ribicic

68 e4f485cc Hrvoje Ribicic
  @type job_id: string
69 e4f485cc Hrvoje Ribicic
  @param job_id: The job id, represented as a string.
70 e4f485cc Hrvoje Ribicic
  @rtype: string or None
71 e4f485cc Hrvoje Ribicic

72 e4f485cc Hrvoje Ribicic
  @return: The job status, or None if not present.
73 e4f485cc Hrvoje Ribicic

74 e4f485cc Hrvoje Ribicic
  """
75 e4f485cc Hrvoje Ribicic
  return _GetJobStatuses().get(job_id, None)
76 e4f485cc Hrvoje Ribicic
77 e4f485cc Hrvoje Ribicic
78 e4f485cc Hrvoje Ribicic
def _RetryingFetchJobStatus(retry_status, job_id):
79 e4f485cc Hrvoje Ribicic
  """ Used with C{retry.Retry}, waits for a status other than the one given.
80 e4f485cc Hrvoje Ribicic

81 e4f485cc Hrvoje Ribicic
  @type retry_status: string
82 e4f485cc Hrvoje Ribicic
  @param retry_status: The old job status, expected to change.
83 e4f485cc Hrvoje Ribicic
  @type job_id: string
84 e4f485cc Hrvoje Ribicic
  @param job_id: The job id, represented as a string.
85 e4f485cc Hrvoje Ribicic

86 e4f485cc Hrvoje Ribicic
  @rtype: string or None
87 e4f485cc Hrvoje Ribicic
  @return: The new job status, or None if none could be retrieved.
88 e4f485cc Hrvoje Ribicic

89 e4f485cc Hrvoje Ribicic
  """
90 e4f485cc Hrvoje Ribicic
  status = _GetJobStatus(job_id)
91 e4f485cc Hrvoje Ribicic
  if status == retry_status:
92 e4f485cc Hrvoje Ribicic
    raise retry.RetryAgain()
93 e4f485cc Hrvoje Ribicic
  return status
94 e4f485cc Hrvoje Ribicic
95 e4f485cc Hrvoje Ribicic
96 66cb789f Hrvoje Ribicic
def TestJobCancellation():
97 66cb789f Hrvoje Ribicic
  """gnt-job cancel"""
98 66cb789f Hrvoje Ribicic
  # The delay used for the first command should be large enough for the next
99 66cb789f Hrvoje Ribicic
  # command and the cancellation command to complete before the first job is
100 66cb789f Hrvoje Ribicic
  # done. The second delay should be small enough that not too much time is
101 66cb789f Hrvoje Ribicic
  # spend waiting in the case of a failed cancel and a running command.
102 66cb789f Hrvoje Ribicic
  FIRST_COMMAND_DELAY = 10.0
103 66cb789f Hrvoje Ribicic
  AssertCommand(["gnt-debug", "delay", "--submit", str(FIRST_COMMAND_DELAY)])
104 66cb789f Hrvoje Ribicic
105 66cb789f Hrvoje Ribicic
  SECOND_COMMAND_DELAY = 1.0
106 66cb789f Hrvoje Ribicic
  master = qa_config.GetMasterNode()
107 66cb789f Hrvoje Ribicic
108 66cb789f Hrvoje Ribicic
  # Forcing tty usage does not work on buildbot, so force all output of this
109 66cb789f Hrvoje Ribicic
  # command to be redirected to stdout
110 66cb789f Hrvoje Ribicic
  job_id_output = GetCommandOutput(
111 66cb789f Hrvoje Ribicic
    master.primary, "gnt-debug delay --submit %s 2>&1" % SECOND_COMMAND_DELAY
112 66cb789f Hrvoje Ribicic
  )
113 66cb789f Hrvoje Ribicic
114 66cb789f Hrvoje Ribicic
  possible_job_ids = re.findall("JobID: ([0-9]+)", job_id_output)
115 66cb789f Hrvoje Ribicic
  if len(possible_job_ids) != 1:
116 66cb789f Hrvoje Ribicic
    raise qa_error.Error("Cannot parse gnt-debug delay output to find job id")
117 66cb789f Hrvoje Ribicic
118 66cb789f Hrvoje Ribicic
  job_id = possible_job_ids[0]
119 66cb789f Hrvoje Ribicic
  AssertCommand(["gnt-job", "cancel", job_id])
120 66cb789f Hrvoje Ribicic
121 66cb789f Hrvoje Ribicic
  # Now wait until the second job finishes, and expect the watch to fail due to
122 66cb789f Hrvoje Ribicic
  # job cancellation
123 66cb789f Hrvoje Ribicic
  AssertCommand(["gnt-job", "watch", job_id], fail=True)
124 66cb789f Hrvoje Ribicic
125 66cb789f Hrvoje Ribicic
  # Then check for job cancellation
126 e4f485cc Hrvoje Ribicic
  job_status = _GetJobStatus(job_id)
127 e4f485cc Hrvoje Ribicic
  if job_status != constants.JOB_STATUS_CANCELED:
128 e4f485cc Hrvoje Ribicic
    # Try and see if the job is being cancelled, and wait until the status
129 e4f485cc Hrvoje Ribicic
    # changes or we hit a timeout
130 e4f485cc Hrvoje Ribicic
    if job_status == constants.JOB_STATUS_CANCELING:
131 e4f485cc Hrvoje Ribicic
      retry_fn = functools.partial(_RetryingFetchJobStatus,
132 e4f485cc Hrvoje Ribicic
                                   constants.JOB_STATUS_CANCELING, job_id)
133 e4f485cc Hrvoje Ribicic
      try:
134 e4f485cc Hrvoje Ribicic
        job_status = retry.Retry(retry_fn, 2.0, 2 * FIRST_COMMAND_DELAY)
135 e4f485cc Hrvoje Ribicic
      except retry.RetryTimeout:
136 e4f485cc Hrvoje Ribicic
        # The job status remains the same
137 e4f485cc Hrvoje Ribicic
        pass
138 e4f485cc Hrvoje Ribicic
139 e4f485cc Hrvoje Ribicic
    if job_status != constants.JOB_STATUS_CANCELED:
140 e4f485cc Hrvoje Ribicic
      raise qa_error.Error("Job was not successfully cancelled, status "
141 e4f485cc Hrvoje Ribicic
                           "found: %s" % job_status)