Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.utils.io_unittest.py @ d01e51a5

History | View | Annotate | Download (35.5 kB)

1 3865ca48 Michael Hanselmann
#!/usr/bin/python
2 3865ca48 Michael Hanselmann
#
3 3865ca48 Michael Hanselmann
4 3865ca48 Michael Hanselmann
# Copyright (C) 2006, 2007, 2010, 2011 Google Inc.
5 3865ca48 Michael Hanselmann
#
6 3865ca48 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 3865ca48 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 3865ca48 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 3865ca48 Michael Hanselmann
# (at your option) any later version.
10 3865ca48 Michael Hanselmann
#
11 3865ca48 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 3865ca48 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 3865ca48 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3865ca48 Michael Hanselmann
# General Public License for more details.
15 3865ca48 Michael Hanselmann
#
16 3865ca48 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 3865ca48 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 3865ca48 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 3865ca48 Michael Hanselmann
# 02110-1301, USA.
20 3865ca48 Michael Hanselmann
21 3865ca48 Michael Hanselmann
22 3865ca48 Michael Hanselmann
"""Script for testing ganeti.utils.io"""
23 3865ca48 Michael Hanselmann
24 3865ca48 Michael Hanselmann
import os
25 3865ca48 Michael Hanselmann
import tempfile
26 3865ca48 Michael Hanselmann
import unittest
27 3865ca48 Michael Hanselmann
import shutil
28 3865ca48 Michael Hanselmann
import glob
29 3865ca48 Michael Hanselmann
import time
30 3ae8dd03 Michael Hanselmann
import signal
31 b81b3c96 René Nussbaumer
import stat
32 b81b3c96 René Nussbaumer
import errno
33 3865ca48 Michael Hanselmann
34 3865ca48 Michael Hanselmann
from ganeti import constants
35 3865ca48 Michael Hanselmann
from ganeti import utils
36 3865ca48 Michael Hanselmann
from ganeti import compat
37 3865ca48 Michael Hanselmann
from ganeti import errors
38 3865ca48 Michael Hanselmann
39 3865ca48 Michael Hanselmann
import testutils
40 3865ca48 Michael Hanselmann
41 3865ca48 Michael Hanselmann
42 3865ca48 Michael Hanselmann
class TestReadFile(testutils.GanetiTestCase):
43 3865ca48 Michael Hanselmann
  def testReadAll(self):
44 00ef625c Michael Hanselmann
    data = utils.ReadFile(testutils.TestDataFilename("cert1.pem"))
45 3865ca48 Michael Hanselmann
    self.assertEqual(len(data), 814)
46 3865ca48 Michael Hanselmann
47 3865ca48 Michael Hanselmann
    h = compat.md5_hash()
48 3865ca48 Michael Hanselmann
    h.update(data)
49 3865ca48 Michael Hanselmann
    self.assertEqual(h.hexdigest(), "a491efb3efe56a0535f924d5f8680fd4")
50 3865ca48 Michael Hanselmann
51 3865ca48 Michael Hanselmann
  def testReadSize(self):
52 00ef625c Michael Hanselmann
    data = utils.ReadFile(testutils.TestDataFilename("cert1.pem"),
53 3865ca48 Michael Hanselmann
                          size=100)
54 3865ca48 Michael Hanselmann
    self.assertEqual(len(data), 100)
55 3865ca48 Michael Hanselmann
56 3865ca48 Michael Hanselmann
    h = compat.md5_hash()
57 3865ca48 Michael Hanselmann
    h.update(data)
58 3865ca48 Michael Hanselmann
    self.assertEqual(h.hexdigest(), "893772354e4e690b9efd073eed433ce7")
59 3865ca48 Michael Hanselmann
60 0e5084ee Michael Hanselmann
  def testCallback(self):
61 0e5084ee Michael Hanselmann
    def _Cb(fh):
62 0e5084ee Michael Hanselmann
      self.assertEqual(fh.tell(), 0)
63 00ef625c Michael Hanselmann
    data = utils.ReadFile(testutils.TestDataFilename("cert1.pem"), preread=_Cb)
64 0e5084ee Michael Hanselmann
    self.assertEqual(len(data), 814)
65 0e5084ee Michael Hanselmann
66 3865ca48 Michael Hanselmann
  def testError(self):
67 3865ca48 Michael Hanselmann
    self.assertRaises(EnvironmentError, utils.ReadFile,
68 3865ca48 Michael Hanselmann
                      "/dev/null/does-not-exist")
69 3865ca48 Michael Hanselmann
70 3865ca48 Michael Hanselmann
71 3865ca48 Michael Hanselmann
class TestReadOneLineFile(testutils.GanetiTestCase):
72 3865ca48 Michael Hanselmann
  def setUp(self):
73 3865ca48 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
74 3865ca48 Michael Hanselmann
75 3865ca48 Michael Hanselmann
  def testDefault(self):
76 00ef625c Michael Hanselmann
    data = utils.ReadOneLineFile(testutils.TestDataFilename("cert1.pem"))
77 3865ca48 Michael Hanselmann
    self.assertEqual(len(data), 27)
78 3865ca48 Michael Hanselmann
    self.assertEqual(data, "-----BEGIN CERTIFICATE-----")
79 3865ca48 Michael Hanselmann
80 3865ca48 Michael Hanselmann
  def testNotStrict(self):
81 00ef625c Michael Hanselmann
    data = utils.ReadOneLineFile(testutils.TestDataFilename("cert1.pem"),
82 3865ca48 Michael Hanselmann
                                 strict=False)
83 3865ca48 Michael Hanselmann
    self.assertEqual(len(data), 27)
84 3865ca48 Michael Hanselmann
    self.assertEqual(data, "-----BEGIN CERTIFICATE-----")
85 3865ca48 Michael Hanselmann
86 3865ca48 Michael Hanselmann
  def testStrictFailure(self):
87 3865ca48 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.ReadOneLineFile,
88 00ef625c Michael Hanselmann
                      testutils.TestDataFilename("cert1.pem"), strict=True)
89 3865ca48 Michael Hanselmann
90 3865ca48 Michael Hanselmann
  def testLongLine(self):
91 3865ca48 Michael Hanselmann
    dummydata = (1024 * "Hello World! ")
92 3865ca48 Michael Hanselmann
    myfile = self._CreateTempFile()
93 3865ca48 Michael Hanselmann
    utils.WriteFile(myfile, data=dummydata)
94 3865ca48 Michael Hanselmann
    datastrict = utils.ReadOneLineFile(myfile, strict=True)
95 3865ca48 Michael Hanselmann
    datalax = utils.ReadOneLineFile(myfile, strict=False)
96 3865ca48 Michael Hanselmann
    self.assertEqual(dummydata, datastrict)
97 3865ca48 Michael Hanselmann
    self.assertEqual(dummydata, datalax)
98 3865ca48 Michael Hanselmann
99 3865ca48 Michael Hanselmann
  def testNewline(self):
100 3865ca48 Michael Hanselmann
    myfile = self._CreateTempFile()
101 3865ca48 Michael Hanselmann
    myline = "myline"
102 3865ca48 Michael Hanselmann
    for nl in ["", "\n", "\r\n"]:
103 3865ca48 Michael Hanselmann
      dummydata = "%s%s" % (myline, nl)
104 3865ca48 Michael Hanselmann
      utils.WriteFile(myfile, data=dummydata)
105 3865ca48 Michael Hanselmann
      datalax = utils.ReadOneLineFile(myfile, strict=False)
106 3865ca48 Michael Hanselmann
      self.assertEqual(myline, datalax)
107 3865ca48 Michael Hanselmann
      datastrict = utils.ReadOneLineFile(myfile, strict=True)
108 3865ca48 Michael Hanselmann
      self.assertEqual(myline, datastrict)
109 3865ca48 Michael Hanselmann
110 3865ca48 Michael Hanselmann
  def testWhitespaceAndMultipleLines(self):
111 3865ca48 Michael Hanselmann
    myfile = self._CreateTempFile()
112 3865ca48 Michael Hanselmann
    for nl in ["", "\n", "\r\n"]:
113 3865ca48 Michael Hanselmann
      for ws in [" ", "\t", "\t\t  \t", "\t "]:
114 3865ca48 Michael Hanselmann
        dummydata = (1024 * ("Foo bar baz %s%s" % (ws, nl)))
115 3865ca48 Michael Hanselmann
        utils.WriteFile(myfile, data=dummydata)
116 3865ca48 Michael Hanselmann
        datalax = utils.ReadOneLineFile(myfile, strict=False)
117 3865ca48 Michael Hanselmann
        if nl:
118 3865ca48 Michael Hanselmann
          self.assert_(set("\r\n") & set(dummydata))
119 3865ca48 Michael Hanselmann
          self.assertRaises(errors.GenericError, utils.ReadOneLineFile,
120 3865ca48 Michael Hanselmann
                            myfile, strict=True)
121 3865ca48 Michael Hanselmann
          explen = len("Foo bar baz ") + len(ws)
122 3865ca48 Michael Hanselmann
          self.assertEqual(len(datalax), explen)
123 3865ca48 Michael Hanselmann
          self.assertEqual(datalax, dummydata[:explen])
124 3865ca48 Michael Hanselmann
          self.assertFalse(set("\r\n") & set(datalax))
125 3865ca48 Michael Hanselmann
        else:
126 3865ca48 Michael Hanselmann
          datastrict = utils.ReadOneLineFile(myfile, strict=True)
127 3865ca48 Michael Hanselmann
          self.assertEqual(dummydata, datastrict)
128 3865ca48 Michael Hanselmann
          self.assertEqual(dummydata, datalax)
129 3865ca48 Michael Hanselmann
130 3865ca48 Michael Hanselmann
  def testEmptylines(self):
131 3865ca48 Michael Hanselmann
    myfile = self._CreateTempFile()
132 3865ca48 Michael Hanselmann
    myline = "myline"
133 3865ca48 Michael Hanselmann
    for nl in ["\n", "\r\n"]:
134 3865ca48 Michael Hanselmann
      for ol in ["", "otherline"]:
135 3865ca48 Michael Hanselmann
        dummydata = "%s%s%s%s%s%s" % (nl, nl, myline, nl, ol, nl)
136 3865ca48 Michael Hanselmann
        utils.WriteFile(myfile, data=dummydata)
137 3865ca48 Michael Hanselmann
        self.assert_(set("\r\n") & set(dummydata))
138 3865ca48 Michael Hanselmann
        datalax = utils.ReadOneLineFile(myfile, strict=False)
139 3865ca48 Michael Hanselmann
        self.assertEqual(myline, datalax)
140 3865ca48 Michael Hanselmann
        if ol:
141 3865ca48 Michael Hanselmann
          self.assertRaises(errors.GenericError, utils.ReadOneLineFile,
142 3865ca48 Michael Hanselmann
                            myfile, strict=True)
143 3865ca48 Michael Hanselmann
        else:
144 3865ca48 Michael Hanselmann
          datastrict = utils.ReadOneLineFile(myfile, strict=True)
145 3865ca48 Michael Hanselmann
          self.assertEqual(myline, datastrict)
146 3865ca48 Michael Hanselmann
147 3865ca48 Michael Hanselmann
  def testEmptyfile(self):
148 3865ca48 Michael Hanselmann
    myfile = self._CreateTempFile()
149 3865ca48 Michael Hanselmann
    self.assertRaises(errors.GenericError, utils.ReadOneLineFile, myfile)
150 3865ca48 Michael Hanselmann
151 3865ca48 Michael Hanselmann
152 3865ca48 Michael Hanselmann
class TestTimestampForFilename(unittest.TestCase):
153 3865ca48 Michael Hanselmann
  def test(self):
154 3865ca48 Michael Hanselmann
    self.assert_("." not in utils.TimestampForFilename())
155 3865ca48 Michael Hanselmann
    self.assert_(":" not in utils.TimestampForFilename())
156 3865ca48 Michael Hanselmann
157 3865ca48 Michael Hanselmann
158 3865ca48 Michael Hanselmann
class TestCreateBackup(testutils.GanetiTestCase):
159 3865ca48 Michael Hanselmann
  def setUp(self):
160 3865ca48 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
161 3865ca48 Michael Hanselmann
162 3865ca48 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
163 3865ca48 Michael Hanselmann
164 3865ca48 Michael Hanselmann
  def tearDown(self):
165 3865ca48 Michael Hanselmann
    testutils.GanetiTestCase.tearDown(self)
166 3865ca48 Michael Hanselmann
167 3865ca48 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
168 3865ca48 Michael Hanselmann
169 3865ca48 Michael Hanselmann
  def testEmpty(self):
170 3865ca48 Michael Hanselmann
    filename = utils.PathJoin(self.tmpdir, "config.data")
171 3865ca48 Michael Hanselmann
    utils.WriteFile(filename, data="")
172 3865ca48 Michael Hanselmann
    bname = utils.CreateBackup(filename)
173 3865ca48 Michael Hanselmann
    self.assertFileContent(bname, "")
174 3865ca48 Michael Hanselmann
    self.assertEqual(len(glob.glob("%s*" % filename)), 2)
175 3865ca48 Michael Hanselmann
    utils.CreateBackup(filename)
176 3865ca48 Michael Hanselmann
    self.assertEqual(len(glob.glob("%s*" % filename)), 3)
177 3865ca48 Michael Hanselmann
    utils.CreateBackup(filename)
178 3865ca48 Michael Hanselmann
    self.assertEqual(len(glob.glob("%s*" % filename)), 4)
179 3865ca48 Michael Hanselmann
180 3865ca48 Michael Hanselmann
    fifoname = utils.PathJoin(self.tmpdir, "fifo")
181 3865ca48 Michael Hanselmann
    os.mkfifo(fifoname)
182 3865ca48 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.CreateBackup, fifoname)
183 3865ca48 Michael Hanselmann
184 3865ca48 Michael Hanselmann
  def testContent(self):
185 3865ca48 Michael Hanselmann
    bkpcount = 0
186 3865ca48 Michael Hanselmann
    for data in ["", "X", "Hello World!\n" * 100, "Binary data\0\x01\x02\n"]:
187 3865ca48 Michael Hanselmann
      for rep in [1, 2, 10, 127]:
188 3865ca48 Michael Hanselmann
        testdata = data * rep
189 3865ca48 Michael Hanselmann
190 3865ca48 Michael Hanselmann
        filename = utils.PathJoin(self.tmpdir, "test.data_")
191 3865ca48 Michael Hanselmann
        utils.WriteFile(filename, data=testdata)
192 3865ca48 Michael Hanselmann
        self.assertFileContent(filename, testdata)
193 3865ca48 Michael Hanselmann
194 3865ca48 Michael Hanselmann
        for _ in range(3):
195 3865ca48 Michael Hanselmann
          bname = utils.CreateBackup(filename)
196 3865ca48 Michael Hanselmann
          bkpcount += 1
197 3865ca48 Michael Hanselmann
          self.assertFileContent(bname, testdata)
198 3865ca48 Michael Hanselmann
          self.assertEqual(len(glob.glob("%s*" % filename)), 1 + bkpcount)
199 3865ca48 Michael Hanselmann
200 3865ca48 Michael Hanselmann
201 3865ca48 Michael Hanselmann
class TestListVisibleFiles(unittest.TestCase):
202 3865ca48 Michael Hanselmann
  """Test case for ListVisibleFiles"""
203 3865ca48 Michael Hanselmann
204 3865ca48 Michael Hanselmann
  def setUp(self):
205 3865ca48 Michael Hanselmann
    self.path = tempfile.mkdtemp()
206 3865ca48 Michael Hanselmann
207 3865ca48 Michael Hanselmann
  def tearDown(self):
208 3865ca48 Michael Hanselmann
    shutil.rmtree(self.path)
209 3865ca48 Michael Hanselmann
210 3865ca48 Michael Hanselmann
  def _CreateFiles(self, files):
211 3865ca48 Michael Hanselmann
    for name in files:
212 3865ca48 Michael Hanselmann
      utils.WriteFile(os.path.join(self.path, name), data="test")
213 3865ca48 Michael Hanselmann
214 3865ca48 Michael Hanselmann
  def _test(self, files, expected):
215 3865ca48 Michael Hanselmann
    self._CreateFiles(files)
216 3865ca48 Michael Hanselmann
    found = utils.ListVisibleFiles(self.path)
217 3865ca48 Michael Hanselmann
    self.assertEqual(set(found), set(expected))
218 3865ca48 Michael Hanselmann
219 3865ca48 Michael Hanselmann
  def testAllVisible(self):
220 3865ca48 Michael Hanselmann
    files = ["a", "b", "c"]
221 3865ca48 Michael Hanselmann
    expected = files
222 3865ca48 Michael Hanselmann
    self._test(files, expected)
223 3865ca48 Michael Hanselmann
224 3865ca48 Michael Hanselmann
  def testNoneVisible(self):
225 3865ca48 Michael Hanselmann
    files = [".a", ".b", ".c"]
226 3865ca48 Michael Hanselmann
    expected = []
227 3865ca48 Michael Hanselmann
    self._test(files, expected)
228 3865ca48 Michael Hanselmann
229 3865ca48 Michael Hanselmann
  def testSomeVisible(self):
230 3865ca48 Michael Hanselmann
    files = ["a", "b", ".c"]
231 3865ca48 Michael Hanselmann
    expected = ["a", "b"]
232 3865ca48 Michael Hanselmann
    self._test(files, expected)
233 3865ca48 Michael Hanselmann
234 3865ca48 Michael Hanselmann
  def testNonAbsolutePath(self):
235 3865ca48 Michael Hanselmann
    self.failUnlessRaises(errors.ProgrammerError, utils.ListVisibleFiles,
236 3865ca48 Michael Hanselmann
                          "abc")
237 3865ca48 Michael Hanselmann
238 3865ca48 Michael Hanselmann
  def testNonNormalizedPath(self):
239 3865ca48 Michael Hanselmann
    self.failUnlessRaises(errors.ProgrammerError, utils.ListVisibleFiles,
240 3865ca48 Michael Hanselmann
                          "/bin/../tmp")
241 3865ca48 Michael Hanselmann
242 2dbc6857 Michael Hanselmann
  def testMountpoint(self):
243 2dbc6857 Michael Hanselmann
    lvfmp_fn = compat.partial(utils.ListVisibleFiles,
244 2dbc6857 Michael Hanselmann
                              _is_mountpoint=lambda _: True)
245 2dbc6857 Michael Hanselmann
    self.assertEqual(lvfmp_fn(self.path), [])
246 2dbc6857 Michael Hanselmann
247 2dbc6857 Michael Hanselmann
    # Create "lost+found" as a regular file
248 2dbc6857 Michael Hanselmann
    self._CreateFiles(["foo", "bar", ".baz", "lost+found"])
249 2dbc6857 Michael Hanselmann
    self.assertEqual(set(lvfmp_fn(self.path)),
250 2dbc6857 Michael Hanselmann
                     set(["foo", "bar", "lost+found"]))
251 2dbc6857 Michael Hanselmann
252 2dbc6857 Michael Hanselmann
    # Replace "lost+found" with a directory
253 2dbc6857 Michael Hanselmann
    laf_path = utils.PathJoin(self.path, "lost+found")
254 2dbc6857 Michael Hanselmann
    utils.RemoveFile(laf_path)
255 2dbc6857 Michael Hanselmann
    os.mkdir(laf_path)
256 2dbc6857 Michael Hanselmann
    self.assertEqual(set(lvfmp_fn(self.path)), set(["foo", "bar"]))
257 2dbc6857 Michael Hanselmann
258 2dbc6857 Michael Hanselmann
  def testLostAndFoundNoMountpoint(self):
259 2dbc6857 Michael Hanselmann
    files = ["foo", "bar", ".Hello World", "lost+found"]
260 2dbc6857 Michael Hanselmann
    expected = ["foo", "bar", "lost+found"]
261 2dbc6857 Michael Hanselmann
    self._test(files, expected)
262 2dbc6857 Michael Hanselmann
263 3865ca48 Michael Hanselmann
264 fd6eaa09 Bernardo Dal Seno
class TestWriteFile(testutils.GanetiTestCase):
265 3865ca48 Michael Hanselmann
  def setUp(self):
266 fd6eaa09 Bernardo Dal Seno
    testutils.GanetiTestCase.setUp(self)
267 a9d68e40 Michael Hanselmann
    self.tmpdir = None
268 3865ca48 Michael Hanselmann
    self.tfile = tempfile.NamedTemporaryFile()
269 3865ca48 Michael Hanselmann
    self.did_pre = False
270 3865ca48 Michael Hanselmann
    self.did_post = False
271 3865ca48 Michael Hanselmann
    self.did_write = False
272 3865ca48 Michael Hanselmann
273 a9d68e40 Michael Hanselmann
  def tearDown(self):
274 fd6eaa09 Bernardo Dal Seno
    testutils.GanetiTestCase.tearDown(self)
275 a9d68e40 Michael Hanselmann
    if self.tmpdir:
276 a9d68e40 Michael Hanselmann
      shutil.rmtree(self.tmpdir)
277 a9d68e40 Michael Hanselmann
278 3865ca48 Michael Hanselmann
  def markPre(self, fd):
279 3865ca48 Michael Hanselmann
    self.did_pre = True
280 3865ca48 Michael Hanselmann
281 3865ca48 Michael Hanselmann
  def markPost(self, fd):
282 3865ca48 Michael Hanselmann
    self.did_post = True
283 3865ca48 Michael Hanselmann
284 3865ca48 Michael Hanselmann
  def markWrite(self, fd):
285 3865ca48 Michael Hanselmann
    self.did_write = True
286 3865ca48 Michael Hanselmann
287 3865ca48 Michael Hanselmann
  def testWrite(self):
288 3865ca48 Michael Hanselmann
    data = "abc"
289 3865ca48 Michael Hanselmann
    utils.WriteFile(self.tfile.name, data=data)
290 3865ca48 Michael Hanselmann
    self.assertEqual(utils.ReadFile(self.tfile.name), data)
291 3865ca48 Michael Hanselmann
292 1d39e245 Iustin Pop
  def testWriteSimpleUnicode(self):
293 1d39e245 Iustin Pop
    data = u"abc"
294 1d39e245 Iustin Pop
    utils.WriteFile(self.tfile.name, data=data)
295 1d39e245 Iustin Pop
    self.assertEqual(utils.ReadFile(self.tfile.name), data)
296 1d39e245 Iustin Pop
297 3865ca48 Michael Hanselmann
  def testErrors(self):
298 3865ca48 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.WriteFile,
299 3865ca48 Michael Hanselmann
                      self.tfile.name, data="test", fn=lambda fd: None)
300 3865ca48 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.WriteFile, self.tfile.name)
301 3865ca48 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.WriteFile,
302 3865ca48 Michael Hanselmann
                      self.tfile.name, data="test", atime=0)
303 fd6eaa09 Bernardo Dal Seno
    self.assertRaises(errors.ProgrammerError, utils.WriteFile, self.tfile.name,
304 fd6eaa09 Bernardo Dal Seno
                      mode=0400, keep_perms=utils.KP_ALWAYS)
305 fd6eaa09 Bernardo Dal Seno
    self.assertRaises(errors.ProgrammerError, utils.WriteFile, self.tfile.name,
306 fd6eaa09 Bernardo Dal Seno
                      uid=0, keep_perms=utils.KP_ALWAYS)
307 fd6eaa09 Bernardo Dal Seno
    self.assertRaises(errors.ProgrammerError, utils.WriteFile, self.tfile.name,
308 fd6eaa09 Bernardo Dal Seno
                      gid=0, keep_perms=utils.KP_ALWAYS)
309 fd6eaa09 Bernardo Dal Seno
    self.assertRaises(errors.ProgrammerError, utils.WriteFile, self.tfile.name,
310 fd6eaa09 Bernardo Dal Seno
                      mode=0400, uid=0, keep_perms=utils.KP_ALWAYS)
311 3865ca48 Michael Hanselmann
312 a9d68e40 Michael Hanselmann
  def testPreWrite(self):
313 a9d68e40 Michael Hanselmann
    utils.WriteFile(self.tfile.name, data="", prewrite=self.markPre)
314 3865ca48 Michael Hanselmann
    self.assertTrue(self.did_pre)
315 a9d68e40 Michael Hanselmann
    self.assertFalse(self.did_post)
316 a9d68e40 Michael Hanselmann
    self.assertFalse(self.did_write)
317 a9d68e40 Michael Hanselmann
318 a9d68e40 Michael Hanselmann
  def testPostWrite(self):
319 a9d68e40 Michael Hanselmann
    utils.WriteFile(self.tfile.name, data="", postwrite=self.markPost)
320 a9d68e40 Michael Hanselmann
    self.assertFalse(self.did_pre)
321 3865ca48 Michael Hanselmann
    self.assertTrue(self.did_post)
322 a9d68e40 Michael Hanselmann
    self.assertFalse(self.did_write)
323 a9d68e40 Michael Hanselmann
324 a9d68e40 Michael Hanselmann
  def testWriteFunction(self):
325 a9d68e40 Michael Hanselmann
    utils.WriteFile(self.tfile.name, fn=self.markWrite)
326 a9d68e40 Michael Hanselmann
    self.assertFalse(self.did_pre)
327 a9d68e40 Michael Hanselmann
    self.assertFalse(self.did_post)
328 3865ca48 Michael Hanselmann
    self.assertTrue(self.did_write)
329 3865ca48 Michael Hanselmann
330 3865ca48 Michael Hanselmann
  def testDryRun(self):
331 3865ca48 Michael Hanselmann
    orig = "abc"
332 3865ca48 Michael Hanselmann
    self.tfile.write(orig)
333 3865ca48 Michael Hanselmann
    self.tfile.flush()
334 3865ca48 Michael Hanselmann
    utils.WriteFile(self.tfile.name, data="hello", dry_run=True)
335 3865ca48 Michael Hanselmann
    self.assertEqual(utils.ReadFile(self.tfile.name), orig)
336 3865ca48 Michael Hanselmann
337 3865ca48 Michael Hanselmann
  def testTimes(self):
338 3865ca48 Michael Hanselmann
    f = self.tfile.name
339 3865ca48 Michael Hanselmann
    for at, mt in [(0, 0), (1000, 1000), (2000, 3000),
340 3865ca48 Michael Hanselmann
                   (int(time.time()), 5000)]:
341 3865ca48 Michael Hanselmann
      utils.WriteFile(f, data="hello", atime=at, mtime=mt)
342 3865ca48 Michael Hanselmann
      st = os.stat(f)
343 3865ca48 Michael Hanselmann
      self.assertEqual(st.st_atime, at)
344 3865ca48 Michael Hanselmann
      self.assertEqual(st.st_mtime, mt)
345 3865ca48 Michael Hanselmann
346 3865ca48 Michael Hanselmann
  def testNoClose(self):
347 3865ca48 Michael Hanselmann
    data = "hello"
348 3865ca48 Michael Hanselmann
    self.assertEqual(utils.WriteFile(self.tfile.name, data="abc"), None)
349 3865ca48 Michael Hanselmann
    fd = utils.WriteFile(self.tfile.name, data=data, close=False)
350 3865ca48 Michael Hanselmann
    try:
351 3865ca48 Michael Hanselmann
      os.lseek(fd, 0, 0)
352 3865ca48 Michael Hanselmann
      self.assertEqual(os.read(fd, 4096), data)
353 3865ca48 Michael Hanselmann
    finally:
354 3865ca48 Michael Hanselmann
      os.close(fd)
355 3865ca48 Michael Hanselmann
356 a9d68e40 Michael Hanselmann
  def testNoLeftovers(self):
357 a9d68e40 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
358 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.WriteFile(utils.PathJoin(self.tmpdir, "test"),
359 a9d68e40 Michael Hanselmann
                                     data="abc"),
360 a9d68e40 Michael Hanselmann
                     None)
361 a9d68e40 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), ["test"])
362 a9d68e40 Michael Hanselmann
363 a9d68e40 Michael Hanselmann
  def testFailRename(self):
364 a9d68e40 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
365 a9d68e40 Michael Hanselmann
    target = utils.PathJoin(self.tmpdir, "target")
366 a9d68e40 Michael Hanselmann
    os.mkdir(target)
367 a9d68e40 Michael Hanselmann
    self.assertRaises(OSError, utils.WriteFile, target, data="abc")
368 a9d68e40 Michael Hanselmann
    self.assertTrue(os.path.isdir(target))
369 a9d68e40 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), ["target"])
370 a9d68e40 Michael Hanselmann
    self.assertFalse(os.listdir(target))
371 a9d68e40 Michael Hanselmann
372 a9d68e40 Michael Hanselmann
  def testFailRenameDryRun(self):
373 a9d68e40 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
374 a9d68e40 Michael Hanselmann
    target = utils.PathJoin(self.tmpdir, "target")
375 a9d68e40 Michael Hanselmann
    os.mkdir(target)
376 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.WriteFile(target, data="abc", dry_run=True), None)
377 a9d68e40 Michael Hanselmann
    self.assertTrue(os.path.isdir(target))
378 a9d68e40 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), ["target"])
379 a9d68e40 Michael Hanselmann
    self.assertFalse(os.listdir(target))
380 a9d68e40 Michael Hanselmann
381 a9d68e40 Michael Hanselmann
  def testBackup(self):
382 a9d68e40 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
383 a9d68e40 Michael Hanselmann
    testfile = utils.PathJoin(self.tmpdir, "test")
384 a9d68e40 Michael Hanselmann
385 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.WriteFile(testfile, data="foo", backup=True), None)
386 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.ReadFile(testfile), "foo")
387 a9d68e40 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), ["test"])
388 a9d68e40 Michael Hanselmann
389 a9d68e40 Michael Hanselmann
    # Write again
390 a9d68e40 Michael Hanselmann
    assert os.path.isfile(testfile)
391 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.WriteFile(testfile, data="bar", backup=True), None)
392 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.ReadFile(testfile), "bar")
393 a9d68e40 Michael Hanselmann
    self.assertEqual(len(glob.glob("%s.backup*" % testfile)), 1)
394 a9d68e40 Michael Hanselmann
    self.assertTrue("test" in os.listdir(self.tmpdir))
395 a9d68e40 Michael Hanselmann
    self.assertEqual(len(os.listdir(self.tmpdir)), 2)
396 a9d68e40 Michael Hanselmann
397 a9d68e40 Michael Hanselmann
    # Write again as dry-run
398 a9d68e40 Michael Hanselmann
    assert os.path.isfile(testfile)
399 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.WriteFile(testfile, data="000", backup=True,
400 a9d68e40 Michael Hanselmann
                                     dry_run=True),
401 a9d68e40 Michael Hanselmann
                     None)
402 a9d68e40 Michael Hanselmann
    self.assertEqual(utils.ReadFile(testfile), "bar")
403 a9d68e40 Michael Hanselmann
    self.assertEqual(len(glob.glob("%s.backup*" % testfile)), 1)
404 a9d68e40 Michael Hanselmann
    self.assertTrue("test" in os.listdir(self.tmpdir))
405 a9d68e40 Michael Hanselmann
    self.assertEqual(len(os.listdir(self.tmpdir)), 2)
406 a9d68e40 Michael Hanselmann
407 fd6eaa09 Bernardo Dal Seno
  def testFileMode(self):
408 fd6eaa09 Bernardo Dal Seno
    self.tmpdir = tempfile.mkdtemp()
409 fd6eaa09 Bernardo Dal Seno
    target = utils.PathJoin(self.tmpdir, "target")
410 fd6eaa09 Bernardo Dal Seno
    self.assertRaises(OSError, utils.WriteFile, target, data="data",
411 fd6eaa09 Bernardo Dal Seno
                      keep_perms=utils.KP_ALWAYS)
412 fd6eaa09 Bernardo Dal Seno
    # All masks have only user bits set, to avoid interactions with umask
413 fd6eaa09 Bernardo Dal Seno
    utils.WriteFile(target, data="data", mode=0200)
414 fd6eaa09 Bernardo Dal Seno
    self.assertFileMode(target, 0200)
415 fd6eaa09 Bernardo Dal Seno
    utils.WriteFile(target, data="data", mode=0400,
416 fd6eaa09 Bernardo Dal Seno
                    keep_perms=utils.KP_IF_EXISTS)
417 fd6eaa09 Bernardo Dal Seno
    self.assertFileMode(target, 0200)
418 fd6eaa09 Bernardo Dal Seno
    utils.WriteFile(target, data="data", keep_perms=utils.KP_ALWAYS)
419 fd6eaa09 Bernardo Dal Seno
    self.assertFileMode(target, 0200)
420 fd6eaa09 Bernardo Dal Seno
    utils.WriteFile(target, data="data", mode=0700)
421 fd6eaa09 Bernardo Dal Seno
    self.assertFileMode(target, 0700)
422 fd6eaa09 Bernardo Dal Seno
423 fd6eaa09 Bernardo Dal Seno
  def testNewFileMode(self):
424 fd6eaa09 Bernardo Dal Seno
    self.tmpdir = tempfile.mkdtemp()
425 fd6eaa09 Bernardo Dal Seno
    target = utils.PathJoin(self.tmpdir, "target")
426 fd6eaa09 Bernardo Dal Seno
    utils.WriteFile(target, data="data", mode=0400,
427 fd6eaa09 Bernardo Dal Seno
                    keep_perms=utils.KP_IF_EXISTS)
428 fd6eaa09 Bernardo Dal Seno
    self.assertFileMode(target, 0400)
429 3865ca48 Michael Hanselmann
430 3865ca48 Michael Hanselmann
class TestFileID(testutils.GanetiTestCase):
431 3865ca48 Michael Hanselmann
  def testEquality(self):
432 3865ca48 Michael Hanselmann
    name = self._CreateTempFile()
433 3865ca48 Michael Hanselmann
    oldi = utils.GetFileID(path=name)
434 3865ca48 Michael Hanselmann
    self.failUnless(utils.VerifyFileID(oldi, oldi))
435 3865ca48 Michael Hanselmann
436 3865ca48 Michael Hanselmann
  def testUpdate(self):
437 3865ca48 Michael Hanselmann
    name = self._CreateTempFile()
438 3865ca48 Michael Hanselmann
    oldi = utils.GetFileID(path=name)
439 3865ca48 Michael Hanselmann
    fd = os.open(name, os.O_RDWR)
440 3865ca48 Michael Hanselmann
    try:
441 3865ca48 Michael Hanselmann
      newi = utils.GetFileID(fd=fd)
442 3865ca48 Michael Hanselmann
      self.failUnless(utils.VerifyFileID(oldi, newi))
443 3865ca48 Michael Hanselmann
      self.failUnless(utils.VerifyFileID(newi, oldi))
444 3865ca48 Michael Hanselmann
    finally:
445 3865ca48 Michael Hanselmann
      os.close(fd)
446 3865ca48 Michael Hanselmann
447 3865ca48 Michael Hanselmann
  def testWriteFile(self):
448 3865ca48 Michael Hanselmann
    name = self._CreateTempFile()
449 3865ca48 Michael Hanselmann
    oldi = utils.GetFileID(path=name)
450 3865ca48 Michael Hanselmann
    mtime = oldi[2]
451 3865ca48 Michael Hanselmann
    os.utime(name, (mtime + 10, mtime + 10))
452 3865ca48 Michael Hanselmann
    self.assertRaises(errors.LockError, utils.SafeWriteFile, name,
453 3865ca48 Michael Hanselmann
                      oldi, data="")
454 3865ca48 Michael Hanselmann
    os.utime(name, (mtime - 10, mtime - 10))
455 3865ca48 Michael Hanselmann
    utils.SafeWriteFile(name, oldi, data="")
456 3865ca48 Michael Hanselmann
    oldi = utils.GetFileID(path=name)
457 3865ca48 Michael Hanselmann
    mtime = oldi[2]
458 3865ca48 Michael Hanselmann
    os.utime(name, (mtime + 10, mtime + 10))
459 3865ca48 Michael Hanselmann
    # this doesn't raise, since we passed None
460 3865ca48 Michael Hanselmann
    utils.SafeWriteFile(name, None, data="")
461 3865ca48 Michael Hanselmann
462 3865ca48 Michael Hanselmann
  def testError(self):
463 3865ca48 Michael Hanselmann
    t = tempfile.NamedTemporaryFile()
464 3865ca48 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, utils.GetFileID,
465 3865ca48 Michael Hanselmann
                      path=t.name, fd=t.fileno())
466 3865ca48 Michael Hanselmann
467 3865ca48 Michael Hanselmann
468 3865ca48 Michael Hanselmann
class TestRemoveFile(unittest.TestCase):
469 3865ca48 Michael Hanselmann
  """Test case for the RemoveFile function"""
470 3865ca48 Michael Hanselmann
471 3865ca48 Michael Hanselmann
  def setUp(self):
472 3865ca48 Michael Hanselmann
    """Create a temp dir and file for each case"""
473 8c114acd Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp("", "ganeti-unittest-")
474 8c114acd Michael Hanselmann
    fd, self.tmpfile = tempfile.mkstemp("", "", self.tmpdir)
475 3865ca48 Michael Hanselmann
    os.close(fd)
476 3865ca48 Michael Hanselmann
477 3865ca48 Michael Hanselmann
  def tearDown(self):
478 3865ca48 Michael Hanselmann
    if os.path.exists(self.tmpfile):
479 3865ca48 Michael Hanselmann
      os.unlink(self.tmpfile)
480 3865ca48 Michael Hanselmann
    os.rmdir(self.tmpdir)
481 3865ca48 Michael Hanselmann
482 3865ca48 Michael Hanselmann
  def testIgnoreDirs(self):
483 3865ca48 Michael Hanselmann
    """Test that RemoveFile() ignores directories"""
484 3865ca48 Michael Hanselmann
    self.assertEqual(None, utils.RemoveFile(self.tmpdir))
485 3865ca48 Michael Hanselmann
486 3865ca48 Michael Hanselmann
  def testIgnoreNotExisting(self):
487 3865ca48 Michael Hanselmann
    """Test that RemoveFile() ignores non-existing files"""
488 3865ca48 Michael Hanselmann
    utils.RemoveFile(self.tmpfile)
489 3865ca48 Michael Hanselmann
    utils.RemoveFile(self.tmpfile)
490 3865ca48 Michael Hanselmann
491 3865ca48 Michael Hanselmann
  def testRemoveFile(self):
492 3865ca48 Michael Hanselmann
    """Test that RemoveFile does remove a file"""
493 3865ca48 Michael Hanselmann
    utils.RemoveFile(self.tmpfile)
494 3865ca48 Michael Hanselmann
    if os.path.exists(self.tmpfile):
495 3865ca48 Michael Hanselmann
      self.fail("File '%s' not removed" % self.tmpfile)
496 3865ca48 Michael Hanselmann
497 3865ca48 Michael Hanselmann
  def testRemoveSymlink(self):
498 3865ca48 Michael Hanselmann
    """Test that RemoveFile does remove symlinks"""
499 3865ca48 Michael Hanselmann
    symlink = self.tmpdir + "/symlink"
500 3865ca48 Michael Hanselmann
    os.symlink("no-such-file", symlink)
501 3865ca48 Michael Hanselmann
    utils.RemoveFile(symlink)
502 3865ca48 Michael Hanselmann
    if os.path.exists(symlink):
503 3865ca48 Michael Hanselmann
      self.fail("File '%s' not removed" % symlink)
504 3865ca48 Michael Hanselmann
    os.symlink(self.tmpfile, symlink)
505 3865ca48 Michael Hanselmann
    utils.RemoveFile(symlink)
506 3865ca48 Michael Hanselmann
    if os.path.exists(symlink):
507 3865ca48 Michael Hanselmann
      self.fail("File '%s' not removed" % symlink)
508 3865ca48 Michael Hanselmann
509 3865ca48 Michael Hanselmann
510 3865ca48 Michael Hanselmann
class TestRemoveDir(unittest.TestCase):
511 3865ca48 Michael Hanselmann
  def setUp(self):
512 3865ca48 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
513 3865ca48 Michael Hanselmann
514 3865ca48 Michael Hanselmann
  def tearDown(self):
515 3865ca48 Michael Hanselmann
    try:
516 3865ca48 Michael Hanselmann
      shutil.rmtree(self.tmpdir)
517 3865ca48 Michael Hanselmann
    except EnvironmentError:
518 3865ca48 Michael Hanselmann
      pass
519 3865ca48 Michael Hanselmann
520 3865ca48 Michael Hanselmann
  def testEmptyDir(self):
521 3865ca48 Michael Hanselmann
    utils.RemoveDir(self.tmpdir)
522 3865ca48 Michael Hanselmann
    self.assertFalse(os.path.isdir(self.tmpdir))
523 3865ca48 Michael Hanselmann
524 3865ca48 Michael Hanselmann
  def testNonEmptyDir(self):
525 3865ca48 Michael Hanselmann
    self.tmpfile = os.path.join(self.tmpdir, "test1")
526 3865ca48 Michael Hanselmann
    open(self.tmpfile, "w").close()
527 3865ca48 Michael Hanselmann
    self.assertRaises(EnvironmentError, utils.RemoveDir, self.tmpdir)
528 3865ca48 Michael Hanselmann
529 3865ca48 Michael Hanselmann
530 3865ca48 Michael Hanselmann
class TestRename(unittest.TestCase):
531 3865ca48 Michael Hanselmann
  """Test case for RenameFile"""
532 3865ca48 Michael Hanselmann
533 3865ca48 Michael Hanselmann
  def setUp(self):
534 3865ca48 Michael Hanselmann
    """Create a temporary directory"""
535 3865ca48 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
536 3865ca48 Michael Hanselmann
    self.tmpfile = os.path.join(self.tmpdir, "test1")
537 3865ca48 Michael Hanselmann
538 3865ca48 Michael Hanselmann
    # Touch the file
539 3865ca48 Michael Hanselmann
    open(self.tmpfile, "w").close()
540 3865ca48 Michael Hanselmann
541 3865ca48 Michael Hanselmann
  def tearDown(self):
542 3865ca48 Michael Hanselmann
    """Remove temporary directory"""
543 3865ca48 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
544 3865ca48 Michael Hanselmann
545 3865ca48 Michael Hanselmann
  def testSimpleRename1(self):
546 3865ca48 Michael Hanselmann
    """Simple rename 1"""
547 3865ca48 Michael Hanselmann
    utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "xyz"))
548 3865ca48 Michael Hanselmann
    self.assert_(os.path.isfile(os.path.join(self.tmpdir, "xyz")))
549 3865ca48 Michael Hanselmann
550 3865ca48 Michael Hanselmann
  def testSimpleRename2(self):
551 3865ca48 Michael Hanselmann
    """Simple rename 2"""
552 3865ca48 Michael Hanselmann
    utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "xyz"),
553 3865ca48 Michael Hanselmann
                     mkdir=True)
554 3865ca48 Michael Hanselmann
    self.assert_(os.path.isfile(os.path.join(self.tmpdir, "xyz")))
555 3865ca48 Michael Hanselmann
556 3865ca48 Michael Hanselmann
  def testRenameMkdir(self):
557 3865ca48 Michael Hanselmann
    """Rename with mkdir"""
558 3865ca48 Michael Hanselmann
    utils.RenameFile(self.tmpfile, os.path.join(self.tmpdir, "test/xyz"),
559 3865ca48 Michael Hanselmann
                     mkdir=True)
560 3865ca48 Michael Hanselmann
    self.assert_(os.path.isdir(os.path.join(self.tmpdir, "test")))
561 3865ca48 Michael Hanselmann
    self.assert_(os.path.isfile(os.path.join(self.tmpdir, "test/xyz")))
562 3865ca48 Michael Hanselmann
563 9c2b3a70 René Nussbaumer
    self.assertRaises(EnvironmentError, utils.RenameFile,
564 9c2b3a70 René Nussbaumer
                      os.path.join(self.tmpdir, "test/xyz"),
565 9c2b3a70 René Nussbaumer
                      os.path.join(self.tmpdir, "test/foo/bar/baz"),
566 9c2b3a70 René Nussbaumer
                      mkdir=True)
567 9c2b3a70 René Nussbaumer
568 9c2b3a70 René Nussbaumer
    self.assertTrue(os.path.exists(os.path.join(self.tmpdir, "test/xyz")))
569 9c2b3a70 René Nussbaumer
    self.assertFalse(os.path.exists(os.path.join(self.tmpdir, "test/foo/bar")))
570 b355affb René Nussbaumer
    self.assertFalse(os.path.exists(os.path.join(self.tmpdir,
571 b355affb René Nussbaumer
                                                 "test/foo/bar/baz")))
572 3865ca48 Michael Hanselmann
573 3865ca48 Michael Hanselmann
574 3865ca48 Michael Hanselmann
class TestMakedirs(unittest.TestCase):
575 3865ca48 Michael Hanselmann
  def setUp(self):
576 3865ca48 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
577 3865ca48 Michael Hanselmann
578 3865ca48 Michael Hanselmann
  def tearDown(self):
579 3865ca48 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
580 3865ca48 Michael Hanselmann
581 3865ca48 Michael Hanselmann
  def testNonExisting(self):
582 3865ca48 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "foo")
583 3865ca48 Michael Hanselmann
    utils.Makedirs(path)
584 3865ca48 Michael Hanselmann
    self.assert_(os.path.isdir(path))
585 3865ca48 Michael Hanselmann
586 3865ca48 Michael Hanselmann
  def testExisting(self):
587 3865ca48 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "foo")
588 3865ca48 Michael Hanselmann
    os.mkdir(path)
589 3865ca48 Michael Hanselmann
    utils.Makedirs(path)
590 3865ca48 Michael Hanselmann
    self.assert_(os.path.isdir(path))
591 3865ca48 Michael Hanselmann
592 3865ca48 Michael Hanselmann
  def testRecursiveNonExisting(self):
593 3865ca48 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "foo/bar/baz")
594 3865ca48 Michael Hanselmann
    utils.Makedirs(path)
595 3865ca48 Michael Hanselmann
    self.assert_(os.path.isdir(path))
596 3865ca48 Michael Hanselmann
597 3865ca48 Michael Hanselmann
  def testRecursiveExisting(self):
598 3865ca48 Michael Hanselmann
    path = utils.PathJoin(self.tmpdir, "B/moo/xyz")
599 3865ca48 Michael Hanselmann
    self.assertFalse(os.path.exists(path))
600 3865ca48 Michael Hanselmann
    os.mkdir(utils.PathJoin(self.tmpdir, "B"))
601 3865ca48 Michael Hanselmann
    utils.Makedirs(path)
602 3865ca48 Michael Hanselmann
    self.assert_(os.path.isdir(path))
603 3865ca48 Michael Hanselmann
604 3865ca48 Michael Hanselmann
605 3865ca48 Michael Hanselmann
class TestEnsureDirs(unittest.TestCase):
606 3865ca48 Michael Hanselmann
  """Tests for EnsureDirs"""
607 3865ca48 Michael Hanselmann
608 3865ca48 Michael Hanselmann
  def setUp(self):
609 3865ca48 Michael Hanselmann
    self.dir = tempfile.mkdtemp()
610 3865ca48 Michael Hanselmann
    self.old_umask = os.umask(0777)
611 3865ca48 Michael Hanselmann
612 3865ca48 Michael Hanselmann
  def testEnsureDirs(self):
613 3865ca48 Michael Hanselmann
    utils.EnsureDirs([
614 3865ca48 Michael Hanselmann
        (utils.PathJoin(self.dir, "foo"), 0777),
615 3865ca48 Michael Hanselmann
        (utils.PathJoin(self.dir, "bar"), 0000),
616 3865ca48 Michael Hanselmann
        ])
617 3865ca48 Michael Hanselmann
    self.assertEquals(os.stat(utils.PathJoin(self.dir, "foo"))[0] & 0777, 0777)
618 3865ca48 Michael Hanselmann
    self.assertEquals(os.stat(utils.PathJoin(self.dir, "bar"))[0] & 0777, 0000)
619 3865ca48 Michael Hanselmann
620 3865ca48 Michael Hanselmann
  def tearDown(self):
621 3865ca48 Michael Hanselmann
    os.rmdir(utils.PathJoin(self.dir, "foo"))
622 3865ca48 Michael Hanselmann
    os.rmdir(utils.PathJoin(self.dir, "bar"))
623 3865ca48 Michael Hanselmann
    os.rmdir(self.dir)
624 3865ca48 Michael Hanselmann
    os.umask(self.old_umask)
625 3865ca48 Michael Hanselmann
626 3865ca48 Michael Hanselmann
627 3865ca48 Michael Hanselmann
class TestIsNormAbsPath(unittest.TestCase):
628 3865ca48 Michael Hanselmann
  """Testing case for IsNormAbsPath"""
629 3865ca48 Michael Hanselmann
630 3865ca48 Michael Hanselmann
  def _pathTestHelper(self, path, result):
631 3865ca48 Michael Hanselmann
    if result:
632 3865ca48 Michael Hanselmann
      self.assert_(utils.IsNormAbsPath(path),
633 2826897c Michael Hanselmann
          msg="Path %s should result absolute and normalized" % path)
634 3865ca48 Michael Hanselmann
    else:
635 3865ca48 Michael Hanselmann
      self.assertFalse(utils.IsNormAbsPath(path),
636 2826897c Michael Hanselmann
          msg="Path %s should not result absolute and normalized" % path)
637 3865ca48 Michael Hanselmann
638 3865ca48 Michael Hanselmann
  def testBase(self):
639 3865ca48 Michael Hanselmann
    self._pathTestHelper("/etc", True)
640 3865ca48 Michael Hanselmann
    self._pathTestHelper("/srv", True)
641 3865ca48 Michael Hanselmann
    self._pathTestHelper("etc", False)
642 3865ca48 Michael Hanselmann
    self._pathTestHelper("/etc/../root", False)
643 3865ca48 Michael Hanselmann
    self._pathTestHelper("/etc/", False)
644 3865ca48 Michael Hanselmann
645 2826897c Michael Hanselmann
  def testSlashes(self):
646 2826897c Michael Hanselmann
    # Root directory
647 2826897c Michael Hanselmann
    self._pathTestHelper("/", True)
648 2826897c Michael Hanselmann
649 2826897c Michael Hanselmann
    # POSIX' "implementation-defined" double slashes
650 2826897c Michael Hanselmann
    self._pathTestHelper("//", True)
651 2826897c Michael Hanselmann
652 2826897c Michael Hanselmann
    # Three and more slashes count as one, so the path is not normalized
653 2826897c Michael Hanselmann
    for i in range(3, 10):
654 2826897c Michael Hanselmann
      self._pathTestHelper("/" * i, False)
655 2826897c Michael Hanselmann
656 3865ca48 Michael Hanselmann
657 fb17bebd René Nussbaumer
class TestIsBelowDir(unittest.TestCase):
658 fb17bebd René Nussbaumer
  """Testing case for IsBelowDir"""
659 fb17bebd René Nussbaumer
660 fbdac0d9 Michael Hanselmann
  def testExactlyTheSame(self):
661 fbdac0d9 Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("/a/b", "/a/b"))
662 fbdac0d9 Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("/a/b", "/a/b/"))
663 fbdac0d9 Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("/a/b/", "/a/b"))
664 fbdac0d9 Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("/a/b/", "/a/b/"))
665 fbdac0d9 Michael Hanselmann
666 fb17bebd René Nussbaumer
  def testSamePrefix(self):
667 fb17bebd René Nussbaumer
    self.assertTrue(utils.IsBelowDir("/a/b", "/a/b/c"))
668 fb17bebd René Nussbaumer
    self.assertTrue(utils.IsBelowDir("/a/b/", "/a/b/e"))
669 fb17bebd René Nussbaumer
670 fb17bebd René Nussbaumer
  def testSamePrefixButDifferentDir(self):
671 fb17bebd René Nussbaumer
    self.assertFalse(utils.IsBelowDir("/a/b", "/a/bc/d"))
672 fb17bebd René Nussbaumer
    self.assertFalse(utils.IsBelowDir("/a/b/", "/a/bc/e"))
673 fb17bebd René Nussbaumer
674 fb17bebd René Nussbaumer
  def testSamePrefixButDirTraversal(self):
675 fb17bebd René Nussbaumer
    self.assertFalse(utils.IsBelowDir("/a/b", "/a/b/../c"))
676 fb17bebd René Nussbaumer
    self.assertFalse(utils.IsBelowDir("/a/b/", "/a/b/../d"))
677 fb17bebd René Nussbaumer
678 fb17bebd René Nussbaumer
  def testSamePrefixAndTraversal(self):
679 fb17bebd René Nussbaumer
    self.assertTrue(utils.IsBelowDir("/a/b", "/a/b/c/../d"))
680 fb17bebd René Nussbaumer
    self.assertTrue(utils.IsBelowDir("/a/b", "/a/b/c/./e"))
681 fb17bebd René Nussbaumer
    self.assertTrue(utils.IsBelowDir("/a/b", "/a/b/../b/./e"))
682 fb17bebd René Nussbaumer
683 fb17bebd René Nussbaumer
  def testBothAbsPath(self):
684 fb17bebd René Nussbaumer
    self.assertRaises(ValueError, utils.IsBelowDir, "/a/b/c", "d")
685 fb17bebd René Nussbaumer
    self.assertRaises(ValueError, utils.IsBelowDir, "a/b/c", "/d")
686 fb17bebd René Nussbaumer
    self.assertRaises(ValueError, utils.IsBelowDir, "a/b/c", "d")
687 2826897c Michael Hanselmann
    self.assertRaises(ValueError, utils.IsBelowDir, "", "/")
688 2826897c Michael Hanselmann
    self.assertRaises(ValueError, utils.IsBelowDir, "/", "")
689 2826897c Michael Hanselmann
690 2826897c Michael Hanselmann
  def testRoot(self):
691 2826897c Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("/", "/"))
692 2826897c Michael Hanselmann
693 2826897c Michael Hanselmann
    for i in ["/a", "/tmp", "/tmp/foo/bar", "/tmp/"]:
694 2826897c Michael Hanselmann
      self.assertTrue(utils.IsBelowDir("/", i))
695 2826897c Michael Hanselmann
696 2826897c Michael Hanselmann
  def testSlashes(self):
697 2826897c Michael Hanselmann
    # In POSIX a double slash is "implementation-defined".
698 2826897c Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("//", "//"))
699 2826897c Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("//", "/tmp"))
700 2826897c Michael Hanselmann
    self.assertTrue(utils.IsBelowDir("//tmp", "//tmp/x"))
701 2826897c Michael Hanselmann
702 2826897c Michael Hanselmann
    # Three (or more) slashes count as one
703 2826897c Michael Hanselmann
    self.assertFalse(utils.IsBelowDir("/", "///"))
704 2826897c Michael Hanselmann
    self.assertTrue(utils.IsBelowDir("/", "///tmp"))
705 2826897c Michael Hanselmann
    self.assertTrue(utils.IsBelowDir("/tmp", "///tmp/a/b"))
706 fb17bebd René Nussbaumer
707 fb17bebd René Nussbaumer
708 3865ca48 Michael Hanselmann
class TestPathJoin(unittest.TestCase):
709 3865ca48 Michael Hanselmann
  """Testing case for PathJoin"""
710 3865ca48 Michael Hanselmann
711 3865ca48 Michael Hanselmann
  def testBasicItems(self):
712 3865ca48 Michael Hanselmann
    mlist = ["/a", "b", "c"]
713 3865ca48 Michael Hanselmann
    self.failUnlessEqual(utils.PathJoin(*mlist), "/".join(mlist))
714 3865ca48 Michael Hanselmann
715 3865ca48 Michael Hanselmann
  def testNonAbsPrefix(self):
716 3865ca48 Michael Hanselmann
    self.failUnlessRaises(ValueError, utils.PathJoin, "a", "b")
717 3865ca48 Michael Hanselmann
718 3865ca48 Michael Hanselmann
  def testBackTrack(self):
719 3865ca48 Michael Hanselmann
    self.failUnlessRaises(ValueError, utils.PathJoin, "/a", "b/../c")
720 3865ca48 Michael Hanselmann
721 3865ca48 Michael Hanselmann
  def testMultiAbs(self):
722 3865ca48 Michael Hanselmann
    self.failUnlessRaises(ValueError, utils.PathJoin, "/a", "/b")
723 3865ca48 Michael Hanselmann
724 3865ca48 Michael Hanselmann
725 3865ca48 Michael Hanselmann
class TestTailFile(testutils.GanetiTestCase):
726 3865ca48 Michael Hanselmann
  """Test case for the TailFile function"""
727 3865ca48 Michael Hanselmann
728 3865ca48 Michael Hanselmann
  def testEmpty(self):
729 3865ca48 Michael Hanselmann
    fname = self._CreateTempFile()
730 3865ca48 Michael Hanselmann
    self.failUnlessEqual(utils.TailFile(fname), [])
731 3865ca48 Michael Hanselmann
    self.failUnlessEqual(utils.TailFile(fname, lines=25), [])
732 3865ca48 Michael Hanselmann
733 3865ca48 Michael Hanselmann
  def testAllLines(self):
734 3865ca48 Michael Hanselmann
    data = ["test %d" % i for i in range(30)]
735 3865ca48 Michael Hanselmann
    for i in range(30):
736 3865ca48 Michael Hanselmann
      fname = self._CreateTempFile()
737 3865ca48 Michael Hanselmann
      fd = open(fname, "w")
738 3865ca48 Michael Hanselmann
      fd.write("\n".join(data[:i]))
739 3865ca48 Michael Hanselmann
      if i > 0:
740 3865ca48 Michael Hanselmann
        fd.write("\n")
741 3865ca48 Michael Hanselmann
      fd.close()
742 3865ca48 Michael Hanselmann
      self.failUnlessEqual(utils.TailFile(fname, lines=i), data[:i])
743 3865ca48 Michael Hanselmann
744 3865ca48 Michael Hanselmann
  def testPartialLines(self):
745 3865ca48 Michael Hanselmann
    data = ["test %d" % i for i in range(30)]
746 3865ca48 Michael Hanselmann
    fname = self._CreateTempFile()
747 3865ca48 Michael Hanselmann
    fd = open(fname, "w")
748 3865ca48 Michael Hanselmann
    fd.write("\n".join(data))
749 3865ca48 Michael Hanselmann
    fd.write("\n")
750 3865ca48 Michael Hanselmann
    fd.close()
751 3865ca48 Michael Hanselmann
    for i in range(1, 30):
752 3865ca48 Michael Hanselmann
      self.failUnlessEqual(utils.TailFile(fname, lines=i), data[-i:])
753 3865ca48 Michael Hanselmann
754 3865ca48 Michael Hanselmann
  def testBigFile(self):
755 3865ca48 Michael Hanselmann
    data = ["test %d" % i for i in range(30)]
756 3865ca48 Michael Hanselmann
    fname = self._CreateTempFile()
757 3865ca48 Michael Hanselmann
    fd = open(fname, "w")
758 3865ca48 Michael Hanselmann
    fd.write("X" * 1048576)
759 3865ca48 Michael Hanselmann
    fd.write("\n")
760 3865ca48 Michael Hanselmann
    fd.write("\n".join(data))
761 3865ca48 Michael Hanselmann
    fd.write("\n")
762 3865ca48 Michael Hanselmann
    fd.close()
763 3865ca48 Michael Hanselmann
    for i in range(1, 30):
764 3865ca48 Michael Hanselmann
      self.failUnlessEqual(utils.TailFile(fname, lines=i), data[-i:])
765 3865ca48 Michael Hanselmann
766 3865ca48 Michael Hanselmann
767 3865ca48 Michael Hanselmann
class TestPidFileFunctions(unittest.TestCase):
768 79b60c1c Michael Hanselmann
  """Tests for WritePidFile and ReadPidFile"""
769 3865ca48 Michael Hanselmann
770 3865ca48 Michael Hanselmann
  def setUp(self):
771 3865ca48 Michael Hanselmann
    self.dir = tempfile.mkdtemp()
772 3865ca48 Michael Hanselmann
    self.f_dpn = lambda name: os.path.join(self.dir, "%s.pid" % name)
773 3865ca48 Michael Hanselmann
774 3865ca48 Michael Hanselmann
  def testPidFileFunctions(self):
775 8c114acd Michael Hanselmann
    pid_file = self.f_dpn("test")
776 8c114acd Michael Hanselmann
    fd = utils.WritePidFile(self.f_dpn("test"))
777 3865ca48 Michael Hanselmann
    self.failUnless(os.path.exists(pid_file),
778 3865ca48 Michael Hanselmann
                    "PID file should have been created")
779 3865ca48 Michael Hanselmann
    read_pid = utils.ReadPidFile(pid_file)
780 3865ca48 Michael Hanselmann
    self.failUnlessEqual(read_pid, os.getpid())
781 3865ca48 Michael Hanselmann
    self.failUnless(utils.IsProcessAlive(read_pid))
782 b6522276 Michael Hanselmann
    self.failUnlessRaises(errors.PidFileLockError, utils.WritePidFile,
783 8c114acd Michael Hanselmann
                          self.f_dpn("test"))
784 3865ca48 Michael Hanselmann
    os.close(fd)
785 79b60c1c Michael Hanselmann
    utils.RemoveFile(self.f_dpn("test"))
786 3865ca48 Michael Hanselmann
    self.failIf(os.path.exists(pid_file),
787 3865ca48 Michael Hanselmann
                "PID file should not exist anymore")
788 3865ca48 Michael Hanselmann
    self.failUnlessEqual(utils.ReadPidFile(pid_file), 0,
789 3865ca48 Michael Hanselmann
                         "ReadPidFile should return 0 for missing pid file")
790 3865ca48 Michael Hanselmann
    fh = open(pid_file, "w")
791 3865ca48 Michael Hanselmann
    fh.write("blah\n")
792 3865ca48 Michael Hanselmann
    fh.close()
793 3865ca48 Michael Hanselmann
    self.failUnlessEqual(utils.ReadPidFile(pid_file), 0,
794 3865ca48 Michael Hanselmann
                         "ReadPidFile should return 0 for invalid pid file")
795 3865ca48 Michael Hanselmann
    # but now, even with the file existing, we should be able to lock it
796 8c114acd Michael Hanselmann
    fd = utils.WritePidFile(self.f_dpn("test"))
797 3865ca48 Michael Hanselmann
    os.close(fd)
798 79b60c1c Michael Hanselmann
    utils.RemoveFile(self.f_dpn("test"))
799 3865ca48 Michael Hanselmann
    self.failIf(os.path.exists(pid_file),
800 3865ca48 Michael Hanselmann
                "PID file should not exist anymore")
801 3865ca48 Michael Hanselmann
802 3865ca48 Michael Hanselmann
  def testKill(self):
803 8c114acd Michael Hanselmann
    pid_file = self.f_dpn("child")
804 3865ca48 Michael Hanselmann
    r_fd, w_fd = os.pipe()
805 3865ca48 Michael Hanselmann
    new_pid = os.fork()
806 3865ca48 Michael Hanselmann
    if new_pid == 0: #child
807 8c114acd Michael Hanselmann
      utils.WritePidFile(self.f_dpn("child"))
808 8c114acd Michael Hanselmann
      os.write(w_fd, "a")
809 3865ca48 Michael Hanselmann
      signal.pause()
810 3865ca48 Michael Hanselmann
      os._exit(0)
811 3865ca48 Michael Hanselmann
      return
812 3865ca48 Michael Hanselmann
    # else we are in the parent
813 3865ca48 Michael Hanselmann
    # wait until the child has written the pid file
814 3865ca48 Michael Hanselmann
    os.read(r_fd, 1)
815 3865ca48 Michael Hanselmann
    read_pid = utils.ReadPidFile(pid_file)
816 3865ca48 Michael Hanselmann
    self.failUnlessEqual(read_pid, new_pid)
817 3865ca48 Michael Hanselmann
    self.failUnless(utils.IsProcessAlive(new_pid))
818 b6522276 Michael Hanselmann
819 b6522276 Michael Hanselmann
    # Try writing to locked file
820 b6522276 Michael Hanselmann
    try:
821 b6522276 Michael Hanselmann
      utils.WritePidFile(pid_file)
822 b6522276 Michael Hanselmann
    except errors.PidFileLockError, err:
823 b6522276 Michael Hanselmann
      errmsg = str(err)
824 b6522276 Michael Hanselmann
      self.assertTrue(errmsg.endswith(" %s" % new_pid),
825 b6522276 Michael Hanselmann
                      msg=("Error message ('%s') didn't contain correct"
826 b6522276 Michael Hanselmann
                           " PID (%s)" % (errmsg, new_pid)))
827 b6522276 Michael Hanselmann
    else:
828 b6522276 Michael Hanselmann
      self.fail("Writing to locked file didn't fail")
829 b6522276 Michael Hanselmann
830 3865ca48 Michael Hanselmann
    utils.KillProcess(new_pid, waitpid=True)
831 3865ca48 Michael Hanselmann
    self.failIf(utils.IsProcessAlive(new_pid))
832 8c114acd Michael Hanselmann
    utils.RemoveFile(self.f_dpn("child"))
833 3865ca48 Michael Hanselmann
    self.failUnlessRaises(errors.ProgrammerError, utils.KillProcess, 0)
834 3865ca48 Michael Hanselmann
835 b6522276 Michael Hanselmann
  def testExceptionType(self):
836 b6522276 Michael Hanselmann
    # Make sure the PID lock error is a subclass of LockError in case some code
837 b6522276 Michael Hanselmann
    # depends on it
838 b6522276 Michael Hanselmann
    self.assertTrue(issubclass(errors.PidFileLockError, errors.LockError))
839 b6522276 Michael Hanselmann
840 3865ca48 Michael Hanselmann
  def tearDown(self):
841 3865ca48 Michael Hanselmann
    shutil.rmtree(self.dir)
842 3865ca48 Michael Hanselmann
843 3865ca48 Michael Hanselmann
844 3865ca48 Michael Hanselmann
class TestSshKeys(testutils.GanetiTestCase):
845 3865ca48 Michael Hanselmann
  """Test case for the AddAuthorizedKey function"""
846 3865ca48 Michael Hanselmann
847 8c114acd Michael Hanselmann
  KEY_A = "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a"
848 3865ca48 Michael Hanselmann
  KEY_B = ('command="/usr/bin/fooserver -t --verbose",from="198.51.100.4" '
849 8c114acd Michael Hanselmann
           "ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b")
850 3865ca48 Michael Hanselmann
851 3865ca48 Michael Hanselmann
  def setUp(self):
852 3865ca48 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
853 3865ca48 Michael Hanselmann
    self.tmpname = self._CreateTempFile()
854 8c114acd Michael Hanselmann
    handle = open(self.tmpname, "w")
855 3865ca48 Michael Hanselmann
    try:
856 3865ca48 Michael Hanselmann
      handle.write("%s\n" % TestSshKeys.KEY_A)
857 3865ca48 Michael Hanselmann
      handle.write("%s\n" % TestSshKeys.KEY_B)
858 3865ca48 Michael Hanselmann
    finally:
859 3865ca48 Michael Hanselmann
      handle.close()
860 3865ca48 Michael Hanselmann
861 3865ca48 Michael Hanselmann
  def testAddingNewKey(self):
862 3865ca48 Michael Hanselmann
    utils.AddAuthorizedKey(self.tmpname,
863 8c114acd Michael Hanselmann
                           "ssh-dss AAAAB3NzaC1kc3MAAACB root@test")
864 3865ca48 Michael Hanselmann
865 3865ca48 Michael Hanselmann
    self.assertFileContent(self.tmpname,
866 3865ca48 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
867 3865ca48 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="198.51.100.4"'
868 3865ca48 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
869 3865ca48 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1kc3MAAACB root@test\n")
870 3865ca48 Michael Hanselmann
871 3865ca48 Michael Hanselmann
  def testAddingAlmostButNotCompletelyTheSameKey(self):
872 3865ca48 Michael Hanselmann
    utils.AddAuthorizedKey(self.tmpname,
873 8c114acd Michael Hanselmann
        "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test")
874 3865ca48 Michael Hanselmann
875 0232b768 Michael Hanselmann
    # Only significant fields are compared, therefore the key won't be
876 0232b768 Michael Hanselmann
    # updated/added
877 3865ca48 Michael Hanselmann
    self.assertFileContent(self.tmpname,
878 3865ca48 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
879 3865ca48 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="198.51.100.4"'
880 0232b768 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
881 3865ca48 Michael Hanselmann
882 3865ca48 Michael Hanselmann
  def testAddingExistingKeyWithSomeMoreSpaces(self):
883 3865ca48 Michael Hanselmann
    utils.AddAuthorizedKey(self.tmpname,
884 0232b768 Michael Hanselmann
      "ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a")
885 0232b768 Michael Hanselmann
    utils.AddAuthorizedKey(self.tmpname,
886 0232b768 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22")
887 3865ca48 Michael Hanselmann
888 3865ca48 Michael Hanselmann
    self.assertFileContent(self.tmpname,
889 3865ca48 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
890 3865ca48 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="198.51.100.4"'
891 0232b768 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
892 0232b768 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22\n")
893 3865ca48 Michael Hanselmann
894 3865ca48 Michael Hanselmann
  def testRemovingExistingKeyWithSomeMoreSpaces(self):
895 3865ca48 Michael Hanselmann
    utils.RemoveAuthorizedKey(self.tmpname,
896 8c114acd Michael Hanselmann
        "ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a")
897 3865ca48 Michael Hanselmann
898 3865ca48 Michael Hanselmann
    self.assertFileContent(self.tmpname,
899 3865ca48 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="198.51.100.4"'
900 3865ca48 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
901 3865ca48 Michael Hanselmann
902 3865ca48 Michael Hanselmann
  def testRemovingNonExistingKey(self):
903 3865ca48 Michael Hanselmann
    utils.RemoveAuthorizedKey(self.tmpname,
904 8c114acd Michael Hanselmann
        "ssh-dss  AAAAB3Nsdfj230xxjxJjsjwjsjdjU   root@test")
905 3865ca48 Michael Hanselmann
906 3865ca48 Michael Hanselmann
    self.assertFileContent(self.tmpname,
907 3865ca48 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
908 3865ca48 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="198.51.100.4"'
909 3865ca48 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
910 3865ca48 Michael Hanselmann
911 3865ca48 Michael Hanselmann
912 90e234a6 Michael Hanselmann
class TestNewUUID(unittest.TestCase):
913 90e234a6 Michael Hanselmann
  """Test case for NewUUID"""
914 90e234a6 Michael Hanselmann
915 90e234a6 Michael Hanselmann
  def runTest(self):
916 90e234a6 Michael Hanselmann
    self.failUnless(utils.UUID_RE.match(utils.NewUUID()))
917 90e234a6 Michael Hanselmann
918 90e234a6 Michael Hanselmann
919 b81b3c96 René Nussbaumer
def _MockStatResult(cb, mode, uid, gid):
920 b81b3c96 René Nussbaumer
  def _fn(path):
921 b81b3c96 René Nussbaumer
    if cb:
922 b81b3c96 René Nussbaumer
      cb()
923 b81b3c96 René Nussbaumer
    return {
924 b81b3c96 René Nussbaumer
      stat.ST_MODE: mode,
925 b81b3c96 René Nussbaumer
      stat.ST_UID: uid,
926 b81b3c96 René Nussbaumer
      stat.ST_GID: gid,
927 b81b3c96 René Nussbaumer
      }
928 b81b3c96 René Nussbaumer
  return _fn
929 b81b3c96 René Nussbaumer
930 b81b3c96 René Nussbaumer
931 b81b3c96 René Nussbaumer
def _RaiseNoEntError():
932 b81b3c96 René Nussbaumer
  raise EnvironmentError(errno.ENOENT, "not found")
933 b81b3c96 René Nussbaumer
934 b81b3c96 René Nussbaumer
935 b81b3c96 René Nussbaumer
def _OtherStatRaise():
936 b81b3c96 René Nussbaumer
  raise EnvironmentError()
937 b81b3c96 René Nussbaumer
938 b81b3c96 René Nussbaumer
939 b81b3c96 René Nussbaumer
class TestPermissionEnforcements(unittest.TestCase):
940 b81b3c96 René Nussbaumer
  UID_A = 16024
941 b81b3c96 René Nussbaumer
  UID_B = 25850
942 b81b3c96 René Nussbaumer
  GID_A = 14028
943 b81b3c96 René Nussbaumer
  GID_B = 29801
944 b81b3c96 René Nussbaumer
945 b81b3c96 René Nussbaumer
  def setUp(self):
946 b81b3c96 René Nussbaumer
    self._chown_calls = []
947 b81b3c96 René Nussbaumer
    self._chmod_calls = []
948 b81b3c96 René Nussbaumer
    self._mkdir_calls = []
949 b81b3c96 René Nussbaumer
950 b81b3c96 René Nussbaumer
  def tearDown(self):
951 b81b3c96 René Nussbaumer
    self.assertRaises(IndexError, self._mkdir_calls.pop)
952 b81b3c96 René Nussbaumer
    self.assertRaises(IndexError, self._chmod_calls.pop)
953 b81b3c96 René Nussbaumer
    self.assertRaises(IndexError, self._chown_calls.pop)
954 b81b3c96 René Nussbaumer
955 b81b3c96 René Nussbaumer
  def _FakeMkdir(self, path):
956 b81b3c96 René Nussbaumer
    self._mkdir_calls.append(path)
957 b81b3c96 René Nussbaumer
958 b81b3c96 René Nussbaumer
  def _FakeChown(self, path, uid, gid):
959 b81b3c96 René Nussbaumer
    self._chown_calls.append((path, uid, gid))
960 b81b3c96 René Nussbaumer
961 b81b3c96 René Nussbaumer
  def _ChmodWrapper(self, cb):
962 b81b3c96 René Nussbaumer
    def _fn(path, mode):
963 b81b3c96 René Nussbaumer
      self._chmod_calls.append((path, mode))
964 b81b3c96 René Nussbaumer
      if cb:
965 b81b3c96 René Nussbaumer
        cb()
966 b81b3c96 René Nussbaumer
    return _fn
967 b81b3c96 René Nussbaumer
968 b81b3c96 René Nussbaumer
  def _VerifyPerm(self, path, mode, uid=-1, gid=-1):
969 b81b3c96 René Nussbaumer
    self.assertEqual(path, "/ganeti-qa-non-test")
970 b81b3c96 René Nussbaumer
    self.assertEqual(mode, 0700)
971 b81b3c96 René Nussbaumer
    self.assertEqual(uid, self.UID_A)
972 b81b3c96 René Nussbaumer
    self.assertEqual(gid, self.GID_A)
973 b81b3c96 René Nussbaumer
974 b81b3c96 René Nussbaumer
  def testMakeDirWithPerm(self):
975 b81b3c96 René Nussbaumer
    is_dir_stat = _MockStatResult(None, stat.S_IFDIR, 0, 0)
976 b81b3c96 René Nussbaumer
    utils.MakeDirWithPerm("/ganeti-qa-non-test", 0700, self.UID_A, self.GID_A,
977 b81b3c96 René Nussbaumer
                          _lstat_fn=is_dir_stat, _perm_fn=self._VerifyPerm)
978 b81b3c96 René Nussbaumer
979 b81b3c96 René Nussbaumer
  def testDirErrors(self):
980 b81b3c96 René Nussbaumer
    self.assertRaises(errors.GenericError, utils.MakeDirWithPerm,
981 b81b3c96 René Nussbaumer
                      "/ganeti-qa-non-test", 0700, 0, 0,
982 b81b3c96 René Nussbaumer
                      _lstat_fn=_MockStatResult(None, 0, 0, 0))
983 b81b3c96 René Nussbaumer
    self.assertRaises(IndexError, self._mkdir_calls.pop)
984 b81b3c96 René Nussbaumer
985 b81b3c96 René Nussbaumer
    other_stat_raise = _MockStatResult(_OtherStatRaise, stat.S_IFDIR, 0, 0)
986 b81b3c96 René Nussbaumer
    self.assertRaises(errors.GenericError, utils.MakeDirWithPerm,
987 b81b3c96 René Nussbaumer
                      "/ganeti-qa-non-test", 0700, 0, 0,
988 b81b3c96 René Nussbaumer
                      _lstat_fn=other_stat_raise)
989 b81b3c96 René Nussbaumer
    self.assertRaises(IndexError, self._mkdir_calls.pop)
990 b81b3c96 René Nussbaumer
991 b81b3c96 René Nussbaumer
    non_exist_stat = _MockStatResult(_RaiseNoEntError, stat.S_IFDIR, 0, 0)
992 b81b3c96 René Nussbaumer
    utils.MakeDirWithPerm("/ganeti-qa-non-test", 0700, self.UID_A, self.GID_A,
993 b81b3c96 René Nussbaumer
                          _lstat_fn=non_exist_stat, _mkdir_fn=self._FakeMkdir,
994 b81b3c96 René Nussbaumer
                          _perm_fn=self._VerifyPerm)
995 b81b3c96 René Nussbaumer
    self.assertEqual(self._mkdir_calls.pop(0), "/ganeti-qa-non-test")
996 b81b3c96 René Nussbaumer
997 b81b3c96 René Nussbaumer
  def testEnforcePermissionNoEnt(self):
998 b81b3c96 René Nussbaumer
    self.assertRaises(errors.GenericError, utils.EnforcePermission,
999 b81b3c96 René Nussbaumer
                      "/ganeti-qa-non-test", 0600,
1000 b81b3c96 René Nussbaumer
                      _chmod_fn=NotImplemented, _chown_fn=NotImplemented,
1001 b81b3c96 René Nussbaumer
                      _stat_fn=_MockStatResult(_RaiseNoEntError, 0, 0, 0))
1002 b81b3c96 René Nussbaumer
1003 b81b3c96 René Nussbaumer
  def testEnforcePermissionNoEntMustNotExist(self):
1004 b81b3c96 René Nussbaumer
    utils.EnforcePermission("/ganeti-qa-non-test", 0600, must_exist=False,
1005 b81b3c96 René Nussbaumer
                            _chmod_fn=NotImplemented,
1006 b81b3c96 René Nussbaumer
                            _chown_fn=NotImplemented,
1007 b81b3c96 René Nussbaumer
                            _stat_fn=_MockStatResult(_RaiseNoEntError,
1008 b81b3c96 René Nussbaumer
                                                          0, 0, 0))
1009 b81b3c96 René Nussbaumer
1010 b81b3c96 René Nussbaumer
  def testEnforcePermissionOtherErrorMustNotExist(self):
1011 b81b3c96 René Nussbaumer
    self.assertRaises(errors.GenericError, utils.EnforcePermission,
1012 b81b3c96 René Nussbaumer
                      "/ganeti-qa-non-test", 0600, must_exist=False,
1013 b81b3c96 René Nussbaumer
                      _chmod_fn=NotImplemented, _chown_fn=NotImplemented,
1014 b81b3c96 René Nussbaumer
                      _stat_fn=_MockStatResult(_OtherStatRaise, 0, 0, 0))
1015 b81b3c96 René Nussbaumer
1016 b81b3c96 René Nussbaumer
  def testEnforcePermissionNoChanges(self):
1017 b81b3c96 René Nussbaumer
    utils.EnforcePermission("/ganeti-qa-non-test", 0600,
1018 b81b3c96 René Nussbaumer
                            _stat_fn=_MockStatResult(None, 0600, 0, 0),
1019 b81b3c96 René Nussbaumer
                            _chmod_fn=self._ChmodWrapper(None),
1020 b81b3c96 René Nussbaumer
                            _chown_fn=self._FakeChown)
1021 b81b3c96 René Nussbaumer
1022 b81b3c96 René Nussbaumer
  def testEnforcePermissionChangeMode(self):
1023 b81b3c96 René Nussbaumer
    utils.EnforcePermission("/ganeti-qa-non-test", 0444,
1024 b81b3c96 René Nussbaumer
                            _stat_fn=_MockStatResult(None, 0600, 0, 0),
1025 b81b3c96 René Nussbaumer
                            _chmod_fn=self._ChmodWrapper(None),
1026 b81b3c96 René Nussbaumer
                            _chown_fn=self._FakeChown)
1027 b81b3c96 René Nussbaumer
    self.assertEqual(self._chmod_calls.pop(0), ("/ganeti-qa-non-test", 0444))
1028 b81b3c96 René Nussbaumer
1029 b81b3c96 René Nussbaumer
  def testEnforcePermissionSetUidGid(self):
1030 b81b3c96 René Nussbaumer
    utils.EnforcePermission("/ganeti-qa-non-test", 0600,
1031 b81b3c96 René Nussbaumer
                            uid=self.UID_B, gid=self.GID_B,
1032 b81b3c96 René Nussbaumer
                            _stat_fn=_MockStatResult(None, 0600,
1033 b81b3c96 René Nussbaumer
                                                     self.UID_A,
1034 b81b3c96 René Nussbaumer
                                                     self.GID_A),
1035 b81b3c96 René Nussbaumer
                            _chmod_fn=self._ChmodWrapper(None),
1036 b81b3c96 René Nussbaumer
                            _chown_fn=self._FakeChown)
1037 b81b3c96 René Nussbaumer
    self.assertEqual(self._chown_calls.pop(0),
1038 b81b3c96 René Nussbaumer
                     ("/ganeti-qa-non-test", self.UID_B, self.GID_B))
1039 b81b3c96 René Nussbaumer
1040 b81b3c96 René Nussbaumer
1041 3865ca48 Michael Hanselmann
if __name__ == "__main__":
1042 3865ca48 Michael Hanselmann
  testutils.GanetiTestProgram()