Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.jqueue_unittest.py @ 858905fb

History | View | Annotate | Download (6.6 kB)

1 989a8bee Michael Hanselmann
#!/usr/bin/python
2 989a8bee Michael Hanselmann
#
3 989a8bee Michael Hanselmann
4 989a8bee Michael Hanselmann
# Copyright (C) 2010 Google Inc.
5 989a8bee Michael Hanselmann
#
6 989a8bee Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 989a8bee Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 989a8bee Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 989a8bee Michael Hanselmann
# (at your option) any later version.
10 989a8bee Michael Hanselmann
#
11 989a8bee Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 989a8bee Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 989a8bee Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 989a8bee Michael Hanselmann
# General Public License for more details.
15 989a8bee Michael Hanselmann
#
16 989a8bee Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 989a8bee Michael Hanselmann
# along with this program; if not, write to the Free Software
18 989a8bee Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 989a8bee Michael Hanselmann
# 02110-1301, USA.
20 989a8bee Michael Hanselmann
21 989a8bee Michael Hanselmann
22 989a8bee Michael Hanselmann
"""Script for testing ganeti.jqueue"""
23 989a8bee Michael Hanselmann
24 989a8bee Michael Hanselmann
import os
25 989a8bee Michael Hanselmann
import sys
26 989a8bee Michael Hanselmann
import unittest
27 989a8bee Michael Hanselmann
import tempfile
28 989a8bee Michael Hanselmann
import shutil
29 989a8bee Michael Hanselmann
import errno
30 989a8bee Michael Hanselmann
31 989a8bee Michael Hanselmann
from ganeti import constants
32 989a8bee Michael Hanselmann
from ganeti import utils
33 989a8bee Michael Hanselmann
from ganeti import errors
34 989a8bee Michael Hanselmann
from ganeti import jqueue
35 989a8bee Michael Hanselmann
36 989a8bee Michael Hanselmann
import testutils
37 989a8bee Michael Hanselmann
38 989a8bee Michael Hanselmann
39 989a8bee Michael Hanselmann
class _FakeJob:
40 989a8bee Michael Hanselmann
  def __init__(self, job_id, status):
41 989a8bee Michael Hanselmann
    self.id = job_id
42 989a8bee Michael Hanselmann
    self._status = status
43 989a8bee Michael Hanselmann
    self._log = []
44 989a8bee Michael Hanselmann
45 989a8bee Michael Hanselmann
  def SetStatus(self, status):
46 989a8bee Michael Hanselmann
    self._status = status
47 989a8bee Michael Hanselmann
48 989a8bee Michael Hanselmann
  def AddLogEntry(self, msg):
49 989a8bee Michael Hanselmann
    self._log.append((len(self._log), msg))
50 989a8bee Michael Hanselmann
51 989a8bee Michael Hanselmann
  def CalcStatus(self):
52 989a8bee Michael Hanselmann
    return self._status
53 989a8bee Michael Hanselmann
54 989a8bee Michael Hanselmann
  def GetInfo(self, fields):
55 989a8bee Michael Hanselmann
    result = []
56 989a8bee Michael Hanselmann
57 989a8bee Michael Hanselmann
    for name in fields:
58 989a8bee Michael Hanselmann
      if name == "status":
59 989a8bee Michael Hanselmann
        result.append(self._status)
60 989a8bee Michael Hanselmann
      else:
61 989a8bee Michael Hanselmann
        raise Exception("Unknown field")
62 989a8bee Michael Hanselmann
63 989a8bee Michael Hanselmann
    return result
64 989a8bee Michael Hanselmann
65 989a8bee Michael Hanselmann
  def GetLogEntries(self, newer_than):
66 989a8bee Michael Hanselmann
    assert newer_than is None or newer_than >= 0
67 989a8bee Michael Hanselmann
68 989a8bee Michael Hanselmann
    if newer_than is None:
69 989a8bee Michael Hanselmann
      return self._log
70 989a8bee Michael Hanselmann
71 989a8bee Michael Hanselmann
    return self._log[newer_than:]
72 989a8bee Michael Hanselmann
73 989a8bee Michael Hanselmann
74 989a8bee Michael Hanselmann
class TestJobChangesChecker(unittest.TestCase):
75 989a8bee Michael Hanselmann
  def testStatus(self):
76 989a8bee Michael Hanselmann
    job = _FakeJob(9094, constants.JOB_STATUS_QUEUED)
77 989a8bee Michael Hanselmann
    checker = jqueue._JobChangesChecker(["status"], None, None)
78 989a8bee Michael Hanselmann
    self.assertEqual(checker(job), ([constants.JOB_STATUS_QUEUED], []))
79 989a8bee Michael Hanselmann
80 989a8bee Michael Hanselmann
    job.SetStatus(constants.JOB_STATUS_RUNNING)
81 989a8bee Michael Hanselmann
    self.assertEqual(checker(job), ([constants.JOB_STATUS_RUNNING], []))
82 989a8bee Michael Hanselmann
83 989a8bee Michael Hanselmann
    job.SetStatus(constants.JOB_STATUS_SUCCESS)
84 989a8bee Michael Hanselmann
    self.assertEqual(checker(job), ([constants.JOB_STATUS_SUCCESS], []))
85 989a8bee Michael Hanselmann
86 989a8bee Michael Hanselmann
    # job.id is used by checker
87 989a8bee Michael Hanselmann
    self.assertEqual(job.id, 9094)
88 989a8bee Michael Hanselmann
89 989a8bee Michael Hanselmann
  def testStatusWithPrev(self):
90 989a8bee Michael Hanselmann
    job = _FakeJob(12807, constants.JOB_STATUS_QUEUED)
91 989a8bee Michael Hanselmann
    checker = jqueue._JobChangesChecker(["status"],
92 989a8bee Michael Hanselmann
                                        [constants.JOB_STATUS_QUEUED], None)
93 989a8bee Michael Hanselmann
    self.assert_(checker(job) is None)
94 989a8bee Michael Hanselmann
95 989a8bee Michael Hanselmann
    job.SetStatus(constants.JOB_STATUS_RUNNING)
96 989a8bee Michael Hanselmann
    self.assertEqual(checker(job), ([constants.JOB_STATUS_RUNNING], []))
97 989a8bee Michael Hanselmann
98 989a8bee Michael Hanselmann
  def testFinalStatus(self):
99 989a8bee Michael Hanselmann
    for status in constants.JOBS_FINALIZED:
100 989a8bee Michael Hanselmann
      job = _FakeJob(2178711, status)
101 989a8bee Michael Hanselmann
      checker = jqueue._JobChangesChecker(["status"], [status], None)
102 989a8bee Michael Hanselmann
      # There won't be any changes in this status, hence it should signal
103 989a8bee Michael Hanselmann
      # a change immediately
104 989a8bee Michael Hanselmann
      self.assertEqual(checker(job), ([status], []))
105 989a8bee Michael Hanselmann
106 989a8bee Michael Hanselmann
  def testLog(self):
107 989a8bee Michael Hanselmann
    job = _FakeJob(9094, constants.JOB_STATUS_RUNNING)
108 989a8bee Michael Hanselmann
    checker = jqueue._JobChangesChecker(["status"], None, None)
109 989a8bee Michael Hanselmann
    self.assertEqual(checker(job), ([constants.JOB_STATUS_RUNNING], []))
110 989a8bee Michael Hanselmann
111 989a8bee Michael Hanselmann
    job.AddLogEntry("Hello World")
112 989a8bee Michael Hanselmann
    (job_info, log_entries) = checker(job)
113 989a8bee Michael Hanselmann
    self.assertEqual(job_info, [constants.JOB_STATUS_RUNNING])
114 989a8bee Michael Hanselmann
    self.assertEqual(log_entries, [[0, "Hello World"]])
115 989a8bee Michael Hanselmann
116 989a8bee Michael Hanselmann
    checker2 = jqueue._JobChangesChecker(["status"], job_info, len(log_entries))
117 989a8bee Michael Hanselmann
    self.assert_(checker2(job) is None)
118 989a8bee Michael Hanselmann
119 989a8bee Michael Hanselmann
    job.AddLogEntry("Foo Bar")
120 989a8bee Michael Hanselmann
    job.SetStatus(constants.JOB_STATUS_ERROR)
121 989a8bee Michael Hanselmann
122 989a8bee Michael Hanselmann
    (job_info, log_entries) = checker2(job)
123 989a8bee Michael Hanselmann
    self.assertEqual(job_info, [constants.JOB_STATUS_ERROR])
124 989a8bee Michael Hanselmann
    self.assertEqual(log_entries, [[1, "Foo Bar"]])
125 989a8bee Michael Hanselmann
126 989a8bee Michael Hanselmann
    checker3 = jqueue._JobChangesChecker(["status"], None, None)
127 989a8bee Michael Hanselmann
    (job_info, log_entries) = checker3(job)
128 989a8bee Michael Hanselmann
    self.assertEqual(job_info, [constants.JOB_STATUS_ERROR])
129 989a8bee Michael Hanselmann
    self.assertEqual(log_entries, [[0, "Hello World"], [1, "Foo Bar"]])
130 989a8bee Michael Hanselmann
131 989a8bee Michael Hanselmann
132 989a8bee Michael Hanselmann
class TestJobChangesWaiter(unittest.TestCase):
133 989a8bee Michael Hanselmann
  def setUp(self):
134 989a8bee Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
135 989a8bee Michael Hanselmann
    self.filename = utils.PathJoin(self.tmpdir, "job-1")
136 989a8bee Michael Hanselmann
    utils.WriteFile(self.filename, data="")
137 989a8bee Michael Hanselmann
138 989a8bee Michael Hanselmann
  def tearDown(self):
139 989a8bee Michael Hanselmann
    shutil.rmtree(self.tmpdir)
140 989a8bee Michael Hanselmann
141 989a8bee Michael Hanselmann
  def _EnsureNotifierClosed(self, notifier):
142 989a8bee Michael Hanselmann
    try:
143 989a8bee Michael Hanselmann
      os.fstat(notifier._fd)
144 989a8bee Michael Hanselmann
    except EnvironmentError, err:
145 989a8bee Michael Hanselmann
      self.assertEqual(err.errno, errno.EBADF)
146 989a8bee Michael Hanselmann
    else:
147 989a8bee Michael Hanselmann
      self.fail("File descriptor wasn't closed")
148 989a8bee Michael Hanselmann
149 989a8bee Michael Hanselmann
  def testClose(self):
150 989a8bee Michael Hanselmann
    for wait in [False, True]:
151 989a8bee Michael Hanselmann
      waiter = jqueue._JobFileChangesWaiter(self.filename)
152 989a8bee Michael Hanselmann
      try:
153 989a8bee Michael Hanselmann
        if wait:
154 989a8bee Michael Hanselmann
          waiter.Wait(0.001)
155 989a8bee Michael Hanselmann
      finally:
156 989a8bee Michael Hanselmann
        waiter.Close()
157 989a8bee Michael Hanselmann
158 989a8bee Michael Hanselmann
      # Ensure file descriptor was closed
159 989a8bee Michael Hanselmann
      self._EnsureNotifierClosed(waiter._notifier)
160 989a8bee Michael Hanselmann
161 989a8bee Michael Hanselmann
  def testChangingFile(self):
162 989a8bee Michael Hanselmann
    waiter = jqueue._JobFileChangesWaiter(self.filename)
163 989a8bee Michael Hanselmann
    try:
164 989a8bee Michael Hanselmann
      self.assertFalse(waiter.Wait(0.1))
165 989a8bee Michael Hanselmann
      utils.WriteFile(self.filename, data="changed")
166 989a8bee Michael Hanselmann
      self.assert_(waiter.Wait(60))
167 989a8bee Michael Hanselmann
    finally:
168 989a8bee Michael Hanselmann
      waiter.Close()
169 989a8bee Michael Hanselmann
170 989a8bee Michael Hanselmann
    self._EnsureNotifierClosed(waiter._notifier)
171 989a8bee Michael Hanselmann
172 989a8bee Michael Hanselmann
  def testChangingFile2(self):
173 989a8bee Michael Hanselmann
    waiter = jqueue._JobChangesWaiter(self.filename)
174 989a8bee Michael Hanselmann
    try:
175 989a8bee Michael Hanselmann
      self.assertFalse(waiter._filewaiter)
176 989a8bee Michael Hanselmann
      self.assert_(waiter.Wait(0.1))
177 989a8bee Michael Hanselmann
      self.assert_(waiter._filewaiter)
178 989a8bee Michael Hanselmann
179 989a8bee Michael Hanselmann
      # File waiter is now used, but there have been no changes
180 989a8bee Michael Hanselmann
      self.assertFalse(waiter.Wait(0.1))
181 989a8bee Michael Hanselmann
      utils.WriteFile(self.filename, data="changed")
182 989a8bee Michael Hanselmann
      self.assert_(waiter.Wait(60))
183 989a8bee Michael Hanselmann
    finally:
184 989a8bee Michael Hanselmann
      waiter.Close()
185 989a8bee Michael Hanselmann
186 989a8bee Michael Hanselmann
    self._EnsureNotifierClosed(waiter._filewaiter._notifier)
187 989a8bee Michael Hanselmann
188 989a8bee Michael Hanselmann
189 989a8bee Michael Hanselmann
class TestWaitForJobChangesHelper(unittest.TestCase):
190 989a8bee Michael Hanselmann
  def setUp(self):
191 989a8bee Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
192 989a8bee Michael Hanselmann
    self.filename = utils.PathJoin(self.tmpdir, "job-2614226563")
193 989a8bee Michael Hanselmann
    utils.WriteFile(self.filename, data="")
194 989a8bee Michael Hanselmann
195 989a8bee Michael Hanselmann
  def tearDown(self):
196 989a8bee Michael Hanselmann
    shutil.rmtree(self.tmpdir)
197 989a8bee Michael Hanselmann
198 989a8bee Michael Hanselmann
  def _LoadWaitingJob(self):
199 989a8bee Michael Hanselmann
    return _FakeJob(2614226563, constants.JOB_STATUS_WAITLOCK)
200 989a8bee Michael Hanselmann
201 989a8bee Michael Hanselmann
  def _LoadLostJob(self):
202 989a8bee Michael Hanselmann
    return None
203 989a8bee Michael Hanselmann
204 989a8bee Michael Hanselmann
  def testNoChanges(self):
205 989a8bee Michael Hanselmann
    wfjc = jqueue._WaitForJobChangesHelper()
206 989a8bee Michael Hanselmann
207 989a8bee Michael Hanselmann
    # No change
208 989a8bee Michael Hanselmann
    self.assertEqual(wfjc(self.filename, self._LoadWaitingJob, ["status"],
209 989a8bee Michael Hanselmann
                          [constants.JOB_STATUS_WAITLOCK], None, 0.1),
210 989a8bee Michael Hanselmann
                     constants.JOB_NOTCHANGED)
211 989a8bee Michael Hanselmann
212 989a8bee Michael Hanselmann
    # No previous information
213 989a8bee Michael Hanselmann
    self.assertEqual(wfjc(self.filename, self._LoadWaitingJob,
214 989a8bee Michael Hanselmann
                          ["status"], None, None, 1.0),
215 989a8bee Michael Hanselmann
                     ([constants.JOB_STATUS_WAITLOCK], []))
216 989a8bee Michael Hanselmann
217 989a8bee Michael Hanselmann
  def testLostJob(self):
218 989a8bee Michael Hanselmann
    wfjc = jqueue._WaitForJobChangesHelper()
219 989a8bee Michael Hanselmann
    self.assert_(wfjc(self.filename, self._LoadLostJob,
220 989a8bee Michael Hanselmann
                      ["status"], None, None, 1.0) is None)
221 989a8bee Michael Hanselmann
222 989a8bee Michael Hanselmann
223 989a8bee Michael Hanselmann
if __name__ == "__main__":
224 989a8bee Michael Hanselmann
  testutils.GanetiTestProgram()