Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.utils_unittest.py @ 59072e7e

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