Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.utils_unittest.py @ f0990e0c

History | View | Annotate | Download (19.3 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 a8083063 Iustin Pop
import md5
30 2c30e9d7 Alexander Schreiber
import socket
31 eedbda4b Michael Hanselmann
import shutil
32 59072e7e Michael Hanselmann
import re
33 a8083063 Iustin Pop
34 a8083063 Iustin Pop
import ganeti
35 16abfbc2 Alexander Schreiber
from ganeti import constants
36 59072e7e Michael Hanselmann
from ganeti import utils
37 a8083063 Iustin Pop
from ganeti.utils import IsProcessAlive, Lock, Unlock, RunCmd, \
38 a8083063 Iustin Pop
     RemoveFile, CheckDict, MatchNameComponent, FormatUnit, \
39 a8083063 Iustin Pop
     ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
40 899d2a81 Michael Hanselmann
     ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \
41 9440aeab Michael Hanselmann
     SetEtcHostsEntry, RemoveEtcHostsEntry
42 a8083063 Iustin Pop
from ganeti.errors import LockError, UnitParseError
43 a8083063 Iustin Pop
44 2c30e9d7 Alexander Schreiber
45 f0990e0c Michael Hanselmann
class GanetiTestCase(unittest.TestCase):
46 f0990e0c Michael Hanselmann
  def assertFileContent(self, file_name, content):
47 f0990e0c Michael Hanselmann
    """Checks the content of a file.
48 f0990e0c Michael Hanselmann

49 f0990e0c Michael Hanselmann
    """
50 f0990e0c Michael Hanselmann
    handle = open(file_name, 'r')
51 f0990e0c Michael Hanselmann
    try:
52 f0990e0c Michael Hanselmann
      self.assertEqual(handle.read(), content)
53 f0990e0c Michael Hanselmann
    finally:
54 f0990e0c Michael Hanselmann
      handle.close()
55 f0990e0c Michael Hanselmann
56 f0990e0c Michael Hanselmann
57 a8083063 Iustin Pop
class TestIsProcessAlive(unittest.TestCase):
58 a8083063 Iustin Pop
  """Testing case for IsProcessAlive"""
59 a8083063 Iustin Pop
  def setUp(self):
60 a8083063 Iustin Pop
    # create a zombie and a (hopefully) non-existing process id
61 a8083063 Iustin Pop
    self.pid_zombie = os.fork()
62 a8083063 Iustin Pop
    if self.pid_zombie == 0:
63 a8083063 Iustin Pop
      os._exit(0)
64 a8083063 Iustin Pop
    elif self.pid_zombie < 0:
65 a8083063 Iustin Pop
      raise SystemError("can't fork")
66 a8083063 Iustin Pop
    self.pid_non_existing = os.fork()
67 a8083063 Iustin Pop
    if self.pid_non_existing == 0:
68 a8083063 Iustin Pop
      os._exit(0)
69 a8083063 Iustin Pop
    elif self.pid_non_existing > 0:
70 a8083063 Iustin Pop
      os.waitpid(self.pid_non_existing, 0)
71 a8083063 Iustin Pop
    else:
72 a8083063 Iustin Pop
      raise SystemError("can't fork")
73 a8083063 Iustin Pop
74 a8083063 Iustin Pop
75 a8083063 Iustin Pop
  def testExists(self):
76 a8083063 Iustin Pop
    mypid = os.getpid()
77 a8083063 Iustin Pop
    self.assert_(IsProcessAlive(mypid),
78 a8083063 Iustin Pop
                 "can't find myself running")
79 a8083063 Iustin Pop
80 a8083063 Iustin Pop
  def testZombie(self):
81 a8083063 Iustin Pop
    self.assert_(not IsProcessAlive(self.pid_zombie),
82 a8083063 Iustin Pop
                 "zombie not detected as zombie")
83 a8083063 Iustin Pop
84 a8083063 Iustin Pop
85 a8083063 Iustin Pop
  def testNotExisting(self):
86 a8083063 Iustin Pop
    self.assert_(not IsProcessAlive(self.pid_non_existing),
87 a8083063 Iustin Pop
                 "noexisting process detected")
88 a8083063 Iustin Pop
89 a8083063 Iustin Pop
90 a8083063 Iustin Pop
class TestLocking(unittest.TestCase):
91 a8083063 Iustin Pop
  """Testing case for the Lock/Unlock functions"""
92 a8083063 Iustin Pop
  def clean_lock(self, name):
93 a8083063 Iustin Pop
    try:
94 a8083063 Iustin Pop
      ganeti.utils.Unlock("unittest")
95 a8083063 Iustin Pop
    except LockError:
96 a8083063 Iustin Pop
      pass
97 a8083063 Iustin Pop
98 a8083063 Iustin Pop
99 a8083063 Iustin Pop
  def testLock(self):
100 a8083063 Iustin Pop
    self.clean_lock("unittest")
101 a8083063 Iustin Pop
    self.assertEqual(None, Lock("unittest"))
102 a8083063 Iustin Pop
103 a8083063 Iustin Pop
104 a8083063 Iustin Pop
  def testUnlock(self):
105 a8083063 Iustin Pop
    self.clean_lock("unittest")
106 a8083063 Iustin Pop
    ganeti.utils.Lock("unittest")
107 a8083063 Iustin Pop
    self.assertEqual(None, Unlock("unittest"))
108 a8083063 Iustin Pop
109 a8083063 Iustin Pop
110 a8083063 Iustin Pop
  def testDoubleLock(self):
111 a8083063 Iustin Pop
    self.clean_lock("unittest")
112 a8083063 Iustin Pop
    ganeti.utils.Lock("unittest")
113 a8083063 Iustin Pop
    self.assertRaises(LockError, Lock, "unittest")
114 a8083063 Iustin Pop
115 a8083063 Iustin Pop
116 a8083063 Iustin Pop
class TestRunCmd(unittest.TestCase):
117 a8083063 Iustin Pop
  """Testing case for the RunCmd function"""
118 a8083063 Iustin Pop
119 a8083063 Iustin Pop
  def setUp(self):
120 a8083063 Iustin Pop
    self.magic = time.ctime() + " ganeti test"
121 a8083063 Iustin Pop
122 a8083063 Iustin Pop
  def testOk(self):
123 31ee599c Michael Hanselmann
    """Test successful exit code"""
124 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c 'exit 0'")
125 a8083063 Iustin Pop
    self.assertEqual(result.exit_code, 0)
126 a8083063 Iustin Pop
127 a8083063 Iustin Pop
  def testFail(self):
128 a8083063 Iustin Pop
    """Test fail exit code"""
129 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c 'exit 1'")
130 a8083063 Iustin Pop
    self.assertEqual(result.exit_code, 1)
131 a8083063 Iustin Pop
132 a8083063 Iustin Pop
133 a8083063 Iustin Pop
  def testStdout(self):
134 a8083063 Iustin Pop
    """Test standard output"""
135 a8083063 Iustin Pop
    cmd = 'echo -n "%s"' % self.magic
136 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c '%s'" % cmd)
137 a8083063 Iustin Pop
    self.assertEqual(result.stdout, self.magic)
138 a8083063 Iustin Pop
139 a8083063 Iustin Pop
140 a8083063 Iustin Pop
  def testStderr(self):
141 a8083063 Iustin Pop
    """Test standard error"""
142 a8083063 Iustin Pop
    cmd = 'echo -n "%s"' % self.magic
143 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c '%s' 1>&2" % cmd)
144 a8083063 Iustin Pop
    self.assertEqual(result.stderr, self.magic)
145 a8083063 Iustin Pop
146 a8083063 Iustin Pop
147 a8083063 Iustin Pop
  def testCombined(self):
148 a8083063 Iustin Pop
    """Test combined output"""
149 a8083063 Iustin Pop
    cmd = 'echo -n "A%s"; echo -n "B%s" 1>&2' % (self.magic, self.magic)
150 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c '%s'" % cmd)
151 a8083063 Iustin Pop
    self.assertEqual(result.output, "A" + self.magic + "B" + self.magic)
152 a8083063 Iustin Pop
153 a8083063 Iustin Pop
  def testSignal(self):
154 a8083063 Iustin Pop
    """Test standard error"""
155 a8083063 Iustin Pop
    result = RunCmd("/bin/sh -c 'kill -15 $$'")
156 a8083063 Iustin Pop
    self.assertEqual(result.signal, 15)
157 a8083063 Iustin Pop
158 7fcf849f Iustin Pop
  def testListRun(self):
159 7fcf849f Iustin Pop
    """Test list runs"""
160 7fcf849f Iustin Pop
    result = RunCmd(["true"])
161 7fcf849f Iustin Pop
    self.assertEqual(result.signal, None)
162 7fcf849f Iustin Pop
    self.assertEqual(result.exit_code, 0)
163 7fcf849f Iustin Pop
    result = RunCmd(["/bin/sh", "-c", "exit 1"])
164 7fcf849f Iustin Pop
    self.assertEqual(result.signal, None)
165 7fcf849f Iustin Pop
    self.assertEqual(result.exit_code, 1)
166 7fcf849f Iustin Pop
    result = RunCmd(["echo", "-n", self.magic])
167 7fcf849f Iustin Pop
    self.assertEqual(result.signal, None)
168 7fcf849f Iustin Pop
    self.assertEqual(result.exit_code, 0)
169 7fcf849f Iustin Pop
    self.assertEqual(result.stdout, self.magic)
170 7fcf849f Iustin Pop
171 f6441c7c Iustin Pop
  def testLang(self):
172 f6441c7c Iustin Pop
    """Test locale environment"""
173 23f41a3e Michael Hanselmann
    old_env = os.environ.copy()
174 23f41a3e Michael Hanselmann
    try:
175 23f41a3e Michael Hanselmann
      os.environ["LANG"] = "en_US.UTF-8"
176 23f41a3e Michael Hanselmann
      os.environ["LC_ALL"] = "en_US.UTF-8"
177 23f41a3e Michael Hanselmann
      result = RunCmd(["locale"])
178 23f41a3e Michael Hanselmann
      for line in result.output.splitlines():
179 23f41a3e Michael Hanselmann
        key, value = line.split("=", 1)
180 23f41a3e Michael Hanselmann
        # Ignore these variables, they're overridden by LC_ALL
181 23f41a3e Michael Hanselmann
        if key == "LANG" or key == "LANGUAGE":
182 23f41a3e Michael Hanselmann
          continue
183 23f41a3e Michael Hanselmann
        self.failIf(value and value != "C" and value != '"C"',
184 23f41a3e Michael Hanselmann
            "Variable %s is set to the invalid value '%s'" % (key, value))
185 23f41a3e Michael Hanselmann
    finally:
186 23f41a3e Michael Hanselmann
      os.environ = old_env
187 f6441c7c Iustin Pop
188 a8083063 Iustin Pop
189 a8083063 Iustin Pop
class TestRemoveFile(unittest.TestCase):
190 a8083063 Iustin Pop
  """Test case for the RemoveFile function"""
191 a8083063 Iustin Pop
192 a8083063 Iustin Pop
  def setUp(self):
193 a8083063 Iustin Pop
    """Create a temp dir and file for each case"""
194 a8083063 Iustin Pop
    self.tmpdir = tempfile.mkdtemp('', 'ganeti-unittest-')
195 a8083063 Iustin Pop
    fd, self.tmpfile = tempfile.mkstemp('', '', self.tmpdir)
196 a8083063 Iustin Pop
    os.close(fd)
197 a8083063 Iustin Pop
198 a8083063 Iustin Pop
  def tearDown(self):
199 a8083063 Iustin Pop
    if os.path.exists(self.tmpfile):
200 a8083063 Iustin Pop
      os.unlink(self.tmpfile)
201 a8083063 Iustin Pop
    os.rmdir(self.tmpdir)
202 a8083063 Iustin Pop
203 a8083063 Iustin Pop
204 a8083063 Iustin Pop
  def testIgnoreDirs(self):
205 a8083063 Iustin Pop
    """Test that RemoveFile() ignores directories"""
206 a8083063 Iustin Pop
    self.assertEqual(None, RemoveFile(self.tmpdir))
207 a8083063 Iustin Pop
208 a8083063 Iustin Pop
209 a8083063 Iustin Pop
  def testIgnoreNotExisting(self):
210 a8083063 Iustin Pop
    """Test that RemoveFile() ignores non-existing files"""
211 a8083063 Iustin Pop
    RemoveFile(self.tmpfile)
212 a8083063 Iustin Pop
    RemoveFile(self.tmpfile)
213 a8083063 Iustin Pop
214 a8083063 Iustin Pop
215 a8083063 Iustin Pop
  def testRemoveFile(self):
216 a8083063 Iustin Pop
    """Test that RemoveFile does remove a file"""
217 a8083063 Iustin Pop
    RemoveFile(self.tmpfile)
218 a8083063 Iustin Pop
    if os.path.exists(self.tmpfile):
219 a8083063 Iustin Pop
      self.fail("File '%s' not removed" % self.tmpfile)
220 a8083063 Iustin Pop
221 a8083063 Iustin Pop
222 a8083063 Iustin Pop
  def testRemoveSymlink(self):
223 a8083063 Iustin Pop
    """Test that RemoveFile does remove symlinks"""
224 a8083063 Iustin Pop
    symlink = self.tmpdir + "/symlink"
225 a8083063 Iustin Pop
    os.symlink("no-such-file", symlink)
226 a8083063 Iustin Pop
    RemoveFile(symlink)
227 a8083063 Iustin Pop
    if os.path.exists(symlink):
228 a8083063 Iustin Pop
      self.fail("File '%s' not removed" % symlink)
229 a8083063 Iustin Pop
    os.symlink(self.tmpfile, symlink)
230 a8083063 Iustin Pop
    RemoveFile(symlink)
231 a8083063 Iustin Pop
    if os.path.exists(symlink):
232 a8083063 Iustin Pop
      self.fail("File '%s' not removed" % symlink)
233 a8083063 Iustin Pop
234 a8083063 Iustin Pop
235 a8083063 Iustin Pop
class TestCheckdict(unittest.TestCase):
236 a8083063 Iustin Pop
  """Test case for the CheckDict function"""
237 a8083063 Iustin Pop
238 a8083063 Iustin Pop
  def testAdd(self):
239 a8083063 Iustin Pop
    """Test that CheckDict adds a missing key with the correct value"""
240 a8083063 Iustin Pop
241 a8083063 Iustin Pop
    tgt = {'a':1}
242 a8083063 Iustin Pop
    tmpl = {'b': 2}
243 a8083063 Iustin Pop
    CheckDict(tgt, tmpl)
244 a8083063 Iustin Pop
    if 'b' not in tgt or tgt['b'] != 2:
245 a8083063 Iustin Pop
      self.fail("Failed to update dict")
246 a8083063 Iustin Pop
247 a8083063 Iustin Pop
248 a8083063 Iustin Pop
  def testNoUpdate(self):
249 a8083063 Iustin Pop
    """Test that CheckDict does not overwrite an existing key"""
250 a8083063 Iustin Pop
    tgt = {'a':1, 'b': 3}
251 a8083063 Iustin Pop
    tmpl = {'b': 2}
252 a8083063 Iustin Pop
    CheckDict(tgt, tmpl)
253 a8083063 Iustin Pop
    self.failUnlessEqual(tgt['b'], 3)
254 a8083063 Iustin Pop
255 a8083063 Iustin Pop
256 a8083063 Iustin Pop
class TestMatchNameComponent(unittest.TestCase):
257 a8083063 Iustin Pop
  """Test case for the MatchNameComponent function"""
258 a8083063 Iustin Pop
259 a8083063 Iustin Pop
  def testEmptyList(self):
260 a8083063 Iustin Pop
    """Test that there is no match against an empty list"""
261 a8083063 Iustin Pop
262 a8083063 Iustin Pop
    self.failUnlessEqual(MatchNameComponent("", []), None)
263 a8083063 Iustin Pop
    self.failUnlessEqual(MatchNameComponent("test", []), None)
264 a8083063 Iustin Pop
265 a8083063 Iustin Pop
  def testSingleMatch(self):
266 a8083063 Iustin Pop
    """Test that a single match is performed correctly"""
267 a8083063 Iustin Pop
    mlist = ["test1.example.com", "test2.example.com", "test3.example.com"]
268 a8083063 Iustin Pop
    for key in "test2", "test2.example", "test2.example.com":
269 a8083063 Iustin Pop
      self.failUnlessEqual(MatchNameComponent(key, mlist), mlist[1])
270 a8083063 Iustin Pop
271 a8083063 Iustin Pop
  def testMultipleMatches(self):
272 a8083063 Iustin Pop
    """Test that a multiple match is returned as None"""
273 a8083063 Iustin Pop
    mlist = ["test1.example.com", "test1.example.org", "test1.example.net"]
274 a8083063 Iustin Pop
    for key in "test1", "test1.example":
275 a8083063 Iustin Pop
      self.failUnlessEqual(MatchNameComponent(key, mlist), None)
276 a8083063 Iustin Pop
277 a8083063 Iustin Pop
278 a8083063 Iustin Pop
class TestFormatUnit(unittest.TestCase):
279 a8083063 Iustin Pop
  """Test case for the FormatUnit function"""
280 a8083063 Iustin Pop
281 a8083063 Iustin Pop
  def testMiB(self):
282 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(1), '1M')
283 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(100), '100M')
284 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(1023), '1023M')
285 a8083063 Iustin Pop
286 a8083063 Iustin Pop
  def testGiB(self):
287 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(1024), '1.0G')
288 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(1536), '1.5G')
289 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(17133), '16.7G')
290 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024 - 1), '1024.0G')
291 a8083063 Iustin Pop
292 a8083063 Iustin Pop
  def testTiB(self):
293 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(1024 * 1024), '1.0T')
294 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(5120 * 1024), '5.0T')
295 a8083063 Iustin Pop
    self.assertEqual(FormatUnit(29829 * 1024), '29.1T')
296 a8083063 Iustin Pop
297 a8083063 Iustin Pop
298 a8083063 Iustin Pop
class TestParseUnit(unittest.TestCase):
299 a8083063 Iustin Pop
  """Test case for the ParseUnit function"""
300 a8083063 Iustin Pop
301 a8083063 Iustin Pop
  SCALES = (('', 1),
302 a8083063 Iustin Pop
            ('M', 1), ('G', 1024), ('T', 1024 * 1024),
303 a8083063 Iustin Pop
            ('MB', 1), ('GB', 1024), ('TB', 1024 * 1024),
304 a8083063 Iustin Pop
            ('MiB', 1), ('GiB', 1024), ('TiB', 1024 * 1024))
305 a8083063 Iustin Pop
306 a8083063 Iustin Pop
  def testRounding(self):
307 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('0'), 0)
308 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1'), 4)
309 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('2'), 4)
310 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('3'), 4)
311 a8083063 Iustin Pop
312 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('124'), 124)
313 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('125'), 128)
314 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('126'), 128)
315 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('127'), 128)
316 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('128'), 128)
317 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('129'), 132)
318 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('130'), 132)
319 a8083063 Iustin Pop
320 a8083063 Iustin Pop
  def testFloating(self):
321 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('0'), 0)
322 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('0.5'), 4)
323 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.75'), 4)
324 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.99'), 4)
325 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('2.00'), 4)
326 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('2.01'), 4)
327 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('3.99'), 4)
328 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('4.00'), 4)
329 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('4.01'), 8)
330 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.5G'), 1536)
331 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('1.8G'), 1844)
332 a8083063 Iustin Pop
    self.assertEqual(ParseUnit('8.28T'), 8682212)
333 a8083063 Iustin Pop
334 a8083063 Iustin Pop
  def testSuffixes(self):
335 a8083063 Iustin Pop
    for sep in ('', ' ', '   ', "\t", "\t "):
336 a8083063 Iustin Pop
      for suffix, scale in TestParseUnit.SCALES:
337 a8083063 Iustin Pop
        for func in (lambda x: x, str.lower, str.upper):
338 a8083063 Iustin Pop
          self.assertEqual(ParseUnit('1024' + sep + func(suffix)), 1024 * scale)
339 a8083063 Iustin Pop
340 a8083063 Iustin Pop
  def testInvalidInput(self):
341 a8083063 Iustin Pop
    for sep in ('-', '_', ',', 'a'):
342 a8083063 Iustin Pop
      for suffix, _ in TestParseUnit.SCALES:
343 a8083063 Iustin Pop
        self.assertRaises(UnitParseError, ParseUnit, '1' + sep + suffix)
344 a8083063 Iustin Pop
345 a8083063 Iustin Pop
    for suffix, _ in TestParseUnit.SCALES:
346 a8083063 Iustin Pop
      self.assertRaises(UnitParseError, ParseUnit, '1,3' + suffix)
347 a8083063 Iustin Pop
348 a8083063 Iustin Pop
349 f0990e0c Michael Hanselmann
class TestSshKeys(GanetiTestCase):
350 a8083063 Iustin Pop
  """Test case for the AddAuthorizedKey function"""
351 a8083063 Iustin Pop
352 a8083063 Iustin Pop
  KEY_A = 'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a'
353 a8083063 Iustin Pop
  KEY_B = ('command="/usr/bin/fooserver -t --verbose",from="1.2.3.4" '
354 a8083063 Iustin Pop
           'ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b')
355 a8083063 Iustin Pop
356 a8083063 Iustin Pop
  def writeTestFile(self):
357 a8083063 Iustin Pop
    (fd, tmpname) = tempfile.mkstemp(prefix = 'ganeti-test')
358 a8083063 Iustin Pop
    f = os.fdopen(fd, 'w')
359 a8083063 Iustin Pop
    try:
360 a8083063 Iustin Pop
      f.write(TestSshKeys.KEY_A)
361 a8083063 Iustin Pop
      f.write("\n")
362 a8083063 Iustin Pop
      f.write(TestSshKeys.KEY_B)
363 a8083063 Iustin Pop
      f.write("\n")
364 a8083063 Iustin Pop
    finally:
365 a8083063 Iustin Pop
      f.close()
366 a8083063 Iustin Pop
367 a8083063 Iustin Pop
    return tmpname
368 a8083063 Iustin Pop
369 a8083063 Iustin Pop
  def testAddingNewKey(self):
370 a8083063 Iustin Pop
    tmpname = self.writeTestFile()
371 a8083063 Iustin Pop
    try:
372 a8083063 Iustin Pop
      AddAuthorizedKey(tmpname, 'ssh-dss AAAAB3NzaC1kc3MAAACB root@test')
373 a8083063 Iustin Pop
374 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
375 f0990e0c Michael Hanselmann
        "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
376 f0990e0c Michael Hanselmann
        'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
377 f0990e0c Michael Hanselmann
        " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
378 f0990e0c Michael Hanselmann
        "ssh-dss AAAAB3NzaC1kc3MAAACB root@test\n")
379 a8083063 Iustin Pop
    finally:
380 a8083063 Iustin Pop
      os.unlink(tmpname)
381 a8083063 Iustin Pop
382 a8083063 Iustin Pop
  def testAddingAlmostButNotCompletlyTheSameKey(self):
383 a8083063 Iustin Pop
    tmpname = self.writeTestFile()
384 a8083063 Iustin Pop
    try:
385 a8083063 Iustin Pop
      AddAuthorizedKey(tmpname,
386 a8083063 Iustin Pop
          'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test')
387 a8083063 Iustin Pop
388 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
389 f0990e0c Michael Hanselmann
        "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
390 f0990e0c Michael Hanselmann
        'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
391 f0990e0c Michael Hanselmann
        " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
392 f0990e0c Michael Hanselmann
        "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test\n")
393 a8083063 Iustin Pop
    finally:
394 a8083063 Iustin Pop
      os.unlink(tmpname)
395 a8083063 Iustin Pop
396 a8083063 Iustin Pop
  def testAddingExistingKeyWithSomeMoreSpaces(self):
397 a8083063 Iustin Pop
    tmpname = self.writeTestFile()
398 a8083063 Iustin Pop
    try:
399 a8083063 Iustin Pop
      AddAuthorizedKey(tmpname,
400 a8083063 Iustin Pop
          'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
401 a8083063 Iustin Pop
402 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
403 f0990e0c Michael Hanselmann
        "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
404 f0990e0c Michael Hanselmann
        'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
405 f0990e0c Michael Hanselmann
        " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
406 a8083063 Iustin Pop
    finally:
407 a8083063 Iustin Pop
      os.unlink(tmpname)
408 a8083063 Iustin Pop
409 a8083063 Iustin Pop
  def testRemovingExistingKeyWithSomeMoreSpaces(self):
410 a8083063 Iustin Pop
    tmpname = self.writeTestFile()
411 a8083063 Iustin Pop
    try:
412 a8083063 Iustin Pop
      RemoveAuthorizedKey(tmpname,
413 a8083063 Iustin Pop
          'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
414 a8083063 Iustin Pop
415 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
416 f0990e0c Michael Hanselmann
        'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
417 f0990e0c Michael Hanselmann
        " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
418 a8083063 Iustin Pop
    finally:
419 a8083063 Iustin Pop
      os.unlink(tmpname)
420 a8083063 Iustin Pop
421 a8083063 Iustin Pop
  def testRemovingNonExistingKey(self):
422 a8083063 Iustin Pop
    tmpname = self.writeTestFile()
423 a8083063 Iustin Pop
    try:
424 a8083063 Iustin Pop
      RemoveAuthorizedKey(tmpname,
425 a8083063 Iustin Pop
          'ssh-dss  AAAAB3Nsdfj230xxjxJjsjwjsjdjU   root@test')
426 a8083063 Iustin Pop
427 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
428 f0990e0c Michael Hanselmann
        "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
429 f0990e0c Michael Hanselmann
        'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
430 f0990e0c Michael Hanselmann
        " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
431 a8083063 Iustin Pop
    finally:
432 a8083063 Iustin Pop
      os.unlink(tmpname)
433 a8083063 Iustin Pop
434 a8083063 Iustin Pop
435 f0990e0c Michael Hanselmann
class TestEtcHosts(GanetiTestCase):
436 899d2a81 Michael Hanselmann
  """Test functions modifying /etc/hosts"""
437 899d2a81 Michael Hanselmann
438 899d2a81 Michael Hanselmann
  def writeTestFile(self):
439 899d2a81 Michael Hanselmann
    (fd, tmpname) = tempfile.mkstemp(prefix = 'ganeti-test')
440 899d2a81 Michael Hanselmann
    f = os.fdopen(fd, 'w')
441 899d2a81 Michael Hanselmann
    try:
442 899d2a81 Michael Hanselmann
      f.write('# This is a test file for /etc/hosts\n')
443 899d2a81 Michael Hanselmann
      f.write('127.0.0.1\tlocalhost\n')
444 899d2a81 Michael Hanselmann
      f.write('192.168.1.1 router gw\n')
445 899d2a81 Michael Hanselmann
    finally:
446 899d2a81 Michael Hanselmann
      f.close()
447 899d2a81 Michael Hanselmann
448 899d2a81 Michael Hanselmann
    return tmpname
449 899d2a81 Michael Hanselmann
450 9440aeab Michael Hanselmann
  def testSettingNewIp(self):
451 899d2a81 Michael Hanselmann
    tmpname = self.writeTestFile()
452 899d2a81 Michael Hanselmann
    try:
453 9440aeab Michael Hanselmann
      SetEtcHostsEntry(tmpname, '1.2.3.4', 'myhost.domain.tld', ['myhost'])
454 899d2a81 Michael Hanselmann
455 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
456 f0990e0c Michael Hanselmann
        "# This is a test file for /etc/hosts\n"
457 f0990e0c Michael Hanselmann
        "127.0.0.1\tlocalhost\n"
458 f0990e0c Michael Hanselmann
        "192.168.1.1 router gw\n"
459 f0990e0c Michael Hanselmann
        "1.2.3.4\tmyhost.domain.tld myhost\n")
460 899d2a81 Michael Hanselmann
    finally:
461 899d2a81 Michael Hanselmann
      os.unlink(tmpname)
462 899d2a81 Michael Hanselmann
463 9440aeab Michael Hanselmann
  def testSettingExistingIp(self):
464 899d2a81 Michael Hanselmann
    tmpname = self.writeTestFile()
465 899d2a81 Michael Hanselmann
    try:
466 9440aeab Michael Hanselmann
      SetEtcHostsEntry(tmpname, '192.168.1.1', 'myhost.domain.tld', ['myhost'])
467 899d2a81 Michael Hanselmann
468 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
469 f0990e0c Michael Hanselmann
        "# This is a test file for /etc/hosts\n"
470 f0990e0c Michael Hanselmann
        "127.0.0.1\tlocalhost\n"
471 f0990e0c Michael Hanselmann
        "192.168.1.1\tmyhost.domain.tld myhost\n")
472 899d2a81 Michael Hanselmann
    finally:
473 899d2a81 Michael Hanselmann
      os.unlink(tmpname)
474 899d2a81 Michael Hanselmann
475 899d2a81 Michael Hanselmann
  def testRemovingExistingHost(self):
476 899d2a81 Michael Hanselmann
    tmpname = self.writeTestFile()
477 899d2a81 Michael Hanselmann
    try:
478 899d2a81 Michael Hanselmann
      RemoveEtcHostsEntry(tmpname, 'router')
479 899d2a81 Michael Hanselmann
480 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
481 f0990e0c Michael Hanselmann
        "# This is a test file for /etc/hosts\n"
482 f0990e0c Michael Hanselmann
        "127.0.0.1\tlocalhost\n"
483 f0990e0c Michael Hanselmann
        "192.168.1.1 gw\n")
484 899d2a81 Michael Hanselmann
    finally:
485 899d2a81 Michael Hanselmann
      os.unlink(tmpname)
486 899d2a81 Michael Hanselmann
487 899d2a81 Michael Hanselmann
  def testRemovingSingleExistingHost(self):
488 899d2a81 Michael Hanselmann
    tmpname = self.writeTestFile()
489 899d2a81 Michael Hanselmann
    try:
490 899d2a81 Michael Hanselmann
      RemoveEtcHostsEntry(tmpname, 'localhost')
491 899d2a81 Michael Hanselmann
492 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
493 f0990e0c Michael Hanselmann
        "# This is a test file for /etc/hosts\n"
494 f0990e0c Michael Hanselmann
        "192.168.1.1 router gw\n")
495 899d2a81 Michael Hanselmann
    finally:
496 899d2a81 Michael Hanselmann
      os.unlink(tmpname)
497 899d2a81 Michael Hanselmann
498 899d2a81 Michael Hanselmann
  def testRemovingNonExistingHost(self):
499 899d2a81 Michael Hanselmann
    tmpname = self.writeTestFile()
500 899d2a81 Michael Hanselmann
    try:
501 899d2a81 Michael Hanselmann
      RemoveEtcHostsEntry(tmpname, 'myhost')
502 899d2a81 Michael Hanselmann
503 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
504 f0990e0c Michael Hanselmann
        "# This is a test file for /etc/hosts\n"
505 f0990e0c Michael Hanselmann
        "127.0.0.1\tlocalhost\n"
506 f0990e0c Michael Hanselmann
        "192.168.1.1 router gw\n")
507 899d2a81 Michael Hanselmann
    finally:
508 899d2a81 Michael Hanselmann
      os.unlink(tmpname)
509 899d2a81 Michael Hanselmann
510 9440aeab Michael Hanselmann
  def testRemovingAlias(self):
511 9440aeab Michael Hanselmann
    tmpname = self.writeTestFile()
512 9440aeab Michael Hanselmann
    try:
513 9440aeab Michael Hanselmann
      RemoveEtcHostsEntry(tmpname, 'gw')
514 9440aeab Michael Hanselmann
515 f0990e0c Michael Hanselmann
      self.assertFileContent(tmpname,
516 f0990e0c Michael Hanselmann
        "# This is a test file for /etc/hosts\n"
517 f0990e0c Michael Hanselmann
        "127.0.0.1\tlocalhost\n"
518 f0990e0c Michael Hanselmann
        "192.168.1.1 router\n")
519 9440aeab Michael Hanselmann
    finally:
520 9440aeab Michael Hanselmann
      os.unlink(tmpname)
521 9440aeab Michael Hanselmann
522 899d2a81 Michael Hanselmann
523 a8083063 Iustin Pop
class TestShellQuoting(unittest.TestCase):
524 a8083063 Iustin Pop
  """Test case for shell quoting functions"""
525 a8083063 Iustin Pop
526 a8083063 Iustin Pop
  def testShellQuote(self):
527 a8083063 Iustin Pop
    self.assertEqual(ShellQuote('abc'), "abc")
528 a8083063 Iustin Pop
    self.assertEqual(ShellQuote('ab"c'), "'ab\"c'")
529 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a'bc"), "'a'\\''bc'")
530 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a b c"), "'a b c'")
531 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a b\\ c"), "'a b\\ c'")
532 a8083063 Iustin Pop
533 a8083063 Iustin Pop
  def testShellQuoteArgs(self):
534 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b', 'c']), "a b c")
535 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b"', 'c']), "a 'b\"' c")
536 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b\'', 'c']), "a 'b'\\\''' c")
537 a8083063 Iustin Pop
538 a8083063 Iustin Pop
539 2c30e9d7 Alexander Schreiber
class TestTcpPing(unittest.TestCase):
540 2c30e9d7 Alexander Schreiber
  """Testcase for TCP version of ping - against listen(2)ing port"""
541 2c30e9d7 Alexander Schreiber
542 2c30e9d7 Alexander Schreiber
  def setUp(self):
543 2c30e9d7 Alexander Schreiber
    self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
544 16abfbc2 Alexander Schreiber
    self.listener.bind((constants.LOCALHOST_IP_ADDRESS, 0))
545 2c30e9d7 Alexander Schreiber
    self.listenerport = self.listener.getsockname()[1]
546 2c30e9d7 Alexander Schreiber
    self.listener.listen(1)
547 2c30e9d7 Alexander Schreiber
548 2c30e9d7 Alexander Schreiber
  def tearDown(self):
549 2c30e9d7 Alexander Schreiber
    self.listener.shutdown(socket.SHUT_RDWR)
550 2c30e9d7 Alexander Schreiber
    del self.listener
551 2c30e9d7 Alexander Schreiber
    del self.listenerport
552 2c30e9d7 Alexander Schreiber
553 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostAccept(self):
554 16abfbc2 Alexander Schreiber
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
555 16abfbc2 Alexander Schreiber
                         constants.LOCALHOST_IP_ADDRESS,
556 2c30e9d7 Alexander Schreiber
                         self.listenerport,
557 2c30e9d7 Alexander Schreiber
                         timeout=10,
558 2c30e9d7 Alexander Schreiber
                         live_port_needed=True),
559 2c30e9d7 Alexander Schreiber
                 "failed to connect to test listener")
560 2c30e9d7 Alexander Schreiber
561 2c30e9d7 Alexander Schreiber
562 2c30e9d7 Alexander Schreiber
class TestTcpPingDeaf(unittest.TestCase):
563 2c30e9d7 Alexander Schreiber
  """Testcase for TCP version of ping - against non listen(2)ing port"""
564 2c30e9d7 Alexander Schreiber
565 2c30e9d7 Alexander Schreiber
  def setUp(self):
566 2c30e9d7 Alexander Schreiber
    self.deaflistener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
567 16abfbc2 Alexander Schreiber
    self.deaflistener.bind((constants.LOCALHOST_IP_ADDRESS, 0))
568 2c30e9d7 Alexander Schreiber
    self.deaflistenerport = self.deaflistener.getsockname()[1]
569 2c30e9d7 Alexander Schreiber
570 2c30e9d7 Alexander Schreiber
  def tearDown(self):
571 2c30e9d7 Alexander Schreiber
    del self.deaflistener
572 2c30e9d7 Alexander Schreiber
    del self.deaflistenerport
573 2c30e9d7 Alexander Schreiber
574 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostAcceptDeaf(self):
575 16abfbc2 Alexander Schreiber
    self.failIf(TcpPing(constants.LOCALHOST_IP_ADDRESS,
576 16abfbc2 Alexander Schreiber
                        constants.LOCALHOST_IP_ADDRESS,
577 2c30e9d7 Alexander Schreiber
                        self.deaflistenerport,
578 16abfbc2 Alexander Schreiber
                        timeout=constants.TCP_PING_TIMEOUT,
579 2c30e9d7 Alexander Schreiber
                        live_port_needed=True), # need successful connect(2)
580 2c30e9d7 Alexander Schreiber
                "successfully connected to deaf listener")
581 2c30e9d7 Alexander Schreiber
582 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostNoAccept(self):
583 16abfbc2 Alexander Schreiber
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
584 16abfbc2 Alexander Schreiber
                         constants.LOCALHOST_IP_ADDRESS,
585 2c30e9d7 Alexander Schreiber
                         self.deaflistenerport,
586 16abfbc2 Alexander Schreiber
                         timeout=constants.TCP_PING_TIMEOUT,
587 2c30e9d7 Alexander Schreiber
                         live_port_needed=False), # ECONNREFUSED is OK
588 2c30e9d7 Alexander Schreiber
                 "failed to ping alive host on deaf port")
589 2c30e9d7 Alexander Schreiber
590 2c30e9d7 Alexander Schreiber
591 eedbda4b Michael Hanselmann
class TestListVisibleFiles(unittest.TestCase):
592 eedbda4b Michael Hanselmann
  """Test case for ListVisibleFiles"""
593 eedbda4b Michael Hanselmann
594 eedbda4b Michael Hanselmann
  def setUp(self):
595 eedbda4b Michael Hanselmann
    self.path = tempfile.mkdtemp()
596 eedbda4b Michael Hanselmann
597 eedbda4b Michael Hanselmann
  def tearDown(self):
598 eedbda4b Michael Hanselmann
    shutil.rmtree(self.path)
599 eedbda4b Michael Hanselmann
600 eedbda4b Michael Hanselmann
  def _test(self, files, expected):
601 eedbda4b Michael Hanselmann
    # Sort a copy
602 eedbda4b Michael Hanselmann
    expected = expected[:]
603 eedbda4b Michael Hanselmann
    expected.sort()
604 eedbda4b Michael Hanselmann
605 eedbda4b Michael Hanselmann
    for name in files:
606 eedbda4b Michael Hanselmann
      f = open(os.path.join(self.path, name), 'w')
607 eedbda4b Michael Hanselmann
      try:
608 eedbda4b Michael Hanselmann
        f.write("Test\n")
609 eedbda4b Michael Hanselmann
      finally:
610 eedbda4b Michael Hanselmann
        f.close()
611 eedbda4b Michael Hanselmann
612 eedbda4b Michael Hanselmann
    found = ListVisibleFiles(self.path)
613 eedbda4b Michael Hanselmann
    found.sort()
614 eedbda4b Michael Hanselmann
615 eedbda4b Michael Hanselmann
    self.assertEqual(found, expected)
616 eedbda4b Michael Hanselmann
617 eedbda4b Michael Hanselmann
  def testAllVisible(self):
618 eedbda4b Michael Hanselmann
    files = ["a", "b", "c"]
619 eedbda4b Michael Hanselmann
    expected = files
620 eedbda4b Michael Hanselmann
    self._test(files, expected)
621 eedbda4b Michael Hanselmann
622 eedbda4b Michael Hanselmann
  def testNoneVisible(self):
623 eedbda4b Michael Hanselmann
    files = [".a", ".b", ".c"]
624 eedbda4b Michael Hanselmann
    expected = []
625 eedbda4b Michael Hanselmann
    self._test(files, expected)
626 eedbda4b Michael Hanselmann
627 eedbda4b Michael Hanselmann
  def testSomeVisible(self):
628 eedbda4b Michael Hanselmann
    files = ["a", "b", ".c"]
629 eedbda4b Michael Hanselmann
    expected = ["a", "b"]
630 eedbda4b Michael Hanselmann
    self._test(files, expected)
631 eedbda4b Michael Hanselmann
632 eedbda4b Michael Hanselmann
633 24818e8f Michael Hanselmann
class TestNewUUID(unittest.TestCase):
634 24818e8f Michael Hanselmann
  """Test case for NewUUID"""
635 59072e7e Michael Hanselmann
636 59072e7e Michael Hanselmann
  _re_uuid = re.compile('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-'
637 59072e7e Michael Hanselmann
                        '[a-f0-9]{4}-[a-f0-9]{12}$')
638 59072e7e Michael Hanselmann
639 59072e7e Michael Hanselmann
  def runTest(self):
640 24818e8f Michael Hanselmann
    self.failUnless(self._re_uuid.match(utils.NewUUID()))
641 59072e7e Michael Hanselmann
642 59072e7e Michael Hanselmann
643 a8083063 Iustin Pop
if __name__ == '__main__':
644 a8083063 Iustin Pop
  unittest.main()