root / test / py / ganeti.utils.process_unittest.py @ 8f096849
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() |