Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.backend_unittest.py @ 07809f7d

History | View | Annotate | Download (18.7 kB)

1 f942a838 Michael Hanselmann
#!/usr/bin/python
2 f942a838 Michael Hanselmann
#
3 f942a838 Michael Hanselmann
4 45bc4635 Iustin Pop
# Copyright (C) 2010, 2013 Google Inc.
5 f942a838 Michael Hanselmann
#
6 f942a838 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 f942a838 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 f942a838 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 f942a838 Michael Hanselmann
# (at your option) any later version.
10 f942a838 Michael Hanselmann
#
11 f942a838 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 f942a838 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 f942a838 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 f942a838 Michael Hanselmann
# General Public License for more details.
15 f942a838 Michael Hanselmann
#
16 f942a838 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 f942a838 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 f942a838 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 f942a838 Michael Hanselmann
# 02110-1301, USA.
20 f942a838 Michael Hanselmann
21 f942a838 Michael Hanselmann
22 f942a838 Michael Hanselmann
"""Script for testing ganeti.backend"""
23 f942a838 Michael Hanselmann
24 f942a838 Michael Hanselmann
import os
25 f942a838 Michael Hanselmann
import sys
26 f942a838 Michael Hanselmann
import shutil
27 f942a838 Michael Hanselmann
import tempfile
28 f942a838 Michael Hanselmann
import unittest
29 f942a838 Michael Hanselmann
30 f942a838 Michael Hanselmann
from ganeti import utils
31 31ff0247 Michael Hanselmann
from ganeti import constants
32 f942a838 Michael Hanselmann
from ganeti import backend
33 a744b676 Manuel Franceschini
from ganeti import netutils
34 1a2eb2dc Michael Hanselmann
from ganeti import errors
35 a59d5fa1 Michele Tartara
from ganeti import serializer
36 f942a838 Michael Hanselmann
37 f942a838 Michael Hanselmann
import testutils
38 1a2eb2dc Michael Hanselmann
import mocks
39 f942a838 Michael Hanselmann
40 f942a838 Michael Hanselmann
41 f942a838 Michael Hanselmann
class TestX509Certificates(unittest.TestCase):
42 f942a838 Michael Hanselmann
  def setUp(self):
43 f942a838 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
44 f942a838 Michael Hanselmann
45 f942a838 Michael Hanselmann
  def tearDown(self):
46 f942a838 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
47 f942a838 Michael Hanselmann
48 f942a838 Michael Hanselmann
  def test(self):
49 f942a838 Michael Hanselmann
    (name, cert_pem) = backend.CreateX509Certificate(300, cryptodir=self.tmpdir)
50 f942a838 Michael Hanselmann
51 f942a838 Michael Hanselmann
    self.assertEqual(utils.ReadFile(os.path.join(self.tmpdir, name,
52 f942a838 Michael Hanselmann
                                                 backend._X509_CERT_FILE)),
53 f942a838 Michael Hanselmann
                     cert_pem)
54 f942a838 Michael Hanselmann
    self.assert_(0 < os.path.getsize(os.path.join(self.tmpdir, name,
55 f942a838 Michael Hanselmann
                                                  backend._X509_KEY_FILE)))
56 f942a838 Michael Hanselmann
57 f942a838 Michael Hanselmann
    (name2, cert_pem2) = \
58 f942a838 Michael Hanselmann
      backend.CreateX509Certificate(300, cryptodir=self.tmpdir)
59 f942a838 Michael Hanselmann
60 f942a838 Michael Hanselmann
    backend.RemoveX509Certificate(name, cryptodir=self.tmpdir)
61 f942a838 Michael Hanselmann
    backend.RemoveX509Certificate(name2, cryptodir=self.tmpdir)
62 f942a838 Michael Hanselmann
63 f942a838 Michael Hanselmann
    self.assertEqual(utils.ListVisibleFiles(self.tmpdir), [])
64 f942a838 Michael Hanselmann
65 f942a838 Michael Hanselmann
  def testNonEmpty(self):
66 f942a838 Michael Hanselmann
    (name, _) = backend.CreateX509Certificate(300, cryptodir=self.tmpdir)
67 f942a838 Michael Hanselmann
68 f942a838 Michael Hanselmann
    utils.WriteFile(utils.PathJoin(self.tmpdir, name, "hello-world"),
69 f942a838 Michael Hanselmann
                    data="Hello World")
70 f942a838 Michael Hanselmann
71 f942a838 Michael Hanselmann
    self.assertRaises(backend.RPCFail, backend.RemoveX509Certificate,
72 f942a838 Michael Hanselmann
                      name, cryptodir=self.tmpdir)
73 f942a838 Michael Hanselmann
74 f942a838 Michael Hanselmann
    self.assertEqual(utils.ListVisibleFiles(self.tmpdir), [name])
75 f942a838 Michael Hanselmann
76 f942a838 Michael Hanselmann
77 a3a5f850 Iustin Pop
class TestNodeVerify(testutils.GanetiTestCase):
78 a3a5f850 Iustin Pop
  def testMasterIPLocalhost(self):
79 a3a5f850 Iustin Pop
    # this a real functional test, but requires localhost to be reachable
80 b705c7a6 Manuel Franceschini
    local_data = (netutils.Hostname.GetSysName(),
81 b705c7a6 Manuel Franceschini
                  constants.IP4_ADDRESS_LOCALHOST)
82 a3a5f850 Iustin Pop
    result = backend.VerifyNode({constants.NV_MASTERIP: local_data}, None)
83 a3a5f850 Iustin Pop
    self.failUnless(constants.NV_MASTERIP in result,
84 a3a5f850 Iustin Pop
                    "Master IP data not returned")
85 a3a5f850 Iustin Pop
    self.failUnless(result[constants.NV_MASTERIP], "Cannot reach localhost")
86 a3a5f850 Iustin Pop
87 a3a5f850 Iustin Pop
  def testMasterIPUnreachable(self):
88 a3a5f850 Iustin Pop
    # Network 192.0.2.0/24 is reserved for test/documentation as per
89 926feaf1 Manuel Franceschini
    # RFC 5737
90 a3a5f850 Iustin Pop
    bad_data =  ("master.example.com", "192.0.2.1")
91 a3a5f850 Iustin Pop
    # we just test that whatever TcpPing returns, VerifyNode returns too
92 a744b676 Manuel Franceschini
    netutils.TcpPing = lambda a, b, source=None: False
93 a3a5f850 Iustin Pop
    result = backend.VerifyNode({constants.NV_MASTERIP: bad_data}, None)
94 a3a5f850 Iustin Pop
    self.failUnless(constants.NV_MASTERIP in result,
95 a3a5f850 Iustin Pop
                    "Master IP data not returned")
96 a3a5f850 Iustin Pop
    self.failIf(result[constants.NV_MASTERIP],
97 a744b676 Manuel Franceschini
                "Result from netutils.TcpPing corrupted")
98 a3a5f850 Iustin Pop
99 a3a5f850 Iustin Pop
100 405bffe2 Michael Hanselmann
def _DefRestrictedCmdOwner():
101 1a2eb2dc Michael Hanselmann
  return (os.getuid(), os.getgid())
102 1a2eb2dc Michael Hanselmann
103 1a2eb2dc Michael Hanselmann
104 405bffe2 Michael Hanselmann
class TestVerifyRestrictedCmdName(unittest.TestCase):
105 1a2eb2dc Michael Hanselmann
  def testAcceptableName(self):
106 1a2eb2dc Michael Hanselmann
    for i in ["foo", "bar", "z1", "000first", "hello-world"]:
107 1a2eb2dc Michael Hanselmann
      for fn in [lambda s: s, lambda s: s.upper(), lambda s: s.title()]:
108 405bffe2 Michael Hanselmann
        (status, msg) = backend._VerifyRestrictedCmdName(fn(i))
109 1a2eb2dc Michael Hanselmann
        self.assertTrue(status)
110 1a2eb2dc Michael Hanselmann
        self.assertTrue(msg is None)
111 1a2eb2dc Michael Hanselmann
112 1a2eb2dc Michael Hanselmann
  def testEmptyAndSpace(self):
113 1a2eb2dc Michael Hanselmann
    for i in ["", " ", "\t", "\n"]:
114 405bffe2 Michael Hanselmann
      (status, msg) = backend._VerifyRestrictedCmdName(i)
115 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
116 1a2eb2dc Michael Hanselmann
      self.assertEqual(msg, "Missing command name")
117 1a2eb2dc Michael Hanselmann
118 1a2eb2dc Michael Hanselmann
  def testNameWithSlashes(self):
119 1a2eb2dc Michael Hanselmann
    for i in ["/", "./foo", "../moo", "some/name"]:
120 405bffe2 Michael Hanselmann
      (status, msg) = backend._VerifyRestrictedCmdName(i)
121 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
122 1a2eb2dc Michael Hanselmann
      self.assertEqual(msg, "Invalid command name")
123 1a2eb2dc Michael Hanselmann
124 1a2eb2dc Michael Hanselmann
  def testForbiddenCharacters(self):
125 1a2eb2dc Michael Hanselmann
    for i in ["#", ".", "..", "bash -c ls", "'"]:
126 405bffe2 Michael Hanselmann
      (status, msg) = backend._VerifyRestrictedCmdName(i)
127 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
128 1a2eb2dc Michael Hanselmann
      self.assertEqual(msg, "Command name contains forbidden characters")
129 1a2eb2dc Michael Hanselmann
130 1a2eb2dc Michael Hanselmann
131 405bffe2 Michael Hanselmann
class TestVerifyRestrictedCmdDirectory(unittest.TestCase):
132 1a2eb2dc Michael Hanselmann
  def setUp(self):
133 1a2eb2dc Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
134 1a2eb2dc Michael Hanselmann
135 1a2eb2dc Michael Hanselmann
  def tearDown(self):
136 1a2eb2dc Michael Hanselmann
    shutil.rmtree(self.tmpdir)
137 1a2eb2dc Michael Hanselmann
138 1a2eb2dc Michael Hanselmann
  def testCanNotStat(self):
139 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
140 1a2eb2dc Michael Hanselmann
    self.assertFalse(os.path.exists(tmpname))
141 1a2eb2dc Michael Hanselmann
    (status, msg) = \
142 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmdDirectory(tmpname, _owner=NotImplemented)
143 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
144 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.startswith("Can't stat(2) '"))
145 1a2eb2dc Michael Hanselmann
146 1a2eb2dc Michael Hanselmann
  def testTooPermissive(self):
147 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
148 1a2eb2dc Michael Hanselmann
    os.mkdir(tmpname)
149 1a2eb2dc Michael Hanselmann
150 1a2eb2dc Michael Hanselmann
    for mode in [0777, 0706, 0760, 0722]:
151 1a2eb2dc Michael Hanselmann
      os.chmod(tmpname, mode)
152 1a2eb2dc Michael Hanselmann
      self.assertTrue(os.path.isdir(tmpname))
153 1a2eb2dc Michael Hanselmann
      (status, msg) = \
154 405bffe2 Michael Hanselmann
        backend._VerifyRestrictedCmdDirectory(tmpname, _owner=NotImplemented)
155 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
156 1a2eb2dc Michael Hanselmann
      self.assertTrue(msg.startswith("Permissions on '"))
157 1a2eb2dc Michael Hanselmann
158 1a2eb2dc Michael Hanselmann
  def testNoDirectory(self):
159 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
160 1a2eb2dc Michael Hanselmann
    utils.WriteFile(tmpname, data="empty\n")
161 1a2eb2dc Michael Hanselmann
    self.assertTrue(os.path.isfile(tmpname))
162 1a2eb2dc Michael Hanselmann
    (status, msg) = \
163 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmdDirectory(tmpname,
164 405bffe2 Michael Hanselmann
                                            _owner=_DefRestrictedCmdOwner())
165 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
166 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.endswith("is not a directory"))
167 1a2eb2dc Michael Hanselmann
168 1a2eb2dc Michael Hanselmann
  def testNormal(self):
169 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
170 1a2eb2dc Michael Hanselmann
    os.mkdir(tmpname)
171 24cd672e Apollon Oikonomopoulos
    os.chmod(tmpname, 0755)
172 1a2eb2dc Michael Hanselmann
    self.assertTrue(os.path.isdir(tmpname))
173 1a2eb2dc Michael Hanselmann
    (status, msg) = \
174 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmdDirectory(tmpname,
175 405bffe2 Michael Hanselmann
                                            _owner=_DefRestrictedCmdOwner())
176 1a2eb2dc Michael Hanselmann
    self.assertTrue(status)
177 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg is None)
178 1a2eb2dc Michael Hanselmann
179 1a2eb2dc Michael Hanselmann
180 405bffe2 Michael Hanselmann
class TestVerifyRestrictedCmd(unittest.TestCase):
181 1a2eb2dc Michael Hanselmann
  def setUp(self):
182 1a2eb2dc Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
183 1a2eb2dc Michael Hanselmann
184 1a2eb2dc Michael Hanselmann
  def tearDown(self):
185 1a2eb2dc Michael Hanselmann
    shutil.rmtree(self.tmpdir)
186 1a2eb2dc Michael Hanselmann
187 1a2eb2dc Michael Hanselmann
  def testCanNotStat(self):
188 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "helloworld")
189 1a2eb2dc Michael Hanselmann
    self.assertFalse(os.path.exists(tmpname))
190 1a2eb2dc Michael Hanselmann
    (status, msg) = \
191 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmd(self.tmpdir, "helloworld",
192 1a2eb2dc Michael Hanselmann
                                   _owner=NotImplemented)
193 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
194 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.startswith("Can't stat(2) '"))
195 1a2eb2dc Michael Hanselmann
196 1a2eb2dc Michael Hanselmann
  def testNotExecutable(self):
197 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "cmdname")
198 1a2eb2dc Michael Hanselmann
    utils.WriteFile(tmpname, data="empty\n")
199 1a2eb2dc Michael Hanselmann
    (status, msg) = \
200 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmd(self.tmpdir, "cmdname",
201 405bffe2 Michael Hanselmann
                                   _owner=_DefRestrictedCmdOwner())
202 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
203 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.startswith("access(2) thinks '"))
204 1a2eb2dc Michael Hanselmann
205 1a2eb2dc Michael Hanselmann
  def testExecutable(self):
206 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "cmdname")
207 1a2eb2dc Michael Hanselmann
    utils.WriteFile(tmpname, data="empty\n", mode=0700)
208 1a2eb2dc Michael Hanselmann
    (status, executable) = \
209 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmd(self.tmpdir, "cmdname",
210 405bffe2 Michael Hanselmann
                                   _owner=_DefRestrictedCmdOwner())
211 1a2eb2dc Michael Hanselmann
    self.assertTrue(status)
212 1a2eb2dc Michael Hanselmann
    self.assertEqual(executable, tmpname)
213 1a2eb2dc Michael Hanselmann
214 1a2eb2dc Michael Hanselmann
215 405bffe2 Michael Hanselmann
class TestPrepareRestrictedCmd(unittest.TestCase):
216 1a2eb2dc Michael Hanselmann
  _TEST_PATH = "/tmp/some/test/path"
217 1a2eb2dc Michael Hanselmann
218 1a2eb2dc Michael Hanselmann
  def testDirFails(self):
219 1a2eb2dc Michael Hanselmann
    def fn(path):
220 1a2eb2dc Michael Hanselmann
      self.assertEqual(path, self._TEST_PATH)
221 1a2eb2dc Michael Hanselmann
      return (False, "test error 31420")
222 1a2eb2dc Michael Hanselmann
223 1a2eb2dc Michael Hanselmann
    (status, msg) = \
224 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd21152",
225 1a2eb2dc Michael Hanselmann
                                    _verify_dir=fn,
226 1a2eb2dc Michael Hanselmann
                                    _verify_name=NotImplemented,
227 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=NotImplemented)
228 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
229 1a2eb2dc Michael Hanselmann
    self.assertEqual(msg, "test error 31420")
230 1a2eb2dc Michael Hanselmann
231 1a2eb2dc Michael Hanselmann
  def testNameFails(self):
232 1a2eb2dc Michael Hanselmann
    def fn(cmd):
233 1a2eb2dc Michael Hanselmann
      self.assertEqual(cmd, "cmd4617")
234 1a2eb2dc Michael Hanselmann
      return (False, "test error 591")
235 1a2eb2dc Michael Hanselmann
236 1a2eb2dc Michael Hanselmann
    (status, msg) = \
237 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd4617",
238 1a2eb2dc Michael Hanselmann
                                    _verify_dir=lambda _: (True, None),
239 1a2eb2dc Michael Hanselmann
                                    _verify_name=fn,
240 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=NotImplemented)
241 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
242 1a2eb2dc Michael Hanselmann
    self.assertEqual(msg, "test error 591")
243 1a2eb2dc Michael Hanselmann
244 1a2eb2dc Michael Hanselmann
  def testCommandFails(self):
245 1a2eb2dc Michael Hanselmann
    def fn(path, cmd):
246 1a2eb2dc Michael Hanselmann
      self.assertEqual(path, self._TEST_PATH)
247 1a2eb2dc Michael Hanselmann
      self.assertEqual(cmd, "cmd17577")
248 1a2eb2dc Michael Hanselmann
      return (False, "test error 25524")
249 1a2eb2dc Michael Hanselmann
250 1a2eb2dc Michael Hanselmann
    (status, msg) = \
251 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd17577",
252 1a2eb2dc Michael Hanselmann
                                    _verify_dir=lambda _: (True, None),
253 1a2eb2dc Michael Hanselmann
                                    _verify_name=lambda _: (True, None),
254 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=fn)
255 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
256 1a2eb2dc Michael Hanselmann
    self.assertEqual(msg, "test error 25524")
257 1a2eb2dc Michael Hanselmann
258 1a2eb2dc Michael Hanselmann
  def testSuccess(self):
259 1a2eb2dc Michael Hanselmann
    def fn(path, cmd):
260 1a2eb2dc Michael Hanselmann
      return (True, utils.PathJoin(path, cmd))
261 1a2eb2dc Michael Hanselmann
262 1a2eb2dc Michael Hanselmann
    (status, executable) = \
263 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd22633",
264 1a2eb2dc Michael Hanselmann
                                    _verify_dir=lambda _: (True, None),
265 1a2eb2dc Michael Hanselmann
                                    _verify_name=lambda _: (True, None),
266 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=fn)
267 1a2eb2dc Michael Hanselmann
    self.assertTrue(status)
268 1a2eb2dc Michael Hanselmann
    self.assertEqual(executable, utils.PathJoin(self._TEST_PATH, "cmd22633"))
269 1a2eb2dc Michael Hanselmann
270 1a2eb2dc Michael Hanselmann
271 405bffe2 Michael Hanselmann
def _SleepForRestrictedCmd(duration):
272 1a2eb2dc Michael Hanselmann
  assert duration > 5
273 1a2eb2dc Michael Hanselmann
274 1a2eb2dc Michael Hanselmann
275 405bffe2 Michael Hanselmann
def _GenericRestrictedCmdError(cmd):
276 1a2eb2dc Michael Hanselmann
  return "Executing command '%s' failed" % cmd
277 1a2eb2dc Michael Hanselmann
278 1a2eb2dc Michael Hanselmann
279 42bd26e8 Michael Hanselmann
class TestRunRestrictedCmd(unittest.TestCase):
280 1a2eb2dc Michael Hanselmann
  def setUp(self):
281 1a2eb2dc Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
282 1a2eb2dc Michael Hanselmann
283 1a2eb2dc Michael Hanselmann
  def tearDown(self):
284 1a2eb2dc Michael Hanselmann
    shutil.rmtree(self.tmpdir)
285 1a2eb2dc Michael Hanselmann
286 1a2eb2dc Michael Hanselmann
  def testNonExistantLockDirectory(self):
287 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "does", "not", "exist")
288 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
289 1a2eb2dc Michael Hanselmann
    self.assertFalse(os.path.exists(lockfile))
290 1a2eb2dc Michael Hanselmann
    self.assertRaises(backend.RPCFail,
291 42bd26e8 Michael Hanselmann
                      backend.RunRestrictedCmd, "test",
292 1a2eb2dc Michael Hanselmann
                      _lock_timeout=NotImplemented,
293 1a2eb2dc Michael Hanselmann
                      _lock_file=lockfile,
294 1a2eb2dc Michael Hanselmann
                      _path=NotImplemented,
295 1a2eb2dc Michael Hanselmann
                      _sleep_fn=sleep_fn,
296 1a2eb2dc Michael Hanselmann
                      _prepare_fn=NotImplemented,
297 1a2eb2dc Michael Hanselmann
                      _runcmd_fn=NotImplemented,
298 1a2eb2dc Michael Hanselmann
                      _enabled=True)
299 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 1)
300 1a2eb2dc Michael Hanselmann
301 1a2eb2dc Michael Hanselmann
  @staticmethod
302 1a2eb2dc Michael Hanselmann
  def _TryLock(lockfile):
303 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
304 1a2eb2dc Michael Hanselmann
305 1a2eb2dc Michael Hanselmann
    result = False
306 1a2eb2dc Michael Hanselmann
    try:
307 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test22717",
308 1a2eb2dc Michael Hanselmann
                               _lock_timeout=0.1,
309 1a2eb2dc Michael Hanselmann
                               _lock_file=lockfile,
310 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented,
311 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn,
312 1a2eb2dc Michael Hanselmann
                               _prepare_fn=NotImplemented,
313 1a2eb2dc Michael Hanselmann
                               _runcmd_fn=NotImplemented,
314 1a2eb2dc Michael Hanselmann
                               _enabled=True)
315 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
316 405bffe2 Michael Hanselmann
      assert str(err) == _GenericRestrictedCmdError("test22717"), \
317 1a2eb2dc Michael Hanselmann
             "Did not fail with generic error message"
318 1a2eb2dc Michael Hanselmann
      result = True
319 1a2eb2dc Michael Hanselmann
320 1a2eb2dc Michael Hanselmann
    assert sleep_fn.Count() == 1
321 1a2eb2dc Michael Hanselmann
322 1a2eb2dc Michael Hanselmann
    return result
323 1a2eb2dc Michael Hanselmann
324 1a2eb2dc Michael Hanselmann
  def testLockHeldByOtherProcess(self):
325 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
326 1a2eb2dc Michael Hanselmann
327 1a2eb2dc Michael Hanselmann
    lock = utils.FileLock.Open(lockfile)
328 1a2eb2dc Michael Hanselmann
    lock.Exclusive(blocking=True, timeout=1.0)
329 1a2eb2dc Michael Hanselmann
    try:
330 1a2eb2dc Michael Hanselmann
      self.assertTrue(utils.RunInSeparateProcess(self._TryLock, lockfile))
331 1a2eb2dc Michael Hanselmann
    finally:
332 1a2eb2dc Michael Hanselmann
      lock.Close()
333 1a2eb2dc Michael Hanselmann
334 1a2eb2dc Michael Hanselmann
  @staticmethod
335 1a2eb2dc Michael Hanselmann
  def _PrepareRaisingException(path, cmd):
336 1a2eb2dc Michael Hanselmann
    assert cmd == "test23122"
337 1a2eb2dc Michael Hanselmann
    raise Exception("test")
338 1a2eb2dc Michael Hanselmann
339 1a2eb2dc Michael Hanselmann
  def testPrepareRaisesException(self):
340 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
341 1a2eb2dc Michael Hanselmann
342 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
343 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._PrepareRaisingException)
344 1a2eb2dc Michael Hanselmann
345 1a2eb2dc Michael Hanselmann
    try:
346 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test23122",
347 1a2eb2dc Michael Hanselmann
                               _lock_timeout=1.0, _lock_file=lockfile,
348 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented, _runcmd_fn=NotImplemented,
349 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn, _prepare_fn=prepare_fn,
350 1a2eb2dc Michael Hanselmann
                               _enabled=True)
351 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
352 405bffe2 Michael Hanselmann
      self.assertEqual(str(err), _GenericRestrictedCmdError("test23122"))
353 1a2eb2dc Michael Hanselmann
    else:
354 1a2eb2dc Michael Hanselmann
      self.fail("Didn't fail")
355 1a2eb2dc Michael Hanselmann
356 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 1)
357 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
358 1a2eb2dc Michael Hanselmann
359 1a2eb2dc Michael Hanselmann
  @staticmethod
360 1a2eb2dc Michael Hanselmann
  def _PrepareFails(path, cmd):
361 1a2eb2dc Michael Hanselmann
    assert cmd == "test29327"
362 1a2eb2dc Michael Hanselmann
    return ("some error message", None)
363 1a2eb2dc Michael Hanselmann
364 1a2eb2dc Michael Hanselmann
  def testPrepareFails(self):
365 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
366 1a2eb2dc Michael Hanselmann
367 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
368 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._PrepareFails)
369 1a2eb2dc Michael Hanselmann
370 1a2eb2dc Michael Hanselmann
    try:
371 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test29327",
372 1a2eb2dc Michael Hanselmann
                               _lock_timeout=1.0, _lock_file=lockfile,
373 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented, _runcmd_fn=NotImplemented,
374 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn, _prepare_fn=prepare_fn,
375 1a2eb2dc Michael Hanselmann
                               _enabled=True)
376 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
377 405bffe2 Michael Hanselmann
      self.assertEqual(str(err), _GenericRestrictedCmdError("test29327"))
378 1a2eb2dc Michael Hanselmann
    else:
379 1a2eb2dc Michael Hanselmann
      self.fail("Didn't fail")
380 1a2eb2dc Michael Hanselmann
381 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 1)
382 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
383 1a2eb2dc Michael Hanselmann
384 1a2eb2dc Michael Hanselmann
  @staticmethod
385 1a2eb2dc Michael Hanselmann
  def _SuccessfulPrepare(path, cmd):
386 1a2eb2dc Michael Hanselmann
    return (True, utils.PathJoin(path, cmd))
387 1a2eb2dc Michael Hanselmann
388 1a2eb2dc Michael Hanselmann
  def testRunCmdFails(self):
389 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
390 1a2eb2dc Michael Hanselmann
391 1a2eb2dc Michael Hanselmann
    def fn(args, env=NotImplemented, reset_env=NotImplemented,
392 1a2eb2dc Michael Hanselmann
           postfork_fn=NotImplemented):
393 1a2eb2dc Michael Hanselmann
      self.assertEqual(args, [utils.PathJoin(self.tmpdir, "test3079")])
394 1a2eb2dc Michael Hanselmann
      self.assertEqual(env, {})
395 1a2eb2dc Michael Hanselmann
      self.assertTrue(reset_env)
396 1a2eb2dc Michael Hanselmann
      self.assertTrue(callable(postfork_fn))
397 1a2eb2dc Michael Hanselmann
398 1a2eb2dc Michael Hanselmann
      trylock = utils.FileLock.Open(lockfile)
399 1a2eb2dc Michael Hanselmann
      try:
400 1a2eb2dc Michael Hanselmann
        # See if lockfile is still held
401 1a2eb2dc Michael Hanselmann
        self.assertRaises(EnvironmentError, trylock.Exclusive, blocking=False)
402 1a2eb2dc Michael Hanselmann
403 1a2eb2dc Michael Hanselmann
        # Call back to release lock
404 1a2eb2dc Michael Hanselmann
        postfork_fn(NotImplemented)
405 1a2eb2dc Michael Hanselmann
406 1a2eb2dc Michael Hanselmann
        # See if lockfile can be acquired
407 1a2eb2dc Michael Hanselmann
        trylock.Exclusive(blocking=False)
408 1a2eb2dc Michael Hanselmann
      finally:
409 1a2eb2dc Michael Hanselmann
        trylock.Close()
410 1a2eb2dc Michael Hanselmann
411 1a2eb2dc Michael Hanselmann
      # Simulate a failed command
412 1a2eb2dc Michael Hanselmann
      return utils.RunResult(constants.EXIT_FAILURE, None,
413 1a2eb2dc Michael Hanselmann
                             "stdout", "stderr406328567",
414 1a2eb2dc Michael Hanselmann
                             utils.ShellQuoteArgs(args),
415 1a2eb2dc Michael Hanselmann
                             NotImplemented, NotImplemented)
416 1a2eb2dc Michael Hanselmann
417 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
418 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._SuccessfulPrepare)
419 1a2eb2dc Michael Hanselmann
    runcmd_fn = testutils.CallCounter(fn)
420 1a2eb2dc Michael Hanselmann
421 1a2eb2dc Michael Hanselmann
    try:
422 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test3079",
423 1a2eb2dc Michael Hanselmann
                               _lock_timeout=1.0, _lock_file=lockfile,
424 1a2eb2dc Michael Hanselmann
                               _path=self.tmpdir, _runcmd_fn=runcmd_fn,
425 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn, _prepare_fn=prepare_fn,
426 1a2eb2dc Michael Hanselmann
                               _enabled=True)
427 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
428 45bc4635 Iustin Pop
      self.assertTrue(str(err).startswith("Restricted command 'test3079'"
429 45bc4635 Iustin Pop
                                          " failed:"))
430 1a2eb2dc Michael Hanselmann
      self.assertTrue("stderr406328567" in str(err),
431 1a2eb2dc Michael Hanselmann
                      msg="Error did not include output")
432 1a2eb2dc Michael Hanselmann
    else:
433 1a2eb2dc Michael Hanselmann
      self.fail("Didn't fail")
434 1a2eb2dc Michael Hanselmann
435 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 0)
436 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
437 1a2eb2dc Michael Hanselmann
    self.assertEqual(runcmd_fn.Count(), 1)
438 1a2eb2dc Michael Hanselmann
439 1a2eb2dc Michael Hanselmann
  def testRunCmdSucceeds(self):
440 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
441 1a2eb2dc Michael Hanselmann
442 1a2eb2dc Michael Hanselmann
    def fn(args, env=NotImplemented, reset_env=NotImplemented,
443 1a2eb2dc Michael Hanselmann
           postfork_fn=NotImplemented):
444 1a2eb2dc Michael Hanselmann
      self.assertEqual(args, [utils.PathJoin(self.tmpdir, "test5667")])
445 1a2eb2dc Michael Hanselmann
      self.assertEqual(env, {})
446 1a2eb2dc Michael Hanselmann
      self.assertTrue(reset_env)
447 1a2eb2dc Michael Hanselmann
448 1a2eb2dc Michael Hanselmann
      # Call back to release lock
449 1a2eb2dc Michael Hanselmann
      postfork_fn(NotImplemented)
450 1a2eb2dc Michael Hanselmann
451 1a2eb2dc Michael Hanselmann
      # Simulate a successful command
452 1a2eb2dc Michael Hanselmann
      return utils.RunResult(constants.EXIT_SUCCESS, None, "stdout14463", "",
453 1a2eb2dc Michael Hanselmann
                             utils.ShellQuoteArgs(args),
454 1a2eb2dc Michael Hanselmann
                             NotImplemented, NotImplemented)
455 1a2eb2dc Michael Hanselmann
456 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
457 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._SuccessfulPrepare)
458 1a2eb2dc Michael Hanselmann
    runcmd_fn = testutils.CallCounter(fn)
459 1a2eb2dc Michael Hanselmann
460 42bd26e8 Michael Hanselmann
    result = backend.RunRestrictedCmd("test5667",
461 1a2eb2dc Michael Hanselmann
                                      _lock_timeout=1.0, _lock_file=lockfile,
462 1a2eb2dc Michael Hanselmann
                                      _path=self.tmpdir, _runcmd_fn=runcmd_fn,
463 1a2eb2dc Michael Hanselmann
                                      _sleep_fn=sleep_fn,
464 1a2eb2dc Michael Hanselmann
                                      _prepare_fn=prepare_fn,
465 1a2eb2dc Michael Hanselmann
                                      _enabled=True)
466 1a2eb2dc Michael Hanselmann
    self.assertEqual(result, "stdout14463")
467 1a2eb2dc Michael Hanselmann
468 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 0)
469 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
470 1a2eb2dc Michael Hanselmann
    self.assertEqual(runcmd_fn.Count(), 1)
471 1a2eb2dc Michael Hanselmann
472 1a2eb2dc Michael Hanselmann
  def testCommandsDisabled(self):
473 1a2eb2dc Michael Hanselmann
    try:
474 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test",
475 1a2eb2dc Michael Hanselmann
                               _lock_timeout=NotImplemented,
476 1a2eb2dc Michael Hanselmann
                               _lock_file=NotImplemented,
477 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented,
478 1a2eb2dc Michael Hanselmann
                               _sleep_fn=NotImplemented,
479 1a2eb2dc Michael Hanselmann
                               _prepare_fn=NotImplemented,
480 1a2eb2dc Michael Hanselmann
                               _runcmd_fn=NotImplemented,
481 1a2eb2dc Michael Hanselmann
                               _enabled=False)
482 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
483 45bc4635 Iustin Pop
      self.assertEqual(str(err),
484 45bc4635 Iustin Pop
                       "Restricted commands disabled at configure time")
485 1a2eb2dc Michael Hanselmann
    else:
486 1a2eb2dc Michael Hanselmann
      self.fail("Did not raise exception")
487 1a2eb2dc Michael Hanselmann
488 1a2eb2dc Michael Hanselmann
489 99e222b1 Michael Hanselmann
class TestSetWatcherPause(unittest.TestCase):
490 99e222b1 Michael Hanselmann
  def setUp(self):
491 99e222b1 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
492 99e222b1 Michael Hanselmann
    self.filename = utils.PathJoin(self.tmpdir, "pause")
493 99e222b1 Michael Hanselmann
494 99e222b1 Michael Hanselmann
  def tearDown(self):
495 99e222b1 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
496 99e222b1 Michael Hanselmann
497 99e222b1 Michael Hanselmann
  def testUnsetNonExisting(self):
498 99e222b1 Michael Hanselmann
    self.assertFalse(os.path.exists(self.filename))
499 99e222b1 Michael Hanselmann
    backend.SetWatcherPause(None, _filename=self.filename)
500 99e222b1 Michael Hanselmann
    self.assertFalse(os.path.exists(self.filename))
501 99e222b1 Michael Hanselmann
502 99e222b1 Michael Hanselmann
  def testSetNonNumeric(self):
503 99e222b1 Michael Hanselmann
    for i in ["", [], {}, "Hello World", "0", "1.0"]:
504 99e222b1 Michael Hanselmann
      self.assertFalse(os.path.exists(self.filename))
505 99e222b1 Michael Hanselmann
506 99e222b1 Michael Hanselmann
      try:
507 99e222b1 Michael Hanselmann
        backend.SetWatcherPause(i, _filename=self.filename)
508 99e222b1 Michael Hanselmann
      except backend.RPCFail, err:
509 99e222b1 Michael Hanselmann
        self.assertEqual(str(err), "Duration must be numeric")
510 99e222b1 Michael Hanselmann
      else:
511 99e222b1 Michael Hanselmann
        self.fail("Did not raise exception")
512 99e222b1 Michael Hanselmann
513 99e222b1 Michael Hanselmann
      self.assertFalse(os.path.exists(self.filename))
514 99e222b1 Michael Hanselmann
515 99e222b1 Michael Hanselmann
  def testSet(self):
516 99e222b1 Michael Hanselmann
    self.assertFalse(os.path.exists(self.filename))
517 99e222b1 Michael Hanselmann
518 99e222b1 Michael Hanselmann
    for i in range(10):
519 99e222b1 Michael Hanselmann
      backend.SetWatcherPause(i, _filename=self.filename)
520 99e222b1 Michael Hanselmann
      self.assertEqual(utils.ReadFile(self.filename), "%s\n" % i)
521 99e222b1 Michael Hanselmann
      self.assertEqual(os.stat(self.filename).st_mode & 0777, 0644)
522 99e222b1 Michael Hanselmann
523 99e222b1 Michael Hanselmann
524 3b721842 Michael Hanselmann
class TestGetBlockDevSymlinkPath(unittest.TestCase):
525 3b721842 Michael Hanselmann
  def setUp(self):
526 3b721842 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
527 3b721842 Michael Hanselmann
528 3b721842 Michael Hanselmann
  def tearDown(self):
529 3b721842 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
530 3b721842 Michael Hanselmann
531 3b721842 Michael Hanselmann
  def _Test(self, name, idx):
532 3b721842 Michael Hanselmann
    self.assertEqual(backend._GetBlockDevSymlinkPath(name, idx,
533 3b721842 Michael Hanselmann
                                                     _dir=self.tmpdir),
534 3b721842 Michael Hanselmann
                     ("%s/%s%s%s" % (self.tmpdir, name,
535 3b721842 Michael Hanselmann
                                     constants.DISK_SEPARATOR, idx)))
536 3b721842 Michael Hanselmann
537 3b721842 Michael Hanselmann
  def test(self):
538 3b721842 Michael Hanselmann
    for idx in range(100):
539 3b721842 Michael Hanselmann
      self._Test("inst1.example.com", idx)
540 3b721842 Michael Hanselmann
541 3b721842 Michael Hanselmann
542 f942a838 Michael Hanselmann
if __name__ == "__main__":
543 f942a838 Michael Hanselmann
  testutils.GanetiTestProgram()