Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.utils_unittest.py @ eedbda4b

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