Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.utils.process_unittest.py @ cd3b4ff4

History | View | Annotate | Download (24.7 kB)

1 a4ccecf6 Michael Hanselmann
#!/usr/bin/python
2 a4ccecf6 Michael Hanselmann
#
3 a4ccecf6 Michael Hanselmann
4 a4ccecf6 Michael Hanselmann
# Copyright (C) 2011 Google Inc.
5 a4ccecf6 Michael Hanselmann
#
6 a4ccecf6 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 a4ccecf6 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 a4ccecf6 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 a4ccecf6 Michael Hanselmann
# (at your option) any later version.
10 a4ccecf6 Michael Hanselmann
#
11 a4ccecf6 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 a4ccecf6 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a4ccecf6 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a4ccecf6 Michael Hanselmann
# General Public License for more details.
15 a4ccecf6 Michael Hanselmann
#
16 a4ccecf6 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 a4ccecf6 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 a4ccecf6 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a4ccecf6 Michael Hanselmann
# 02110-1301, USA.
20 a4ccecf6 Michael Hanselmann
21 a4ccecf6 Michael Hanselmann
22 a4ccecf6 Michael Hanselmann
"""Script for testing ganeti.utils.process"""
23 a4ccecf6 Michael Hanselmann
24 a4ccecf6 Michael Hanselmann
import unittest
25 a4ccecf6 Michael Hanselmann
import tempfile
26 a4ccecf6 Michael Hanselmann
import shutil
27 a4ccecf6 Michael Hanselmann
import os
28 a4ccecf6 Michael Hanselmann
import stat
29 a4ccecf6 Michael Hanselmann
import time
30 d6491981 René Nussbaumer
import select
31 a4ccecf6 Michael Hanselmann
import signal
32 a4ccecf6 Michael Hanselmann
33 a4ccecf6 Michael Hanselmann
from ganeti import constants
34 a4ccecf6 Michael Hanselmann
from ganeti import utils
35 a4ccecf6 Michael Hanselmann
from ganeti import errors
36 a4ccecf6 Michael Hanselmann
37 a4ccecf6 Michael Hanselmann
import testutils
38 a4ccecf6 Michael Hanselmann
39 a4ccecf6 Michael Hanselmann
40 a4ccecf6 Michael Hanselmann
class TestIsProcessAlive(unittest.TestCase):
41 a4ccecf6 Michael Hanselmann
  """Testing case for IsProcessAlive"""
42 a4ccecf6 Michael Hanselmann
43 a4ccecf6 Michael Hanselmann
  def testExists(self):
44 a4ccecf6 Michael Hanselmann
    mypid = os.getpid()
45 a4ccecf6 Michael Hanselmann
    self.assert_(utils.IsProcessAlive(mypid), "can't find myself running")
46 a4ccecf6 Michael Hanselmann
47 a4ccecf6 Michael Hanselmann
  def testNotExisting(self):
48 a4ccecf6 Michael Hanselmann
    pid_non_existing = os.fork()
49 a4ccecf6 Michael Hanselmann
    if pid_non_existing == 0:
50 a4ccecf6 Michael Hanselmann
      os._exit(0)
51 a4ccecf6 Michael Hanselmann
    elif pid_non_existing < 0:
52 a4ccecf6 Michael Hanselmann
      raise SystemError("can't fork")
53 a4ccecf6 Michael Hanselmann
    os.waitpid(pid_non_existing, 0)
54 a4ccecf6 Michael Hanselmann
    self.assertFalse(utils.IsProcessAlive(pid_non_existing),
55 a4ccecf6 Michael Hanselmann
                     "nonexisting process detected")
56 a4ccecf6 Michael Hanselmann
57 a4ccecf6 Michael Hanselmann
58 a4ccecf6 Michael Hanselmann
class TestGetProcStatusPath(unittest.TestCase):
59 a4ccecf6 Michael Hanselmann
  def test(self):
60 a4ccecf6 Michael Hanselmann
    self.assert_("/1234/" in utils.process._GetProcStatusPath(1234))
61 a4ccecf6 Michael Hanselmann
    self.assertNotEqual(utils.process._GetProcStatusPath(1),
62 a4ccecf6 Michael Hanselmann
                        utils.process._GetProcStatusPath(2))
63 a4ccecf6 Michael Hanselmann
64 a4ccecf6 Michael Hanselmann
65 a4ccecf6 Michael Hanselmann
class TestIsProcessHandlingSignal(unittest.TestCase):
66 a4ccecf6 Michael Hanselmann
  def setUp(self):
67 a4ccecf6 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
68 a4ccecf6 Michael Hanselmann
69 a4ccecf6 Michael Hanselmann
  def tearDown(self):
70 a4ccecf6 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
71 a4ccecf6 Michael Hanselmann
72 a4ccecf6 Michael Hanselmann
  def testParseSigsetT(self):
73 a4ccecf6 Michael Hanselmann
    parse_sigset_t_fn = utils.process._ParseSigsetT
74 a4ccecf6 Michael Hanselmann
    self.assertEqual(len(parse_sigset_t_fn("0")), 0)
75 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("1"), set([1]))
76 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("1000a"), set([2, 4, 17]))
77 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("810002"), set([2, 17, 24, ]))
78 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("0000000180000202"),
79 a4ccecf6 Michael Hanselmann
                     set([2, 10, 32, 33]))
80 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("0000000180000002"),
81 a4ccecf6 Michael Hanselmann
                     set([2, 32, 33]))
82 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("0000000188000002"),
83 a4ccecf6 Michael Hanselmann
                     set([2, 28, 32, 33]))
84 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("000000004b813efb"),
85 a4ccecf6 Michael Hanselmann
                     set([1, 2, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 17,
86 a4ccecf6 Michael Hanselmann
                          24, 25, 26, 28, 31]))
87 a4ccecf6 Michael Hanselmann
    self.assertEqual(parse_sigset_t_fn("ffffff"), set(range(1, 25)))
88 a4ccecf6 Michael Hanselmann
89 a4ccecf6 Michael Hanselmann
  def testGetProcStatusField(self):
90 a4ccecf6 Michael Hanselmann
    for field in ["SigCgt", "Name", "FDSize"]:
91 a4ccecf6 Michael Hanselmann
      for value in ["", "0", "cat", "  1234 KB"]:
92 a4ccecf6 Michael Hanselmann
        pstatus = "\n".join([
93 a4ccecf6 Michael Hanselmann
          "VmPeak: 999 kB",
94 a4ccecf6 Michael Hanselmann
          "%s: %s" % (field, value),
95 a4ccecf6 Michael Hanselmann
          "TracerPid: 0",
96 a4ccecf6 Michael Hanselmann
          ])
97 a4ccecf6 Michael Hanselmann
        result = utils.process._GetProcStatusField(pstatus, field)
98 a4ccecf6 Michael Hanselmann
        self.assertEqual(result, value.strip())
99 a4ccecf6 Michael Hanselmann
100 a4ccecf6 Michael Hanselmann
  def test(self):
101 a4ccecf6 Michael Hanselmann
    sp = utils.PathJoin(self.tmpdir, "status")
102 a4ccecf6 Michael Hanselmann
103 a4ccecf6 Michael Hanselmann
    utils.WriteFile(sp, data="\n".join([
104 a4ccecf6 Michael Hanselmann
      "Name:   bash",
105 a4ccecf6 Michael Hanselmann
      "State:  S (sleeping)",
106 a4ccecf6 Michael Hanselmann
      "SleepAVG:       98%",
107 a4ccecf6 Michael Hanselmann
      "Pid:    22250",
108 a4ccecf6 Michael Hanselmann
      "PPid:   10858",
109 a4ccecf6 Michael Hanselmann
      "TracerPid:      0",
110 a4ccecf6 Michael Hanselmann
      "SigBlk: 0000000000010000",
111 a4ccecf6 Michael Hanselmann
      "SigIgn: 0000000000384004",
112 a4ccecf6 Michael Hanselmann
      "SigCgt: 000000004b813efb",
113 a4ccecf6 Michael Hanselmann
      "CapEff: 0000000000000000",
114 a4ccecf6 Michael Hanselmann
      ]))
115 a4ccecf6 Michael Hanselmann
116 a4ccecf6 Michael Hanselmann
    self.assert_(utils.IsProcessHandlingSignal(1234, 10, status_path=sp))
117 a4ccecf6 Michael Hanselmann
118 a4ccecf6 Michael Hanselmann
  def testNoSigCgt(self):
119 a4ccecf6 Michael Hanselmann
    sp = utils.PathJoin(self.tmpdir, "status")
120 a4ccecf6 Michael Hanselmann
121 a4ccecf6 Michael Hanselmann
    utils.WriteFile(sp, data="\n".join([
122 a4ccecf6 Michael Hanselmann
      "Name:   bash",
123 a4ccecf6 Michael Hanselmann
      ]))
124 a4ccecf6 Michael Hanselmann
125 a4ccecf6 Michael Hanselmann
    self.assertRaises(RuntimeError, utils.IsProcessHandlingSignal,
126 a4ccecf6 Michael Hanselmann
                      1234, 10, status_path=sp)
127 a4ccecf6 Michael Hanselmann
128 a4ccecf6 Michael Hanselmann
  def testNoSuchFile(self):
129 a4ccecf6 Michael Hanselmann
    sp = utils.PathJoin(self.tmpdir, "notexist")
130 a4ccecf6 Michael Hanselmann
131 a4ccecf6 Michael Hanselmann
    self.assertFalse(utils.IsProcessHandlingSignal(1234, 10, status_path=sp))
132 a4ccecf6 Michael Hanselmann
133 a4ccecf6 Michael Hanselmann
  @staticmethod
134 a4ccecf6 Michael Hanselmann
  def _TestRealProcess():
135 a4ccecf6 Michael Hanselmann
    signal.signal(signal.SIGUSR1, signal.SIG_DFL)
136 a4ccecf6 Michael Hanselmann
    if utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1):
137 a4ccecf6 Michael Hanselmann
      raise Exception("SIGUSR1 is handled when it should not be")
138 a4ccecf6 Michael Hanselmann
139 a4ccecf6 Michael Hanselmann
    signal.signal(signal.SIGUSR1, lambda signum, frame: None)
140 a4ccecf6 Michael Hanselmann
    if not utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1):
141 a4ccecf6 Michael Hanselmann
      raise Exception("SIGUSR1 is not handled when it should be")
142 a4ccecf6 Michael Hanselmann
143 a4ccecf6 Michael Hanselmann
    signal.signal(signal.SIGUSR1, signal.SIG_IGN)
144 a4ccecf6 Michael Hanselmann
    if utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1):
145 a4ccecf6 Michael Hanselmann
      raise Exception("SIGUSR1 is not handled when it should be")
146 a4ccecf6 Michael Hanselmann
147 a4ccecf6 Michael Hanselmann
    signal.signal(signal.SIGUSR1, signal.SIG_DFL)
148 a4ccecf6 Michael Hanselmann
    if utils.IsProcessHandlingSignal(os.getpid(), signal.SIGUSR1):
149 a4ccecf6 Michael Hanselmann
      raise Exception("SIGUSR1 is handled when it should not be")
150 a4ccecf6 Michael Hanselmann
151 a4ccecf6 Michael Hanselmann
    return True
152 a4ccecf6 Michael Hanselmann
153 a4ccecf6 Michael Hanselmann
  def testRealProcess(self):
154 a4ccecf6 Michael Hanselmann
    self.assert_(utils.RunInSeparateProcess(self._TestRealProcess))
155 a4ccecf6 Michael Hanselmann
156 a4ccecf6 Michael Hanselmann
157 d6491981 René Nussbaumer
class _PostforkProcessReadyHelper:
158 09b72783 Michael Hanselmann
  """A helper to use with C{postfork_fn} in RunCmd.
159 d6491981 René Nussbaumer

160 d6491981 René Nussbaumer
  It makes sure a process has reached a certain state by reading from a fifo.
161 d6491981 René Nussbaumer

162 d6491981 René Nussbaumer
  @ivar write_fd: The fd number to write to
163 d6491981 René Nussbaumer

164 d6491981 René Nussbaumer
  """
165 d6491981 René Nussbaumer
  def __init__(self, timeout):
166 d6491981 René Nussbaumer
    """Initialize the helper.
167 d6491981 René Nussbaumer

168 d6491981 René Nussbaumer
    @param fifo_dir: The dir where we can create the fifo
169 d6491981 René Nussbaumer
    @param timeout: The time in seconds to wait before giving up
170 d6491981 René Nussbaumer

171 d6491981 René Nussbaumer
    """
172 d6491981 René Nussbaumer
    self.timeout = timeout
173 d6491981 René Nussbaumer
    (self.read_fd, self.write_fd) = os.pipe()
174 d6491981 René Nussbaumer
175 d6491981 René Nussbaumer
  def Ready(self, pid):
176 d6491981 René Nussbaumer
    """Waits until the process is ready.
177 d6491981 René Nussbaumer

178 d6491981 René Nussbaumer
    @param pid: The pid of the process
179 d6491981 René Nussbaumer

180 d6491981 René Nussbaumer
    """
181 d6491981 René Nussbaumer
    (read_ready, _, _) = select.select([self.read_fd], [], [], self.timeout)
182 d6491981 René Nussbaumer
183 d6491981 René Nussbaumer
    if not read_ready:
184 d6491981 René Nussbaumer
      # We hit the timeout
185 d6491981 René Nussbaumer
      raise AssertionError("Timeout %d reached while waiting for process %d"
186 d6491981 René Nussbaumer
                           " to become ready" % (self.timeout, pid))
187 d6491981 René Nussbaumer
188 d6491981 René Nussbaumer
  def Cleanup(self):
189 d6491981 René Nussbaumer
    """Cleans up the helper.
190 d6491981 René Nussbaumer

191 d6491981 René Nussbaumer
    """
192 d6491981 René Nussbaumer
    os.close(self.read_fd)
193 d6491981 René Nussbaumer
    os.close(self.write_fd)
194 d6491981 René Nussbaumer
195 d6491981 René Nussbaumer
196 a4ccecf6 Michael Hanselmann
class TestRunCmd(testutils.GanetiTestCase):
197 a4ccecf6 Michael Hanselmann
  """Testing case for the RunCmd function"""
198 a4ccecf6 Michael Hanselmann
199 a4ccecf6 Michael Hanselmann
  def setUp(self):
200 a4ccecf6 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
201 a4ccecf6 Michael Hanselmann
    self.magic = time.ctime() + " ganeti test"
202 a4ccecf6 Michael Hanselmann
    self.fname = self._CreateTempFile()
203 a4ccecf6 Michael Hanselmann
    self.fifo_tmpdir = tempfile.mkdtemp()
204 a4ccecf6 Michael Hanselmann
    self.fifo_file = os.path.join(self.fifo_tmpdir, "ganeti_test_fifo")
205 a4ccecf6 Michael Hanselmann
    os.mkfifo(self.fifo_file)
206 a4ccecf6 Michael Hanselmann
207 d6491981 René Nussbaumer
    # If the process is not ready after 20 seconds we have bigger issues
208 d6491981 René Nussbaumer
    self.proc_ready_helper = _PostforkProcessReadyHelper(20)
209 d6491981 René Nussbaumer
210 a4ccecf6 Michael Hanselmann
  def tearDown(self):
211 d6491981 René Nussbaumer
    self.proc_ready_helper.Cleanup()
212 a4ccecf6 Michael Hanselmann
    shutil.rmtree(self.fifo_tmpdir)
213 a4ccecf6 Michael Hanselmann
    testutils.GanetiTestCase.tearDown(self)
214 a4ccecf6 Michael Hanselmann
215 a4ccecf6 Michael Hanselmann
  def testOk(self):
216 a4ccecf6 Michael Hanselmann
    """Test successful exit code"""
217 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c 'exit 0'")
218 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.exit_code, 0)
219 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.output, "")
220 a4ccecf6 Michael Hanselmann
221 a4ccecf6 Michael Hanselmann
  def testFail(self):
222 a4ccecf6 Michael Hanselmann
    """Test fail exit code"""
223 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c 'exit 1'")
224 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.exit_code, 1)
225 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.output, "")
226 a4ccecf6 Michael Hanselmann
227 a4ccecf6 Michael Hanselmann
  def testStdout(self):
228 a4ccecf6 Michael Hanselmann
    """Test standard output"""
229 a4ccecf6 Michael Hanselmann
    cmd = 'echo -n "%s"' % self.magic
230 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c '%s'" % cmd)
231 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.stdout, self.magic)
232 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname)
233 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.output, "")
234 a4ccecf6 Michael Hanselmann
    self.assertFileContent(self.fname, self.magic)
235 a4ccecf6 Michael Hanselmann
236 a4ccecf6 Michael Hanselmann
  def testStderr(self):
237 a4ccecf6 Michael Hanselmann
    """Test standard error"""
238 a4ccecf6 Michael Hanselmann
    cmd = 'echo -n "%s"' % self.magic
239 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c '%s' 1>&2" % cmd)
240 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.stderr, self.magic)
241 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c '%s' 1>&2" % cmd, output=self.fname)
242 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.output, "")
243 a4ccecf6 Michael Hanselmann
    self.assertFileContent(self.fname, self.magic)
244 a4ccecf6 Michael Hanselmann
245 a4ccecf6 Michael Hanselmann
  def testCombined(self):
246 a4ccecf6 Michael Hanselmann
    """Test combined output"""
247 a4ccecf6 Michael Hanselmann
    cmd = 'echo -n "A%s"; echo -n "B%s" 1>&2' % (self.magic, self.magic)
248 a4ccecf6 Michael Hanselmann
    expected = "A" + self.magic + "B" + self.magic
249 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c '%s'" % cmd)
250 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.output, expected)
251 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname)
252 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.output, "")
253 a4ccecf6 Michael Hanselmann
    self.assertFileContent(self.fname, expected)
254 a4ccecf6 Michael Hanselmann
255 a4ccecf6 Michael Hanselmann
  def testSignal(self):
256 a4ccecf6 Michael Hanselmann
    """Test signal"""
257 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd(["python", "-c",
258 a4ccecf6 Michael Hanselmann
                           "import os; os.kill(os.getpid(), 15)"])
259 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.signal, 15)
260 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.output, "")
261 a4ccecf6 Michael Hanselmann
262 a4ccecf6 Michael Hanselmann
  def testTimeoutClean(self):
263 d6491981 René Nussbaumer
    cmd = ("trap 'exit 0' TERM; echo >&%d; read < %s" %
264 d6491981 René Nussbaumer
           (self.proc_ready_helper.write_fd, self.fifo_file))
265 d6491981 René Nussbaumer
    result = utils.RunCmd(["/bin/sh", "-c", cmd], timeout=0.2,
266 d6491981 René Nussbaumer
                          noclose_fds=[self.proc_ready_helper.write_fd],
267 09b72783 Michael Hanselmann
                          postfork_fn=self.proc_ready_helper.Ready)
268 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.exit_code, 0)
269 a4ccecf6 Michael Hanselmann
270 a4ccecf6 Michael Hanselmann
  def testTimeoutKill(self):
271 d6491981 René Nussbaumer
    cmd = ["/bin/sh", "-c", "trap '' TERM; echo >&%d; read < %s" %
272 d6491981 René Nussbaumer
           (self.proc_ready_helper.write_fd, self.fifo_file)]
273 a4ccecf6 Michael Hanselmann
    timeout = 0.2
274 a4ccecf6 Michael Hanselmann
    (out, err, status, ta) = \
275 a4ccecf6 Michael Hanselmann
      utils.process._RunCmdPipe(cmd, {}, False, "/", False,
276 d6491981 René Nussbaumer
                                timeout, [self.proc_ready_helper.write_fd],
277 d5d76ab2 Michael Hanselmann
                                None,
278 d6491981 René Nussbaumer
                                _linger_timeout=0.2,
279 09b72783 Michael Hanselmann
                                postfork_fn=self.proc_ready_helper.Ready)
280 a4ccecf6 Michael Hanselmann
    self.assert_(status < 0)
281 a4ccecf6 Michael Hanselmann
    self.assertEqual(-status, signal.SIGKILL)
282 a4ccecf6 Michael Hanselmann
283 a4ccecf6 Michael Hanselmann
  def testTimeoutOutputAfterTerm(self):
284 d6491981 René Nussbaumer
    cmd = ("trap 'echo sigtermed; exit 1' TERM; echo >&%d; read < %s" %
285 d6491981 René Nussbaumer
           (self.proc_ready_helper.write_fd, self.fifo_file))
286 d6491981 René Nussbaumer
    result = utils.RunCmd(["/bin/sh", "-c", cmd], timeout=0.2,
287 d6491981 René Nussbaumer
                          noclose_fds=[self.proc_ready_helper.write_fd],
288 09b72783 Michael Hanselmann
                          postfork_fn=self.proc_ready_helper.Ready)
289 a4ccecf6 Michael Hanselmann
    self.assert_(result.failed)
290 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.stdout, "sigtermed\n")
291 a4ccecf6 Michael Hanselmann
292 a4ccecf6 Michael Hanselmann
  def testListRun(self):
293 a4ccecf6 Michael Hanselmann
    """Test list runs"""
294 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd(["true"])
295 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.signal, None)
296 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.exit_code, 0)
297 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd(["/bin/sh", "-c", "exit 1"])
298 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.signal, None)
299 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.exit_code, 1)
300 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd(["echo", "-n", self.magic])
301 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.signal, None)
302 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.exit_code, 0)
303 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.stdout, self.magic)
304 a4ccecf6 Michael Hanselmann
305 a4ccecf6 Michael Hanselmann
  def testFileEmptyOutput(self):
306 a4ccecf6 Michael Hanselmann
    """Test file output"""
307 a4ccecf6 Michael Hanselmann
    result = utils.RunCmd(["true"], output=self.fname)
308 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.signal, None)
309 a4ccecf6 Michael Hanselmann
    self.assertEqual(result.exit_code, 0)
310 a4ccecf6 Michael Hanselmann
    self.assertFileContent(self.fname, "")
311 a4ccecf6 Michael Hanselmann
312 a4ccecf6 Michael Hanselmann
  def testLang(self):
313 a4ccecf6 Michael Hanselmann
    """Test locale environment"""
314 a4ccecf6 Michael Hanselmann
    old_env = os.environ.copy()
315 a4ccecf6 Michael Hanselmann
    try:
316 a4ccecf6 Michael Hanselmann
      os.environ["LANG"] = "en_US.UTF-8"
317 a4ccecf6 Michael Hanselmann
      os.environ["LC_ALL"] = "en_US.UTF-8"
318 a4ccecf6 Michael Hanselmann
      result = utils.RunCmd(["locale"])
319 a4ccecf6 Michael Hanselmann
      for line in result.output.splitlines():
320 a4ccecf6 Michael Hanselmann
        key, value = line.split("=", 1)
321 a4ccecf6 Michael Hanselmann
        # Ignore these variables, they're overridden by LC_ALL
322 a4ccecf6 Michael Hanselmann
        if key == "LANG" or key == "LANGUAGE":
323 a4ccecf6 Michael Hanselmann
          continue
324 a4ccecf6 Michael Hanselmann
        self.failIf(value and value != "C" and value != '"C"',
325 a4ccecf6 Michael Hanselmann
            "Variable %s is set to the invalid value '%s'" % (key, value))
326 a4ccecf6 Michael Hanselmann
    finally:
327 a4ccecf6 Michael Hanselmann
      os.environ = old_env
328 a4ccecf6 Michael Hanselmann
329 a4ccecf6 Michael Hanselmann
  def testDefaultCwd(self):
330 a4ccecf6 Michael Hanselmann
    """Test default working directory"""
331 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunCmd(["pwd"]).stdout.strip(), "/")
332 a4ccecf6 Michael Hanselmann
333 a4ccecf6 Michael Hanselmann
  def testCwd(self):
334 a4ccecf6 Michael Hanselmann
    """Test default working directory"""
335 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunCmd(["pwd"], cwd="/").stdout.strip(), "/")
336 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunCmd(["pwd"], cwd="/tmp").stdout.strip(),
337 a4ccecf6 Michael Hanselmann
                         "/tmp")
338 a4ccecf6 Michael Hanselmann
    cwd = os.getcwd()
339 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunCmd(["pwd"], cwd=cwd).stdout.strip(), cwd)
340 a4ccecf6 Michael Hanselmann
341 a4ccecf6 Michael Hanselmann
  def testResetEnv(self):
342 a4ccecf6 Michael Hanselmann
    """Test environment reset functionality"""
343 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunCmd(["env"], reset_env=True).stdout.strip(),
344 a4ccecf6 Michael Hanselmann
                         "")
345 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunCmd(["env"], reset_env=True,
346 a4ccecf6 Michael Hanselmann
                                      env={"FOO": "bar",}).stdout.strip(),
347 a4ccecf6 Michael Hanselmann
                         "FOO=bar")
348 a4ccecf6 Michael Hanselmann
349 a4ccecf6 Michael Hanselmann
  def testNoFork(self):
350 a4ccecf6 Michael Hanselmann
    """Test that nofork raise an error"""
351 a4ccecf6 Michael Hanselmann
    self.assertFalse(utils.process._no_fork)
352 a4ccecf6 Michael Hanselmann
    utils.DisableFork()
353 a4ccecf6 Michael Hanselmann
    try:
354 a4ccecf6 Michael Hanselmann
      self.assertTrue(utils.process._no_fork)
355 a4ccecf6 Michael Hanselmann
      self.assertRaises(errors.ProgrammerError, utils.RunCmd, ["true"])
356 a4ccecf6 Michael Hanselmann
    finally:
357 a4ccecf6 Michael Hanselmann
      utils.process._no_fork = False
358 a4ccecf6 Michael Hanselmann
    self.assertFalse(utils.process._no_fork)
359 a4ccecf6 Michael Hanselmann
360 a4ccecf6 Michael Hanselmann
  def testWrongParams(self):
361 a4ccecf6 Michael Hanselmann
    """Test wrong parameters"""
362 a4ccecf6 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.RunCmd, ["true"],
363 a4ccecf6 Michael Hanselmann
                      output="/dev/null", interactive=True)
364 a4ccecf6 Michael Hanselmann
365 7b0bf9cd Apollon Oikonomopoulos
  def testNocloseFds(self):
366 7b0bf9cd Apollon Oikonomopoulos
    """Test selective fd retention (noclose_fds)"""
367 7b0bf9cd Apollon Oikonomopoulos
    temp = open(self.fname, "r+")
368 7b0bf9cd Apollon Oikonomopoulos
    try:
369 7b0bf9cd Apollon Oikonomopoulos
      temp.write("test")
370 7b0bf9cd Apollon Oikonomopoulos
      temp.seek(0)
371 7b0bf9cd Apollon Oikonomopoulos
      cmd = "read -u %d; echo $REPLY" % temp.fileno()
372 7b0bf9cd Apollon Oikonomopoulos
      result = utils.RunCmd(["/bin/bash", "-c", cmd])
373 7b0bf9cd Apollon Oikonomopoulos
      self.assertEqual(result.stdout.strip(), "")
374 7b0bf9cd Apollon Oikonomopoulos
      temp.seek(0)
375 7b0bf9cd Apollon Oikonomopoulos
      result = utils.RunCmd(["/bin/bash", "-c", cmd],
376 7b0bf9cd Apollon Oikonomopoulos
                            noclose_fds=[temp.fileno()])
377 7b0bf9cd Apollon Oikonomopoulos
      self.assertEqual(result.stdout.strip(), "test")
378 7b0bf9cd Apollon Oikonomopoulos
    finally:
379 7b0bf9cd Apollon Oikonomopoulos
      temp.close()
380 7b0bf9cd Apollon Oikonomopoulos
381 d5d76ab2 Michael Hanselmann
  def testNoInputRead(self):
382 00ef625c Michael Hanselmann
    testfile = testutils.TestDataFilename("cert1.pem")
383 d5d76ab2 Michael Hanselmann
384 d5d76ab2 Michael Hanselmann
    result = utils.RunCmd(["cat"], timeout=10.0)
385 d5d76ab2 Michael Hanselmann
    self.assertFalse(result.failed)
386 d5d76ab2 Michael Hanselmann
    self.assertEqual(result.stderr, "")
387 d5d76ab2 Michael Hanselmann
    self.assertEqual(result.stdout, "")
388 d5d76ab2 Michael Hanselmann
389 d5d76ab2 Michael Hanselmann
  def testInputFileHandle(self):
390 00ef625c Michael Hanselmann
    testfile = testutils.TestDataFilename("cert1.pem")
391 d5d76ab2 Michael Hanselmann
392 d5d76ab2 Michael Hanselmann
    result = utils.RunCmd(["cat"], input_fd=open(testfile, "r"))
393 d5d76ab2 Michael Hanselmann
    self.assertFalse(result.failed)
394 d5d76ab2 Michael Hanselmann
    self.assertEqual(result.stdout, utils.ReadFile(testfile))
395 d5d76ab2 Michael Hanselmann
    self.assertEqual(result.stderr, "")
396 d5d76ab2 Michael Hanselmann
397 d5d76ab2 Michael Hanselmann
  def testInputNumericFileDescriptor(self):
398 00ef625c Michael Hanselmann
    testfile = testutils.TestDataFilename("cert2.pem")
399 d5d76ab2 Michael Hanselmann
400 d5d76ab2 Michael Hanselmann
    fh = open(testfile, "r")
401 d5d76ab2 Michael Hanselmann
    try:
402 d5d76ab2 Michael Hanselmann
      result = utils.RunCmd(["cat"], input_fd=fh.fileno())
403 d5d76ab2 Michael Hanselmann
    finally:
404 d5d76ab2 Michael Hanselmann
      fh.close()
405 d5d76ab2 Michael Hanselmann
406 d5d76ab2 Michael Hanselmann
    self.assertFalse(result.failed)
407 d5d76ab2 Michael Hanselmann
    self.assertEqual(result.stdout, utils.ReadFile(testfile))
408 d5d76ab2 Michael Hanselmann
    self.assertEqual(result.stderr, "")
409 d5d76ab2 Michael Hanselmann
410 d5d76ab2 Michael Hanselmann
  def testInputWithCloseFds(self):
411 00ef625c Michael Hanselmann
    testfile = testutils.TestDataFilename("cert1.pem")
412 d5d76ab2 Michael Hanselmann
413 d5d76ab2 Michael Hanselmann
    temp = open(self.fname, "r+")
414 d5d76ab2 Michael Hanselmann
    try:
415 d5d76ab2 Michael Hanselmann
      temp.write("test283523367")
416 d5d76ab2 Michael Hanselmann
      temp.seek(0)
417 d5d76ab2 Michael Hanselmann
418 d5d76ab2 Michael Hanselmann
      result = utils.RunCmd(["/bin/bash", "-c",
419 d5d76ab2 Michael Hanselmann
                             ("cat && read -u %s; echo $REPLY" %
420 d5d76ab2 Michael Hanselmann
                              temp.fileno())],
421 d5d76ab2 Michael Hanselmann
                            input_fd=open(testfile, "r"),
422 d5d76ab2 Michael Hanselmann
                            noclose_fds=[temp.fileno()])
423 d5d76ab2 Michael Hanselmann
      self.assertFalse(result.failed)
424 d5d76ab2 Michael Hanselmann
      self.assertEqual(result.stdout.strip(),
425 d5d76ab2 Michael Hanselmann
                       utils.ReadFile(testfile) + "test283523367")
426 d5d76ab2 Michael Hanselmann
      self.assertEqual(result.stderr, "")
427 d5d76ab2 Michael Hanselmann
    finally:
428 d5d76ab2 Michael Hanselmann
      temp.close()
429 d5d76ab2 Michael Hanselmann
430 d5d76ab2 Michael Hanselmann
  def testOutputAndInteractive(self):
431 d5d76ab2 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.RunCmd,
432 d5d76ab2 Michael Hanselmann
                      [], output=self.fname, interactive=True)
433 d5d76ab2 Michael Hanselmann
434 d5d76ab2 Michael Hanselmann
  def testOutputAndInput(self):
435 d5d76ab2 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.RunCmd,
436 d5d76ab2 Michael Hanselmann
                      [], output=self.fname, input_fd=open(self.fname))
437 d5d76ab2 Michael Hanselmann
438 a4ccecf6 Michael Hanselmann
439 a4ccecf6 Michael Hanselmann
class TestRunParts(testutils.GanetiTestCase):
440 a4ccecf6 Michael Hanselmann
  """Testing case for the RunParts function"""
441 a4ccecf6 Michael Hanselmann
442 a4ccecf6 Michael Hanselmann
  def setUp(self):
443 a4ccecf6 Michael Hanselmann
    self.rundir = tempfile.mkdtemp(prefix="ganeti-test", suffix=".tmp")
444 a4ccecf6 Michael Hanselmann
445 a4ccecf6 Michael Hanselmann
  def tearDown(self):
446 a4ccecf6 Michael Hanselmann
    shutil.rmtree(self.rundir)
447 a4ccecf6 Michael Hanselmann
448 a4ccecf6 Michael Hanselmann
  def testEmpty(self):
449 a4ccecf6 Michael Hanselmann
    """Test on an empty dir"""
450 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunParts(self.rundir, reset_env=True), [])
451 a4ccecf6 Michael Hanselmann
452 a4ccecf6 Michael Hanselmann
  def testSkipWrongName(self):
453 a4ccecf6 Michael Hanselmann
    """Test that wrong files are skipped"""
454 a4ccecf6 Michael Hanselmann
    fname = os.path.join(self.rundir, "00test.dot")
455 a4ccecf6 Michael Hanselmann
    utils.WriteFile(fname, data="")
456 a4ccecf6 Michael Hanselmann
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
457 a4ccecf6 Michael Hanselmann
    relname = os.path.basename(fname)
458 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunParts(self.rundir, reset_env=True),
459 a4ccecf6 Michael Hanselmann
                         [(relname, constants.RUNPARTS_SKIP, None)])
460 a4ccecf6 Michael Hanselmann
461 a4ccecf6 Michael Hanselmann
  def testSkipNonExec(self):
462 a4ccecf6 Michael Hanselmann
    """Test that non executable files are skipped"""
463 a4ccecf6 Michael Hanselmann
    fname = os.path.join(self.rundir, "00test")
464 a4ccecf6 Michael Hanselmann
    utils.WriteFile(fname, data="")
465 a4ccecf6 Michael Hanselmann
    relname = os.path.basename(fname)
466 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(utils.RunParts(self.rundir, reset_env=True),
467 a4ccecf6 Michael Hanselmann
                         [(relname, constants.RUNPARTS_SKIP, None)])
468 a4ccecf6 Michael Hanselmann
469 a4ccecf6 Michael Hanselmann
  def testError(self):
470 a4ccecf6 Michael Hanselmann
    """Test error on a broken executable"""
471 a4ccecf6 Michael Hanselmann
    fname = os.path.join(self.rundir, "00test")
472 a4ccecf6 Michael Hanselmann
    utils.WriteFile(fname, data="")
473 a4ccecf6 Michael Hanselmann
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
474 a4ccecf6 Michael Hanselmann
    (relname, status, error) = utils.RunParts(self.rundir, reset_env=True)[0]
475 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(relname, os.path.basename(fname))
476 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(status, constants.RUNPARTS_ERR)
477 a4ccecf6 Michael Hanselmann
    self.failUnless(error)
478 a4ccecf6 Michael Hanselmann
479 a4ccecf6 Michael Hanselmann
  def testSorted(self):
480 a4ccecf6 Michael Hanselmann
    """Test executions are sorted"""
481 a4ccecf6 Michael Hanselmann
    files = []
482 a4ccecf6 Michael Hanselmann
    files.append(os.path.join(self.rundir, "64test"))
483 a4ccecf6 Michael Hanselmann
    files.append(os.path.join(self.rundir, "00test"))
484 a4ccecf6 Michael Hanselmann
    files.append(os.path.join(self.rundir, "42test"))
485 a4ccecf6 Michael Hanselmann
486 a4ccecf6 Michael Hanselmann
    for fname in files:
487 a4ccecf6 Michael Hanselmann
      utils.WriteFile(fname, data="")
488 a4ccecf6 Michael Hanselmann
489 a4ccecf6 Michael Hanselmann
    results = utils.RunParts(self.rundir, reset_env=True)
490 a4ccecf6 Michael Hanselmann
491 a4ccecf6 Michael Hanselmann
    for fname in sorted(files):
492 a4ccecf6 Michael Hanselmann
      self.failUnlessEqual(os.path.basename(fname), results.pop(0)[0])
493 a4ccecf6 Michael Hanselmann
494 a4ccecf6 Michael Hanselmann
  def testOk(self):
495 a4ccecf6 Michael Hanselmann
    """Test correct execution"""
496 a4ccecf6 Michael Hanselmann
    fname = os.path.join(self.rundir, "00test")
497 a4ccecf6 Michael Hanselmann
    utils.WriteFile(fname, data="#!/bin/sh\n\necho -n ciao")
498 a4ccecf6 Michael Hanselmann
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
499 a4ccecf6 Michael Hanselmann
    (relname, status, runresult) = \
500 a4ccecf6 Michael Hanselmann
      utils.RunParts(self.rundir, reset_env=True)[0]
501 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(relname, os.path.basename(fname))
502 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
503 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(runresult.stdout, "ciao")
504 a4ccecf6 Michael Hanselmann
505 a4ccecf6 Michael Hanselmann
  def testRunFail(self):
506 a4ccecf6 Michael Hanselmann
    """Test correct execution, with run failure"""
507 a4ccecf6 Michael Hanselmann
    fname = os.path.join(self.rundir, "00test")
508 a4ccecf6 Michael Hanselmann
    utils.WriteFile(fname, data="#!/bin/sh\n\nexit 1")
509 a4ccecf6 Michael Hanselmann
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
510 a4ccecf6 Michael Hanselmann
    (relname, status, runresult) = \
511 a4ccecf6 Michael Hanselmann
      utils.RunParts(self.rundir, reset_env=True)[0]
512 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(relname, os.path.basename(fname))
513 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
514 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(runresult.exit_code, 1)
515 a4ccecf6 Michael Hanselmann
    self.failUnless(runresult.failed)
516 a4ccecf6 Michael Hanselmann
517 a4ccecf6 Michael Hanselmann
  def testRunMix(self):
518 a4ccecf6 Michael Hanselmann
    files = []
519 a4ccecf6 Michael Hanselmann
    files.append(os.path.join(self.rundir, "00test"))
520 a4ccecf6 Michael Hanselmann
    files.append(os.path.join(self.rundir, "42test"))
521 a4ccecf6 Michael Hanselmann
    files.append(os.path.join(self.rundir, "64test"))
522 a4ccecf6 Michael Hanselmann
    files.append(os.path.join(self.rundir, "99test"))
523 a4ccecf6 Michael Hanselmann
524 a4ccecf6 Michael Hanselmann
    files.sort()
525 a4ccecf6 Michael Hanselmann
526 a4ccecf6 Michael Hanselmann
    # 1st has errors in execution
527 a4ccecf6 Michael Hanselmann
    utils.WriteFile(files[0], data="#!/bin/sh\n\nexit 1")
528 a4ccecf6 Michael Hanselmann
    os.chmod(files[0], stat.S_IREAD | stat.S_IEXEC)
529 a4ccecf6 Michael Hanselmann
530 a4ccecf6 Michael Hanselmann
    # 2nd is skipped
531 a4ccecf6 Michael Hanselmann
    utils.WriteFile(files[1], data="")
532 a4ccecf6 Michael Hanselmann
533 a4ccecf6 Michael Hanselmann
    # 3rd cannot execute properly
534 a4ccecf6 Michael Hanselmann
    utils.WriteFile(files[2], data="")
535 a4ccecf6 Michael Hanselmann
    os.chmod(files[2], stat.S_IREAD | stat.S_IEXEC)
536 a4ccecf6 Michael Hanselmann
537 a4ccecf6 Michael Hanselmann
    # 4th execs
538 a4ccecf6 Michael Hanselmann
    utils.WriteFile(files[3], data="#!/bin/sh\n\necho -n ciao")
539 a4ccecf6 Michael Hanselmann
    os.chmod(files[3], stat.S_IREAD | stat.S_IEXEC)
540 a4ccecf6 Michael Hanselmann
541 a4ccecf6 Michael Hanselmann
    results = utils.RunParts(self.rundir, reset_env=True)
542 a4ccecf6 Michael Hanselmann
543 a4ccecf6 Michael Hanselmann
    (relname, status, runresult) = results[0]
544 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(relname, os.path.basename(files[0]))
545 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
546 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(runresult.exit_code, 1)
547 a4ccecf6 Michael Hanselmann
    self.failUnless(runresult.failed)
548 a4ccecf6 Michael Hanselmann
549 a4ccecf6 Michael Hanselmann
    (relname, status, runresult) = results[1]
550 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(relname, os.path.basename(files[1]))
551 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(status, constants.RUNPARTS_SKIP)
552 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(runresult, None)
553 a4ccecf6 Michael Hanselmann
554 a4ccecf6 Michael Hanselmann
    (relname, status, runresult) = results[2]
555 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(relname, os.path.basename(files[2]))
556 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(status, constants.RUNPARTS_ERR)
557 a4ccecf6 Michael Hanselmann
    self.failUnless(runresult)
558 a4ccecf6 Michael Hanselmann
559 a4ccecf6 Michael Hanselmann
    (relname, status, runresult) = results[3]
560 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(relname, os.path.basename(files[3]))
561 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
562 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(runresult.output, "ciao")
563 a4ccecf6 Michael Hanselmann
    self.failUnlessEqual(runresult.exit_code, 0)
564 a4ccecf6 Michael Hanselmann
    self.failUnless(not runresult.failed)
565 a4ccecf6 Michael Hanselmann
566 a4ccecf6 Michael Hanselmann
  def testMissingDirectory(self):
567 a4ccecf6 Michael Hanselmann
    nosuchdir = utils.PathJoin(self.rundir, "no/such/directory")
568 a4ccecf6 Michael Hanselmann
    self.assertEqual(utils.RunParts(nosuchdir), [])
569 a4ccecf6 Michael Hanselmann
570 a4ccecf6 Michael Hanselmann
571 a4ccecf6 Michael Hanselmann
class TestStartDaemon(testutils.GanetiTestCase):
572 a4ccecf6 Michael Hanselmann
  def setUp(self):
573 a4ccecf6 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp(prefix="ganeti-test")
574 a4ccecf6 Michael Hanselmann
    self.tmpfile = os.path.join(self.tmpdir, "test")
575 a4ccecf6 Michael Hanselmann
576 a4ccecf6 Michael Hanselmann
  def tearDown(self):
577 a4ccecf6 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
578 a4ccecf6 Michael Hanselmann
579 a4ccecf6 Michael Hanselmann
  def testShell(self):
580 a4ccecf6 Michael Hanselmann
    utils.StartDaemon("echo Hello World > %s" % self.tmpfile)
581 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
582 a4ccecf6 Michael Hanselmann
583 a4ccecf6 Michael Hanselmann
  def testShellOutput(self):
584 a4ccecf6 Michael Hanselmann
    utils.StartDaemon("echo Hello World", output=self.tmpfile)
585 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
586 a4ccecf6 Michael Hanselmann
587 a4ccecf6 Michael Hanselmann
  def testNoShellNoOutput(self):
588 a4ccecf6 Michael Hanselmann
    utils.StartDaemon(["pwd"])
589 a4ccecf6 Michael Hanselmann
590 a4ccecf6 Michael Hanselmann
  def testNoShellNoOutputTouch(self):
591 a4ccecf6 Michael Hanselmann
    testfile = os.path.join(self.tmpdir, "check")
592 a4ccecf6 Michael Hanselmann
    self.failIf(os.path.exists(testfile))
593 a4ccecf6 Michael Hanselmann
    utils.StartDaemon(["touch", testfile])
594 a4ccecf6 Michael Hanselmann
    self._wait(testfile, 60.0, "")
595 a4ccecf6 Michael Hanselmann
596 a4ccecf6 Michael Hanselmann
  def testNoShellOutput(self):
597 a4ccecf6 Michael Hanselmann
    utils.StartDaemon(["pwd"], output=self.tmpfile)
598 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "/")
599 a4ccecf6 Michael Hanselmann
600 a4ccecf6 Michael Hanselmann
  def testNoShellOutputCwd(self):
601 a4ccecf6 Michael Hanselmann
    utils.StartDaemon(["pwd"], output=self.tmpfile, cwd=os.getcwd())
602 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, os.getcwd())
603 a4ccecf6 Michael Hanselmann
604 a4ccecf6 Michael Hanselmann
  def testShellEnv(self):
605 a4ccecf6 Michael Hanselmann
    utils.StartDaemon("echo \"$GNT_TEST_VAR\"", output=self.tmpfile,
606 a4ccecf6 Michael Hanselmann
                      env={ "GNT_TEST_VAR": "Hello World", })
607 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
608 a4ccecf6 Michael Hanselmann
609 a4ccecf6 Michael Hanselmann
  def testNoShellEnv(self):
610 a4ccecf6 Michael Hanselmann
    utils.StartDaemon(["printenv", "GNT_TEST_VAR"], output=self.tmpfile,
611 a4ccecf6 Michael Hanselmann
                      env={ "GNT_TEST_VAR": "Hello World", })
612 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
613 a4ccecf6 Michael Hanselmann
614 a4ccecf6 Michael Hanselmann
  def testOutputFd(self):
615 a4ccecf6 Michael Hanselmann
    fd = os.open(self.tmpfile, os.O_WRONLY | os.O_CREAT)
616 a4ccecf6 Michael Hanselmann
    try:
617 a4ccecf6 Michael Hanselmann
      utils.StartDaemon(["pwd"], output_fd=fd, cwd=os.getcwd())
618 a4ccecf6 Michael Hanselmann
    finally:
619 a4ccecf6 Michael Hanselmann
      os.close(fd)
620 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, os.getcwd())
621 a4ccecf6 Michael Hanselmann
622 a4ccecf6 Michael Hanselmann
  def testPid(self):
623 a4ccecf6 Michael Hanselmann
    pid = utils.StartDaemon("echo $$ > %s" % self.tmpfile)
624 a4ccecf6 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, str(pid))
625 a4ccecf6 Michael Hanselmann
626 a4ccecf6 Michael Hanselmann
  def testPidFile(self):
627 a4ccecf6 Michael Hanselmann
    pidfile = os.path.join(self.tmpdir, "pid")
628 a4ccecf6 Michael Hanselmann
    checkfile = os.path.join(self.tmpdir, "abort")
629 a4ccecf6 Michael Hanselmann
630 a4ccecf6 Michael Hanselmann
    pid = utils.StartDaemon("while sleep 5; do :; done", pidfile=pidfile,
631 a4ccecf6 Michael Hanselmann
                            output=self.tmpfile)
632 a4ccecf6 Michael Hanselmann
    try:
633 a4ccecf6 Michael Hanselmann
      fd = os.open(pidfile, os.O_RDONLY)
634 a4ccecf6 Michael Hanselmann
      try:
635 a4ccecf6 Michael Hanselmann
        # Check file is locked
636 a4ccecf6 Michael Hanselmann
        self.assertRaises(errors.LockError, utils.LockFile, fd)
637 a4ccecf6 Michael Hanselmann
638 a4ccecf6 Michael Hanselmann
        pidtext = os.read(fd, 100)
639 a4ccecf6 Michael Hanselmann
      finally:
640 a4ccecf6 Michael Hanselmann
        os.close(fd)
641 a4ccecf6 Michael Hanselmann
642 a4ccecf6 Michael Hanselmann
      self.assertEqual(int(pidtext.strip()), pid)
643 a4ccecf6 Michael Hanselmann
644 a4ccecf6 Michael Hanselmann
      self.assert_(utils.IsProcessAlive(pid))
645 a4ccecf6 Michael Hanselmann
    finally:
646 a4ccecf6 Michael Hanselmann
      # No matter what happens, kill daemon
647 a4ccecf6 Michael Hanselmann
      utils.KillProcess(pid, timeout=5.0, waitpid=False)
648 a4ccecf6 Michael Hanselmann
      self.failIf(utils.IsProcessAlive(pid))
649 a4ccecf6 Michael Hanselmann
650 a4ccecf6 Michael Hanselmann
    self.assertEqual(utils.ReadFile(self.tmpfile), "")
651 a4ccecf6 Michael Hanselmann
652 a4ccecf6 Michael Hanselmann
  def _wait(self, path, timeout, expected):
653 a4ccecf6 Michael Hanselmann
    # Due to the asynchronous nature of daemon processes, polling is necessary.
654 a4ccecf6 Michael Hanselmann
    # A timeout makes sure the test doesn't hang forever.
655 a4ccecf6 Michael Hanselmann
    def _CheckFile():
656 a4ccecf6 Michael Hanselmann
      if not (os.path.isfile(path) and
657 a4ccecf6 Michael Hanselmann
              utils.ReadFile(path).strip() == expected):
658 a4ccecf6 Michael Hanselmann
        raise utils.RetryAgain()
659 a4ccecf6 Michael Hanselmann
660 a4ccecf6 Michael Hanselmann
    try:
661 a4ccecf6 Michael Hanselmann
      utils.Retry(_CheckFile, (0.01, 1.5, 1.0), timeout)
662 a4ccecf6 Michael Hanselmann
    except utils.RetryTimeout:
663 a4ccecf6 Michael Hanselmann
      self.fail("Apparently the daemon didn't run in %s seconds and/or"
664 a4ccecf6 Michael Hanselmann
                " didn't write the correct output" % timeout)
665 a4ccecf6 Michael Hanselmann
666 a4ccecf6 Michael Hanselmann
  def testError(self):
667 a4ccecf6 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
668 a4ccecf6 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"])
669 a4ccecf6 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
670 a4ccecf6 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"],
671 a4ccecf6 Michael Hanselmann
                      output=os.path.join(self.tmpdir, "DIR/NOT/EXIST"))
672 a4ccecf6 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
673 a4ccecf6 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"],
674 a4ccecf6 Michael Hanselmann
                      cwd=os.path.join(self.tmpdir, "DIR/NOT/EXIST"))
675 a4ccecf6 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
676 a4ccecf6 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"],
677 a4ccecf6 Michael Hanselmann
                      output=os.path.join(self.tmpdir, "DIR/NOT/EXIST"))
678 a4ccecf6 Michael Hanselmann
679 a4ccecf6 Michael Hanselmann
    fd = os.open(self.tmpfile, os.O_WRONLY | os.O_CREAT)
680 a4ccecf6 Michael Hanselmann
    try:
681 a4ccecf6 Michael Hanselmann
      self.assertRaises(errors.ProgrammerError, utils.StartDaemon,
682 a4ccecf6 Michael Hanselmann
                        ["./does-NOT-EXIST/here/0123456789"],
683 a4ccecf6 Michael Hanselmann
                        output=self.tmpfile, output_fd=fd)
684 a4ccecf6 Michael Hanselmann
    finally:
685 a4ccecf6 Michael Hanselmann
      os.close(fd)
686 a4ccecf6 Michael Hanselmann
687 a4ccecf6 Michael Hanselmann
688 a4ccecf6 Michael Hanselmann
class RunInSeparateProcess(unittest.TestCase):
689 a4ccecf6 Michael Hanselmann
  def test(self):
690 a4ccecf6 Michael Hanselmann
    for exp in [True, False]:
691 a4ccecf6 Michael Hanselmann
      def _child():
692 a4ccecf6 Michael Hanselmann
        return exp
693 a4ccecf6 Michael Hanselmann
694 a4ccecf6 Michael Hanselmann
      self.assertEqual(exp, utils.RunInSeparateProcess(_child))
695 a4ccecf6 Michael Hanselmann
696 a4ccecf6 Michael Hanselmann
  def testArgs(self):
697 a4ccecf6 Michael Hanselmann
    for arg in [0, 1, 999, "Hello World", (1, 2, 3)]:
698 a4ccecf6 Michael Hanselmann
      def _child(carg1, carg2):
699 a4ccecf6 Michael Hanselmann
        return carg1 == "Foo" and carg2 == arg
700 a4ccecf6 Michael Hanselmann
701 a4ccecf6 Michael Hanselmann
      self.assert_(utils.RunInSeparateProcess(_child, "Foo", arg))
702 a4ccecf6 Michael Hanselmann
703 a4ccecf6 Michael Hanselmann
  def testPid(self):
704 a4ccecf6 Michael Hanselmann
    parent_pid = os.getpid()
705 a4ccecf6 Michael Hanselmann
706 a4ccecf6 Michael Hanselmann
    def _check():
707 a4ccecf6 Michael Hanselmann
      return os.getpid() == parent_pid
708 a4ccecf6 Michael Hanselmann
709 a4ccecf6 Michael Hanselmann
    self.failIf(utils.RunInSeparateProcess(_check))
710 a4ccecf6 Michael Hanselmann
711 a4ccecf6 Michael Hanselmann
  def testSignal(self):
712 a4ccecf6 Michael Hanselmann
    def _kill():
713 a4ccecf6 Michael Hanselmann
      os.kill(os.getpid(), signal.SIGTERM)
714 a4ccecf6 Michael Hanselmann
715 a4ccecf6 Michael Hanselmann
    self.assertRaises(errors.GenericError,
716 a4ccecf6 Michael Hanselmann
                      utils.RunInSeparateProcess, _kill)
717 a4ccecf6 Michael Hanselmann
718 a4ccecf6 Michael Hanselmann
  def testException(self):
719 a4ccecf6 Michael Hanselmann
    def _exc():
720 a4ccecf6 Michael Hanselmann
      raise errors.GenericError("This is a test")
721 a4ccecf6 Michael Hanselmann
722 a4ccecf6 Michael Hanselmann
    self.assertRaises(errors.GenericError,
723 a4ccecf6 Michael Hanselmann
                      utils.RunInSeparateProcess, _exc)
724 a4ccecf6 Michael Hanselmann
725 a4ccecf6 Michael Hanselmann
726 a4ccecf6 Michael Hanselmann
if __name__ == "__main__":
727 a4ccecf6 Michael Hanselmann
  testutils.GanetiTestProgram()