Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.utils_unittest.py @ 033a1d00

History | View | Annotate | Download (62.9 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Script for unittesting the utils module"""
23 a8083063 Iustin Pop
24 a8083063 Iustin Pop
import unittest
25 a8083063 Iustin Pop
import os
26 a8083063 Iustin Pop
import time
27 a8083063 Iustin Pop
import tempfile
28 a8083063 Iustin Pop
import os.path
29 320b4e2d Alexander Schreiber
import os
30 6bb65e3a Guido Trotter
import stat
31 740c5aab Guido Trotter
import signal
32 2c30e9d7 Alexander Schreiber
import socket
33 eedbda4b Michael Hanselmann
import shutil
34 59072e7e Michael Hanselmann
import re
35 09352fa4 Iustin Pop
import select
36 d392fa34 Iustin Pop
import string
37 73027ed2 Michael Hanselmann
import fcntl
38 bdd5e420 Michael Hanselmann
import OpenSSL
39 27e46076 Michael Hanselmann
import warnings
40 27e46076 Michael Hanselmann
import distutils.version
41 1d466a4f Michael Hanselmann
import glob
42 a8083063 Iustin Pop
43 a8083063 Iustin Pop
import ganeti
44 c9c4f19e Michael Hanselmann
import testutils
45 16abfbc2 Alexander Schreiber
from ganeti import constants
46 59072e7e Michael Hanselmann
from ganeti import utils
47 a5728081 Guido Trotter
from ganeti import errors
48 e5392d79 Iustin Pop
from ganeti.utils import IsProcessAlive, RunCmd, \
49 31e22135 Iustin Pop
     RemoveFile, MatchNameComponent, FormatUnit, \
50 a8083063 Iustin Pop
     ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
51 899d2a81 Michael Hanselmann
     ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \
52 f65f63ef Iustin Pop
     SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree, OwnIpAddress, \
53 5b69bc7c Iustin Pop
     TailFile, ForceDictType, SafeEncode, IsNormAbsPath, FormatTime, \
54 26288e68 Iustin Pop
     UnescapeAndSplit, RunParts, PathJoin, HostInfo
55 f65f63ef Iustin Pop
56 b2a1f511 Iustin Pop
from ganeti.errors import LockError, UnitParseError, GenericError, \
57 26288e68 Iustin Pop
     ProgrammerError, OpPrereqError
58 a8083063 Iustin Pop
59 d9f311d7 Iustin Pop
60 a8083063 Iustin Pop
class TestIsProcessAlive(unittest.TestCase):
61 a8083063 Iustin Pop
  """Testing case for IsProcessAlive"""
62 740c5aab Guido Trotter
63 a8083063 Iustin Pop
  def testExists(self):
64 a8083063 Iustin Pop
    mypid = os.getpid()
65 a8083063 Iustin Pop
    self.assert_(IsProcessAlive(mypid),
66 a8083063 Iustin Pop
                 "can't find myself running")
67 a8083063 Iustin Pop
68 a8083063 Iustin Pop
  def testNotExisting(self):
69 09352fa4 Iustin Pop
    pid_non_existing = os.fork()
70 09352fa4 Iustin Pop
    if pid_non_existing == 0:
71 09352fa4 Iustin Pop
      os._exit(0)
72 09352fa4 Iustin Pop
    elif pid_non_existing < 0:
73 09352fa4 Iustin Pop
      raise SystemError("can't fork")
74 09352fa4 Iustin Pop
    os.waitpid(pid_non_existing, 0)
75 09352fa4 Iustin Pop
    self.assert_(not IsProcessAlive(pid_non_existing),
76 09352fa4 Iustin Pop
                 "nonexisting process detected")
77 a8083063 Iustin Pop
78 d9f311d7 Iustin Pop
79 af99afa6 Guido Trotter
class TestPidFileFunctions(unittest.TestCase):
80 d9f311d7 Iustin Pop
  """Tests for WritePidFile, RemovePidFile and ReadPidFile"""
81 af99afa6 Guido Trotter
82 af99afa6 Guido Trotter
  def setUp(self):
83 af99afa6 Guido Trotter
    self.dir = tempfile.mkdtemp()
84 af99afa6 Guido Trotter
    self.f_dpn = lambda name: os.path.join(self.dir, "%s.pid" % name)
85 53beffbb Iustin Pop
    utils.DaemonPidFileName = self.f_dpn
86 af99afa6 Guido Trotter
87 af99afa6 Guido Trotter
  def testPidFileFunctions(self):
88 d9f311d7 Iustin Pop
    pid_file = self.f_dpn('test')
89 af99afa6 Guido Trotter
    utils.WritePidFile('test')
90 d9f311d7 Iustin Pop
    self.failUnless(os.path.exists(pid_file),
91 d9f311d7 Iustin Pop
                    "PID file should have been created")
92 d9f311d7 Iustin Pop
    read_pid = utils.ReadPidFile(pid_file)
93 d9f311d7 Iustin Pop
    self.failUnlessEqual(read_pid, os.getpid())
94 d9f311d7 Iustin Pop
    self.failUnless(utils.IsProcessAlive(read_pid))
95 d9f311d7 Iustin Pop
    self.failUnlessRaises(GenericError, utils.WritePidFile, 'test')
96 d9f311d7 Iustin Pop
    utils.RemovePidFile('test')
97 d9f311d7 Iustin Pop
    self.failIf(os.path.exists(pid_file),
98 d9f311d7 Iustin Pop
                "PID file should not exist anymore")
99 d9f311d7 Iustin Pop
    self.failUnlessEqual(utils.ReadPidFile(pid_file), 0,
100 d9f311d7 Iustin Pop
                         "ReadPidFile should return 0 for missing pid file")
101 d9f311d7 Iustin Pop
    fh = open(pid_file, "w")
102 d9f311d7 Iustin Pop
    fh.write("blah\n")
103 d9f311d7 Iustin Pop
    fh.close()
104 d9f311d7 Iustin Pop
    self.failUnlessEqual(utils.ReadPidFile(pid_file), 0,
105 d9f311d7 Iustin Pop
                         "ReadPidFile should return 0 for invalid pid file")
106 af99afa6 Guido Trotter
    utils.RemovePidFile('test')
107 d9f311d7 Iustin Pop
    self.failIf(os.path.exists(pid_file),
108 d9f311d7 Iustin Pop
                "PID file should not exist anymore")
109 af99afa6 Guido Trotter
110 b2a1f511 Iustin Pop
  def testKill(self):
111 b2a1f511 Iustin Pop
    pid_file = self.f_dpn('child')
112 b2a1f511 Iustin Pop
    r_fd, w_fd = os.pipe()
113 b2a1f511 Iustin Pop
    new_pid = os.fork()
114 b2a1f511 Iustin Pop
    if new_pid == 0: #child
115 b2a1f511 Iustin Pop
      utils.WritePidFile('child')
116 b2a1f511 Iustin Pop
      os.write(w_fd, 'a')
117 b2a1f511 Iustin Pop
      signal.pause()
118 b2a1f511 Iustin Pop
      os._exit(0)
119 b2a1f511 Iustin Pop
      return
120 b2a1f511 Iustin Pop
    # else we are in the parent
121 b2a1f511 Iustin Pop
    # wait until the child has written the pid file
122 b2a1f511 Iustin Pop
    os.read(r_fd, 1)
123 b2a1f511 Iustin Pop
    read_pid = utils.ReadPidFile(pid_file)
124 b2a1f511 Iustin Pop
    self.failUnlessEqual(read_pid, new_pid)
125 b2a1f511 Iustin Pop
    self.failUnless(utils.IsProcessAlive(new_pid))
126 ff5251bc Iustin Pop
    utils.KillProcess(new_pid, waitpid=True)
127 b2a1f511 Iustin Pop
    self.failIf(utils.IsProcessAlive(new_pid))
128 b2a1f511 Iustin Pop
    utils.RemovePidFile('child')
129 b2a1f511 Iustin Pop
    self.failUnlessRaises(ProgrammerError, utils.KillProcess, 0)
130 b2a1f511 Iustin Pop
131 af99afa6 Guido Trotter
  def tearDown(self):
132 d9f311d7 Iustin Pop
    for name in os.listdir(self.dir):
133 d9f311d7 Iustin Pop
      os.unlink(os.path.join(self.dir, name))
134 af99afa6 Guido Trotter
    os.rmdir(self.dir)
135 af99afa6 Guido Trotter
136 a8083063 Iustin Pop
137 36117c2b Iustin Pop
class TestRunCmd(testutils.GanetiTestCase):
138 a8083063 Iustin Pop
  """Testing case for the RunCmd function"""
139 a8083063 Iustin Pop
140 a8083063 Iustin Pop
  def setUp(self):
141 51596eb2 Iustin Pop
    testutils.GanetiTestCase.setUp(self)
142 a8083063 Iustin Pop
    self.magic = time.ctime() + " ganeti test"
143 51596eb2 Iustin Pop
    self.fname = self._CreateTempFile()
144 a8083063 Iustin Pop
145 a8083063 Iustin Pop
  def testOk(self):
146 31ee599c Michael Hanselmann
    """Test successful exit code"""
147 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c 'exit 0'")
148 a8083063 Iustin Pop
    self.assertEqual(result.exit_code, 0)
149 36117c2b Iustin Pop
    self.assertEqual(result.output, "")
150 a8083063 Iustin Pop
151 a8083063 Iustin Pop
  def testFail(self):
152 a8083063 Iustin Pop
    """Test fail exit code"""
153 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c 'exit 1'")
154 a8083063 Iustin Pop
    self.assertEqual(result.exit_code, 1)
155 36117c2b Iustin Pop
    self.assertEqual(result.output, "")
156 a8083063 Iustin Pop
157 a8083063 Iustin Pop
  def testStdout(self):
158 a8083063 Iustin Pop
    """Test standard output"""
159 a8083063 Iustin Pop
    cmd = 'echo -n "%s"' % self.magic
160 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c '%s'" % cmd)
161 a8083063 Iustin Pop
    self.assertEqual(result.stdout, self.magic)
162 36117c2b Iustin Pop
    result = RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname)
163 36117c2b Iustin Pop
    self.assertEqual(result.output, "")
164 36117c2b Iustin Pop
    self.assertFileContent(self.fname, self.magic)
165 a8083063 Iustin Pop
166 a8083063 Iustin Pop
  def testStderr(self):
167 a8083063 Iustin Pop
    """Test standard error"""
168 a8083063 Iustin Pop
    cmd = 'echo -n "%s"' % self.magic
169 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c '%s' 1>&2" % cmd)
170 a8083063 Iustin Pop
    self.assertEqual(result.stderr, self.magic)
171 36117c2b Iustin Pop
    result = RunCmd("/bin/sh -c '%s' 1>&2" % cmd, output=self.fname)
172 36117c2b Iustin Pop
    self.assertEqual(result.output, "")
173 36117c2b Iustin Pop
    self.assertFileContent(self.fname, self.magic)
174 a8083063 Iustin Pop
175 a8083063 Iustin Pop
  def testCombined(self):
176 a8083063 Iustin Pop
    """Test combined output"""
177 a8083063 Iustin Pop
    cmd = 'echo -n "A%s"; echo -n "B%s" 1>&2' % (self.magic, self.magic)
178 36117c2b Iustin Pop
    expected = "A" + self.magic + "B" + self.magic
179 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c '%s'" % cmd)
180 36117c2b Iustin Pop
    self.assertEqual(result.output, expected)
181 36117c2b Iustin Pop
    result = RunCmd("/bin/sh -c '%s'" % cmd, output=self.fname)
182 36117c2b Iustin Pop
    self.assertEqual(result.output, "")
183 36117c2b Iustin Pop
    self.assertFileContent(self.fname, expected)
184 a8083063 Iustin Pop
185 a8083063 Iustin Pop
  def testSignal(self):
186 01fd6005 Manuel Franceschini
    """Test signal"""
187 01fd6005 Manuel Franceschini
    result = RunCmd(["python", "-c", "import os; os.kill(os.getpid(), 15)"])
188 a8083063 Iustin Pop
    self.assertEqual(result.signal, 15)
189 36117c2b Iustin Pop
    self.assertEqual(result.output, "")
190 a8083063 Iustin Pop
191 7fcf849f Iustin Pop
  def testListRun(self):
192 7fcf849f Iustin Pop
    """Test list runs"""
193 7fcf849f Iustin Pop
    result = RunCmd(["true"])
194 7fcf849f Iustin Pop
    self.assertEqual(result.signal, None)
195 7fcf849f Iustin Pop
    self.assertEqual(result.exit_code, 0)
196 7fcf849f Iustin Pop
    result = RunCmd(["/bin/sh", "-c", "exit 1"])
197 7fcf849f Iustin Pop
    self.assertEqual(result.signal, None)
198 7fcf849f Iustin Pop
    self.assertEqual(result.exit_code, 1)
199 7fcf849f Iustin Pop
    result = RunCmd(["echo", "-n", self.magic])
200 7fcf849f Iustin Pop
    self.assertEqual(result.signal, None)
201 7fcf849f Iustin Pop
    self.assertEqual(result.exit_code, 0)
202 7fcf849f Iustin Pop
    self.assertEqual(result.stdout, self.magic)
203 7fcf849f Iustin Pop
204 36117c2b Iustin Pop
  def testFileEmptyOutput(self):
205 36117c2b Iustin Pop
    """Test file output"""
206 36117c2b Iustin Pop
    result = RunCmd(["true"], output=self.fname)
207 36117c2b Iustin Pop
    self.assertEqual(result.signal, None)
208 36117c2b Iustin Pop
    self.assertEqual(result.exit_code, 0)
209 36117c2b Iustin Pop
    self.assertFileContent(self.fname, "")
210 36117c2b Iustin Pop
211 f6441c7c Iustin Pop
  def testLang(self):
212 f6441c7c Iustin Pop
    """Test locale environment"""
213 23f41a3e Michael Hanselmann
    old_env = os.environ.copy()
214 23f41a3e Michael Hanselmann
    try:
215 23f41a3e Michael Hanselmann
      os.environ["LANG"] = "en_US.UTF-8"
216 23f41a3e Michael Hanselmann
      os.environ["LC_ALL"] = "en_US.UTF-8"
217 23f41a3e Michael Hanselmann
      result = RunCmd(["locale"])
218 23f41a3e Michael Hanselmann
      for line in result.output.splitlines():
219 23f41a3e Michael Hanselmann
        key, value = line.split("=", 1)
220 23f41a3e Michael Hanselmann
        # Ignore these variables, they're overridden by LC_ALL
221 23f41a3e Michael Hanselmann
        if key == "LANG" or key == "LANGUAGE":
222 23f41a3e Michael Hanselmann
          continue
223 23f41a3e Michael Hanselmann
        self.failIf(value and value != "C" and value != '"C"',
224 23f41a3e Michael Hanselmann
            "Variable %s is set to the invalid value '%s'" % (key, value))
225 23f41a3e Michael Hanselmann
    finally:
226 23f41a3e Michael Hanselmann
      os.environ = old_env
227 f6441c7c Iustin Pop
228 8797df43 Iustin Pop
  def testDefaultCwd(self):
229 8797df43 Iustin Pop
    """Test default working directory"""
230 8797df43 Iustin Pop
    self.failUnlessEqual(RunCmd(["pwd"]).stdout.strip(), "/")
231 8797df43 Iustin Pop
232 8797df43 Iustin Pop
  def testCwd(self):
233 8797df43 Iustin Pop
    """Test default working directory"""
234 8797df43 Iustin Pop
    self.failUnlessEqual(RunCmd(["pwd"], cwd="/").stdout.strip(), "/")
235 8797df43 Iustin Pop
    self.failUnlessEqual(RunCmd(["pwd"], cwd="/tmp").stdout.strip(), "/tmp")
236 8797df43 Iustin Pop
    cwd = os.getcwd()
237 8797df43 Iustin Pop
    self.failUnlessEqual(RunCmd(["pwd"], cwd=cwd).stdout.strip(), cwd)
238 8797df43 Iustin Pop
239 bf4daac9 Guido Trotter
  def testResetEnv(self):
240 bf4daac9 Guido Trotter
    """Test environment reset functionality"""
241 bf4daac9 Guido Trotter
    self.failUnlessEqual(RunCmd(["env"], reset_env=True).stdout.strip(), "")
242 0babc371 Michael Hanselmann
    self.failUnlessEqual(RunCmd(["env"], reset_env=True,
243 0babc371 Michael Hanselmann
                                env={"FOO": "bar",}).stdout.strip(), "FOO=bar")
244 bf4daac9 Guido Trotter
245 a8083063 Iustin Pop
246 6bb65e3a Guido Trotter
class TestRunParts(unittest.TestCase):
247 6bb65e3a Guido Trotter
  """Testing case for the RunParts function"""
248 6bb65e3a Guido Trotter
249 6bb65e3a Guido Trotter
  def setUp(self):
250 6bb65e3a Guido Trotter
    self.rundir = tempfile.mkdtemp(prefix="ganeti-test", suffix=".tmp")
251 6bb65e3a Guido Trotter
252 6bb65e3a Guido Trotter
  def tearDown(self):
253 6bb65e3a Guido Trotter
    shutil.rmtree(self.rundir)
254 6bb65e3a Guido Trotter
255 6bb65e3a Guido Trotter
  def testEmpty(self):
256 6bb65e3a Guido Trotter
    """Test on an empty dir"""
257 6bb65e3a Guido Trotter
    self.failUnlessEqual(RunParts(self.rundir, reset_env=True), [])
258 6bb65e3a Guido Trotter
259 6bb65e3a Guido Trotter
  def testSkipWrongName(self):
260 6bb65e3a Guido Trotter
    """Test that wrong files are skipped"""
261 6bb65e3a Guido Trotter
    fname = os.path.join(self.rundir, "00test.dot")
262 6bb65e3a Guido Trotter
    utils.WriteFile(fname, data="")
263 6bb65e3a Guido Trotter
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
264 6bb65e3a Guido Trotter
    relname = os.path.basename(fname)
265 6bb65e3a Guido Trotter
    self.failUnlessEqual(RunParts(self.rundir, reset_env=True),
266 6bb65e3a Guido Trotter
                         [(relname, constants.RUNPARTS_SKIP, None)])
267 6bb65e3a Guido Trotter
268 6bb65e3a Guido Trotter
  def testSkipNonExec(self):
269 6bb65e3a Guido Trotter
    """Test that non executable files are skipped"""
270 6bb65e3a Guido Trotter
    fname = os.path.join(self.rundir, "00test")
271 6bb65e3a Guido Trotter
    utils.WriteFile(fname, data="")
272 6bb65e3a Guido Trotter
    relname = os.path.basename(fname)
273 6bb65e3a Guido Trotter
    self.failUnlessEqual(RunParts(self.rundir, reset_env=True),
274 6bb65e3a Guido Trotter
                         [(relname, constants.RUNPARTS_SKIP, None)])
275 6bb65e3a Guido Trotter
276 6bb65e3a Guido Trotter
  def testError(self):
277 6bb65e3a Guido Trotter
    """Test error on a broken executable"""
278 6bb65e3a Guido Trotter
    fname = os.path.join(self.rundir, "00test")
279 6bb65e3a Guido Trotter
    utils.WriteFile(fname, data="")
280 6bb65e3a Guido Trotter
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
281 6bb65e3a Guido Trotter
    (relname, status, error) = RunParts(self.rundir, reset_env=True)[0]
282 6bb65e3a Guido Trotter
    self.failUnlessEqual(relname, os.path.basename(fname))
283 6bb65e3a Guido Trotter
    self.failUnlessEqual(status, constants.RUNPARTS_ERR)
284 6bb65e3a Guido Trotter
    self.failUnless(error)
285 6bb65e3a Guido Trotter
286 6bb65e3a Guido Trotter
  def testSorted(self):
287 6bb65e3a Guido Trotter
    """Test executions are sorted"""
288 6bb65e3a Guido Trotter
    files = []
289 6bb65e3a Guido Trotter
    files.append(os.path.join(self.rundir, "64test"))
290 6bb65e3a Guido Trotter
    files.append(os.path.join(self.rundir, "00test"))
291 6bb65e3a Guido Trotter
    files.append(os.path.join(self.rundir, "42test"))
292 6bb65e3a Guido Trotter
293 6bb65e3a Guido Trotter
    for fname in files:
294 6bb65e3a Guido Trotter
      utils.WriteFile(fname, data="")
295 6bb65e3a Guido Trotter
296 6bb65e3a Guido Trotter
    results = RunParts(self.rundir, reset_env=True)
297 6bb65e3a Guido Trotter
298 6bb65e3a Guido Trotter
    for fname in sorted(files):
299 6bb65e3a Guido Trotter
      self.failUnlessEqual(os.path.basename(fname), results.pop(0)[0])
300 6bb65e3a Guido Trotter
301 6bb65e3a Guido Trotter
  def testOk(self):
302 6bb65e3a Guido Trotter
    """Test correct execution"""
303 6bb65e3a Guido Trotter
    fname = os.path.join(self.rundir, "00test")
304 6bb65e3a Guido Trotter
    utils.WriteFile(fname, data="#!/bin/sh\n\necho -n ciao")
305 6bb65e3a Guido Trotter
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
306 6bb65e3a Guido Trotter
    (relname, status, runresult) = RunParts(self.rundir, reset_env=True)[0]
307 6bb65e3a Guido Trotter
    self.failUnlessEqual(relname, os.path.basename(fname))
308 6bb65e3a Guido Trotter
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
309 6bb65e3a Guido Trotter
    self.failUnlessEqual(runresult.stdout, "ciao")
310 6bb65e3a Guido Trotter
311 6bb65e3a Guido Trotter
  def testRunFail(self):
312 6bb65e3a Guido Trotter
    """Test correct execution, with run failure"""
313 6bb65e3a Guido Trotter
    fname = os.path.join(self.rundir, "00test")
314 6bb65e3a Guido Trotter
    utils.WriteFile(fname, data="#!/bin/sh\n\nexit 1")
315 6bb65e3a Guido Trotter
    os.chmod(fname, stat.S_IREAD | stat.S_IEXEC)
316 6bb65e3a Guido Trotter
    (relname, status, runresult) = RunParts(self.rundir, reset_env=True)[0]
317 6bb65e3a Guido Trotter
    self.failUnlessEqual(relname, os.path.basename(fname))
318 6bb65e3a Guido Trotter
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
319 6bb65e3a Guido Trotter
    self.failUnlessEqual(runresult.exit_code, 1)
320 6bb65e3a Guido Trotter
    self.failUnless(runresult.failed)
321 6bb65e3a Guido Trotter
322 6bb65e3a Guido Trotter
  def testRunMix(self):
323 6bb65e3a Guido Trotter
    files = []
324 6bb65e3a Guido Trotter
    files.append(os.path.join(self.rundir, "00test"))
325 6bb65e3a Guido Trotter
    files.append(os.path.join(self.rundir, "42test"))
326 6bb65e3a Guido Trotter
    files.append(os.path.join(self.rundir, "64test"))
327 6bb65e3a Guido Trotter
    files.append(os.path.join(self.rundir, "99test"))
328 6bb65e3a Guido Trotter
329 6bb65e3a Guido Trotter
    files.sort()
330 6bb65e3a Guido Trotter
331 6bb65e3a Guido Trotter
    # 1st has errors in execution
332 6bb65e3a Guido Trotter
    utils.WriteFile(files[0], data="#!/bin/sh\n\nexit 1")
333 6bb65e3a Guido Trotter
    os.chmod(files[0], stat.S_IREAD | stat.S_IEXEC)
334 6bb65e3a Guido Trotter
335 6bb65e3a Guido Trotter
    # 2nd is skipped
336 6bb65e3a Guido Trotter
    utils.WriteFile(files[1], data="")
337 6bb65e3a Guido Trotter
338 6bb65e3a Guido Trotter
    # 3rd cannot execute properly
339 6bb65e3a Guido Trotter
    utils.WriteFile(files[2], data="")
340 6bb65e3a Guido Trotter
    os.chmod(files[2], stat.S_IREAD | stat.S_IEXEC)
341 6bb65e3a Guido Trotter
342 6bb65e3a Guido Trotter
    # 4th execs
343 6bb65e3a Guido Trotter
    utils.WriteFile(files[3], data="#!/bin/sh\n\necho -n ciao")
344 6bb65e3a Guido Trotter
    os.chmod(files[3], stat.S_IREAD | stat.S_IEXEC)
345 6bb65e3a Guido Trotter
346 6bb65e3a Guido Trotter
    results = RunParts(self.rundir, reset_env=True)
347 6bb65e3a Guido Trotter
348 6bb65e3a Guido Trotter
    (relname, status, runresult) = results[0]
349 6bb65e3a Guido Trotter
    self.failUnlessEqual(relname, os.path.basename(files[0]))
350 6bb65e3a Guido Trotter
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
351 6bb65e3a Guido Trotter
    self.failUnlessEqual(runresult.exit_code, 1)
352 6bb65e3a Guido Trotter
    self.failUnless(runresult.failed)
353 6bb65e3a Guido Trotter
354 6bb65e3a Guido Trotter
    (relname, status, runresult) = results[1]
355 6bb65e3a Guido Trotter
    self.failUnlessEqual(relname, os.path.basename(files[1]))
356 6bb65e3a Guido Trotter
    self.failUnlessEqual(status, constants.RUNPARTS_SKIP)
357 6bb65e3a Guido Trotter
    self.failUnlessEqual(runresult, None)
358 6bb65e3a Guido Trotter
359 6bb65e3a Guido Trotter
    (relname, status, runresult) = results[2]
360 6bb65e3a Guido Trotter
    self.failUnlessEqual(relname, os.path.basename(files[2]))
361 6bb65e3a Guido Trotter
    self.failUnlessEqual(status, constants.RUNPARTS_ERR)
362 6bb65e3a Guido Trotter
    self.failUnless(runresult)
363 6bb65e3a Guido Trotter
364 6bb65e3a Guido Trotter
    (relname, status, runresult) = results[3]
365 6bb65e3a Guido Trotter
    self.failUnlessEqual(relname, os.path.basename(files[3]))
366 6bb65e3a Guido Trotter
    self.failUnlessEqual(status, constants.RUNPARTS_RUN)
367 6bb65e3a Guido Trotter
    self.failUnlessEqual(runresult.output, "ciao")
368 6bb65e3a Guido Trotter
    self.failUnlessEqual(runresult.exit_code, 0)
369 6bb65e3a Guido Trotter
    self.failUnless(not runresult.failed)
370 6bb65e3a Guido Trotter
371 a8083063 Iustin Pop
372 c1dd99d4 Michael Hanselmann
class TestStartDaemon(testutils.GanetiTestCase):
373 c1dd99d4 Michael Hanselmann
  def setUp(self):
374 c1dd99d4 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp(prefix="ganeti-test")
375 c1dd99d4 Michael Hanselmann
    self.tmpfile = os.path.join(self.tmpdir, "test")
376 c1dd99d4 Michael Hanselmann
377 c1dd99d4 Michael Hanselmann
  def tearDown(self):
378 c1dd99d4 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
379 c1dd99d4 Michael Hanselmann
380 c1dd99d4 Michael Hanselmann
  def testShell(self):
381 c1dd99d4 Michael Hanselmann
    utils.StartDaemon("echo Hello World > %s" % self.tmpfile)
382 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
383 c1dd99d4 Michael Hanselmann
384 c1dd99d4 Michael Hanselmann
  def testShellOutput(self):
385 c1dd99d4 Michael Hanselmann
    utils.StartDaemon("echo Hello World", output=self.tmpfile)
386 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
387 c1dd99d4 Michael Hanselmann
388 c1dd99d4 Michael Hanselmann
  def testNoShellNoOutput(self):
389 c1dd99d4 Michael Hanselmann
    utils.StartDaemon(["pwd"])
390 c1dd99d4 Michael Hanselmann
391 c1dd99d4 Michael Hanselmann
  def testNoShellNoOutputTouch(self):
392 c1dd99d4 Michael Hanselmann
    testfile = os.path.join(self.tmpdir, "check")
393 c1dd99d4 Michael Hanselmann
    self.failIf(os.path.exists(testfile))
394 c1dd99d4 Michael Hanselmann
    utils.StartDaemon(["touch", testfile])
395 c1dd99d4 Michael Hanselmann
    self._wait(testfile, 60.0, "")
396 c1dd99d4 Michael Hanselmann
397 c1dd99d4 Michael Hanselmann
  def testNoShellOutput(self):
398 c1dd99d4 Michael Hanselmann
    utils.StartDaemon(["pwd"], output=self.tmpfile)
399 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "/")
400 c1dd99d4 Michael Hanselmann
401 c1dd99d4 Michael Hanselmann
  def testNoShellOutputCwd(self):
402 c1dd99d4 Michael Hanselmann
    utils.StartDaemon(["pwd"], output=self.tmpfile, cwd=os.getcwd())
403 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, os.getcwd())
404 c1dd99d4 Michael Hanselmann
405 c1dd99d4 Michael Hanselmann
  def testShellEnv(self):
406 c1dd99d4 Michael Hanselmann
    utils.StartDaemon("echo \"$GNT_TEST_VAR\"", output=self.tmpfile,
407 c1dd99d4 Michael Hanselmann
                      env={ "GNT_TEST_VAR": "Hello World", })
408 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
409 c1dd99d4 Michael Hanselmann
410 c1dd99d4 Michael Hanselmann
  def testNoShellEnv(self):
411 c1dd99d4 Michael Hanselmann
    utils.StartDaemon(["printenv", "GNT_TEST_VAR"], output=self.tmpfile,
412 c1dd99d4 Michael Hanselmann
                      env={ "GNT_TEST_VAR": "Hello World", })
413 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, "Hello World")
414 c1dd99d4 Michael Hanselmann
415 c1dd99d4 Michael Hanselmann
  def testOutputFd(self):
416 c1dd99d4 Michael Hanselmann
    fd = os.open(self.tmpfile, os.O_WRONLY | os.O_CREAT)
417 c1dd99d4 Michael Hanselmann
    try:
418 c1dd99d4 Michael Hanselmann
      utils.StartDaemon(["pwd"], output_fd=fd, cwd=os.getcwd())
419 c1dd99d4 Michael Hanselmann
    finally:
420 c1dd99d4 Michael Hanselmann
      os.close(fd)
421 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, os.getcwd())
422 c1dd99d4 Michael Hanselmann
423 c1dd99d4 Michael Hanselmann
  def testPid(self):
424 c1dd99d4 Michael Hanselmann
    pid = utils.StartDaemon("echo $$ > %s" % self.tmpfile)
425 c1dd99d4 Michael Hanselmann
    self._wait(self.tmpfile, 60.0, str(pid))
426 c1dd99d4 Michael Hanselmann
427 c1dd99d4 Michael Hanselmann
  def testPidFile(self):
428 c1dd99d4 Michael Hanselmann
    pidfile = os.path.join(self.tmpdir, "pid")
429 c1dd99d4 Michael Hanselmann
    checkfile = os.path.join(self.tmpdir, "abort")
430 c1dd99d4 Michael Hanselmann
431 c1dd99d4 Michael Hanselmann
    pid = utils.StartDaemon("while sleep 5; do :; done", pidfile=pidfile,
432 c1dd99d4 Michael Hanselmann
                            output=self.tmpfile)
433 c1dd99d4 Michael Hanselmann
    try:
434 c1dd99d4 Michael Hanselmann
      fd = os.open(pidfile, os.O_RDONLY)
435 c1dd99d4 Michael Hanselmann
      try:
436 c1dd99d4 Michael Hanselmann
        # Check file is locked
437 c1dd99d4 Michael Hanselmann
        self.assertRaises(errors.LockError, utils.LockFile, fd)
438 c1dd99d4 Michael Hanselmann
439 c1dd99d4 Michael Hanselmann
        pidtext = os.read(fd, 100)
440 c1dd99d4 Michael Hanselmann
      finally:
441 c1dd99d4 Michael Hanselmann
        os.close(fd)
442 c1dd99d4 Michael Hanselmann
443 c1dd99d4 Michael Hanselmann
      self.assertEqual(int(pidtext.strip()), pid)
444 c1dd99d4 Michael Hanselmann
445 c1dd99d4 Michael Hanselmann
      self.assert_(utils.IsProcessAlive(pid))
446 c1dd99d4 Michael Hanselmann
    finally:
447 c1dd99d4 Michael Hanselmann
      # No matter what happens, kill daemon
448 c1dd99d4 Michael Hanselmann
      utils.KillProcess(pid, timeout=5.0, waitpid=False)
449 c1dd99d4 Michael Hanselmann
      self.failIf(utils.IsProcessAlive(pid))
450 c1dd99d4 Michael Hanselmann
451 c1dd99d4 Michael Hanselmann
    self.assertEqual(utils.ReadFile(self.tmpfile), "")
452 c1dd99d4 Michael Hanselmann
453 c1dd99d4 Michael Hanselmann
  def _wait(self, path, timeout, expected):
454 c1dd99d4 Michael Hanselmann
    # Due to the asynchronous nature of daemon processes, polling is necessary.
455 c1dd99d4 Michael Hanselmann
    # A timeout makes sure the test doesn't hang forever.
456 c1dd99d4 Michael Hanselmann
    def _CheckFile():
457 c1dd99d4 Michael Hanselmann
      if not (os.path.isfile(path) and
458 c1dd99d4 Michael Hanselmann
              utils.ReadFile(path).strip() == expected):
459 c1dd99d4 Michael Hanselmann
        raise utils.RetryAgain()
460 c1dd99d4 Michael Hanselmann
461 c1dd99d4 Michael Hanselmann
    try:
462 c1dd99d4 Michael Hanselmann
      utils.Retry(_CheckFile, (0.01, 1.5, 1.0), timeout)
463 c1dd99d4 Michael Hanselmann
    except utils.RetryTimeout:
464 c1dd99d4 Michael Hanselmann
      self.fail("Apparently the daemon didn't run in %s seconds and/or"
465 c1dd99d4 Michael Hanselmann
                " didn't write the correct output" % timeout)
466 c1dd99d4 Michael Hanselmann
467 c1dd99d4 Michael Hanselmann
  def testError(self):
468 c1dd99d4 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
469 c1dd99d4 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"])
470 c1dd99d4 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
471 c1dd99d4 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"],
472 c1dd99d4 Michael Hanselmann
                      output=os.path.join(self.tmpdir, "DIR/NOT/EXIST"))
473 c1dd99d4 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
474 c1dd99d4 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"],
475 c1dd99d4 Michael Hanselmann
                      cwd=os.path.join(self.tmpdir, "DIR/NOT/EXIST"))
476 c1dd99d4 Michael Hanselmann
    self.assertRaises(errors.OpExecError, utils.StartDaemon,
477 c1dd99d4 Michael Hanselmann
                      ["./does-NOT-EXIST/here/0123456789"],
478 c1dd99d4 Michael Hanselmann
                      output=os.path.join(self.tmpdir, "DIR/NOT/EXIST"))
479 c1dd99d4 Michael Hanselmann
480 c1dd99d4 Michael Hanselmann
    fd = os.open(self.tmpfile, os.O_WRONLY | os.O_CREAT)
481 c1dd99d4 Michael Hanselmann
    try:
482 c1dd99d4 Michael Hanselmann
      self.assertRaises(errors.ProgrammerError, utils.StartDaemon,
483 c1dd99d4 Michael Hanselmann
                        ["./does-NOT-EXIST/here/0123456789"],
484 c1dd99d4 Michael Hanselmann
                        output=self.tmpfile, output_fd=fd)
485 c1dd99d4 Michael Hanselmann
    finally:
486 c1dd99d4 Michael Hanselmann
      os.close(fd)
487 c1dd99d4 Michael Hanselmann
488 c1dd99d4 Michael Hanselmann
489 73027ed2 Michael Hanselmann
class TestSetCloseOnExecFlag(unittest.TestCase):
490 73027ed2 Michael Hanselmann
  """Tests for SetCloseOnExecFlag"""
491 73027ed2 Michael Hanselmann
492 73027ed2 Michael Hanselmann
  def setUp(self):
493 73027ed2 Michael Hanselmann
    self.tmpfile = tempfile.TemporaryFile()
494 73027ed2 Michael Hanselmann
495 73027ed2 Michael Hanselmann
  def testEnable(self):
496 73027ed2 Michael Hanselmann
    utils.SetCloseOnExecFlag(self.tmpfile.fileno(), True)
497 73027ed2 Michael Hanselmann
    self.failUnless(fcntl.fcntl(self.tmpfile.fileno(), fcntl.F_GETFD) &
498 73027ed2 Michael Hanselmann
                    fcntl.FD_CLOEXEC)
499 73027ed2 Michael Hanselmann
500 73027ed2 Michael Hanselmann
  def testDisable(self):
501 73027ed2 Michael Hanselmann
    utils.SetCloseOnExecFlag(self.tmpfile.fileno(), False)
502 73027ed2 Michael Hanselmann
    self.failIf(fcntl.fcntl(self.tmpfile.fileno(), fcntl.F_GETFD) &
503 73027ed2 Michael Hanselmann
                fcntl.FD_CLOEXEC)
504 73027ed2 Michael Hanselmann
505 73027ed2 Michael Hanselmann
506 287a1740 Michael Hanselmann
class TestSetNonblockFlag(unittest.TestCase):
507 287a1740 Michael Hanselmann
  def setUp(self):
508 287a1740 Michael Hanselmann
    self.tmpfile = tempfile.TemporaryFile()
509 287a1740 Michael Hanselmann
510 287a1740 Michael Hanselmann
  def testEnable(self):
511 287a1740 Michael Hanselmann
    utils.SetNonblockFlag(self.tmpfile.fileno(), True)
512 287a1740 Michael Hanselmann
    self.failUnless(fcntl.fcntl(self.tmpfile.fileno(), fcntl.F_GETFL) &
513 287a1740 Michael Hanselmann
                    os.O_NONBLOCK)
514 287a1740 Michael Hanselmann
515 287a1740 Michael Hanselmann
  def testDisable(self):
516 287a1740 Michael Hanselmann
    utils.SetNonblockFlag(self.tmpfile.fileno(), False)
517 287a1740 Michael Hanselmann
    self.failIf(fcntl.fcntl(self.tmpfile.fileno(), fcntl.F_GETFL) &
518 287a1740 Michael Hanselmann
                os.O_NONBLOCK)
519 287a1740 Michael Hanselmann
520 287a1740 Michael Hanselmann
521 a8083063 Iustin Pop
class TestRemoveFile(unittest.TestCase):
522 a8083063 Iustin Pop
  """Test case for the RemoveFile function"""
523 a8083063 Iustin Pop
524 a8083063 Iustin Pop
  def setUp(self):
525 a8083063 Iustin Pop
    """Create a temp dir and file for each case"""
526 a8083063 Iustin Pop
    self.tmpdir = tempfile.mkdtemp('', 'ganeti-unittest-')
527 a8083063 Iustin Pop
    fd, self.tmpfile = tempfile.mkstemp('', '', self.tmpdir)
528 a8083063 Iustin Pop
    os.close(fd)
529 a8083063 Iustin Pop
530 a8083063 Iustin Pop
  def tearDown(self):
531 a8083063 Iustin Pop
    if os.path.exists(self.tmpfile):
532 a8083063 Iustin Pop
      os.unlink(self.tmpfile)
533 a8083063 Iustin Pop
    os.rmdir(self.tmpdir)
534 a8083063 Iustin Pop
535 a8083063 Iustin Pop
  def testIgnoreDirs(self):
536 a8083063 Iustin Pop
    """Test that RemoveFile() ignores directories"""
537 a8083063 Iustin Pop
    self.assertEqual(None, RemoveFile(self.tmpdir))
538 a8083063 Iustin Pop
539 a8083063 Iustin Pop
  def testIgnoreNotExisting(self):
540 a8083063 Iustin Pop
    """Test that RemoveFile() ignores non-existing files"""
541 a8083063 Iustin Pop
    RemoveFile(self.tmpfile)
542 a8083063 Iustin Pop
    RemoveFile(self.tmpfile)
543 a8083063 Iustin Pop
544 a8083063 Iustin Pop
  def testRemoveFile(self):
545 a8083063 Iustin Pop
    """Test that RemoveFile does remove a file"""
546 a8083063 Iustin Pop
    RemoveFile(self.tmpfile)
547 a8083063 Iustin Pop
    if os.path.exists(self.tmpfile):
548 a8083063 Iustin Pop
      self.fail("File '%s' not removed" % self.tmpfile)
549 a8083063 Iustin Pop
550 a8083063 Iustin Pop
  def testRemoveSymlink(self):
551 a8083063 Iustin Pop
    """Test that RemoveFile does remove symlinks"""
552 a8083063 Iustin Pop
    symlink = self.tmpdir + "/symlink"
553 a8083063 Iustin Pop
    os.symlink("no-such-file", symlink)
554 a8083063 Iustin Pop
    RemoveFile(symlink)
555 a8083063 Iustin Pop
    if os.path.exists(symlink):
556 a8083063 Iustin Pop
      self.fail("File '%s' not removed" % symlink)
557 a8083063 Iustin Pop
    os.symlink(self.tmpfile, symlink)
558 a8083063 Iustin Pop
    RemoveFile(symlink)
559 a8083063 Iustin Pop
    if os.path.exists(symlink):
560 a8083063 Iustin Pop
      self.fail("File '%s' not removed" % symlink)
561 a8083063 Iustin Pop
562 a8083063 Iustin Pop
563 6e797216 Michael Hanselmann
class TestRename(unittest.TestCase):
564 6e797216 Michael Hanselmann
  """Test case for RenameFile"""
565 6e797216 Michael Hanselmann
566 6e797216 Michael Hanselmann
  def setUp(self):
567 6e797216 Michael Hanselmann
    """Create a temporary directory"""
568 6e797216 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
569 6e797216 Michael Hanselmann
    self.tmpfile = os.path.join(self.tmpdir, "test1")
570 6e797216 Michael Hanselmann
571 6e797216 Michael Hanselmann
    # Touch the file
572 6e797216 Michael Hanselmann
    open(self.tmpfile, "w").close()
573 6e797216 Michael Hanselmann
574 6e797216 Michael Hanselmann
  def tearDown(self):
575 6e797216 Michael Hanselmann
    """Remove temporary directory"""
576 6e797216 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
577 6e797216 Michael Hanselmann
578 6e797216 Michael Hanselmann
  def testSimpleRename1(self):
579 6e797216 Michael Hanselmann
    """Simple rename 1"""
580 6e797216 Michael Hanselmann
    utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "xyz"))
581 a426508d Michael Hanselmann
    self.assert_(os.path.isfile(os.path.join(self.tmpdir, "xyz")))
582 6e797216 Michael Hanselmann
583 6e797216 Michael Hanselmann
  def testSimpleRename2(self):
584 6e797216 Michael Hanselmann
    """Simple rename 2"""
585 6e797216 Michael Hanselmann
    utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "xyz"),
586 6e797216 Michael Hanselmann
                     mkdir=True)
587 a426508d Michael Hanselmann
    self.assert_(os.path.isfile(os.path.join(self.tmpdir, "xyz")))
588 6e797216 Michael Hanselmann
589 6e797216 Michael Hanselmann
  def testRenameMkdir(self):
590 6e797216 Michael Hanselmann
    """Rename with mkdir"""
591 6e797216 Michael Hanselmann
    utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "test/xyz"),
592 6e797216 Michael Hanselmann
                     mkdir=True)
593 a426508d Michael Hanselmann
    self.assert_(os.path.isdir(os.path.join(self.tmpdir, "test")))
594 a426508d Michael Hanselmann
    self.assert_(os.path.isfile(os.path.join(self.tmpdir, "test/xyz")))
595 a426508d Michael Hanselmann
596 a426508d Michael Hanselmann
    utils.RenameFile(os.path.join(self.tmpdir, "test/xyz"),
597 a426508d Michael Hanselmann
                     os.path.join(self.tmpdir, "test/foo/bar/baz"),
598 a426508d Michael Hanselmann
                     mkdir=True)
599 a426508d Michael Hanselmann
    self.assert_(os.path.isdir(os.path.join(self.tmpdir, "test")))
600 a426508d Michael Hanselmann
    self.assert_(os.path.isdir(os.path.join(self.tmpdir, "test/foo/bar")))
601 a426508d Michael Hanselmann
    self.assert_(os.path.isfile(os.path.join(self.tmpdir, "test/foo/bar/baz")))
602 6e797216 Michael Hanselmann
603 6e797216 Michael Hanselmann
604 a8083063 Iustin Pop
class TestMatchNameComponent(unittest.TestCase):
605 a8083063 Iustin Pop
  """Test case for the MatchNameComponent function"""
606 a8083063 Iustin Pop
607 a8083063 Iustin Pop
  def testEmptyList(self):
608 a8083063 Iustin Pop
    """Test that there is no match against an empty list"""
609 a8083063 Iustin Pop
610 a8083063 Iustin Pop
    self.failUnlessEqual(MatchNameComponent("", []), None)
611 a8083063 Iustin Pop
    self.failUnlessEqual(MatchNameComponent("test", []), None)
612 a8083063 Iustin Pop
613 a8083063 Iustin Pop
  def testSingleMatch(self):
614 a8083063 Iustin Pop
    """Test that a single match is performed correctly"""
615 a8083063 Iustin Pop
    mlist = ["test1.example.com", "test2.example.com", "test3.example.com"]
616 a8083063 Iustin Pop
    for key in "test2", "test2.example", "test2.example.com":
617 a8083063 Iustin Pop
      self.failUnlessEqual(MatchNameComponent(key, mlist), mlist[1])
618 a8083063 Iustin Pop
619 a8083063 Iustin Pop
  def testMultipleMatches(self):
620 a8083063 Iustin Pop
    """Test that a multiple match is returned as None"""
621 a8083063 Iustin Pop
    mlist = ["test1.example.com", "test1.example.org", "test1.example.net"]
622 a8083063 Iustin Pop
    for key in "test1", "test1.example":
623 a8083063 Iustin Pop
      self.failUnlessEqual(MatchNameComponent(key, mlist), None)
624 a8083063 Iustin Pop
625 3a541d90 Iustin Pop
  def testFullMatch(self):
626 3a541d90 Iustin Pop
    """Test that a full match is returned correctly"""
627 3a541d90 Iustin Pop
    key1 = "test1"
628 3a541d90 Iustin Pop
    key2 = "test1.example"
629 3a541d90 Iustin Pop
    mlist = [key2, key2 + ".com"]
630 3a541d90 Iustin Pop
    self.failUnlessEqual(MatchNameComponent(key1, mlist), None)
631 3a541d90 Iustin Pop
    self.failUnlessEqual(MatchNameComponent(key2, mlist), key2)
632 3a541d90 Iustin Pop
633 256eb94b Guido Trotter
  def testCaseInsensitivePartialMatch(self):
634 256eb94b Guido Trotter
    """Test for the case_insensitive keyword"""
635 256eb94b Guido Trotter
    mlist = ["test1.example.com", "test2.example.net"]
636 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("test2", mlist, case_sensitive=False),
637 256eb94b Guido Trotter
                     "test2.example.net")
638 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("Test2", mlist, case_sensitive=False),
639 256eb94b Guido Trotter
                     "test2.example.net")
640 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("teSt2", mlist, case_sensitive=False),
641 256eb94b Guido Trotter
                     "test2.example.net")
642 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("TeSt2", mlist, case_sensitive=False),
643 256eb94b Guido Trotter
                     "test2.example.net")
644 256eb94b Guido Trotter
645 256eb94b Guido Trotter
646 256eb94b Guido Trotter
  def testCaseInsensitiveFullMatch(self):
647 256eb94b Guido Trotter
    mlist = ["ts1.ex", "ts1.ex.org", "ts2.ex", "Ts2.ex"]
648 256eb94b Guido Trotter
    # Between the two ts1 a full string match non-case insensitive should work
649 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("Ts1", mlist, case_sensitive=False),
650 256eb94b Guido Trotter
                     None)
651 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("Ts1.ex", mlist, case_sensitive=False),
652 256eb94b Guido Trotter
                     "ts1.ex")
653 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("ts1.ex", mlist, case_sensitive=False),
654 256eb94b Guido Trotter
                     "ts1.ex")
655 256eb94b Guido Trotter
    # Between the two ts2 only case differs, so only case-match works
656 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("ts2.ex", mlist, case_sensitive=False),
657 256eb94b Guido Trotter
                     "ts2.ex")
658 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("Ts2.ex", mlist, case_sensitive=False),
659 256eb94b Guido Trotter
                     "Ts2.ex")
660 256eb94b Guido Trotter
    self.assertEqual(MatchNameComponent("TS2.ex", mlist, case_sensitive=False),
661 256eb94b Guido Trotter
                     None)
662 256eb94b Guido Trotter
663 a8083063 Iustin Pop
664 1d466a4f Michael Hanselmann
class TestTimestampForFilename(unittest.TestCase):
665 1d466a4f Michael Hanselmann
  def test(self):
666 1d466a4f Michael Hanselmann
    self.assert_("." not in utils.TimestampForFilename())
667 1d466a4f Michael Hanselmann
    self.assert_(":" not in utils.TimestampForFilename())
668 1d466a4f Michael Hanselmann
669 1d466a4f Michael Hanselmann
670 1d466a4f Michael Hanselmann
class TestCreateBackup(testutils.GanetiTestCase):
671 1d466a4f Michael Hanselmann
  def setUp(self):
672 1d466a4f Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
673 1d466a4f Michael Hanselmann
674 1d466a4f Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
675 1d466a4f Michael Hanselmann
676 1d466a4f Michael Hanselmann
  def tearDown(self):
677 1d466a4f Michael Hanselmann
    testutils.GanetiTestCase.tearDown(self)
678 1d466a4f Michael Hanselmann
679 1d466a4f Michael Hanselmann
    shutil.rmtree(self.tmpdir)
680 1d466a4f Michael Hanselmann
681 1d466a4f Michael Hanselmann
  def testEmpty(self):
682 1d466a4f Michael Hanselmann
    filename = utils.PathJoin(self.tmpdir, "config.data")
683 1d466a4f Michael Hanselmann
    utils.WriteFile(filename, data="")
684 1d466a4f Michael Hanselmann
    bname = utils.CreateBackup(filename)
685 1d466a4f Michael Hanselmann
    self.assertFileContent(bname, "")
686 1d466a4f Michael Hanselmann
    self.assertEqual(len(glob.glob("%s*" % filename)), 2)
687 1d466a4f Michael Hanselmann
    utils.CreateBackup(filename)
688 1d466a4f Michael Hanselmann
    self.assertEqual(len(glob.glob("%s*" % filename)), 3)
689 1d466a4f Michael Hanselmann
    utils.CreateBackup(filename)
690 1d466a4f Michael Hanselmann
    self.assertEqual(len(glob.glob("%s*" % filename)), 4)
691 1d466a4f Michael Hanselmann
692 1d466a4f Michael Hanselmann
    fifoname = utils.PathJoin(self.tmpdir, "fifo")
693 1d466a4f Michael Hanselmann
    os.mkfifo(fifoname)
694 1d466a4f Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.CreateBackup, fifoname)
695 1d466a4f Michael Hanselmann
696 1d466a4f Michael Hanselmann
  def testContent(self):
697 1d466a4f Michael Hanselmann
    bkpcount = 0
698 1d466a4f Michael Hanselmann
    for data in ["", "X", "Hello World!\n" * 100, "Binary data\0\x01\x02\n"]:
699 1d466a4f Michael Hanselmann
      for rep in [1, 2, 10, 127]:
700 1d466a4f Michael Hanselmann
        testdata = data * rep
701 1d466a4f Michael Hanselmann
702 1d466a4f Michael Hanselmann
        filename = utils.PathJoin(self.tmpdir, "test.data_")
703 1d466a4f Michael Hanselmann
        utils.WriteFile(filename, data=testdata)
704 1d466a4f Michael Hanselmann
        self.assertFileContent(filename, testdata)
705 1d466a4f Michael Hanselmann
706 1d466a4f Michael Hanselmann
        for _ in range(3):
707 1d466a4f Michael Hanselmann
          bname = utils.CreateBackup(filename)
708 1d466a4f Michael Hanselmann
          bkpcount += 1
709 1d466a4f Michael Hanselmann
          self.assertFileContent(bname, testdata)
710 1d466a4f Michael Hanselmann
          self.assertEqual(len(glob.glob("%s*" % filename)), 1 + bkpcount)
711 1d466a4f Michael Hanselmann
712 1d466a4f Michael Hanselmann
713 a8083063 Iustin Pop
class TestFormatUnit(unittest.TestCase):
714 a8083063 Iustin Pop
  """Test case for the FormatUnit function"""
715 a8083063 Iustin Pop
716 a8083063 Iustin Pop
  def testMiB(self):
717 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1, 'h'), '1M')
718 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(100, 'h'), '100M')
719 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1023, 'h'), '1023M')
720 9fbfbb7b Iustin Pop
721 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1, 'm'), '1')
722 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(100, 'm'), '100')
723 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1023, 'm'), '1023')
724 9fbfbb7b Iustin Pop
725 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024, 'm'), '1024')
726 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1536, 'm'), '1536')
727 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(17133, 'm'), '17133')
728 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024 - 1, 'm'), '1048575')
729 a8083063 Iustin Pop
730 a8083063 Iustin Pop
  def testGiB(self):
731 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024, 'h'), '1.0G')
732 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1536, 'h'), '1.5G')
733 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(17133, 'h'), '16.7G')
734 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024 - 1, 'h'), '1024.0G')
735 9fbfbb7b Iustin Pop
736 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024, 'g'), '1.0')
737 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1536, 'g'), '1.5')
738 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(17133, 'g'), '16.7')
739 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024 - 1, 'g'), '1024.0')
740 9fbfbb7b Iustin Pop
741 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024, 'g'), '1024.0')
742 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(5120 * 1024, 'g'), '5120.0')
743 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(29829 * 1024, 'g'), '29829.0')
744 a8083063 Iustin Pop
745 a8083063 Iustin Pop
  def testTiB(self):
746 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024, 'h'), '1.0T')
747 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(5120 * 1024, 'h'), '5.0T')
748 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(29829 * 1024, 'h'), '29.1T')
749 a8083063 Iustin Pop
750 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024, 't'), '1.0')
751 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(5120 * 1024, 't'), '5.0')
752 9fbfbb7b Iustin Pop
    self.assertEqual(FormatUnit(29829 * 1024, 't'), '29.1')
753 a8083063 Iustin Pop
754 a8083063 Iustin Pop
class TestParseUnit(unittest.TestCase):
755 a8083063 Iustin Pop
  """Test case for the ParseUnit function"""
756 a8083063 Iustin Pop
757 a8083063 Iustin Pop
  SCALES = (('', 1),
758 a8083063 Iustin Pop
            ('M', 1), ('G', 1024), ('T', 1024 * 1024),
759 a8083063 Iustin Pop
            ('MB', 1), ('GB', 1024), ('TB', 1024 * 1024),
760 a8083063 Iustin Pop
            ('MiB', 1), ('GiB', 1024), ('TiB', 1024 * 1024))
761 a8083063 Iustin Pop
762 a8083063 Iustin Pop
  def testRounding(self):
763 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('0'), 0)
764 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1'), 4)
765 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('2'), 4)
766 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('3'), 4)
767 a8083063 Iustin Pop
768 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('124'), 124)
769 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('125'), 128)
770 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('126'), 128)
771 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('127'), 128)
772 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('128'), 128)
773 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('129'), 132)
774 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('130'), 132)
775 a8083063 Iustin Pop
776 a8083063 Iustin Pop
  def testFloating(self):
777 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('0'), 0)
778 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('0.5'), 4)
779 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.75'), 4)
780 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.99'), 4)
781 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('2.00'), 4)
782 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('2.01'), 4)
783 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('3.99'), 4)
784 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('4.00'), 4)
785 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('4.01'), 8)
786 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.5G'), 1536)
787 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.8G'), 1844)
788 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('8.28T'), 8682212)
789 a8083063 Iustin Pop
790 a8083063 Iustin Pop
  def testSuffixes(self):
791 a8083063 Iustin Pop
    for sep in ('', ' ', '   ', "\t", "\t "):
792 a8083063 Iustin Pop
      for suffix, scale in TestParseUnit.SCALES:
793 a8083063 Iustin Pop
        for func in (lambda x: x, str.lower, str.upper):
794 667479d5 Michael Hanselmann
          self.assertEqual(ParseUnit('1024' + sep + func(suffix)),
795 667479d5 Michael Hanselmann
                           1024 * scale)
796 a8083063 Iustin Pop
797 a8083063 Iustin Pop
  def testInvalidInput(self):
798 a8083063 Iustin Pop
    for sep in ('-', '_', ',', 'a'):
799 a8083063 Iustin Pop
      for suffix, _ in TestParseUnit.SCALES:
800 a8083063 Iustin Pop
        self.assertRaises(UnitParseError, ParseUnit, '1' + sep + suffix)
801 a8083063 Iustin Pop
802 a8083063 Iustin Pop
    for suffix, _ in TestParseUnit.SCALES:
803 a8083063 Iustin Pop
      self.assertRaises(UnitParseError, ParseUnit, '1,3' + suffix)
804 a8083063 Iustin Pop
805 a8083063 Iustin Pop
806 c9c4f19e Michael Hanselmann
class TestSshKeys(testutils.GanetiTestCase):
807 a8083063 Iustin Pop
  """Test case for the AddAuthorizedKey function"""
808 a8083063 Iustin Pop
809 a8083063 Iustin Pop
  KEY_A = 'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a'
810 a8083063 Iustin Pop
  KEY_B = ('command="/usr/bin/fooserver -t --verbose",from="1.2.3.4" '
811 a8083063 Iustin Pop
           'ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b')
812 a8083063 Iustin Pop
813 ebe8ef17 Michael Hanselmann
  def setUp(self):
814 51596eb2 Iustin Pop
    testutils.GanetiTestCase.setUp(self)
815 51596eb2 Iustin Pop
    self.tmpname = self._CreateTempFile()
816 51596eb2 Iustin Pop
    handle = open(self.tmpname, 'w')
817 a8083063 Iustin Pop
    try:
818 51596eb2 Iustin Pop
      handle.write("%s\n" % TestSshKeys.KEY_A)
819 51596eb2 Iustin Pop
      handle.write("%s\n" % TestSshKeys.KEY_B)
820 51596eb2 Iustin Pop
    finally:
821 51596eb2 Iustin Pop
      handle.close()
822 a8083063 Iustin Pop
823 a8083063 Iustin Pop
  def testAddingNewKey(self):
824 ebe8ef17 Michael Hanselmann
    AddAuthorizedKey(self.tmpname, 'ssh-dss AAAAB3NzaC1kc3MAAACB root@test')
825 a8083063 Iustin Pop
826 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
827 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
828 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
829 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
830 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1kc3MAAACB root@test\n")
831 a8083063 Iustin Pop
832 f89f17a8 Michael Hanselmann
  def testAddingAlmostButNotCompletelyTheSameKey(self):
833 ebe8ef17 Michael Hanselmann
    AddAuthorizedKey(self.tmpname,
834 ebe8ef17 Michael Hanselmann
        'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test')
835 ebe8ef17 Michael Hanselmann
836 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
837 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
838 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
839 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
840 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test\n")
841 a8083063 Iustin Pop
842 a8083063 Iustin Pop
  def testAddingExistingKeyWithSomeMoreSpaces(self):
843 ebe8ef17 Michael Hanselmann
    AddAuthorizedKey(self.tmpname,
844 ebe8ef17 Michael Hanselmann
        'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
845 a8083063 Iustin Pop
846 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
847 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
848 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
849 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
850 a8083063 Iustin Pop
851 a8083063 Iustin Pop
  def testRemovingExistingKeyWithSomeMoreSpaces(self):
852 ebe8ef17 Michael Hanselmann
    RemoveAuthorizedKey(self.tmpname,
853 ebe8ef17 Michael Hanselmann
        'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
854 a8083063 Iustin Pop
855 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
856 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
857 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
858 a8083063 Iustin Pop
859 a8083063 Iustin Pop
  def testRemovingNonExistingKey(self):
860 ebe8ef17 Michael Hanselmann
    RemoveAuthorizedKey(self.tmpname,
861 ebe8ef17 Michael Hanselmann
        'ssh-dss  AAAAB3Nsdfj230xxjxJjsjwjsjdjU   root@test')
862 a8083063 Iustin Pop
863 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
864 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
865 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
866 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
867 a8083063 Iustin Pop
868 a8083063 Iustin Pop
869 c9c4f19e Michael Hanselmann
class TestEtcHosts(testutils.GanetiTestCase):
870 899d2a81 Michael Hanselmann
  """Test functions modifying /etc/hosts"""
871 899d2a81 Michael Hanselmann
872 ebe8ef17 Michael Hanselmann
  def setUp(self):
873 51596eb2 Iustin Pop
    testutils.GanetiTestCase.setUp(self)
874 51596eb2 Iustin Pop
    self.tmpname = self._CreateTempFile()
875 51596eb2 Iustin Pop
    handle = open(self.tmpname, 'w')
876 899d2a81 Michael Hanselmann
    try:
877 51596eb2 Iustin Pop
      handle.write('# This is a test file for /etc/hosts\n')
878 51596eb2 Iustin Pop
      handle.write('127.0.0.1\tlocalhost\n')
879 51596eb2 Iustin Pop
      handle.write('192.168.1.1 router gw\n')
880 51596eb2 Iustin Pop
    finally:
881 51596eb2 Iustin Pop
      handle.close()
882 899d2a81 Michael Hanselmann
883 9440aeab Michael Hanselmann
  def testSettingNewIp(self):
884 ebe8ef17 Michael Hanselmann
    SetEtcHostsEntry(self.tmpname, '1.2.3.4', 'myhost.domain.tld', ['myhost'])
885 899d2a81 Michael Hanselmann
886 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
887 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
888 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
889 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router gw\n"
890 ebe8ef17 Michael Hanselmann
      "1.2.3.4\tmyhost.domain.tld myhost\n")
891 9b977740 Guido Trotter
    self.assertFileMode(self.tmpname, 0644)
892 899d2a81 Michael Hanselmann
893 9440aeab Michael Hanselmann
  def testSettingExistingIp(self):
894 ebe8ef17 Michael Hanselmann
    SetEtcHostsEntry(self.tmpname, '192.168.1.1', 'myhost.domain.tld',
895 ebe8ef17 Michael Hanselmann
                     ['myhost'])
896 899d2a81 Michael Hanselmann
897 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
898 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
899 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
900 ebe8ef17 Michael Hanselmann
      "192.168.1.1\tmyhost.domain.tld myhost\n")
901 9b977740 Guido Trotter
    self.assertFileMode(self.tmpname, 0644)
902 899d2a81 Michael Hanselmann
903 7fbb1f65 Michael Hanselmann
  def testSettingDuplicateName(self):
904 7fbb1f65 Michael Hanselmann
    SetEtcHostsEntry(self.tmpname, '1.2.3.4', 'myhost', ['myhost'])
905 7fbb1f65 Michael Hanselmann
906 7fbb1f65 Michael Hanselmann
    self.assertFileContent(self.tmpname,
907 7fbb1f65 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
908 7fbb1f65 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
909 7fbb1f65 Michael Hanselmann
      "192.168.1.1 router gw\n"
910 7fbb1f65 Michael Hanselmann
      "1.2.3.4\tmyhost\n")
911 9b977740 Guido Trotter
    self.assertFileMode(self.tmpname, 0644)
912 7fbb1f65 Michael Hanselmann
913 899d2a81 Michael Hanselmann
  def testRemovingExistingHost(self):
914 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'router')
915 899d2a81 Michael Hanselmann
916 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
917 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
918 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
919 ebe8ef17 Michael Hanselmann
      "192.168.1.1 gw\n")
920 9b977740 Guido Trotter
    self.assertFileMode(self.tmpname, 0644)
921 899d2a81 Michael Hanselmann
922 899d2a81 Michael Hanselmann
  def testRemovingSingleExistingHost(self):
923 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'localhost')
924 899d2a81 Michael Hanselmann
925 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
926 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
927 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router gw\n")
928 9b977740 Guido Trotter
    self.assertFileMode(self.tmpname, 0644)
929 899d2a81 Michael Hanselmann
930 899d2a81 Michael Hanselmann
  def testRemovingNonExistingHost(self):
931 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'myhost')
932 899d2a81 Michael Hanselmann
933 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
934 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
935 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
936 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router gw\n")
937 9b977740 Guido Trotter
    self.assertFileMode(self.tmpname, 0644)
938 899d2a81 Michael Hanselmann
939 9440aeab Michael Hanselmann
  def testRemovingAlias(self):
940 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'gw')
941 9440aeab Michael Hanselmann
942 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
943 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
944 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
945 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router\n")
946 9b977740 Guido Trotter
    self.assertFileMode(self.tmpname, 0644)
947 9440aeab Michael Hanselmann
948 899d2a81 Michael Hanselmann
949 a8083063 Iustin Pop
class TestShellQuoting(unittest.TestCase):
950 a8083063 Iustin Pop
  """Test case for shell quoting functions"""
951 a8083063 Iustin Pop
952 a8083063 Iustin Pop
  def testShellQuote(self):
953 a8083063 Iustin Pop
    self.assertEqual(ShellQuote('abc'), "abc")
954 a8083063 Iustin Pop
    self.assertEqual(ShellQuote('ab"c'), "'ab\"c'")
955 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a'bc"), "'a'\\''bc'")
956 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a b c"), "'a b c'")
957 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a b\\ c"), "'a b\\ c'")
958 a8083063 Iustin Pop
959 a8083063 Iustin Pop
  def testShellQuoteArgs(self):
960 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b', 'c']), "a b c")
961 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b"', 'c']), "a 'b\"' c")
962 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b\'', 'c']), "a 'b'\\\''' c")
963 a8083063 Iustin Pop
964 a8083063 Iustin Pop
965 2c30e9d7 Alexander Schreiber
class TestTcpPing(unittest.TestCase):
966 2c30e9d7 Alexander Schreiber
  """Testcase for TCP version of ping - against listen(2)ing port"""
967 2c30e9d7 Alexander Schreiber
968 2c30e9d7 Alexander Schreiber
  def setUp(self):
969 2c30e9d7 Alexander Schreiber
    self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
970 16abfbc2 Alexander Schreiber
    self.listener.bind((constants.LOCALHOST_IP_ADDRESS, 0))
971 2c30e9d7 Alexander Schreiber
    self.listenerport = self.listener.getsockname()[1]
972 2c30e9d7 Alexander Schreiber
    self.listener.listen(1)
973 2c30e9d7 Alexander Schreiber
974 2c30e9d7 Alexander Schreiber
  def tearDown(self):
975 2c30e9d7 Alexander Schreiber
    self.listener.shutdown(socket.SHUT_RDWR)
976 2c30e9d7 Alexander Schreiber
    del self.listener
977 2c30e9d7 Alexander Schreiber
    del self.listenerport
978 2c30e9d7 Alexander Schreiber
979 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostAccept(self):
980 16abfbc2 Alexander Schreiber
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
981 2c30e9d7 Alexander Schreiber
                         self.listenerport,
982 2c30e9d7 Alexander Schreiber
                         timeout=10,
983 b15d625f Iustin Pop
                         live_port_needed=True,
984 b15d625f Iustin Pop
                         source=constants.LOCALHOST_IP_ADDRESS,
985 b15d625f Iustin Pop
                         ),
986 2c30e9d7 Alexander Schreiber
                 "failed to connect to test listener")
987 2c30e9d7 Alexander Schreiber
988 b15d625f Iustin Pop
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
989 b15d625f Iustin Pop
                         self.listenerport,
990 b15d625f Iustin Pop
                         timeout=10,
991 b15d625f Iustin Pop
                         live_port_needed=True,
992 b15d625f Iustin Pop
                         ),
993 b15d625f Iustin Pop
                 "failed to connect to test listener (no source)")
994 b15d625f Iustin Pop
995 2c30e9d7 Alexander Schreiber
996 2c30e9d7 Alexander Schreiber
class TestTcpPingDeaf(unittest.TestCase):
997 2c30e9d7 Alexander Schreiber
  """Testcase for TCP version of ping - against non listen(2)ing port"""
998 2c30e9d7 Alexander Schreiber
999 2c30e9d7 Alexander Schreiber
  def setUp(self):
1000 2c30e9d7 Alexander Schreiber
    self.deaflistener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1001 16abfbc2 Alexander Schreiber
    self.deaflistener.bind((constants.LOCALHOST_IP_ADDRESS, 0))
1002 2c30e9d7 Alexander Schreiber
    self.deaflistenerport = self.deaflistener.getsockname()[1]
1003 2c30e9d7 Alexander Schreiber
1004 2c30e9d7 Alexander Schreiber
  def tearDown(self):
1005 2c30e9d7 Alexander Schreiber
    del self.deaflistener
1006 2c30e9d7 Alexander Schreiber
    del self.deaflistenerport
1007 2c30e9d7 Alexander Schreiber
1008 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostAcceptDeaf(self):
1009 16abfbc2 Alexander Schreiber
    self.failIf(TcpPing(constants.LOCALHOST_IP_ADDRESS,
1010 2c30e9d7 Alexander Schreiber
                        self.deaflistenerport,
1011 16abfbc2 Alexander Schreiber
                        timeout=constants.TCP_PING_TIMEOUT,
1012 b15d625f Iustin Pop
                        live_port_needed=True,
1013 b15d625f Iustin Pop
                        source=constants.LOCALHOST_IP_ADDRESS,
1014 b15d625f Iustin Pop
                        ), # need successful connect(2)
1015 2c30e9d7 Alexander Schreiber
                "successfully connected to deaf listener")
1016 2c30e9d7 Alexander Schreiber
1017 b15d625f Iustin Pop
    self.failIf(TcpPing(constants.LOCALHOST_IP_ADDRESS,
1018 b15d625f Iustin Pop
                        self.deaflistenerport,
1019 b15d625f Iustin Pop
                        timeout=constants.TCP_PING_TIMEOUT,
1020 b15d625f Iustin Pop
                        live_port_needed=True,
1021 b15d625f Iustin Pop
                        ), # need successful connect(2)
1022 b15d625f Iustin Pop
                "successfully connected to deaf listener (no source addr)")
1023 b15d625f Iustin Pop
1024 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostNoAccept(self):
1025 16abfbc2 Alexander Schreiber
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
1026 2c30e9d7 Alexander Schreiber
                         self.deaflistenerport,
1027 16abfbc2 Alexander Schreiber
                         timeout=constants.TCP_PING_TIMEOUT,
1028 b15d625f Iustin Pop
                         live_port_needed=False,
1029 b15d625f Iustin Pop
                         source=constants.LOCALHOST_IP_ADDRESS,
1030 b15d625f Iustin Pop
                         ), # ECONNREFUSED is OK
1031 2c30e9d7 Alexander Schreiber
                 "failed to ping alive host on deaf port")
1032 2c30e9d7 Alexander Schreiber
1033 b15d625f Iustin Pop
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
1034 b15d625f Iustin Pop
                         self.deaflistenerport,
1035 b15d625f Iustin Pop
                         timeout=constants.TCP_PING_TIMEOUT,
1036 b15d625f Iustin Pop
                         live_port_needed=False,
1037 b15d625f Iustin Pop
                         ), # ECONNREFUSED is OK
1038 b15d625f Iustin Pop
                 "failed to ping alive host on deaf port (no source addr)")
1039 b15d625f Iustin Pop
1040 2c30e9d7 Alexander Schreiber
1041 caad16e2 Iustin Pop
class TestOwnIpAddress(unittest.TestCase):
1042 caad16e2 Iustin Pop
  """Testcase for OwnIpAddress"""
1043 caad16e2 Iustin Pop
1044 caad16e2 Iustin Pop
  def testOwnLoopback(self):
1045 caad16e2 Iustin Pop
    """check having the loopback ip"""
1046 caad16e2 Iustin Pop
    self.failUnless(OwnIpAddress(constants.LOCALHOST_IP_ADDRESS),
1047 caad16e2 Iustin Pop
                    "Should own the loopback address")
1048 caad16e2 Iustin Pop
1049 caad16e2 Iustin Pop
  def testNowOwnAddress(self):
1050 caad16e2 Iustin Pop
    """check that I don't own an address"""
1051 caad16e2 Iustin Pop
1052 caad16e2 Iustin Pop
    # network 192.0.2.0/24 is reserved for test/documentation as per
1053 caad16e2 Iustin Pop
    # rfc 3330, so we *should* not have an address of this range... if
1054 caad16e2 Iustin Pop
    # this fails, we should extend the test to multiple addresses
1055 caad16e2 Iustin Pop
    DST_IP = "192.0.2.1"
1056 caad16e2 Iustin Pop
    self.failIf(OwnIpAddress(DST_IP), "Should not own IP address %s" % DST_IP)
1057 caad16e2 Iustin Pop
1058 caad16e2 Iustin Pop
1059 eedbda4b Michael Hanselmann
class TestListVisibleFiles(unittest.TestCase):
1060 eedbda4b Michael Hanselmann
  """Test case for ListVisibleFiles"""
1061 eedbda4b Michael Hanselmann
1062 eedbda4b Michael Hanselmann
  def setUp(self):
1063 eedbda4b Michael Hanselmann
    self.path = tempfile.mkdtemp()
1064 eedbda4b Michael Hanselmann
1065 eedbda4b Michael Hanselmann
  def tearDown(self):
1066 eedbda4b Michael Hanselmann
    shutil.rmtree(self.path)
1067 eedbda4b Michael Hanselmann
1068 eedbda4b Michael Hanselmann
  def _test(self, files, expected):
1069 eedbda4b Michael Hanselmann
    # Sort a copy
1070 eedbda4b Michael Hanselmann
    expected = expected[:]
1071 eedbda4b Michael Hanselmann
    expected.sort()
1072 eedbda4b Michael Hanselmann
1073 eedbda4b Michael Hanselmann
    for name in files:
1074 eedbda4b Michael Hanselmann
      f = open(os.path.join(self.path, name), 'w')
1075 eedbda4b Michael Hanselmann
      try:
1076 eedbda4b Michael Hanselmann
        f.write("Test\n")
1077 eedbda4b Michael Hanselmann
      finally:
1078 eedbda4b Michael Hanselmann
        f.close()
1079 eedbda4b Michael Hanselmann
1080 eedbda4b Michael Hanselmann
    found = ListVisibleFiles(self.path)
1081 eedbda4b Michael Hanselmann
    found.sort()
1082 eedbda4b Michael Hanselmann
1083 eedbda4b Michael Hanselmann
    self.assertEqual(found, expected)
1084 eedbda4b Michael Hanselmann
1085 eedbda4b Michael Hanselmann
  def testAllVisible(self):
1086 eedbda4b Michael Hanselmann
    files = ["a", "b", "c"]
1087 eedbda4b Michael Hanselmann
    expected = files
1088 eedbda4b Michael Hanselmann
    self._test(files, expected)
1089 eedbda4b Michael Hanselmann
1090 eedbda4b Michael Hanselmann
  def testNoneVisible(self):
1091 eedbda4b Michael Hanselmann
    files = [".a", ".b", ".c"]
1092 eedbda4b Michael Hanselmann
    expected = []
1093 eedbda4b Michael Hanselmann
    self._test(files, expected)
1094 eedbda4b Michael Hanselmann
1095 eedbda4b Michael Hanselmann
  def testSomeVisible(self):
1096 eedbda4b Michael Hanselmann
    files = ["a", "b", ".c"]
1097 eedbda4b Michael Hanselmann
    expected = ["a", "b"]
1098 eedbda4b Michael Hanselmann
    self._test(files, expected)
1099 eedbda4b Michael Hanselmann
1100 04a69a18 Iustin Pop
  def testNonAbsolutePath(self):
1101 04a69a18 Iustin Pop
    self.failUnlessRaises(errors.ProgrammerError, ListVisibleFiles, "abc")
1102 04a69a18 Iustin Pop
1103 04a69a18 Iustin Pop
  def testNonNormalizedPath(self):
1104 04a69a18 Iustin Pop
    self.failUnlessRaises(errors.ProgrammerError, ListVisibleFiles,
1105 04a69a18 Iustin Pop
                          "/bin/../tmp")
1106 04a69a18 Iustin Pop
1107 eedbda4b Michael Hanselmann
1108 24818e8f Michael Hanselmann
class TestNewUUID(unittest.TestCase):
1109 24818e8f Michael Hanselmann
  """Test case for NewUUID"""
1110 59072e7e Michael Hanselmann
1111 59072e7e Michael Hanselmann
  _re_uuid = re.compile('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-'
1112 59072e7e Michael Hanselmann
                        '[a-f0-9]{4}-[a-f0-9]{12}$')
1113 59072e7e Michael Hanselmann
1114 59072e7e Michael Hanselmann
  def runTest(self):
1115 24818e8f Michael Hanselmann
    self.failUnless(self._re_uuid.match(utils.NewUUID()))
1116 59072e7e Michael Hanselmann
1117 59072e7e Michael Hanselmann
1118 f7414041 Michael Hanselmann
class TestUniqueSequence(unittest.TestCase):
1119 f7414041 Michael Hanselmann
  """Test case for UniqueSequence"""
1120 f7414041 Michael Hanselmann
1121 f7414041 Michael Hanselmann
  def _test(self, input, expected):
1122 f7414041 Michael Hanselmann
    self.assertEqual(utils.UniqueSequence(input), expected)
1123 f7414041 Michael Hanselmann
1124 f7414041 Michael Hanselmann
  def runTest(self):
1125 f7414041 Michael Hanselmann
    # Ordered input
1126 f7414041 Michael Hanselmann
    self._test([1, 2, 3], [1, 2, 3])
1127 f7414041 Michael Hanselmann
    self._test([1, 1, 2, 2, 3, 3], [1, 2, 3])
1128 f7414041 Michael Hanselmann
    self._test([1, 2, 2, 3], [1, 2, 3])
1129 f7414041 Michael Hanselmann
    self._test([1, 2, 3, 3], [1, 2, 3])
1130 f7414041 Michael Hanselmann
1131 f7414041 Michael Hanselmann
    # Unordered input
1132 f7414041 Michael Hanselmann
    self._test([1, 2, 3, 1, 2, 3], [1, 2, 3])
1133 f7414041 Michael Hanselmann
    self._test([1, 1, 2, 3, 3, 1, 2], [1, 2, 3])
1134 f7414041 Michael Hanselmann
1135 f7414041 Michael Hanselmann
    # Strings
1136 f7414041 Michael Hanselmann
    self._test(["a", "a"], ["a"])
1137 f7414041 Michael Hanselmann
    self._test(["a", "b"], ["a", "b"])
1138 f7414041 Michael Hanselmann
    self._test(["a", "b", "a"], ["a", "b"])
1139 f7414041 Michael Hanselmann
1140 a87b4824 Michael Hanselmann
1141 7b4126b7 Iustin Pop
class TestFirstFree(unittest.TestCase):
1142 7b4126b7 Iustin Pop
  """Test case for the FirstFree function"""
1143 7b4126b7 Iustin Pop
1144 7b4126b7 Iustin Pop
  def test(self):
1145 7b4126b7 Iustin Pop
    """Test FirstFree"""
1146 7b4126b7 Iustin Pop
    self.failUnlessEqual(FirstFree([0, 1, 3]), 2)
1147 7b4126b7 Iustin Pop
    self.failUnlessEqual(FirstFree([]), None)
1148 7b4126b7 Iustin Pop
    self.failUnlessEqual(FirstFree([3, 4, 6]), 0)
1149 7b4126b7 Iustin Pop
    self.failUnlessEqual(FirstFree([3, 4, 6], base=3), 5)
1150 7b4126b7 Iustin Pop
    self.failUnlessRaises(AssertionError, FirstFree, [0, 3, 4, 6], base=3)
1151 f7414041 Michael Hanselmann
1152 a87b4824 Michael Hanselmann
1153 f65f63ef Iustin Pop
class TestTailFile(testutils.GanetiTestCase):
1154 f65f63ef Iustin Pop
  """Test case for the TailFile function"""
1155 f65f63ef Iustin Pop
1156 f65f63ef Iustin Pop
  def testEmpty(self):
1157 f65f63ef Iustin Pop
    fname = self._CreateTempFile()
1158 f65f63ef Iustin Pop
    self.failUnlessEqual(TailFile(fname), [])
1159 f65f63ef Iustin Pop
    self.failUnlessEqual(TailFile(fname, lines=25), [])
1160 f65f63ef Iustin Pop
1161 f65f63ef Iustin Pop
  def testAllLines(self):
1162 f65f63ef Iustin Pop
    data = ["test %d" % i for i in range(30)]
1163 f65f63ef Iustin Pop
    for i in range(30):
1164 f65f63ef Iustin Pop
      fname = self._CreateTempFile()
1165 f65f63ef Iustin Pop
      fd = open(fname, "w")
1166 f65f63ef Iustin Pop
      fd.write("\n".join(data[:i]))
1167 f65f63ef Iustin Pop
      if i > 0:
1168 f65f63ef Iustin Pop
        fd.write("\n")
1169 f65f63ef Iustin Pop
      fd.close()
1170 f65f63ef Iustin Pop
      self.failUnlessEqual(TailFile(fname, lines=i), data[:i])
1171 f65f63ef Iustin Pop
1172 f65f63ef Iustin Pop
  def testPartialLines(self):
1173 f65f63ef Iustin Pop
    data = ["test %d" % i for i in range(30)]
1174 f65f63ef Iustin Pop
    fname = self._CreateTempFile()
1175 f65f63ef Iustin Pop
    fd = open(fname, "w")
1176 f65f63ef Iustin Pop
    fd.write("\n".join(data))
1177 f65f63ef Iustin Pop
    fd.write("\n")
1178 f65f63ef Iustin Pop
    fd.close()
1179 f65f63ef Iustin Pop
    for i in range(1, 30):
1180 f65f63ef Iustin Pop
      self.failUnlessEqual(TailFile(fname, lines=i), data[-i:])
1181 f65f63ef Iustin Pop
1182 f65f63ef Iustin Pop
  def testBigFile(self):
1183 f65f63ef Iustin Pop
    data = ["test %d" % i for i in range(30)]
1184 f65f63ef Iustin Pop
    fname = self._CreateTempFile()
1185 f65f63ef Iustin Pop
    fd = open(fname, "w")
1186 f65f63ef Iustin Pop
    fd.write("X" * 1048576)
1187 f65f63ef Iustin Pop
    fd.write("\n")
1188 f65f63ef Iustin Pop
    fd.write("\n".join(data))
1189 f65f63ef Iustin Pop
    fd.write("\n")
1190 f65f63ef Iustin Pop
    fd.close()
1191 f65f63ef Iustin Pop
    for i in range(1, 30):
1192 f65f63ef Iustin Pop
      self.failUnlessEqual(TailFile(fname, lines=i), data[-i:])
1193 f65f63ef Iustin Pop
1194 f65f63ef Iustin Pop
1195 b4478d34 Michael Hanselmann
class _BaseFileLockTest:
1196 a87b4824 Michael Hanselmann
  """Test case for the FileLock class"""
1197 a87b4824 Michael Hanselmann
1198 a87b4824 Michael Hanselmann
  def testSharedNonblocking(self):
1199 a87b4824 Michael Hanselmann
    self.lock.Shared(blocking=False)
1200 a87b4824 Michael Hanselmann
    self.lock.Close()
1201 a87b4824 Michael Hanselmann
1202 a87b4824 Michael Hanselmann
  def testExclusiveNonblocking(self):
1203 a87b4824 Michael Hanselmann
    self.lock.Exclusive(blocking=False)
1204 a87b4824 Michael Hanselmann
    self.lock.Close()
1205 a87b4824 Michael Hanselmann
1206 a87b4824 Michael Hanselmann
  def testUnlockNonblocking(self):
1207 a87b4824 Michael Hanselmann
    self.lock.Unlock(blocking=False)
1208 a87b4824 Michael Hanselmann
    self.lock.Close()
1209 a87b4824 Michael Hanselmann
1210 a87b4824 Michael Hanselmann
  def testSharedBlocking(self):
1211 a87b4824 Michael Hanselmann
    self.lock.Shared(blocking=True)
1212 a87b4824 Michael Hanselmann
    self.lock.Close()
1213 a87b4824 Michael Hanselmann
1214 a87b4824 Michael Hanselmann
  def testExclusiveBlocking(self):
1215 a87b4824 Michael Hanselmann
    self.lock.Exclusive(blocking=True)
1216 a87b4824 Michael Hanselmann
    self.lock.Close()
1217 a87b4824 Michael Hanselmann
1218 a87b4824 Michael Hanselmann
  def testUnlockBlocking(self):
1219 a87b4824 Michael Hanselmann
    self.lock.Unlock(blocking=True)
1220 a87b4824 Michael Hanselmann
    self.lock.Close()
1221 a87b4824 Michael Hanselmann
1222 a87b4824 Michael Hanselmann
  def testSharedExclusiveUnlock(self):
1223 a87b4824 Michael Hanselmann
    self.lock.Shared(blocking=False)
1224 a87b4824 Michael Hanselmann
    self.lock.Exclusive(blocking=False)
1225 a87b4824 Michael Hanselmann
    self.lock.Unlock(blocking=False)
1226 a87b4824 Michael Hanselmann
    self.lock.Close()
1227 a87b4824 Michael Hanselmann
1228 a87b4824 Michael Hanselmann
  def testExclusiveSharedUnlock(self):
1229 a87b4824 Michael Hanselmann
    self.lock.Exclusive(blocking=False)
1230 a87b4824 Michael Hanselmann
    self.lock.Shared(blocking=False)
1231 a87b4824 Michael Hanselmann
    self.lock.Unlock(blocking=False)
1232 a87b4824 Michael Hanselmann
    self.lock.Close()
1233 a87b4824 Michael Hanselmann
1234 b4478d34 Michael Hanselmann
  def testSimpleTimeout(self):
1235 b4478d34 Michael Hanselmann
    # These will succeed on the first attempt, hence a short timeout
1236 b4478d34 Michael Hanselmann
    self.lock.Shared(blocking=True, timeout=10.0)
1237 b4478d34 Michael Hanselmann
    self.lock.Exclusive(blocking=False, timeout=10.0)
1238 b4478d34 Michael Hanselmann
    self.lock.Unlock(blocking=True, timeout=10.0)
1239 b4478d34 Michael Hanselmann
    self.lock.Close()
1240 b4478d34 Michael Hanselmann
1241 b4478d34 Michael Hanselmann
  @staticmethod
1242 b4478d34 Michael Hanselmann
  def _TryLockInner(filename, shared, blocking):
1243 b4478d34 Michael Hanselmann
    lock = utils.FileLock.Open(filename)
1244 b4478d34 Michael Hanselmann
1245 b4478d34 Michael Hanselmann
    if shared:
1246 b4478d34 Michael Hanselmann
      fn = lock.Shared
1247 b4478d34 Michael Hanselmann
    else:
1248 b4478d34 Michael Hanselmann
      fn = lock.Exclusive
1249 b4478d34 Michael Hanselmann
1250 b4478d34 Michael Hanselmann
    try:
1251 b4478d34 Michael Hanselmann
      # The timeout doesn't really matter as the parent process waits for us to
1252 b4478d34 Michael Hanselmann
      # finish anyway.
1253 b4478d34 Michael Hanselmann
      fn(blocking=blocking, timeout=0.01)
1254 b4478d34 Michael Hanselmann
    except errors.LockError, err:
1255 b4478d34 Michael Hanselmann
      return False
1256 b4478d34 Michael Hanselmann
1257 b4478d34 Michael Hanselmann
    return True
1258 b4478d34 Michael Hanselmann
1259 b4478d34 Michael Hanselmann
  def _TryLock(self, *args):
1260 b4478d34 Michael Hanselmann
    return utils.RunInSeparateProcess(self._TryLockInner, self.tmpfile.name,
1261 b4478d34 Michael Hanselmann
                                      *args)
1262 b4478d34 Michael Hanselmann
1263 b4478d34 Michael Hanselmann
  def testTimeout(self):
1264 b4478d34 Michael Hanselmann
    for blocking in [True, False]:
1265 b4478d34 Michael Hanselmann
      self.lock.Exclusive(blocking=True)
1266 b4478d34 Michael Hanselmann
      self.failIf(self._TryLock(False, blocking))
1267 b4478d34 Michael Hanselmann
      self.failIf(self._TryLock(True, blocking))
1268 b4478d34 Michael Hanselmann
1269 b4478d34 Michael Hanselmann
      self.lock.Shared(blocking=True)
1270 b4478d34 Michael Hanselmann
      self.assert_(self._TryLock(True, blocking))
1271 b4478d34 Michael Hanselmann
      self.failIf(self._TryLock(False, blocking))
1272 b4478d34 Michael Hanselmann
1273 a87b4824 Michael Hanselmann
  def testCloseShared(self):
1274 a87b4824 Michael Hanselmann
    self.lock.Close()
1275 a87b4824 Michael Hanselmann
    self.assertRaises(AssertionError, self.lock.Shared, blocking=False)
1276 a87b4824 Michael Hanselmann
1277 a87b4824 Michael Hanselmann
  def testCloseExclusive(self):
1278 a87b4824 Michael Hanselmann
    self.lock.Close()
1279 a87b4824 Michael Hanselmann
    self.assertRaises(AssertionError, self.lock.Exclusive, blocking=False)
1280 a87b4824 Michael Hanselmann
1281 a87b4824 Michael Hanselmann
  def testCloseUnlock(self):
1282 a87b4824 Michael Hanselmann
    self.lock.Close()
1283 a87b4824 Michael Hanselmann
    self.assertRaises(AssertionError, self.lock.Unlock, blocking=False)
1284 a87b4824 Michael Hanselmann
1285 a87b4824 Michael Hanselmann
1286 b4478d34 Michael Hanselmann
class TestFileLockWithFilename(testutils.GanetiTestCase, _BaseFileLockTest):
1287 b4478d34 Michael Hanselmann
  TESTDATA = "Hello World\n" * 10
1288 b4478d34 Michael Hanselmann
1289 b4478d34 Michael Hanselmann
  def setUp(self):
1290 b4478d34 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
1291 b4478d34 Michael Hanselmann
1292 b4478d34 Michael Hanselmann
    self.tmpfile = tempfile.NamedTemporaryFile()
1293 b4478d34 Michael Hanselmann
    utils.WriteFile(self.tmpfile.name, data=self.TESTDATA)
1294 b4478d34 Michael Hanselmann
    self.lock = utils.FileLock.Open(self.tmpfile.name)
1295 b4478d34 Michael Hanselmann
1296 b4478d34 Michael Hanselmann
    # Ensure "Open" didn't truncate file
1297 b4478d34 Michael Hanselmann
    self.assertFileContent(self.tmpfile.name, self.TESTDATA)
1298 b4478d34 Michael Hanselmann
1299 b4478d34 Michael Hanselmann
  def tearDown(self):
1300 b4478d34 Michael Hanselmann
    self.assertFileContent(self.tmpfile.name, self.TESTDATA)
1301 b4478d34 Michael Hanselmann
1302 b4478d34 Michael Hanselmann
    testutils.GanetiTestCase.tearDown(self)
1303 b4478d34 Michael Hanselmann
1304 b4478d34 Michael Hanselmann
1305 b4478d34 Michael Hanselmann
class TestFileLockWithFileObject(unittest.TestCase, _BaseFileLockTest):
1306 b4478d34 Michael Hanselmann
  def setUp(self):
1307 b4478d34 Michael Hanselmann
    self.tmpfile = tempfile.NamedTemporaryFile()
1308 b4478d34 Michael Hanselmann
    self.lock = utils.FileLock(open(self.tmpfile.name, "w"), self.tmpfile.name)
1309 b4478d34 Michael Hanselmann
1310 b4478d34 Michael Hanselmann
1311 739be818 Michael Hanselmann
class TestTimeFunctions(unittest.TestCase):
1312 739be818 Michael Hanselmann
  """Test case for time functions"""
1313 739be818 Michael Hanselmann
1314 739be818 Michael Hanselmann
  def runTest(self):
1315 739be818 Michael Hanselmann
    self.assertEqual(utils.SplitTime(1), (1, 0))
1316 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.SplitTime(1.5), (1, 500000))
1317 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.SplitTime(1218448917.4809151), (1218448917, 480915))
1318 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.SplitTime(123.48012), (123, 480120))
1319 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.SplitTime(123.9996), (123, 999600))
1320 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.SplitTime(123.9995), (123, 999500))
1321 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.SplitTime(123.9994), (123, 999400))
1322 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.SplitTime(123.999999999), (123, 999999))
1323 45bc5e4a Michael Hanselmann
1324 45bc5e4a Michael Hanselmann
    self.assertRaises(AssertionError, utils.SplitTime, -1)
1325 739be818 Michael Hanselmann
1326 739be818 Michael Hanselmann
    self.assertEqual(utils.MergeTime((1, 0)), 1.0)
1327 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.MergeTime((1, 500000)), 1.5)
1328 45bc5e4a Michael Hanselmann
    self.assertEqual(utils.MergeTime((1218448917, 500000)), 1218448917.5)
1329 739be818 Michael Hanselmann
1330 4d4a651d Michael Hanselmann
    self.assertEqual(round(utils.MergeTime((1218448917, 481000)), 3),
1331 4d4a651d Michael Hanselmann
                     1218448917.481)
1332 45bc5e4a Michael Hanselmann
    self.assertEqual(round(utils.MergeTime((1, 801000)), 3), 1.801)
1333 739be818 Michael Hanselmann
1334 739be818 Michael Hanselmann
    self.assertRaises(AssertionError, utils.MergeTime, (0, -1))
1335 45bc5e4a Michael Hanselmann
    self.assertRaises(AssertionError, utils.MergeTime, (0, 1000000))
1336 45bc5e4a Michael Hanselmann
    self.assertRaises(AssertionError, utils.MergeTime, (0, 9999999))
1337 739be818 Michael Hanselmann
    self.assertRaises(AssertionError, utils.MergeTime, (-1, 0))
1338 739be818 Michael Hanselmann
    self.assertRaises(AssertionError, utils.MergeTime, (-9999, 0))
1339 739be818 Michael Hanselmann
1340 739be818 Michael Hanselmann
1341 a2d2e1a7 Iustin Pop
class FieldSetTestCase(unittest.TestCase):
1342 a2d2e1a7 Iustin Pop
  """Test case for FieldSets"""
1343 a2d2e1a7 Iustin Pop
1344 a2d2e1a7 Iustin Pop
  def testSimpleMatch(self):
1345 a2d2e1a7 Iustin Pop
    f = utils.FieldSet("a", "b", "c", "def")
1346 a2d2e1a7 Iustin Pop
    self.failUnless(f.Matches("a"))
1347 a2d2e1a7 Iustin Pop
    self.failIf(f.Matches("d"), "Substring matched")
1348 a2d2e1a7 Iustin Pop
    self.failIf(f.Matches("defghi"), "Prefix string matched")
1349 a2d2e1a7 Iustin Pop
    self.failIf(f.NonMatching(["b", "c"]))
1350 a2d2e1a7 Iustin Pop
    self.failIf(f.NonMatching(["a", "b", "c", "def"]))
1351 a2d2e1a7 Iustin Pop
    self.failUnless(f.NonMatching(["a", "d"]))
1352 a2d2e1a7 Iustin Pop
1353 a2d2e1a7 Iustin Pop
  def testRegexMatch(self):
1354 a2d2e1a7 Iustin Pop
    f = utils.FieldSet("a", "b([0-9]+)", "c")
1355 a2d2e1a7 Iustin Pop
    self.failUnless(f.Matches("b1"))
1356 a2d2e1a7 Iustin Pop
    self.failUnless(f.Matches("b99"))
1357 a2d2e1a7 Iustin Pop
    self.failIf(f.Matches("b/1"))
1358 a2d2e1a7 Iustin Pop
    self.failIf(f.NonMatching(["b12", "c"]))
1359 a2d2e1a7 Iustin Pop
    self.failUnless(f.NonMatching(["a", "1"]))
1360 a2d2e1a7 Iustin Pop
1361 a5728081 Guido Trotter
class TestForceDictType(unittest.TestCase):
1362 a5728081 Guido Trotter
  """Test case for ForceDictType"""
1363 a5728081 Guido Trotter
1364 a5728081 Guido Trotter
  def setUp(self):
1365 a5728081 Guido Trotter
    self.key_types = {
1366 a5728081 Guido Trotter
      'a': constants.VTYPE_INT,
1367 a5728081 Guido Trotter
      'b': constants.VTYPE_BOOL,
1368 a5728081 Guido Trotter
      'c': constants.VTYPE_STRING,
1369 a5728081 Guido Trotter
      'd': constants.VTYPE_SIZE,
1370 a5728081 Guido Trotter
      }
1371 a5728081 Guido Trotter
1372 a5728081 Guido Trotter
  def _fdt(self, dict, allowed_values=None):
1373 a5728081 Guido Trotter
    if allowed_values is None:
1374 a5728081 Guido Trotter
      ForceDictType(dict, self.key_types)
1375 a5728081 Guido Trotter
    else:
1376 a5728081 Guido Trotter
      ForceDictType(dict, self.key_types, allowed_values=allowed_values)
1377 a5728081 Guido Trotter
1378 a5728081 Guido Trotter
    return dict
1379 a5728081 Guido Trotter
1380 a5728081 Guido Trotter
  def testSimpleDict(self):
1381 a5728081 Guido Trotter
    self.assertEqual(self._fdt({}), {})
1382 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'a': 1}), {'a': 1})
1383 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'a': '1'}), {'a': 1})
1384 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'a': 1, 'b': 1}), {'a':1, 'b': True})
1385 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'b': 1, 'c': 'foo'}), {'b': True, 'c': 'foo'})
1386 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'b': 1, 'c': False}), {'b': True, 'c': ''})
1387 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'b': 'false'}), {'b': False})
1388 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'b': 'False'}), {'b': False})
1389 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'b': 'true'}), {'b': True})
1390 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'b': 'True'}), {'b': True})
1391 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'d': '4'}), {'d': 4})
1392 a5728081 Guido Trotter
    self.assertEqual(self._fdt({'d': '4M'}), {'d': 4})
1393 a5728081 Guido Trotter
1394 a5728081 Guido Trotter
  def testErrors(self):
1395 a5728081 Guido Trotter
    self.assertRaises(errors.TypeEnforcementError, self._fdt, {'a': 'astring'})
1396 a5728081 Guido Trotter
    self.assertRaises(errors.TypeEnforcementError, self._fdt, {'c': True})
1397 a5728081 Guido Trotter
    self.assertRaises(errors.TypeEnforcementError, self._fdt, {'d': 'astring'})
1398 a5728081 Guido Trotter
    self.assertRaises(errors.TypeEnforcementError, self._fdt, {'d': '4 L'})
1399 a5728081 Guido Trotter
1400 a2d2e1a7 Iustin Pop
1401 da961187 Guido Trotter
class TestIsAbsNormPath(unittest.TestCase):
1402 c1dd99d4 Michael Hanselmann
  """Testing case for IsNormAbsPath"""
1403 da961187 Guido Trotter
1404 da961187 Guido Trotter
  def _pathTestHelper(self, path, result):
1405 da961187 Guido Trotter
    if result:
1406 da961187 Guido Trotter
      self.assert_(IsNormAbsPath(path),
1407 17c61836 Guido Trotter
          "Path %s should result absolute and normalized" % path)
1408 da961187 Guido Trotter
    else:
1409 da961187 Guido Trotter
      self.assert_(not IsNormAbsPath(path),
1410 17c61836 Guido Trotter
          "Path %s should not result absolute and normalized" % path)
1411 da961187 Guido Trotter
1412 da961187 Guido Trotter
  def testBase(self):
1413 da961187 Guido Trotter
    self._pathTestHelper('/etc', True)
1414 da961187 Guido Trotter
    self._pathTestHelper('/srv', True)
1415 da961187 Guido Trotter
    self._pathTestHelper('etc', False)
1416 da961187 Guido Trotter
    self._pathTestHelper('/etc/../root', False)
1417 da961187 Guido Trotter
    self._pathTestHelper('/etc/', False)
1418 da961187 Guido Trotter
1419 af0413bb Guido Trotter
1420 d392fa34 Iustin Pop
class TestSafeEncode(unittest.TestCase):
1421 d392fa34 Iustin Pop
  """Test case for SafeEncode"""
1422 d392fa34 Iustin Pop
1423 d392fa34 Iustin Pop
  def testAscii(self):
1424 d392fa34 Iustin Pop
    for txt in [string.digits, string.letters, string.punctuation]:
1425 d392fa34 Iustin Pop
      self.failUnlessEqual(txt, SafeEncode(txt))
1426 d392fa34 Iustin Pop
1427 d392fa34 Iustin Pop
  def testDoubleEncode(self):
1428 d392fa34 Iustin Pop
    for i in range(255):
1429 d392fa34 Iustin Pop
      txt = SafeEncode(chr(i))
1430 d392fa34 Iustin Pop
      self.failUnlessEqual(txt, SafeEncode(txt))
1431 d392fa34 Iustin Pop
1432 d392fa34 Iustin Pop
  def testUnicode(self):
1433 d392fa34 Iustin Pop
    # 1024 is high enough to catch non-direct ASCII mappings
1434 d392fa34 Iustin Pop
    for i in range(1024):
1435 d392fa34 Iustin Pop
      txt = SafeEncode(unichr(i))
1436 d392fa34 Iustin Pop
      self.failUnlessEqual(txt, SafeEncode(txt))
1437 d392fa34 Iustin Pop
1438 d392fa34 Iustin Pop
1439 3b813dd2 Iustin Pop
class TestFormatTime(unittest.TestCase):
1440 3b813dd2 Iustin Pop
  """Testing case for FormatTime"""
1441 3b813dd2 Iustin Pop
1442 3b813dd2 Iustin Pop
  def testNone(self):
1443 3b813dd2 Iustin Pop
    self.failUnlessEqual(FormatTime(None), "N/A")
1444 3b813dd2 Iustin Pop
1445 3b813dd2 Iustin Pop
  def testInvalid(self):
1446 3b813dd2 Iustin Pop
    self.failUnlessEqual(FormatTime(()), "N/A")
1447 3b813dd2 Iustin Pop
1448 3b813dd2 Iustin Pop
  def testNow(self):
1449 3b813dd2 Iustin Pop
    # tests that we accept time.time input
1450 3b813dd2 Iustin Pop
    FormatTime(time.time())
1451 3b813dd2 Iustin Pop
    # tests that we accept int input
1452 3b813dd2 Iustin Pop
    FormatTime(int(time.time()))
1453 3b813dd2 Iustin Pop
1454 3b813dd2 Iustin Pop
1455 eb58f7bd Michael Hanselmann
class RunInSeparateProcess(unittest.TestCase):
1456 eb58f7bd Michael Hanselmann
  def test(self):
1457 eb58f7bd Michael Hanselmann
    for exp in [True, False]:
1458 eb58f7bd Michael Hanselmann
      def _child():
1459 eb58f7bd Michael Hanselmann
        return exp
1460 eb58f7bd Michael Hanselmann
1461 eb58f7bd Michael Hanselmann
      self.assertEqual(exp, utils.RunInSeparateProcess(_child))
1462 eb58f7bd Michael Hanselmann
1463 bdefe5dd Michael Hanselmann
  def testArgs(self):
1464 bdefe5dd Michael Hanselmann
    for arg in [0, 1, 999, "Hello World", (1, 2, 3)]:
1465 bdefe5dd Michael Hanselmann
      def _child(carg1, carg2):
1466 bdefe5dd Michael Hanselmann
        return carg1 == "Foo" and carg2 == arg
1467 bdefe5dd Michael Hanselmann
1468 bdefe5dd Michael Hanselmann
      self.assert_(utils.RunInSeparateProcess(_child, "Foo", arg))
1469 bdefe5dd Michael Hanselmann
1470 eb58f7bd Michael Hanselmann
  def testPid(self):
1471 eb58f7bd Michael Hanselmann
    parent_pid = os.getpid()
1472 eb58f7bd Michael Hanselmann
1473 eb58f7bd Michael Hanselmann
    def _check():
1474 eb58f7bd Michael Hanselmann
      return os.getpid() == parent_pid
1475 eb58f7bd Michael Hanselmann
1476 eb58f7bd Michael Hanselmann
    self.failIf(utils.RunInSeparateProcess(_check))
1477 eb58f7bd Michael Hanselmann
1478 eb58f7bd Michael Hanselmann
  def testSignal(self):
1479 eb58f7bd Michael Hanselmann
    def _kill():
1480 eb58f7bd Michael Hanselmann
      os.kill(os.getpid(), signal.SIGTERM)
1481 eb58f7bd Michael Hanselmann
1482 eb58f7bd Michael Hanselmann
    self.assertRaises(errors.GenericError,
1483 eb58f7bd Michael Hanselmann
                      utils.RunInSeparateProcess, _kill)
1484 eb58f7bd Michael Hanselmann
1485 eb58f7bd Michael Hanselmann
  def testException(self):
1486 eb58f7bd Michael Hanselmann
    def _exc():
1487 eb58f7bd Michael Hanselmann
      raise errors.GenericError("This is a test")
1488 eb58f7bd Michael Hanselmann
1489 eb58f7bd Michael Hanselmann
    self.assertRaises(errors.GenericError,
1490 eb58f7bd Michael Hanselmann
                      utils.RunInSeparateProcess, _exc)
1491 eb58f7bd Michael Hanselmann
1492 eb58f7bd Michael Hanselmann
1493 fabee4b2 Michael Hanselmann
class TestFingerprintFile(unittest.TestCase):
1494 fabee4b2 Michael Hanselmann
  def setUp(self):
1495 fabee4b2 Michael Hanselmann
    self.tmpfile = tempfile.NamedTemporaryFile()
1496 fabee4b2 Michael Hanselmann
1497 fabee4b2 Michael Hanselmann
  def test(self):
1498 fabee4b2 Michael Hanselmann
    self.assertEqual(utils._FingerprintFile(self.tmpfile.name),
1499 fabee4b2 Michael Hanselmann
                     "da39a3ee5e6b4b0d3255bfef95601890afd80709")
1500 fabee4b2 Michael Hanselmann
1501 fabee4b2 Michael Hanselmann
    utils.WriteFile(self.tmpfile.name, data="Hello World\n")
1502 fabee4b2 Michael Hanselmann
    self.assertEqual(utils._FingerprintFile(self.tmpfile.name),
1503 fabee4b2 Michael Hanselmann
                     "648a6a6ffffdaa0badb23b8baf90b6168dd16b3a")
1504 fabee4b2 Michael Hanselmann
1505 fabee4b2 Michael Hanselmann
1506 5b69bc7c Iustin Pop
class TestUnescapeAndSplit(unittest.TestCase):
1507 5b69bc7c Iustin Pop
  """Testing case for UnescapeAndSplit"""
1508 5b69bc7c Iustin Pop
1509 5b69bc7c Iustin Pop
  def setUp(self):
1510 5b69bc7c Iustin Pop
    # testing more that one separator for regexp safety
1511 5b69bc7c Iustin Pop
    self._seps = [",", "+", "."]
1512 5b69bc7c Iustin Pop
1513 5b69bc7c Iustin Pop
  def testSimple(self):
1514 5b69bc7c Iustin Pop
    a = ["a", "b", "c", "d"]
1515 5b69bc7c Iustin Pop
    for sep in self._seps:
1516 5b69bc7c Iustin Pop
      self.failUnlessEqual(UnescapeAndSplit(sep.join(a), sep=sep), a)
1517 5b69bc7c Iustin Pop
1518 5b69bc7c Iustin Pop
  def testEscape(self):
1519 5b69bc7c Iustin Pop
    for sep in self._seps:
1520 5b69bc7c Iustin Pop
      a = ["a", "b\\" + sep + "c", "d"]
1521 5b69bc7c Iustin Pop
      b = ["a", "b" + sep + "c", "d"]
1522 5b69bc7c Iustin Pop
      self.failUnlessEqual(UnescapeAndSplit(sep.join(a), sep=sep), b)
1523 5b69bc7c Iustin Pop
1524 5b69bc7c Iustin Pop
  def testDoubleEscape(self):
1525 5b69bc7c Iustin Pop
    for sep in self._seps:
1526 5b69bc7c Iustin Pop
      a = ["a", "b\\\\", "c", "d"]
1527 5b69bc7c Iustin Pop
      b = ["a", "b\\", "c", "d"]
1528 5b69bc7c Iustin Pop
      self.failUnlessEqual(UnescapeAndSplit(sep.join(a), sep=sep), b)
1529 5b69bc7c Iustin Pop
1530 5b69bc7c Iustin Pop
  def testThreeEscape(self):
1531 5b69bc7c Iustin Pop
    for sep in self._seps:
1532 5b69bc7c Iustin Pop
      a = ["a", "b\\\\\\" + sep + "c", "d"]
1533 5b69bc7c Iustin Pop
      b = ["a", "b\\" + sep + "c", "d"]
1534 5b69bc7c Iustin Pop
      self.failUnlessEqual(UnescapeAndSplit(sep.join(a), sep=sep), b)
1535 5b69bc7c Iustin Pop
1536 5b69bc7c Iustin Pop
1537 bdd5e420 Michael Hanselmann
class TestGenerateSelfSignedX509Cert(unittest.TestCase):
1538 a55474c7 Michael Hanselmann
  def setUp(self):
1539 a55474c7 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
1540 a55474c7 Michael Hanselmann
1541 a55474c7 Michael Hanselmann
  def tearDown(self):
1542 a55474c7 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
1543 a55474c7 Michael Hanselmann
1544 bdd5e420 Michael Hanselmann
  def _checkRsaPrivateKey(self, key):
1545 a55474c7 Michael Hanselmann
    lines = key.splitlines()
1546 bdd5e420 Michael Hanselmann
    return ("-----BEGIN RSA PRIVATE KEY-----" in lines and
1547 bdd5e420 Michael Hanselmann
            "-----END RSA PRIVATE KEY-----" in lines)
1548 a55474c7 Michael Hanselmann
1549 bdd5e420 Michael Hanselmann
  def _checkCertificate(self, cert):
1550 a55474c7 Michael Hanselmann
    lines = cert.splitlines()
1551 bdd5e420 Michael Hanselmann
    return ("-----BEGIN CERTIFICATE-----" in lines and
1552 bdd5e420 Michael Hanselmann
            "-----END CERTIFICATE-----" in lines)
1553 a55474c7 Michael Hanselmann
1554 bdd5e420 Michael Hanselmann
  def test(self):
1555 bdd5e420 Michael Hanselmann
    for common_name in [None, ".", "Ganeti", "node1.example.com"]:
1556 bdd5e420 Michael Hanselmann
      (key_pem, cert_pem) = utils.GenerateSelfSignedX509Cert(common_name, 300)
1557 bdd5e420 Michael Hanselmann
      self._checkRsaPrivateKey(key_pem)
1558 bdd5e420 Michael Hanselmann
      self._checkCertificate(cert_pem)
1559 bdd5e420 Michael Hanselmann
1560 bdd5e420 Michael Hanselmann
      key = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM,
1561 bdd5e420 Michael Hanselmann
                                           key_pem)
1562 bdd5e420 Michael Hanselmann
      self.assert_(key.bits() >= 1024)
1563 bdd5e420 Michael Hanselmann
      self.assertEqual(key.bits(), constants.RSA_KEY_BITS)
1564 bdd5e420 Michael Hanselmann
      self.assertEqual(key.type(), OpenSSL.crypto.TYPE_RSA)
1565 bdd5e420 Michael Hanselmann
1566 bdd5e420 Michael Hanselmann
      x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
1567 bdd5e420 Michael Hanselmann
                                             cert_pem)
1568 bdd5e420 Michael Hanselmann
      self.failIf(x509.has_expired())
1569 bdd5e420 Michael Hanselmann
      self.assertEqual(x509.get_issuer().CN, common_name)
1570 bdd5e420 Michael Hanselmann
      self.assertEqual(x509.get_subject().CN, common_name)
1571 bdd5e420 Michael Hanselmann
      self.assertEqual(x509.get_pubkey().bits(), constants.RSA_KEY_BITS)
1572 bdd5e420 Michael Hanselmann
1573 bdd5e420 Michael Hanselmann
  def testLegacy(self):
1574 a55474c7 Michael Hanselmann
    cert1_filename = os.path.join(self.tmpdir, "cert1.pem")
1575 a55474c7 Michael Hanselmann
1576 a55474c7 Michael Hanselmann
    utils.GenerateSelfSignedSslCert(cert1_filename, validity=1)
1577 a55474c7 Michael Hanselmann
1578 a55474c7 Michael Hanselmann
    cert1 = utils.ReadFile(cert1_filename)
1579 a55474c7 Michael Hanselmann
1580 bdd5e420 Michael Hanselmann
    self.assert_(self._checkRsaPrivateKey(cert1))
1581 bdd5e420 Michael Hanselmann
    self.assert_(self._checkCertificate(cert1))
1582 a55474c7 Michael Hanselmann
1583 a55474c7 Michael Hanselmann
1584 4bb678e9 Iustin Pop
class TestPathJoin(unittest.TestCase):
1585 4bb678e9 Iustin Pop
  """Testing case for PathJoin"""
1586 4bb678e9 Iustin Pop
1587 4bb678e9 Iustin Pop
  def testBasicItems(self):
1588 4bb678e9 Iustin Pop
    mlist = ["/a", "b", "c"]
1589 4bb678e9 Iustin Pop
    self.failUnlessEqual(PathJoin(*mlist), "/".join(mlist))
1590 4bb678e9 Iustin Pop
1591 4bb678e9 Iustin Pop
  def testNonAbsPrefix(self):
1592 4bb678e9 Iustin Pop
    self.failUnlessRaises(ValueError, PathJoin, "a", "b")
1593 4bb678e9 Iustin Pop
1594 4bb678e9 Iustin Pop
  def testBackTrack(self):
1595 4bb678e9 Iustin Pop
    self.failUnlessRaises(ValueError, PathJoin, "/a", "b/../c")
1596 4bb678e9 Iustin Pop
1597 4bb678e9 Iustin Pop
  def testMultiAbs(self):
1598 4bb678e9 Iustin Pop
    self.failUnlessRaises(ValueError, PathJoin, "/a", "/b")
1599 4bb678e9 Iustin Pop
1600 4bb678e9 Iustin Pop
1601 26288e68 Iustin Pop
class TestHostInfo(unittest.TestCase):
1602 26288e68 Iustin Pop
  """Testing case for HostInfo"""
1603 26288e68 Iustin Pop
1604 26288e68 Iustin Pop
  def testUppercase(self):
1605 26288e68 Iustin Pop
    data = "AbC.example.com"
1606 26288e68 Iustin Pop
    self.failUnlessEqual(HostInfo.NormalizeName(data), data.lower())
1607 26288e68 Iustin Pop
1608 26288e68 Iustin Pop
  def testTooLongName(self):
1609 26288e68 Iustin Pop
    data = "a.b." + "c" * 255
1610 26288e68 Iustin Pop
    self.failUnlessRaises(OpPrereqError, HostInfo.NormalizeName, data)
1611 26288e68 Iustin Pop
1612 26288e68 Iustin Pop
  def testTrailingDot(self):
1613 26288e68 Iustin Pop
    data = "a.b.c"
1614 26288e68 Iustin Pop
    self.failUnlessEqual(HostInfo.NormalizeName(data + "."), data)
1615 26288e68 Iustin Pop
1616 26288e68 Iustin Pop
  def testInvalidName(self):
1617 26288e68 Iustin Pop
    data = [
1618 26288e68 Iustin Pop
      "a b",
1619 26288e68 Iustin Pop
      "a/b",
1620 26288e68 Iustin Pop
      ".a.b",
1621 26288e68 Iustin Pop
      "a..b",
1622 26288e68 Iustin Pop
      ]
1623 26288e68 Iustin Pop
    for value in data:
1624 26288e68 Iustin Pop
      self.failUnlessRaises(OpPrereqError, HostInfo.NormalizeName, value)
1625 26288e68 Iustin Pop
1626 26288e68 Iustin Pop
  def testValidName(self):
1627 26288e68 Iustin Pop
    data = [
1628 26288e68 Iustin Pop
      "a.b",
1629 26288e68 Iustin Pop
      "a-b",
1630 26288e68 Iustin Pop
      "a_b",
1631 26288e68 Iustin Pop
      "a.b.c",
1632 26288e68 Iustin Pop
      ]
1633 26288e68 Iustin Pop
    for value in data:
1634 26288e68 Iustin Pop
      HostInfo.NormalizeName(value)
1635 26288e68 Iustin Pop
1636 26288e68 Iustin Pop
1637 27e46076 Michael Hanselmann
class TestParseAsn1Generalizedtime(unittest.TestCase):
1638 27e46076 Michael Hanselmann
  def test(self):
1639 27e46076 Michael Hanselmann
    # UTC
1640 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("19700101000000Z"), 0)
1641 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("20100222174152Z"),
1642 27e46076 Michael Hanselmann
                     1266860512)
1643 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("20380119031407Z"),
1644 27e46076 Michael Hanselmann
                     (2**31) - 1)
1645 27e46076 Michael Hanselmann
1646 27e46076 Michael Hanselmann
    # With offset
1647 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("20100222174152+0000"),
1648 27e46076 Michael Hanselmann
                     1266860512)
1649 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("20100223131652+0000"),
1650 27e46076 Michael Hanselmann
                     1266931012)
1651 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("20100223051808-0800"),
1652 27e46076 Michael Hanselmann
                     1266931088)
1653 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("20100224002135+1100"),
1654 27e46076 Michael Hanselmann
                     1266931295)
1655 27e46076 Michael Hanselmann
    self.assertEqual(utils._ParseAsn1Generalizedtime("19700101000000-0100"),
1656 27e46076 Michael Hanselmann
                     3600)
1657 27e46076 Michael Hanselmann
1658 27e46076 Michael Hanselmann
    # Leap seconds are not supported by datetime.datetime
1659 27e46076 Michael Hanselmann
    self.assertRaises(ValueError, utils._ParseAsn1Generalizedtime,
1660 27e46076 Michael Hanselmann
                      "19841231235960+0000")
1661 27e46076 Michael Hanselmann
    self.assertRaises(ValueError, utils._ParseAsn1Generalizedtime,
1662 27e46076 Michael Hanselmann
                      "19920630235960+0000")
1663 27e46076 Michael Hanselmann
1664 27e46076 Michael Hanselmann
    # Errors
1665 27e46076 Michael Hanselmann
    self.assertRaises(ValueError, utils._ParseAsn1Generalizedtime, "")
1666 27e46076 Michael Hanselmann
    self.assertRaises(ValueError, utils._ParseAsn1Generalizedtime, "invalid")
1667 27e46076 Michael Hanselmann
    self.assertRaises(ValueError, utils._ParseAsn1Generalizedtime,
1668 27e46076 Michael Hanselmann
                      "20100222174152")
1669 27e46076 Michael Hanselmann
    self.assertRaises(ValueError, utils._ParseAsn1Generalizedtime,
1670 27e46076 Michael Hanselmann
                      "Mon Feb 22 17:47:02 UTC 2010")
1671 27e46076 Michael Hanselmann
    self.assertRaises(ValueError, utils._ParseAsn1Generalizedtime,
1672 27e46076 Michael Hanselmann
                      "2010-02-22 17:42:02")
1673 27e46076 Michael Hanselmann
1674 27e46076 Michael Hanselmann
1675 27e46076 Michael Hanselmann
class TestGetX509CertValidity(testutils.GanetiTestCase):
1676 27e46076 Michael Hanselmann
  def setUp(self):
1677 27e46076 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
1678 27e46076 Michael Hanselmann
1679 27e46076 Michael Hanselmann
    pyopenssl_version = distutils.version.LooseVersion(OpenSSL.__version__)
1680 27e46076 Michael Hanselmann
1681 27e46076 Michael Hanselmann
    # Test whether we have pyOpenSSL 0.7 or above
1682 27e46076 Michael Hanselmann
    self.pyopenssl0_7 = (pyopenssl_version >= "0.7")
1683 27e46076 Michael Hanselmann
1684 27e46076 Michael Hanselmann
    if not self.pyopenssl0_7:
1685 27e46076 Michael Hanselmann
      warnings.warn("This test requires pyOpenSSL 0.7 or above to"
1686 27e46076 Michael Hanselmann
                    " function correctly")
1687 27e46076 Michael Hanselmann
1688 27e46076 Michael Hanselmann
  def _LoadCert(self, name):
1689 27e46076 Michael Hanselmann
    return OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
1690 27e46076 Michael Hanselmann
                                           self._ReadTestData(name))
1691 27e46076 Michael Hanselmann
1692 27e46076 Michael Hanselmann
  def test(self):
1693 27e46076 Michael Hanselmann
    validity = utils.GetX509CertValidity(self._LoadCert("cert1.pem"))
1694 27e46076 Michael Hanselmann
    if self.pyopenssl0_7:
1695 27e46076 Michael Hanselmann
      self.assertEqual(validity, (1266919967, 1267524767))
1696 27e46076 Michael Hanselmann
    else:
1697 27e46076 Michael Hanselmann
      self.assertEqual(validity, (None, None))
1698 27e46076 Michael Hanselmann
1699 26288e68 Iustin Pop
1700 68857643 Michael Hanselmann
class TestSignX509Certificate(unittest.TestCase):
1701 68857643 Michael Hanselmann
  KEY = "My private key!"
1702 68857643 Michael Hanselmann
  KEY_OTHER = "Another key"
1703 68857643 Michael Hanselmann
1704 68857643 Michael Hanselmann
  def test(self):
1705 68857643 Michael Hanselmann
    # Generate certificate valid for 5 minutes
1706 68857643 Michael Hanselmann
    (_, cert_pem) = utils.GenerateSelfSignedX509Cert(None, 300)
1707 68857643 Michael Hanselmann
1708 68857643 Michael Hanselmann
    cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
1709 68857643 Michael Hanselmann
                                           cert_pem)
1710 68857643 Michael Hanselmann
1711 68857643 Michael Hanselmann
    # No signature at all
1712 68857643 Michael Hanselmann
    self.assertRaises(errors.GenericError,
1713 68857643 Michael Hanselmann
                      utils.LoadSignedX509Certificate, cert_pem, self.KEY)
1714 68857643 Michael Hanselmann
1715 68857643 Michael Hanselmann
    # Invalid input
1716 68857643 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
1717 68857643 Michael Hanselmann
                      "", self.KEY)
1718 68857643 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
1719 68857643 Michael Hanselmann
                      "X-Ganeti-Signature: \n", self.KEY)
1720 68857643 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
1721 68857643 Michael Hanselmann
                      "X-Ganeti-Sign: $1234$abcdef\n", self.KEY)
1722 68857643 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
1723 68857643 Michael Hanselmann
                      "X-Ganeti-Signature: $1234567890$abcdef\n", self.KEY)
1724 68857643 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
1725 68857643 Michael Hanselmann
                      "X-Ganeti-Signature: $1234$abc\n\n" + cert_pem, self.KEY)
1726 68857643 Michael Hanselmann
1727 68857643 Michael Hanselmann
    # Invalid salt
1728 68857643 Michael Hanselmann
    for salt in list("-_@$,:;/\\ \t\n"):
1729 68857643 Michael Hanselmann
      self.assertRaises(errors.GenericError, utils.SignX509Certificate,
1730 68857643 Michael Hanselmann
                        cert_pem, self.KEY, "foo%sbar" % salt)
1731 68857643 Michael Hanselmann
1732 68857643 Michael Hanselmann
    for salt in ["HelloWorld", "salt", string.letters, string.digits,
1733 68857643 Michael Hanselmann
                 utils.GenerateSecret(numbytes=4),
1734 68857643 Michael Hanselmann
                 utils.GenerateSecret(numbytes=16),
1735 68857643 Michael Hanselmann
                 "{123:456}".encode("hex")]:
1736 68857643 Michael Hanselmann
      signed_pem = utils.SignX509Certificate(cert, self.KEY, salt)
1737 68857643 Michael Hanselmann
1738 68857643 Michael Hanselmann
      self._Check(cert, salt, signed_pem)
1739 68857643 Michael Hanselmann
1740 68857643 Michael Hanselmann
      self._Check(cert, salt, "X-Another-Header: with a value\n" + signed_pem)
1741 68857643 Michael Hanselmann
      self._Check(cert, salt, (10 * "Hello World!\n") + signed_pem)
1742 68857643 Michael Hanselmann
      self._Check(cert, salt, (signed_pem + "\n\na few more\n"
1743 68857643 Michael Hanselmann
                               "lines----\n------ at\nthe end!"))
1744 68857643 Michael Hanselmann
1745 68857643 Michael Hanselmann
  def _Check(self, cert, salt, pem):
1746 68857643 Michael Hanselmann
    (cert2, salt2) = utils.LoadSignedX509Certificate(pem, self.KEY)
1747 68857643 Michael Hanselmann
    self.assertEqual(salt, salt2)
1748 68857643 Michael Hanselmann
    self.assertEqual(cert.digest("sha1"), cert2.digest("sha1"))
1749 68857643 Michael Hanselmann
1750 68857643 Michael Hanselmann
    # Other key
1751 68857643 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.LoadSignedX509Certificate,
1752 68857643 Michael Hanselmann
                      pem, self.KEY_OTHER)
1753 68857643 Michael Hanselmann
1754 68857643 Michael Hanselmann
1755 76e5f8b5 Michael Hanselmann
class TestMakedirs(unittest.TestCase):
1756 76e5f8b5 Michael Hanselmann
  def setUp(self):
1757 76e5f8b5 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
1758 76e5f8b5 Michael Hanselmann
1759 76e5f8b5 Michael Hanselmann
  def tearDown(self):
1760 76e5f8b5 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
1761 76e5f8b5 Michael Hanselmann
1762 76e5f8b5 Michael Hanselmann
  def testNonExisting(self):
1763 76e5f8b5 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "foo")
1764 76e5f8b5 Michael Hanselmann
    utils.Makedirs(path)
1765 76e5f8b5 Michael Hanselmann
    self.assert_(os.path.isdir(path))
1766 76e5f8b5 Michael Hanselmann
1767 76e5f8b5 Michael Hanselmann
  def testExisting(self):
1768 76e5f8b5 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "foo")
1769 76e5f8b5 Michael Hanselmann
    os.mkdir(path)
1770 76e5f8b5 Michael Hanselmann
    utils.Makedirs(path)
1771 76e5f8b5 Michael Hanselmann
    self.assert_(os.path.isdir(path))
1772 76e5f8b5 Michael Hanselmann
1773 76e5f8b5 Michael Hanselmann
  def testRecursiveNonExisting(self):
1774 76e5f8b5 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "foo/bar/baz")
1775 76e5f8b5 Michael Hanselmann
    utils.Makedirs(path)
1776 76e5f8b5 Michael Hanselmann
    self.assert_(os.path.isdir(path))
1777 76e5f8b5 Michael Hanselmann
1778 76e5f8b5 Michael Hanselmann
  def testRecursiveExisting(self):
1779 76e5f8b5 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "B/moo/xyz")
1780 76e5f8b5 Michael Hanselmann
    self.assert_(not os.path.exists(path))
1781 76e5f8b5 Michael Hanselmann
    os.mkdir(utils.PathJoin(self.tmpdir, "B"))
1782 76e5f8b5 Michael Hanselmann
    utils.Makedirs(path)
1783 76e5f8b5 Michael Hanselmann
    self.assert_(os.path.isdir(path))
1784 76e5f8b5 Michael Hanselmann
1785 76e5f8b5 Michael Hanselmann
1786 1b429e2a Iustin Pop
class TestRetry(testutils.GanetiTestCase):
1787 1b429e2a Iustin Pop
  @staticmethod
1788 1b429e2a Iustin Pop
  def _RaiseRetryAgain():
1789 1b429e2a Iustin Pop
    raise utils.RetryAgain()
1790 1b429e2a Iustin Pop
1791 1b429e2a Iustin Pop
  def _WrongNestedLoop(self):
1792 1b429e2a Iustin Pop
    return utils.Retry(self._RaiseRetryAgain, 0.01, 0.02)
1793 1b429e2a Iustin Pop
1794 1b429e2a Iustin Pop
  def testRaiseTimeout(self):
1795 1b429e2a Iustin Pop
    self.failUnlessRaises(utils.RetryTimeout, utils.Retry,
1796 1b429e2a Iustin Pop
                          self._RaiseRetryAgain, 0.01, 0.02)
1797 1b429e2a Iustin Pop
1798 1b429e2a Iustin Pop
  def testComplete(self):
1799 1b429e2a Iustin Pop
    self.failUnlessEqual(utils.Retry(lambda: True, 0, 1), True)
1800 1b429e2a Iustin Pop
1801 1b429e2a Iustin Pop
  def testNestedLoop(self):
1802 1b429e2a Iustin Pop
    try:
1803 1b429e2a Iustin Pop
      self.failUnlessRaises(errors.ProgrammerError, utils.Retry,
1804 1b429e2a Iustin Pop
                            self._WrongNestedLoop, 0, 1)
1805 1b429e2a Iustin Pop
    except utils.RetryTimeout:
1806 1b429e2a Iustin Pop
      self.fail("Didn't detect inner loop's exception")
1807 1b429e2a Iustin Pop
1808 1b429e2a Iustin Pop
1809 339be5a8 Michael Hanselmann
class TestLineSplitter(unittest.TestCase):
1810 339be5a8 Michael Hanselmann
  def test(self):
1811 339be5a8 Michael Hanselmann
    lines = []
1812 339be5a8 Michael Hanselmann
    ls = utils.LineSplitter(lines.append)
1813 339be5a8 Michael Hanselmann
    ls.write("Hello World\n")
1814 339be5a8 Michael Hanselmann
    self.assertEqual(lines, [])
1815 339be5a8 Michael Hanselmann
    ls.write("Foo\n Bar\r\n ")
1816 339be5a8 Michael Hanselmann
    ls.write("Baz")
1817 339be5a8 Michael Hanselmann
    ls.write("Moo")
1818 339be5a8 Michael Hanselmann
    self.assertEqual(lines, [])
1819 339be5a8 Michael Hanselmann
    ls.flush()
1820 339be5a8 Michael Hanselmann
    self.assertEqual(lines, ["Hello World", "Foo", " Bar"])
1821 339be5a8 Michael Hanselmann
    ls.close()
1822 339be5a8 Michael Hanselmann
    self.assertEqual(lines, ["Hello World", "Foo", " Bar", " BazMoo"])
1823 339be5a8 Michael Hanselmann
1824 339be5a8 Michael Hanselmann
  def _testExtra(self, line, all_lines, p1, p2):
1825 339be5a8 Michael Hanselmann
    self.assertEqual(p1, 999)
1826 339be5a8 Michael Hanselmann
    self.assertEqual(p2, "extra")
1827 339be5a8 Michael Hanselmann
    all_lines.append(line)
1828 339be5a8 Michael Hanselmann
1829 339be5a8 Michael Hanselmann
  def testExtraArgsNoFlush(self):
1830 339be5a8 Michael Hanselmann
    lines = []
1831 339be5a8 Michael Hanselmann
    ls = utils.LineSplitter(self._testExtra, lines, 999, "extra")
1832 339be5a8 Michael Hanselmann
    ls.write("\n\nHello World\n")
1833 339be5a8 Michael Hanselmann
    ls.write("Foo\n Bar\r\n ")
1834 339be5a8 Michael Hanselmann
    ls.write("")
1835 339be5a8 Michael Hanselmann
    ls.write("Baz")
1836 339be5a8 Michael Hanselmann
    ls.write("Moo\n\nx\n")
1837 339be5a8 Michael Hanselmann
    self.assertEqual(lines, [])
1838 339be5a8 Michael Hanselmann
    ls.close()
1839 339be5a8 Michael Hanselmann
    self.assertEqual(lines, ["", "", "Hello World", "Foo", " Bar", " BazMoo",
1840 339be5a8 Michael Hanselmann
                             "", "x"])
1841 339be5a8 Michael Hanselmann
1842 339be5a8 Michael Hanselmann
1843 debed9ae Michael Hanselmann
class TestReadLockedPidFile(unittest.TestCase):
1844 debed9ae Michael Hanselmann
  def setUp(self):
1845 debed9ae Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
1846 debed9ae Michael Hanselmann
1847 debed9ae Michael Hanselmann
  def tearDown(self):
1848 debed9ae Michael Hanselmann
    shutil.rmtree(self.tmpdir)
1849 debed9ae Michael Hanselmann
1850 debed9ae Michael Hanselmann
  def testNonExistent(self):
1851 debed9ae Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "nonexist")
1852 debed9ae Michael Hanselmann
    self.assert_(utils.ReadLockedPidFile(path) is None)
1853 debed9ae Michael Hanselmann
1854 debed9ae Michael Hanselmann
  def testUnlocked(self):
1855 debed9ae Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "pid")
1856 debed9ae Michael Hanselmann
    utils.WriteFile(path, data="123")
1857 debed9ae Michael Hanselmann
    self.assert_(utils.ReadLockedPidFile(path) is None)
1858 debed9ae Michael Hanselmann
1859 debed9ae Michael Hanselmann
  def testLocked(self):
1860 debed9ae Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "pid")
1861 debed9ae Michael Hanselmann
    utils.WriteFile(path, data="123")
1862 debed9ae Michael Hanselmann
1863 debed9ae Michael Hanselmann
    fl = utils.FileLock.Open(path)
1864 debed9ae Michael Hanselmann
    try:
1865 debed9ae Michael Hanselmann
      fl.Exclusive(blocking=True)
1866 debed9ae Michael Hanselmann
1867 debed9ae Michael Hanselmann
      self.assertEqual(utils.ReadLockedPidFile(path), 123)
1868 debed9ae Michael Hanselmann
    finally:
1869 debed9ae Michael Hanselmann
      fl.Close()
1870 debed9ae Michael Hanselmann
1871 debed9ae Michael Hanselmann
    self.assert_(utils.ReadLockedPidFile(path) is None)
1872 debed9ae Michael Hanselmann
1873 debed9ae Michael Hanselmann
  def testError(self):
1874 debed9ae Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "foobar", "pid")
1875 debed9ae Michael Hanselmann
    utils.WriteFile(utils.PathJoin(self.tmpdir, "foobar"), data="")
1876 debed9ae Michael Hanselmann
    # open(2) should return ENOTDIR
1877 debed9ae Michael Hanselmann
    self.assertRaises(EnvironmentError, utils.ReadLockedPidFile, path)
1878 debed9ae Michael Hanselmann
1879 debed9ae Michael Hanselmann
1880 a8083063 Iustin Pop
if __name__ == '__main__':
1881 25231ec5 Michael Hanselmann
  testutils.GanetiTestProgram()