Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.utils_unittest.py @ 9cd372ad

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