Statistics
| Branch: | Tag: | Revision:

root / testing / ganeti.utils_unittest.py @ 23f41a3e

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