Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.utils_unittest.py @ f89f17a8

History | View | Annotate | Download (18.8 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 667479d5 Michael Hanselmann
          self.assertEqual(ParseUnit('1024' + sep + func(suffix)),
339 667479d5 Michael Hanselmann
                           1024 * scale)
340 a8083063 Iustin Pop
341 a8083063 Iustin Pop
  def testInvalidInput(self):
342 a8083063 Iustin Pop
    for sep in ('-', '_', ',', 'a'):
343 a8083063 Iustin Pop
      for suffix, _ in TestParseUnit.SCALES:
344 a8083063 Iustin Pop
        self.assertRaises(UnitParseError, ParseUnit, '1' + sep + suffix)
345 a8083063 Iustin Pop
346 a8083063 Iustin Pop
    for suffix, _ in TestParseUnit.SCALES:
347 a8083063 Iustin Pop
      self.assertRaises(UnitParseError, ParseUnit, '1,3' + suffix)
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
350 f0990e0c Michael Hanselmann
class TestSshKeys(GanetiTestCase):
351 a8083063 Iustin Pop
  """Test case for the AddAuthorizedKey function"""
352 a8083063 Iustin Pop
353 a8083063 Iustin Pop
  KEY_A = 'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a'
354 a8083063 Iustin Pop
  KEY_B = ('command="/usr/bin/fooserver -t --verbose",from="1.2.3.4" '
355 a8083063 Iustin Pop
           'ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b')
356 a8083063 Iustin Pop
357 ebe8ef17 Michael Hanselmann
  def setUp(self):
358 ebe8ef17 Michael Hanselmann
    (fd, self.tmpname) = tempfile.mkstemp(prefix='ganeti-test')
359 a8083063 Iustin Pop
    try:
360 ebe8ef17 Michael Hanselmann
      handle = os.fdopen(fd, 'w')
361 ebe8ef17 Michael Hanselmann
      try:
362 ebe8ef17 Michael Hanselmann
        handle.write("%s\n" % TestSshKeys.KEY_A)
363 ebe8ef17 Michael Hanselmann
        handle.write("%s\n" % TestSshKeys.KEY_B)
364 ebe8ef17 Michael Hanselmann
      finally:
365 ebe8ef17 Michael Hanselmann
        handle.close()
366 ebe8ef17 Michael Hanselmann
    except:
367 ebe8ef17 Michael Hanselmann
      utils.RemoveFile(self.tmpname)
368 ebe8ef17 Michael Hanselmann
      raise
369 a8083063 Iustin Pop
370 ebe8ef17 Michael Hanselmann
  def tearDown(self):
371 ebe8ef17 Michael Hanselmann
    utils.RemoveFile(self.tmpname)
372 ebe8ef17 Michael Hanselmann
    del self.tmpname
373 a8083063 Iustin Pop
374 a8083063 Iustin Pop
  def testAddingNewKey(self):
375 ebe8ef17 Michael Hanselmann
    AddAuthorizedKey(self.tmpname, 'ssh-dss AAAAB3NzaC1kc3MAAACB root@test')
376 a8083063 Iustin Pop
377 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
378 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
379 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
380 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
381 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1kc3MAAACB root@test\n")
382 a8083063 Iustin Pop
383 f89f17a8 Michael Hanselmann
  def testAddingAlmostButNotCompletelyTheSameKey(self):
384 ebe8ef17 Michael Hanselmann
    AddAuthorizedKey(self.tmpname,
385 ebe8ef17 Michael Hanselmann
        'ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test')
386 ebe8ef17 Michael Hanselmann
387 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
388 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
389 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
390 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n"
391 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@test\n")
392 a8083063 Iustin Pop
393 a8083063 Iustin Pop
  def testAddingExistingKeyWithSomeMoreSpaces(self):
394 ebe8ef17 Michael Hanselmann
    AddAuthorizedKey(self.tmpname,
395 ebe8ef17 Michael Hanselmann
        'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
396 a8083063 Iustin Pop
397 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
398 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
399 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
400 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
401 a8083063 Iustin Pop
402 a8083063 Iustin Pop
  def testRemovingExistingKeyWithSomeMoreSpaces(self):
403 ebe8ef17 Michael Hanselmann
    RemoveAuthorizedKey(self.tmpname,
404 ebe8ef17 Michael Hanselmann
        'ssh-dss  AAAAB3NzaC1w5256closdj32mZaQU   root@key-a')
405 a8083063 Iustin Pop
406 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
407 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
408 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
409 a8083063 Iustin Pop
410 a8083063 Iustin Pop
  def testRemovingNonExistingKey(self):
411 ebe8ef17 Michael Hanselmann
    RemoveAuthorizedKey(self.tmpname,
412 ebe8ef17 Michael Hanselmann
        'ssh-dss  AAAAB3Nsdfj230xxjxJjsjwjsjdjU   root@test')
413 a8083063 Iustin Pop
414 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
415 ebe8ef17 Michael Hanselmann
      "ssh-dss AAAAB3NzaC1w5256closdj32mZaQU root@key-a\n"
416 ebe8ef17 Michael Hanselmann
      'command="/usr/bin/fooserver -t --verbose",from="1.2.3.4"'
417 ebe8ef17 Michael Hanselmann
      " ssh-dss AAAAB3NzaC1w520smc01ms0jfJs22 root@key-b\n")
418 a8083063 Iustin Pop
419 a8083063 Iustin Pop
420 f0990e0c Michael Hanselmann
class TestEtcHosts(GanetiTestCase):
421 899d2a81 Michael Hanselmann
  """Test functions modifying /etc/hosts"""
422 899d2a81 Michael Hanselmann
423 ebe8ef17 Michael Hanselmann
  def setUp(self):
424 ebe8ef17 Michael Hanselmann
    (fd, self.tmpname) = tempfile.mkstemp(prefix='ganeti-test')
425 899d2a81 Michael Hanselmann
    try:
426 ebe8ef17 Michael Hanselmann
      handle = os.fdopen(fd, 'w')
427 ebe8ef17 Michael Hanselmann
      try:
428 ebe8ef17 Michael Hanselmann
        handle.write('# This is a test file for /etc/hosts\n')
429 ebe8ef17 Michael Hanselmann
        handle.write('127.0.0.1\tlocalhost\n')
430 ebe8ef17 Michael Hanselmann
        handle.write('192.168.1.1 router gw\n')
431 ebe8ef17 Michael Hanselmann
      finally:
432 ebe8ef17 Michael Hanselmann
        handle.close()
433 ebe8ef17 Michael Hanselmann
    except:
434 ebe8ef17 Michael Hanselmann
      utils.RemoveFile(self.tmpname)
435 ebe8ef17 Michael Hanselmann
      raise
436 899d2a81 Michael Hanselmann
437 ebe8ef17 Michael Hanselmann
  def tearDown(self):
438 ebe8ef17 Michael Hanselmann
    utils.RemoveFile(self.tmpname)
439 ebe8ef17 Michael Hanselmann
    del self.tmpname
440 899d2a81 Michael Hanselmann
441 9440aeab Michael Hanselmann
  def testSettingNewIp(self):
442 ebe8ef17 Michael Hanselmann
    SetEtcHostsEntry(self.tmpname, '1.2.3.4', 'myhost.domain.tld', ['myhost'])
443 899d2a81 Michael Hanselmann
444 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
445 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
446 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
447 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router gw\n"
448 ebe8ef17 Michael Hanselmann
      "1.2.3.4\tmyhost.domain.tld myhost\n")
449 899d2a81 Michael Hanselmann
450 9440aeab Michael Hanselmann
  def testSettingExistingIp(self):
451 ebe8ef17 Michael Hanselmann
    SetEtcHostsEntry(self.tmpname, '192.168.1.1', 'myhost.domain.tld',
452 ebe8ef17 Michael Hanselmann
                     ['myhost'])
453 899d2a81 Michael Hanselmann
454 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
455 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
456 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
457 ebe8ef17 Michael Hanselmann
      "192.168.1.1\tmyhost.domain.tld myhost\n")
458 899d2a81 Michael Hanselmann
459 899d2a81 Michael Hanselmann
  def testRemovingExistingHost(self):
460 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'router')
461 899d2a81 Michael Hanselmann
462 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
463 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
464 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
465 ebe8ef17 Michael Hanselmann
      "192.168.1.1 gw\n")
466 899d2a81 Michael Hanselmann
467 899d2a81 Michael Hanselmann
  def testRemovingSingleExistingHost(self):
468 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'localhost')
469 899d2a81 Michael Hanselmann
470 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
471 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
472 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router gw\n")
473 899d2a81 Michael Hanselmann
474 899d2a81 Michael Hanselmann
  def testRemovingNonExistingHost(self):
475 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'myhost')
476 899d2a81 Michael Hanselmann
477 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
478 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
479 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
480 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router gw\n")
481 899d2a81 Michael Hanselmann
482 9440aeab Michael Hanselmann
  def testRemovingAlias(self):
483 ebe8ef17 Michael Hanselmann
    RemoveEtcHostsEntry(self.tmpname, 'gw')
484 9440aeab Michael Hanselmann
485 ebe8ef17 Michael Hanselmann
    self.assertFileContent(self.tmpname,
486 ebe8ef17 Michael Hanselmann
      "# This is a test file for /etc/hosts\n"
487 ebe8ef17 Michael Hanselmann
      "127.0.0.1\tlocalhost\n"
488 ebe8ef17 Michael Hanselmann
      "192.168.1.1 router\n")
489 9440aeab Michael Hanselmann
490 899d2a81 Michael Hanselmann
491 a8083063 Iustin Pop
class TestShellQuoting(unittest.TestCase):
492 a8083063 Iustin Pop
  """Test case for shell quoting functions"""
493 a8083063 Iustin Pop
494 a8083063 Iustin Pop
  def testShellQuote(self):
495 a8083063 Iustin Pop
    self.assertEqual(ShellQuote('abc'), "abc")
496 a8083063 Iustin Pop
    self.assertEqual(ShellQuote('ab"c'), "'ab\"c'")
497 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a'bc"), "'a'\\''bc'")
498 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a b c"), "'a b c'")
499 a8083063 Iustin Pop
    self.assertEqual(ShellQuote("a b\\ c"), "'a b\\ c'")
500 a8083063 Iustin Pop
501 a8083063 Iustin Pop
  def testShellQuoteArgs(self):
502 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b', 'c']), "a b c")
503 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b"', 'c']), "a 'b\"' c")
504 a8083063 Iustin Pop
    self.assertEqual(ShellQuoteArgs(['a', 'b\'', 'c']), "a 'b'\\\''' c")
505 a8083063 Iustin Pop
506 a8083063 Iustin Pop
507 2c30e9d7 Alexander Schreiber
class TestTcpPing(unittest.TestCase):
508 2c30e9d7 Alexander Schreiber
  """Testcase for TCP version of ping - against listen(2)ing port"""
509 2c30e9d7 Alexander Schreiber
510 2c30e9d7 Alexander Schreiber
  def setUp(self):
511 2c30e9d7 Alexander Schreiber
    self.listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
512 16abfbc2 Alexander Schreiber
    self.listener.bind((constants.LOCALHOST_IP_ADDRESS, 0))
513 2c30e9d7 Alexander Schreiber
    self.listenerport = self.listener.getsockname()[1]
514 2c30e9d7 Alexander Schreiber
    self.listener.listen(1)
515 2c30e9d7 Alexander Schreiber
516 2c30e9d7 Alexander Schreiber
  def tearDown(self):
517 2c30e9d7 Alexander Schreiber
    self.listener.shutdown(socket.SHUT_RDWR)
518 2c30e9d7 Alexander Schreiber
    del self.listener
519 2c30e9d7 Alexander Schreiber
    del self.listenerport
520 2c30e9d7 Alexander Schreiber
521 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostAccept(self):
522 16abfbc2 Alexander Schreiber
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
523 16abfbc2 Alexander Schreiber
                         constants.LOCALHOST_IP_ADDRESS,
524 2c30e9d7 Alexander Schreiber
                         self.listenerport,
525 2c30e9d7 Alexander Schreiber
                         timeout=10,
526 2c30e9d7 Alexander Schreiber
                         live_port_needed=True),
527 2c30e9d7 Alexander Schreiber
                 "failed to connect to test listener")
528 2c30e9d7 Alexander Schreiber
529 2c30e9d7 Alexander Schreiber
530 2c30e9d7 Alexander Schreiber
class TestTcpPingDeaf(unittest.TestCase):
531 2c30e9d7 Alexander Schreiber
  """Testcase for TCP version of ping - against non listen(2)ing port"""
532 2c30e9d7 Alexander Schreiber
533 2c30e9d7 Alexander Schreiber
  def setUp(self):
534 2c30e9d7 Alexander Schreiber
    self.deaflistener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
535 16abfbc2 Alexander Schreiber
    self.deaflistener.bind((constants.LOCALHOST_IP_ADDRESS, 0))
536 2c30e9d7 Alexander Schreiber
    self.deaflistenerport = self.deaflistener.getsockname()[1]
537 2c30e9d7 Alexander Schreiber
538 2c30e9d7 Alexander Schreiber
  def tearDown(self):
539 2c30e9d7 Alexander Schreiber
    del self.deaflistener
540 2c30e9d7 Alexander Schreiber
    del self.deaflistenerport
541 2c30e9d7 Alexander Schreiber
542 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostAcceptDeaf(self):
543 16abfbc2 Alexander Schreiber
    self.failIf(TcpPing(constants.LOCALHOST_IP_ADDRESS,
544 16abfbc2 Alexander Schreiber
                        constants.LOCALHOST_IP_ADDRESS,
545 2c30e9d7 Alexander Schreiber
                        self.deaflistenerport,
546 16abfbc2 Alexander Schreiber
                        timeout=constants.TCP_PING_TIMEOUT,
547 2c30e9d7 Alexander Schreiber
                        live_port_needed=True), # need successful connect(2)
548 2c30e9d7 Alexander Schreiber
                "successfully connected to deaf listener")
549 2c30e9d7 Alexander Schreiber
550 2c30e9d7 Alexander Schreiber
  def testTcpPingToLocalHostNoAccept(self):
551 16abfbc2 Alexander Schreiber
    self.assert_(TcpPing(constants.LOCALHOST_IP_ADDRESS,
552 16abfbc2 Alexander Schreiber
                         constants.LOCALHOST_IP_ADDRESS,
553 2c30e9d7 Alexander Schreiber
                         self.deaflistenerport,
554 16abfbc2 Alexander Schreiber
                         timeout=constants.TCP_PING_TIMEOUT,
555 2c30e9d7 Alexander Schreiber
                         live_port_needed=False), # ECONNREFUSED is OK
556 2c30e9d7 Alexander Schreiber
                 "failed to ping alive host on deaf port")
557 2c30e9d7 Alexander Schreiber
558 2c30e9d7 Alexander Schreiber
559 eedbda4b Michael Hanselmann
class TestListVisibleFiles(unittest.TestCase):
560 eedbda4b Michael Hanselmann
  """Test case for ListVisibleFiles"""
561 eedbda4b Michael Hanselmann
562 eedbda4b Michael Hanselmann
  def setUp(self):
563 eedbda4b Michael Hanselmann
    self.path = tempfile.mkdtemp()
564 eedbda4b Michael Hanselmann
565 eedbda4b Michael Hanselmann
  def tearDown(self):
566 eedbda4b Michael Hanselmann
    shutil.rmtree(self.path)
567 eedbda4b Michael Hanselmann
568 eedbda4b Michael Hanselmann
  def _test(self, files, expected):
569 eedbda4b Michael Hanselmann
    # Sort a copy
570 eedbda4b Michael Hanselmann
    expected = expected[:]
571 eedbda4b Michael Hanselmann
    expected.sort()
572 eedbda4b Michael Hanselmann
573 eedbda4b Michael Hanselmann
    for name in files:
574 eedbda4b Michael Hanselmann
      f = open(os.path.join(self.path, name), 'w')
575 eedbda4b Michael Hanselmann
      try:
576 eedbda4b Michael Hanselmann
        f.write("Test\n")
577 eedbda4b Michael Hanselmann
      finally:
578 eedbda4b Michael Hanselmann
        f.close()
579 eedbda4b Michael Hanselmann
580 eedbda4b Michael Hanselmann
    found = ListVisibleFiles(self.path)
581 eedbda4b Michael Hanselmann
    found.sort()
582 eedbda4b Michael Hanselmann
583 eedbda4b Michael Hanselmann
    self.assertEqual(found, expected)
584 eedbda4b Michael Hanselmann
585 eedbda4b Michael Hanselmann
  def testAllVisible(self):
586 eedbda4b Michael Hanselmann
    files = ["a", "b", "c"]
587 eedbda4b Michael Hanselmann
    expected = files
588 eedbda4b Michael Hanselmann
    self._test(files, expected)
589 eedbda4b Michael Hanselmann
590 eedbda4b Michael Hanselmann
  def testNoneVisible(self):
591 eedbda4b Michael Hanselmann
    files = [".a", ".b", ".c"]
592 eedbda4b Michael Hanselmann
    expected = []
593 eedbda4b Michael Hanselmann
    self._test(files, expected)
594 eedbda4b Michael Hanselmann
595 eedbda4b Michael Hanselmann
  def testSomeVisible(self):
596 eedbda4b Michael Hanselmann
    files = ["a", "b", ".c"]
597 eedbda4b Michael Hanselmann
    expected = ["a", "b"]
598 eedbda4b Michael Hanselmann
    self._test(files, expected)
599 eedbda4b Michael Hanselmann
600 eedbda4b Michael Hanselmann
601 24818e8f Michael Hanselmann
class TestNewUUID(unittest.TestCase):
602 24818e8f Michael Hanselmann
  """Test case for NewUUID"""
603 59072e7e Michael Hanselmann
604 59072e7e Michael Hanselmann
  _re_uuid = re.compile('^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-'
605 59072e7e Michael Hanselmann
                        '[a-f0-9]{4}-[a-f0-9]{12}$')
606 59072e7e Michael Hanselmann
607 59072e7e Michael Hanselmann
  def runTest(self):
608 24818e8f Michael Hanselmann
    self.failUnless(self._re_uuid.match(utils.NewUUID()))
609 59072e7e Michael Hanselmann
610 59072e7e Michael Hanselmann
611 a8083063 Iustin Pop
if __name__ == '__main__':
612 a8083063 Iustin Pop
  unittest.main()