Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.backend_unittest.py @ b544a3c2

History | View | Annotate | Download (29.9 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 b01b7a50 Helga Velroyen
import mock
25 f942a838 Michael Hanselmann
import os
26 f942a838 Michael Hanselmann
import shutil
27 f942a838 Michael Hanselmann
import tempfile
28 b01b7a50 Helga Velroyen
import testutils
29 f942a838 Michael Hanselmann
import unittest
30 f942a838 Michael Hanselmann
31 f942a838 Michael Hanselmann
from ganeti import backend
32 b01b7a50 Helga Velroyen
from ganeti import constants
33 b01b7a50 Helga Velroyen
from ganeti import errors
34 fac83f8a Helga Velroyen
from ganeti import hypervisor
35 b01b7a50 Helga Velroyen
from ganeti import netutils
36 b9e12624 Hrvoje Ribicic
from ganeti import objects
37 b01b7a50 Helga Velroyen
from ganeti import utils
38 f942a838 Michael Hanselmann
39 f942a838 Michael Hanselmann
40 f942a838 Michael Hanselmann
class TestX509Certificates(unittest.TestCase):
41 f942a838 Michael Hanselmann
  def setUp(self):
42 f942a838 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
43 f942a838 Michael Hanselmann
44 f942a838 Michael Hanselmann
  def tearDown(self):
45 f942a838 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
46 f942a838 Michael Hanselmann
47 f942a838 Michael Hanselmann
  def test(self):
48 f942a838 Michael Hanselmann
    (name, cert_pem) = backend.CreateX509Certificate(300, cryptodir=self.tmpdir)
49 f942a838 Michael Hanselmann
50 f942a838 Michael Hanselmann
    self.assertEqual(utils.ReadFile(os.path.join(self.tmpdir, name,
51 f942a838 Michael Hanselmann
                                                 backend._X509_CERT_FILE)),
52 f942a838 Michael Hanselmann
                     cert_pem)
53 f942a838 Michael Hanselmann
    self.assert_(0 < os.path.getsize(os.path.join(self.tmpdir, name,
54 f942a838 Michael Hanselmann
                                                  backend._X509_KEY_FILE)))
55 f942a838 Michael Hanselmann
56 f942a838 Michael Hanselmann
    (name2, cert_pem2) = \
57 f942a838 Michael Hanselmann
      backend.CreateX509Certificate(300, cryptodir=self.tmpdir)
58 f942a838 Michael Hanselmann
59 f942a838 Michael Hanselmann
    backend.RemoveX509Certificate(name, cryptodir=self.tmpdir)
60 f942a838 Michael Hanselmann
    backend.RemoveX509Certificate(name2, cryptodir=self.tmpdir)
61 f942a838 Michael Hanselmann
62 f942a838 Michael Hanselmann
    self.assertEqual(utils.ListVisibleFiles(self.tmpdir), [])
63 f942a838 Michael Hanselmann
64 f942a838 Michael Hanselmann
  def testNonEmpty(self):
65 f942a838 Michael Hanselmann
    (name, _) = backend.CreateX509Certificate(300, cryptodir=self.tmpdir)
66 f942a838 Michael Hanselmann
67 f942a838 Michael Hanselmann
    utils.WriteFile(utils.PathJoin(self.tmpdir, name, "hello-world"),
68 f942a838 Michael Hanselmann
                    data="Hello World")
69 f942a838 Michael Hanselmann
70 f942a838 Michael Hanselmann
    self.assertRaises(backend.RPCFail, backend.RemoveX509Certificate,
71 f942a838 Michael Hanselmann
                      name, cryptodir=self.tmpdir)
72 f942a838 Michael Hanselmann
73 f942a838 Michael Hanselmann
    self.assertEqual(utils.ListVisibleFiles(self.tmpdir), [name])
74 f942a838 Michael Hanselmann
75 f942a838 Michael Hanselmann
76 b544a3c2 Helga Velroyen
class TestGetCryptoTokens(testutils.GanetiTestCase):
77 b544a3c2 Helga Velroyen
78 b544a3c2 Helga Velroyen
  def setUp(self):
79 b544a3c2 Helga Velroyen
    self._digest_fn_orig = utils.GetClientCertificateDigest
80 b544a3c2 Helga Velroyen
    self._ssl_digest = "12345"
81 b544a3c2 Helga Velroyen
    utils.GetClientCertificateDigest = mock.Mock(
82 b544a3c2 Helga Velroyen
      return_value=self._ssl_digest)
83 b544a3c2 Helga Velroyen
84 b544a3c2 Helga Velroyen
  def tearDown(self):
85 b544a3c2 Helga Velroyen
    utils.GetClientCertificateDigest = self._digest_fn_orig
86 b544a3c2 Helga Velroyen
87 b544a3c2 Helga Velroyen
  def testSslToken(self):
88 b544a3c2 Helga Velroyen
    result = backend.GetCryptoTokens([constants.CRYPTO_TYPE_SSL_DIGEST])
89 b544a3c2 Helga Velroyen
    self.assertTrue((constants.CRYPTO_TYPE_SSL_DIGEST, self._ssl_digest)
90 b544a3c2 Helga Velroyen
                    in result)
91 b544a3c2 Helga Velroyen
92 b544a3c2 Helga Velroyen
  def testUnknownToken(self):
93 b544a3c2 Helga Velroyen
    self.assertRaises(errors.ProgrammerError,
94 b544a3c2 Helga Velroyen
                      backend.GetCryptoTokens, ["pink_bunny"])
95 b544a3c2 Helga Velroyen
96 b544a3c2 Helga Velroyen
97 a3a5f850 Iustin Pop
class TestNodeVerify(testutils.GanetiTestCase):
98 75bf3149 Helga Velroyen
99 75bf3149 Helga Velroyen
  def setUp(self):
100 75bf3149 Helga Velroyen
    testutils.GanetiTestCase.setUp(self)
101 75bf3149 Helga Velroyen
    self._mock_hv = None
102 75bf3149 Helga Velroyen
103 75bf3149 Helga Velroyen
  def _GetHypervisor(self, hv_name):
104 75bf3149 Helga Velroyen
    self._mock_hv = hypervisor.GetHypervisor(hv_name)
105 75bf3149 Helga Velroyen
    self._mock_hv.ValidateParameters = mock.Mock()
106 75bf3149 Helga Velroyen
    self._mock_hv.Verify = mock.Mock()
107 75bf3149 Helga Velroyen
    return self._mock_hv
108 75bf3149 Helga Velroyen
109 a3a5f850 Iustin Pop
  def testMasterIPLocalhost(self):
110 a3a5f850 Iustin Pop
    # this a real functional test, but requires localhost to be reachable
111 b705c7a6 Manuel Franceschini
    local_data = (netutils.Hostname.GetSysName(),
112 b705c7a6 Manuel Franceschini
                  constants.IP4_ADDRESS_LOCALHOST)
113 33ffda6c Petr Pudlak
    result = backend.VerifyNode({constants.NV_MASTERIP: local_data},
114 33ffda6c Petr Pudlak
                                None, {}, {}, {})
115 a3a5f850 Iustin Pop
    self.failUnless(constants.NV_MASTERIP in result,
116 a3a5f850 Iustin Pop
                    "Master IP data not returned")
117 a3a5f850 Iustin Pop
    self.failUnless(result[constants.NV_MASTERIP], "Cannot reach localhost")
118 a3a5f850 Iustin Pop
119 a3a5f850 Iustin Pop
  def testMasterIPUnreachable(self):
120 a3a5f850 Iustin Pop
    # Network 192.0.2.0/24 is reserved for test/documentation as per
121 926feaf1 Manuel Franceschini
    # RFC 5737
122 a3a5f850 Iustin Pop
    bad_data =  ("master.example.com", "192.0.2.1")
123 a3a5f850 Iustin Pop
    # we just test that whatever TcpPing returns, VerifyNode returns too
124 a744b676 Manuel Franceschini
    netutils.TcpPing = lambda a, b, source=None: False
125 33ffda6c Petr Pudlak
    result = backend.VerifyNode({constants.NV_MASTERIP: bad_data},
126 33ffda6c Petr Pudlak
                                None, {}, {}, {})
127 a3a5f850 Iustin Pop
    self.failUnless(constants.NV_MASTERIP in result,
128 a3a5f850 Iustin Pop
                    "Master IP data not returned")
129 a3a5f850 Iustin Pop
    self.failIf(result[constants.NV_MASTERIP],
130 a744b676 Manuel Franceschini
                "Result from netutils.TcpPing corrupted")
131 a3a5f850 Iustin Pop
132 75bf3149 Helga Velroyen
  def testVerifyHvparams(self):
133 75bf3149 Helga Velroyen
    test_hvparams = {constants.HV_XEN_CMD: constants.XEN_CMD_XL}
134 75bf3149 Helga Velroyen
    test_what = {constants.NV_HVPARAMS: \
135 75bf3149 Helga Velroyen
        [("mynode", constants.HT_XEN_PVM, test_hvparams)]}
136 75bf3149 Helga Velroyen
    result = {}
137 75bf3149 Helga Velroyen
    backend._VerifyHvparams(test_what, True, result,
138 75bf3149 Helga Velroyen
                            get_hv_fn=self._GetHypervisor)
139 75bf3149 Helga Velroyen
    self._mock_hv.ValidateParameters.assert_called_with(test_hvparams)
140 75bf3149 Helga Velroyen
141 75bf3149 Helga Velroyen
  def testVerifyHypervisors(self):
142 75bf3149 Helga Velroyen
    hvname = constants.HT_XEN_PVM
143 75bf3149 Helga Velroyen
    hvparams = {constants.HV_XEN_CMD: constants.XEN_CMD_XL}
144 75bf3149 Helga Velroyen
    all_hvparams = {hvname: hvparams}
145 75bf3149 Helga Velroyen
    test_what = {constants.NV_HYPERVISOR: [hvname]}
146 75bf3149 Helga Velroyen
    result = {}
147 75bf3149 Helga Velroyen
    backend._VerifyHypervisors(
148 75bf3149 Helga Velroyen
        test_what, True, result, all_hvparams=all_hvparams,
149 75bf3149 Helga Velroyen
        get_hv_fn=self._GetHypervisor)
150 75bf3149 Helga Velroyen
    self._mock_hv.Verify.assert_called_with(hvparams=hvparams)
151 75bf3149 Helga Velroyen
152 a3a5f850 Iustin Pop
153 405bffe2 Michael Hanselmann
def _DefRestrictedCmdOwner():
154 1a2eb2dc Michael Hanselmann
  return (os.getuid(), os.getgid())
155 1a2eb2dc Michael Hanselmann
156 1a2eb2dc Michael Hanselmann
157 405bffe2 Michael Hanselmann
class TestVerifyRestrictedCmdName(unittest.TestCase):
158 1a2eb2dc Michael Hanselmann
  def testAcceptableName(self):
159 1a2eb2dc Michael Hanselmann
    for i in ["foo", "bar", "z1", "000first", "hello-world"]:
160 1a2eb2dc Michael Hanselmann
      for fn in [lambda s: s, lambda s: s.upper(), lambda s: s.title()]:
161 405bffe2 Michael Hanselmann
        (status, msg) = backend._VerifyRestrictedCmdName(fn(i))
162 1a2eb2dc Michael Hanselmann
        self.assertTrue(status)
163 1a2eb2dc Michael Hanselmann
        self.assertTrue(msg is None)
164 1a2eb2dc Michael Hanselmann
165 1a2eb2dc Michael Hanselmann
  def testEmptyAndSpace(self):
166 1a2eb2dc Michael Hanselmann
    for i in ["", " ", "\t", "\n"]:
167 405bffe2 Michael Hanselmann
      (status, msg) = backend._VerifyRestrictedCmdName(i)
168 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
169 1a2eb2dc Michael Hanselmann
      self.assertEqual(msg, "Missing command name")
170 1a2eb2dc Michael Hanselmann
171 1a2eb2dc Michael Hanselmann
  def testNameWithSlashes(self):
172 1a2eb2dc Michael Hanselmann
    for i in ["/", "./foo", "../moo", "some/name"]:
173 405bffe2 Michael Hanselmann
      (status, msg) = backend._VerifyRestrictedCmdName(i)
174 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
175 1a2eb2dc Michael Hanselmann
      self.assertEqual(msg, "Invalid command name")
176 1a2eb2dc Michael Hanselmann
177 1a2eb2dc Michael Hanselmann
  def testForbiddenCharacters(self):
178 1a2eb2dc Michael Hanselmann
    for i in ["#", ".", "..", "bash -c ls", "'"]:
179 405bffe2 Michael Hanselmann
      (status, msg) = backend._VerifyRestrictedCmdName(i)
180 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
181 1a2eb2dc Michael Hanselmann
      self.assertEqual(msg, "Command name contains forbidden characters")
182 1a2eb2dc Michael Hanselmann
183 1a2eb2dc Michael Hanselmann
184 405bffe2 Michael Hanselmann
class TestVerifyRestrictedCmdDirectory(unittest.TestCase):
185 1a2eb2dc Michael Hanselmann
  def setUp(self):
186 1a2eb2dc Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
187 1a2eb2dc Michael Hanselmann
188 1a2eb2dc Michael Hanselmann
  def tearDown(self):
189 1a2eb2dc Michael Hanselmann
    shutil.rmtree(self.tmpdir)
190 1a2eb2dc Michael Hanselmann
191 1a2eb2dc Michael Hanselmann
  def testCanNotStat(self):
192 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
193 1a2eb2dc Michael Hanselmann
    self.assertFalse(os.path.exists(tmpname))
194 1a2eb2dc Michael Hanselmann
    (status, msg) = \
195 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmdDirectory(tmpname, _owner=NotImplemented)
196 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
197 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.startswith("Can't stat(2) '"))
198 1a2eb2dc Michael Hanselmann
199 1a2eb2dc Michael Hanselmann
  def testTooPermissive(self):
200 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
201 1a2eb2dc Michael Hanselmann
    os.mkdir(tmpname)
202 1a2eb2dc Michael Hanselmann
203 1a2eb2dc Michael Hanselmann
    for mode in [0777, 0706, 0760, 0722]:
204 1a2eb2dc Michael Hanselmann
      os.chmod(tmpname, mode)
205 1a2eb2dc Michael Hanselmann
      self.assertTrue(os.path.isdir(tmpname))
206 1a2eb2dc Michael Hanselmann
      (status, msg) = \
207 405bffe2 Michael Hanselmann
        backend._VerifyRestrictedCmdDirectory(tmpname, _owner=NotImplemented)
208 1a2eb2dc Michael Hanselmann
      self.assertFalse(status)
209 1a2eb2dc Michael Hanselmann
      self.assertTrue(msg.startswith("Permissions on '"))
210 1a2eb2dc Michael Hanselmann
211 1a2eb2dc Michael Hanselmann
  def testNoDirectory(self):
212 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
213 1a2eb2dc Michael Hanselmann
    utils.WriteFile(tmpname, data="empty\n")
214 1a2eb2dc Michael Hanselmann
    self.assertTrue(os.path.isfile(tmpname))
215 1a2eb2dc Michael Hanselmann
    (status, msg) = \
216 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmdDirectory(tmpname,
217 405bffe2 Michael Hanselmann
                                            _owner=_DefRestrictedCmdOwner())
218 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
219 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.endswith("is not a directory"))
220 1a2eb2dc Michael Hanselmann
221 1a2eb2dc Michael Hanselmann
  def testNormal(self):
222 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "foobar")
223 1a2eb2dc Michael Hanselmann
    os.mkdir(tmpname)
224 24cd672e Apollon Oikonomopoulos
    os.chmod(tmpname, 0755)
225 1a2eb2dc Michael Hanselmann
    self.assertTrue(os.path.isdir(tmpname))
226 1a2eb2dc Michael Hanselmann
    (status, msg) = \
227 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmdDirectory(tmpname,
228 405bffe2 Michael Hanselmann
                                            _owner=_DefRestrictedCmdOwner())
229 1a2eb2dc Michael Hanselmann
    self.assertTrue(status)
230 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg is None)
231 1a2eb2dc Michael Hanselmann
232 1a2eb2dc Michael Hanselmann
233 405bffe2 Michael Hanselmann
class TestVerifyRestrictedCmd(unittest.TestCase):
234 1a2eb2dc Michael Hanselmann
  def setUp(self):
235 1a2eb2dc Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
236 1a2eb2dc Michael Hanselmann
237 1a2eb2dc Michael Hanselmann
  def tearDown(self):
238 1a2eb2dc Michael Hanselmann
    shutil.rmtree(self.tmpdir)
239 1a2eb2dc Michael Hanselmann
240 1a2eb2dc Michael Hanselmann
  def testCanNotStat(self):
241 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "helloworld")
242 1a2eb2dc Michael Hanselmann
    self.assertFalse(os.path.exists(tmpname))
243 1a2eb2dc Michael Hanselmann
    (status, msg) = \
244 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmd(self.tmpdir, "helloworld",
245 1a2eb2dc Michael Hanselmann
                                   _owner=NotImplemented)
246 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
247 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.startswith("Can't stat(2) '"))
248 1a2eb2dc Michael Hanselmann
249 1a2eb2dc Michael Hanselmann
  def testNotExecutable(self):
250 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "cmdname")
251 1a2eb2dc Michael Hanselmann
    utils.WriteFile(tmpname, data="empty\n")
252 1a2eb2dc Michael Hanselmann
    (status, msg) = \
253 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmd(self.tmpdir, "cmdname",
254 405bffe2 Michael Hanselmann
                                   _owner=_DefRestrictedCmdOwner())
255 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
256 1a2eb2dc Michael Hanselmann
    self.assertTrue(msg.startswith("access(2) thinks '"))
257 1a2eb2dc Michael Hanselmann
258 1a2eb2dc Michael Hanselmann
  def testExecutable(self):
259 1a2eb2dc Michael Hanselmann
    tmpname = utils.PathJoin(self.tmpdir, "cmdname")
260 1a2eb2dc Michael Hanselmann
    utils.WriteFile(tmpname, data="empty\n", mode=0700)
261 1a2eb2dc Michael Hanselmann
    (status, executable) = \
262 405bffe2 Michael Hanselmann
      backend._VerifyRestrictedCmd(self.tmpdir, "cmdname",
263 405bffe2 Michael Hanselmann
                                   _owner=_DefRestrictedCmdOwner())
264 1a2eb2dc Michael Hanselmann
    self.assertTrue(status)
265 1a2eb2dc Michael Hanselmann
    self.assertEqual(executable, tmpname)
266 1a2eb2dc Michael Hanselmann
267 1a2eb2dc Michael Hanselmann
268 405bffe2 Michael Hanselmann
class TestPrepareRestrictedCmd(unittest.TestCase):
269 1a2eb2dc Michael Hanselmann
  _TEST_PATH = "/tmp/some/test/path"
270 1a2eb2dc Michael Hanselmann
271 1a2eb2dc Michael Hanselmann
  def testDirFails(self):
272 1a2eb2dc Michael Hanselmann
    def fn(path):
273 1a2eb2dc Michael Hanselmann
      self.assertEqual(path, self._TEST_PATH)
274 1a2eb2dc Michael Hanselmann
      return (False, "test error 31420")
275 1a2eb2dc Michael Hanselmann
276 1a2eb2dc Michael Hanselmann
    (status, msg) = \
277 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd21152",
278 1a2eb2dc Michael Hanselmann
                                    _verify_dir=fn,
279 1a2eb2dc Michael Hanselmann
                                    _verify_name=NotImplemented,
280 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=NotImplemented)
281 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
282 1a2eb2dc Michael Hanselmann
    self.assertEqual(msg, "test error 31420")
283 1a2eb2dc Michael Hanselmann
284 1a2eb2dc Michael Hanselmann
  def testNameFails(self):
285 1a2eb2dc Michael Hanselmann
    def fn(cmd):
286 1a2eb2dc Michael Hanselmann
      self.assertEqual(cmd, "cmd4617")
287 1a2eb2dc Michael Hanselmann
      return (False, "test error 591")
288 1a2eb2dc Michael Hanselmann
289 1a2eb2dc Michael Hanselmann
    (status, msg) = \
290 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd4617",
291 1a2eb2dc Michael Hanselmann
                                    _verify_dir=lambda _: (True, None),
292 1a2eb2dc Michael Hanselmann
                                    _verify_name=fn,
293 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=NotImplemented)
294 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
295 1a2eb2dc Michael Hanselmann
    self.assertEqual(msg, "test error 591")
296 1a2eb2dc Michael Hanselmann
297 1a2eb2dc Michael Hanselmann
  def testCommandFails(self):
298 1a2eb2dc Michael Hanselmann
    def fn(path, cmd):
299 1a2eb2dc Michael Hanselmann
      self.assertEqual(path, self._TEST_PATH)
300 1a2eb2dc Michael Hanselmann
      self.assertEqual(cmd, "cmd17577")
301 1a2eb2dc Michael Hanselmann
      return (False, "test error 25524")
302 1a2eb2dc Michael Hanselmann
303 1a2eb2dc Michael Hanselmann
    (status, msg) = \
304 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd17577",
305 1a2eb2dc Michael Hanselmann
                                    _verify_dir=lambda _: (True, None),
306 1a2eb2dc Michael Hanselmann
                                    _verify_name=lambda _: (True, None),
307 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=fn)
308 1a2eb2dc Michael Hanselmann
    self.assertFalse(status)
309 1a2eb2dc Michael Hanselmann
    self.assertEqual(msg, "test error 25524")
310 1a2eb2dc Michael Hanselmann
311 1a2eb2dc Michael Hanselmann
  def testSuccess(self):
312 1a2eb2dc Michael Hanselmann
    def fn(path, cmd):
313 1a2eb2dc Michael Hanselmann
      return (True, utils.PathJoin(path, cmd))
314 1a2eb2dc Michael Hanselmann
315 1a2eb2dc Michael Hanselmann
    (status, executable) = \
316 405bffe2 Michael Hanselmann
      backend._PrepareRestrictedCmd(self._TEST_PATH, "cmd22633",
317 1a2eb2dc Michael Hanselmann
                                    _verify_dir=lambda _: (True, None),
318 1a2eb2dc Michael Hanselmann
                                    _verify_name=lambda _: (True, None),
319 1a2eb2dc Michael Hanselmann
                                    _verify_cmd=fn)
320 1a2eb2dc Michael Hanselmann
    self.assertTrue(status)
321 1a2eb2dc Michael Hanselmann
    self.assertEqual(executable, utils.PathJoin(self._TEST_PATH, "cmd22633"))
322 1a2eb2dc Michael Hanselmann
323 1a2eb2dc Michael Hanselmann
324 405bffe2 Michael Hanselmann
def _SleepForRestrictedCmd(duration):
325 1a2eb2dc Michael Hanselmann
  assert duration > 5
326 1a2eb2dc Michael Hanselmann
327 1a2eb2dc Michael Hanselmann
328 405bffe2 Michael Hanselmann
def _GenericRestrictedCmdError(cmd):
329 1a2eb2dc Michael Hanselmann
  return "Executing command '%s' failed" % cmd
330 1a2eb2dc Michael Hanselmann
331 1a2eb2dc Michael Hanselmann
332 42bd26e8 Michael Hanselmann
class TestRunRestrictedCmd(unittest.TestCase):
333 1a2eb2dc Michael Hanselmann
  def setUp(self):
334 1a2eb2dc Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
335 1a2eb2dc Michael Hanselmann
336 1a2eb2dc Michael Hanselmann
  def tearDown(self):
337 1a2eb2dc Michael Hanselmann
    shutil.rmtree(self.tmpdir)
338 1a2eb2dc Michael Hanselmann
339 1a2eb2dc Michael Hanselmann
  def testNonExistantLockDirectory(self):
340 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "does", "not", "exist")
341 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
342 1a2eb2dc Michael Hanselmann
    self.assertFalse(os.path.exists(lockfile))
343 1a2eb2dc Michael Hanselmann
    self.assertRaises(backend.RPCFail,
344 42bd26e8 Michael Hanselmann
                      backend.RunRestrictedCmd, "test",
345 1a2eb2dc Michael Hanselmann
                      _lock_timeout=NotImplemented,
346 1a2eb2dc Michael Hanselmann
                      _lock_file=lockfile,
347 1a2eb2dc Michael Hanselmann
                      _path=NotImplemented,
348 1a2eb2dc Michael Hanselmann
                      _sleep_fn=sleep_fn,
349 1a2eb2dc Michael Hanselmann
                      _prepare_fn=NotImplemented,
350 1a2eb2dc Michael Hanselmann
                      _runcmd_fn=NotImplemented,
351 1a2eb2dc Michael Hanselmann
                      _enabled=True)
352 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 1)
353 1a2eb2dc Michael Hanselmann
354 1a2eb2dc Michael Hanselmann
  @staticmethod
355 1a2eb2dc Michael Hanselmann
  def _TryLock(lockfile):
356 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
357 1a2eb2dc Michael Hanselmann
358 1a2eb2dc Michael Hanselmann
    result = False
359 1a2eb2dc Michael Hanselmann
    try:
360 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test22717",
361 1a2eb2dc Michael Hanselmann
                               _lock_timeout=0.1,
362 1a2eb2dc Michael Hanselmann
                               _lock_file=lockfile,
363 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented,
364 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn,
365 1a2eb2dc Michael Hanselmann
                               _prepare_fn=NotImplemented,
366 1a2eb2dc Michael Hanselmann
                               _runcmd_fn=NotImplemented,
367 1a2eb2dc Michael Hanselmann
                               _enabled=True)
368 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
369 405bffe2 Michael Hanselmann
      assert str(err) == _GenericRestrictedCmdError("test22717"), \
370 1a2eb2dc Michael Hanselmann
             "Did not fail with generic error message"
371 1a2eb2dc Michael Hanselmann
      result = True
372 1a2eb2dc Michael Hanselmann
373 1a2eb2dc Michael Hanselmann
    assert sleep_fn.Count() == 1
374 1a2eb2dc Michael Hanselmann
375 1a2eb2dc Michael Hanselmann
    return result
376 1a2eb2dc Michael Hanselmann
377 1a2eb2dc Michael Hanselmann
  def testLockHeldByOtherProcess(self):
378 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
379 1a2eb2dc Michael Hanselmann
380 1a2eb2dc Michael Hanselmann
    lock = utils.FileLock.Open(lockfile)
381 1a2eb2dc Michael Hanselmann
    lock.Exclusive(blocking=True, timeout=1.0)
382 1a2eb2dc Michael Hanselmann
    try:
383 1a2eb2dc Michael Hanselmann
      self.assertTrue(utils.RunInSeparateProcess(self._TryLock, lockfile))
384 1a2eb2dc Michael Hanselmann
    finally:
385 1a2eb2dc Michael Hanselmann
      lock.Close()
386 1a2eb2dc Michael Hanselmann
387 1a2eb2dc Michael Hanselmann
  @staticmethod
388 1a2eb2dc Michael Hanselmann
  def _PrepareRaisingException(path, cmd):
389 1a2eb2dc Michael Hanselmann
    assert cmd == "test23122"
390 1a2eb2dc Michael Hanselmann
    raise Exception("test")
391 1a2eb2dc Michael Hanselmann
392 1a2eb2dc Michael Hanselmann
  def testPrepareRaisesException(self):
393 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
394 1a2eb2dc Michael Hanselmann
395 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
396 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._PrepareRaisingException)
397 1a2eb2dc Michael Hanselmann
398 1a2eb2dc Michael Hanselmann
    try:
399 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test23122",
400 1a2eb2dc Michael Hanselmann
                               _lock_timeout=1.0, _lock_file=lockfile,
401 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented, _runcmd_fn=NotImplemented,
402 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn, _prepare_fn=prepare_fn,
403 1a2eb2dc Michael Hanselmann
                               _enabled=True)
404 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
405 405bffe2 Michael Hanselmann
      self.assertEqual(str(err), _GenericRestrictedCmdError("test23122"))
406 1a2eb2dc Michael Hanselmann
    else:
407 1a2eb2dc Michael Hanselmann
      self.fail("Didn't fail")
408 1a2eb2dc Michael Hanselmann
409 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 1)
410 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
411 1a2eb2dc Michael Hanselmann
412 1a2eb2dc Michael Hanselmann
  @staticmethod
413 1a2eb2dc Michael Hanselmann
  def _PrepareFails(path, cmd):
414 1a2eb2dc Michael Hanselmann
    assert cmd == "test29327"
415 1a2eb2dc Michael Hanselmann
    return ("some error message", None)
416 1a2eb2dc Michael Hanselmann
417 1a2eb2dc Michael Hanselmann
  def testPrepareFails(self):
418 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
419 1a2eb2dc Michael Hanselmann
420 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
421 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._PrepareFails)
422 1a2eb2dc Michael Hanselmann
423 1a2eb2dc Michael Hanselmann
    try:
424 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test29327",
425 1a2eb2dc Michael Hanselmann
                               _lock_timeout=1.0, _lock_file=lockfile,
426 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented, _runcmd_fn=NotImplemented,
427 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn, _prepare_fn=prepare_fn,
428 1a2eb2dc Michael Hanselmann
                               _enabled=True)
429 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
430 405bffe2 Michael Hanselmann
      self.assertEqual(str(err), _GenericRestrictedCmdError("test29327"))
431 1a2eb2dc Michael Hanselmann
    else:
432 1a2eb2dc Michael Hanselmann
      self.fail("Didn't fail")
433 1a2eb2dc Michael Hanselmann
434 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 1)
435 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
436 1a2eb2dc Michael Hanselmann
437 1a2eb2dc Michael Hanselmann
  @staticmethod
438 1a2eb2dc Michael Hanselmann
  def _SuccessfulPrepare(path, cmd):
439 1a2eb2dc Michael Hanselmann
    return (True, utils.PathJoin(path, cmd))
440 1a2eb2dc Michael Hanselmann
441 1a2eb2dc Michael Hanselmann
  def testRunCmdFails(self):
442 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
443 1a2eb2dc Michael Hanselmann
444 1a2eb2dc Michael Hanselmann
    def fn(args, env=NotImplemented, reset_env=NotImplemented,
445 1a2eb2dc Michael Hanselmann
           postfork_fn=NotImplemented):
446 1a2eb2dc Michael Hanselmann
      self.assertEqual(args, [utils.PathJoin(self.tmpdir, "test3079")])
447 1a2eb2dc Michael Hanselmann
      self.assertEqual(env, {})
448 1a2eb2dc Michael Hanselmann
      self.assertTrue(reset_env)
449 1a2eb2dc Michael Hanselmann
      self.assertTrue(callable(postfork_fn))
450 1a2eb2dc Michael Hanselmann
451 1a2eb2dc Michael Hanselmann
      trylock = utils.FileLock.Open(lockfile)
452 1a2eb2dc Michael Hanselmann
      try:
453 1a2eb2dc Michael Hanselmann
        # See if lockfile is still held
454 1a2eb2dc Michael Hanselmann
        self.assertRaises(EnvironmentError, trylock.Exclusive, blocking=False)
455 1a2eb2dc Michael Hanselmann
456 1a2eb2dc Michael Hanselmann
        # Call back to release lock
457 1a2eb2dc Michael Hanselmann
        postfork_fn(NotImplemented)
458 1a2eb2dc Michael Hanselmann
459 1a2eb2dc Michael Hanselmann
        # See if lockfile can be acquired
460 1a2eb2dc Michael Hanselmann
        trylock.Exclusive(blocking=False)
461 1a2eb2dc Michael Hanselmann
      finally:
462 1a2eb2dc Michael Hanselmann
        trylock.Close()
463 1a2eb2dc Michael Hanselmann
464 1a2eb2dc Michael Hanselmann
      # Simulate a failed command
465 1a2eb2dc Michael Hanselmann
      return utils.RunResult(constants.EXIT_FAILURE, None,
466 1a2eb2dc Michael Hanselmann
                             "stdout", "stderr406328567",
467 1a2eb2dc Michael Hanselmann
                             utils.ShellQuoteArgs(args),
468 1a2eb2dc Michael Hanselmann
                             NotImplemented, NotImplemented)
469 1a2eb2dc Michael Hanselmann
470 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
471 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._SuccessfulPrepare)
472 1a2eb2dc Michael Hanselmann
    runcmd_fn = testutils.CallCounter(fn)
473 1a2eb2dc Michael Hanselmann
474 1a2eb2dc Michael Hanselmann
    try:
475 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test3079",
476 1a2eb2dc Michael Hanselmann
                               _lock_timeout=1.0, _lock_file=lockfile,
477 1a2eb2dc Michael Hanselmann
                               _path=self.tmpdir, _runcmd_fn=runcmd_fn,
478 1a2eb2dc Michael Hanselmann
                               _sleep_fn=sleep_fn, _prepare_fn=prepare_fn,
479 1a2eb2dc Michael Hanselmann
                               _enabled=True)
480 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
481 45bc4635 Iustin Pop
      self.assertTrue(str(err).startswith("Restricted command 'test3079'"
482 45bc4635 Iustin Pop
                                          " failed:"))
483 1a2eb2dc Michael Hanselmann
      self.assertTrue("stderr406328567" in str(err),
484 1a2eb2dc Michael Hanselmann
                      msg="Error did not include output")
485 1a2eb2dc Michael Hanselmann
    else:
486 1a2eb2dc Michael Hanselmann
      self.fail("Didn't fail")
487 1a2eb2dc Michael Hanselmann
488 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 0)
489 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
490 1a2eb2dc Michael Hanselmann
    self.assertEqual(runcmd_fn.Count(), 1)
491 1a2eb2dc Michael Hanselmann
492 1a2eb2dc Michael Hanselmann
  def testRunCmdSucceeds(self):
493 1a2eb2dc Michael Hanselmann
    lockfile = utils.PathJoin(self.tmpdir, "lock")
494 1a2eb2dc Michael Hanselmann
495 1a2eb2dc Michael Hanselmann
    def fn(args, env=NotImplemented, reset_env=NotImplemented,
496 1a2eb2dc Michael Hanselmann
           postfork_fn=NotImplemented):
497 1a2eb2dc Michael Hanselmann
      self.assertEqual(args, [utils.PathJoin(self.tmpdir, "test5667")])
498 1a2eb2dc Michael Hanselmann
      self.assertEqual(env, {})
499 1a2eb2dc Michael Hanselmann
      self.assertTrue(reset_env)
500 1a2eb2dc Michael Hanselmann
501 1a2eb2dc Michael Hanselmann
      # Call back to release lock
502 1a2eb2dc Michael Hanselmann
      postfork_fn(NotImplemented)
503 1a2eb2dc Michael Hanselmann
504 1a2eb2dc Michael Hanselmann
      # Simulate a successful command
505 1a2eb2dc Michael Hanselmann
      return utils.RunResult(constants.EXIT_SUCCESS, None, "stdout14463", "",
506 1a2eb2dc Michael Hanselmann
                             utils.ShellQuoteArgs(args),
507 1a2eb2dc Michael Hanselmann
                             NotImplemented, NotImplemented)
508 1a2eb2dc Michael Hanselmann
509 405bffe2 Michael Hanselmann
    sleep_fn = testutils.CallCounter(_SleepForRestrictedCmd)
510 1a2eb2dc Michael Hanselmann
    prepare_fn = testutils.CallCounter(self._SuccessfulPrepare)
511 1a2eb2dc Michael Hanselmann
    runcmd_fn = testutils.CallCounter(fn)
512 1a2eb2dc Michael Hanselmann
513 42bd26e8 Michael Hanselmann
    result = backend.RunRestrictedCmd("test5667",
514 1a2eb2dc Michael Hanselmann
                                      _lock_timeout=1.0, _lock_file=lockfile,
515 1a2eb2dc Michael Hanselmann
                                      _path=self.tmpdir, _runcmd_fn=runcmd_fn,
516 1a2eb2dc Michael Hanselmann
                                      _sleep_fn=sleep_fn,
517 1a2eb2dc Michael Hanselmann
                                      _prepare_fn=prepare_fn,
518 1a2eb2dc Michael Hanselmann
                                      _enabled=True)
519 1a2eb2dc Michael Hanselmann
    self.assertEqual(result, "stdout14463")
520 1a2eb2dc Michael Hanselmann
521 1a2eb2dc Michael Hanselmann
    self.assertEqual(sleep_fn.Count(), 0)
522 1a2eb2dc Michael Hanselmann
    self.assertEqual(prepare_fn.Count(), 1)
523 1a2eb2dc Michael Hanselmann
    self.assertEqual(runcmd_fn.Count(), 1)
524 1a2eb2dc Michael Hanselmann
525 1a2eb2dc Michael Hanselmann
  def testCommandsDisabled(self):
526 1a2eb2dc Michael Hanselmann
    try:
527 42bd26e8 Michael Hanselmann
      backend.RunRestrictedCmd("test",
528 1a2eb2dc Michael Hanselmann
                               _lock_timeout=NotImplemented,
529 1a2eb2dc Michael Hanselmann
                               _lock_file=NotImplemented,
530 1a2eb2dc Michael Hanselmann
                               _path=NotImplemented,
531 1a2eb2dc Michael Hanselmann
                               _sleep_fn=NotImplemented,
532 1a2eb2dc Michael Hanselmann
                               _prepare_fn=NotImplemented,
533 1a2eb2dc Michael Hanselmann
                               _runcmd_fn=NotImplemented,
534 1a2eb2dc Michael Hanselmann
                               _enabled=False)
535 1a2eb2dc Michael Hanselmann
    except backend.RPCFail, err:
536 45bc4635 Iustin Pop
      self.assertEqual(str(err),
537 45bc4635 Iustin Pop
                       "Restricted commands disabled at configure time")
538 1a2eb2dc Michael Hanselmann
    else:
539 1a2eb2dc Michael Hanselmann
      self.fail("Did not raise exception")
540 1a2eb2dc Michael Hanselmann
541 1a2eb2dc Michael Hanselmann
542 99e222b1 Michael Hanselmann
class TestSetWatcherPause(unittest.TestCase):
543 99e222b1 Michael Hanselmann
  def setUp(self):
544 99e222b1 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
545 99e222b1 Michael Hanselmann
    self.filename = utils.PathJoin(self.tmpdir, "pause")
546 99e222b1 Michael Hanselmann
547 99e222b1 Michael Hanselmann
  def tearDown(self):
548 99e222b1 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
549 99e222b1 Michael Hanselmann
550 99e222b1 Michael Hanselmann
  def testUnsetNonExisting(self):
551 99e222b1 Michael Hanselmann
    self.assertFalse(os.path.exists(self.filename))
552 99e222b1 Michael Hanselmann
    backend.SetWatcherPause(None, _filename=self.filename)
553 99e222b1 Michael Hanselmann
    self.assertFalse(os.path.exists(self.filename))
554 99e222b1 Michael Hanselmann
555 99e222b1 Michael Hanselmann
  def testSetNonNumeric(self):
556 99e222b1 Michael Hanselmann
    for i in ["", [], {}, "Hello World", "0", "1.0"]:
557 99e222b1 Michael Hanselmann
      self.assertFalse(os.path.exists(self.filename))
558 99e222b1 Michael Hanselmann
559 99e222b1 Michael Hanselmann
      try:
560 99e222b1 Michael Hanselmann
        backend.SetWatcherPause(i, _filename=self.filename)
561 99e222b1 Michael Hanselmann
      except backend.RPCFail, err:
562 99e222b1 Michael Hanselmann
        self.assertEqual(str(err), "Duration must be numeric")
563 99e222b1 Michael Hanselmann
      else:
564 99e222b1 Michael Hanselmann
        self.fail("Did not raise exception")
565 99e222b1 Michael Hanselmann
566 99e222b1 Michael Hanselmann
      self.assertFalse(os.path.exists(self.filename))
567 99e222b1 Michael Hanselmann
568 99e222b1 Michael Hanselmann
  def testSet(self):
569 99e222b1 Michael Hanselmann
    self.assertFalse(os.path.exists(self.filename))
570 99e222b1 Michael Hanselmann
571 99e222b1 Michael Hanselmann
    for i in range(10):
572 99e222b1 Michael Hanselmann
      backend.SetWatcherPause(i, _filename=self.filename)
573 99e222b1 Michael Hanselmann
      self.assertEqual(utils.ReadFile(self.filename), "%s\n" % i)
574 99e222b1 Michael Hanselmann
      self.assertEqual(os.stat(self.filename).st_mode & 0777, 0644)
575 99e222b1 Michael Hanselmann
576 99e222b1 Michael Hanselmann
577 3b721842 Michael Hanselmann
class TestGetBlockDevSymlinkPath(unittest.TestCase):
578 3b721842 Michael Hanselmann
  def setUp(self):
579 3b721842 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
580 3b721842 Michael Hanselmann
581 3b721842 Michael Hanselmann
  def tearDown(self):
582 3b721842 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
583 3b721842 Michael Hanselmann
584 3b721842 Michael Hanselmann
  def _Test(self, name, idx):
585 3b721842 Michael Hanselmann
    self.assertEqual(backend._GetBlockDevSymlinkPath(name, idx,
586 3b721842 Michael Hanselmann
                                                     _dir=self.tmpdir),
587 3b721842 Michael Hanselmann
                     ("%s/%s%s%s" % (self.tmpdir, name,
588 3b721842 Michael Hanselmann
                                     constants.DISK_SEPARATOR, idx)))
589 3b721842 Michael Hanselmann
590 3b721842 Michael Hanselmann
  def test(self):
591 3b721842 Michael Hanselmann
    for idx in range(100):
592 3b721842 Michael Hanselmann
      self._Test("inst1.example.com", idx)
593 3b721842 Michael Hanselmann
594 3b721842 Michael Hanselmann
595 fac83f8a Helga Velroyen
class TestGetInstanceList(unittest.TestCase):
596 fac83f8a Helga Velroyen
597 fac83f8a Helga Velroyen
  def setUp(self):
598 fac83f8a Helga Velroyen
    self._test_hv = self._TestHypervisor()
599 fac83f8a Helga Velroyen
    self._test_hv.ListInstances = mock.Mock(
600 fac83f8a Helga Velroyen
      return_value=["instance1", "instance2", "instance3"] )
601 fac83f8a Helga Velroyen
602 fac83f8a Helga Velroyen
  class _TestHypervisor(hypervisor.hv_base.BaseHypervisor):
603 fac83f8a Helga Velroyen
    def __init__(self):
604 fac83f8a Helga Velroyen
      hypervisor.hv_base.BaseHypervisor.__init__(self)
605 fac83f8a Helga Velroyen
606 fac83f8a Helga Velroyen
  def _GetHypervisor(self, name):
607 fac83f8a Helga Velroyen
    return self._test_hv
608 fac83f8a Helga Velroyen
609 fac83f8a Helga Velroyen
  def testHvparams(self):
610 fac83f8a Helga Velroyen
    fake_hvparams = {constants.HV_XEN_CMD: constants.XEN_CMD_XL}
611 fac83f8a Helga Velroyen
    hvparams = {constants.HT_FAKE: fake_hvparams}
612 fac83f8a Helga Velroyen
    backend.GetInstanceList([constants.HT_FAKE], all_hvparams=hvparams,
613 fac83f8a Helga Velroyen
                            get_hv_fn=self._GetHypervisor)
614 fac83f8a Helga Velroyen
    self._test_hv.ListInstances.assert_called_with(hvparams=fake_hvparams)
615 fac83f8a Helga Velroyen
616 fac83f8a Helga Velroyen
617 b9e12624 Hrvoje Ribicic
class TestInstanceConsoleInfo(unittest.TestCase):
618 b9e12624 Hrvoje Ribicic
619 b9e12624 Hrvoje Ribicic
  def setUp(self):
620 b9e12624 Hrvoje Ribicic
    self._test_hv_a = self._TestHypervisor()
621 b9e12624 Hrvoje Ribicic
    self._test_hv_a.GetInstanceConsole = mock.Mock(
622 b9e12624 Hrvoje Ribicic
      return_value = objects.InstanceConsole(instance="inst", kind="aHy")
623 b9e12624 Hrvoje Ribicic
    )
624 b9e12624 Hrvoje Ribicic
    self._test_hv_b = self._TestHypervisor()
625 b9e12624 Hrvoje Ribicic
    self._test_hv_b.GetInstanceConsole = mock.Mock(
626 b9e12624 Hrvoje Ribicic
      return_value = objects.InstanceConsole(instance="inst", kind="bHy")
627 b9e12624 Hrvoje Ribicic
    )
628 b9e12624 Hrvoje Ribicic
629 b9e12624 Hrvoje Ribicic
  class _TestHypervisor(hypervisor.hv_base.BaseHypervisor):
630 b9e12624 Hrvoje Ribicic
    def __init__(self):
631 b9e12624 Hrvoje Ribicic
      hypervisor.hv_base.BaseHypervisor.__init__(self)
632 b9e12624 Hrvoje Ribicic
633 b9e12624 Hrvoje Ribicic
  def _GetHypervisor(self, name):
634 b9e12624 Hrvoje Ribicic
    if name == "a":
635 b9e12624 Hrvoje Ribicic
      return self._test_hv_a
636 b9e12624 Hrvoje Ribicic
    else:
637 b9e12624 Hrvoje Ribicic
      return self._test_hv_b
638 b9e12624 Hrvoje Ribicic
639 b9e12624 Hrvoje Ribicic
  def testRightHypervisor(self):
640 b9e12624 Hrvoje Ribicic
    dictMaker = lambda hyName: {
641 b9e12624 Hrvoje Ribicic
      "instance":{"hypervisor":hyName},
642 b9e12624 Hrvoje Ribicic
      "node":{},
643 c42be2c0 Petr Pudlak
      "group":{},
644 b9e12624 Hrvoje Ribicic
      "hvParams":{},
645 b9e12624 Hrvoje Ribicic
      "beParams":{},
646 b9e12624 Hrvoje Ribicic
    }
647 b9e12624 Hrvoje Ribicic
648 b9e12624 Hrvoje Ribicic
    call = {
649 b9e12624 Hrvoje Ribicic
      'i1':dictMaker("a"),
650 b9e12624 Hrvoje Ribicic
      'i2':dictMaker("b"),
651 b9e12624 Hrvoje Ribicic
    }
652 b9e12624 Hrvoje Ribicic
653 b9e12624 Hrvoje Ribicic
    res = backend.GetInstanceConsoleInfo(call, get_hv_fn=self._GetHypervisor)
654 b9e12624 Hrvoje Ribicic
655 b9e12624 Hrvoje Ribicic
    self.assertTrue(res["i1"]["kind"] == "aHy")
656 b9e12624 Hrvoje Ribicic
    self.assertTrue(res["i2"]["kind"] == "bHy")
657 b9e12624 Hrvoje Ribicic
658 b9e12624 Hrvoje Ribicic
659 439e1d3f Helga Velroyen
class TestGetHvInfo(unittest.TestCase):
660 439e1d3f Helga Velroyen
661 439e1d3f Helga Velroyen
  def setUp(self):
662 439e1d3f Helga Velroyen
    self._test_hv = self._TestHypervisor()
663 439e1d3f Helga Velroyen
    self._test_hv.GetNodeInfo = mock.Mock()
664 439e1d3f Helga Velroyen
665 439e1d3f Helga Velroyen
  class _TestHypervisor(hypervisor.hv_base.BaseHypervisor):
666 439e1d3f Helga Velroyen
    def __init__(self):
667 439e1d3f Helga Velroyen
      hypervisor.hv_base.BaseHypervisor.__init__(self)
668 439e1d3f Helga Velroyen
669 439e1d3f Helga Velroyen
  def _GetHypervisor(self, name):
670 439e1d3f Helga Velroyen
    return self._test_hv
671 439e1d3f Helga Velroyen
672 439e1d3f Helga Velroyen
  def testGetHvInfoAllNone(self):
673 439e1d3f Helga Velroyen
    result = backend._GetHvInfoAll(None)
674 439e1d3f Helga Velroyen
    self.assertTrue(result is None)
675 439e1d3f Helga Velroyen
676 439e1d3f Helga Velroyen
  def testGetHvInfoAll(self):
677 439e1d3f Helga Velroyen
    hvname = constants.HT_XEN_PVM
678 439e1d3f Helga Velroyen
    hvparams = {constants.HV_XEN_CMD: constants.XEN_CMD_XL}
679 439e1d3f Helga Velroyen
    hv_specs = [(hvname, hvparams)]
680 439e1d3f Helga Velroyen
681 a7d524e7 Helga Velroyen
    backend._GetHvInfoAll(hv_specs, self._GetHypervisor)
682 439e1d3f Helga Velroyen
    self._test_hv.GetNodeInfo.assert_called_with(hvparams=hvparams)
683 439e1d3f Helga Velroyen
684 439e1d3f Helga Velroyen
685 f39a8d14 Helga Velroyen
class TestApplyStorageInfoFunction(unittest.TestCase):
686 f39a8d14 Helga Velroyen
687 f39a8d14 Helga Velroyen
  _STORAGE_KEY = "some_key"
688 b01b7a50 Helga Velroyen
  _SOME_ARGS = ["some_args"]
689 f39a8d14 Helga Velroyen
690 f39a8d14 Helga Velroyen
  def setUp(self):
691 f39a8d14 Helga Velroyen
    self.mock_storage_fn = mock.Mock()
692 f39a8d14 Helga Velroyen
693 f39a8d14 Helga Velroyen
  def testApplyValidStorageType(self):
694 f39a8d14 Helga Velroyen
    storage_type = constants.ST_LVM_VG
695 f79be8ec Helga Velroyen
    info_fn_orig = backend._STORAGE_TYPE_INFO_FN
696 f39a8d14 Helga Velroyen
    backend._STORAGE_TYPE_INFO_FN = {
697 f39a8d14 Helga Velroyen
        storage_type: self.mock_storage_fn
698 f39a8d14 Helga Velroyen
      }
699 f39a8d14 Helga Velroyen
700 f39a8d14 Helga Velroyen
    backend._ApplyStorageInfoFunction(
701 f39a8d14 Helga Velroyen
        storage_type, self._STORAGE_KEY, self._SOME_ARGS)
702 f39a8d14 Helga Velroyen
703 f39a8d14 Helga Velroyen
    self.mock_storage_fn.assert_called_with(self._STORAGE_KEY, self._SOME_ARGS)
704 f79be8ec Helga Velroyen
    backend._STORAGE_TYPE_INFO_FN = info_fn_orig
705 f39a8d14 Helga Velroyen
706 f39a8d14 Helga Velroyen
  def testApplyInValidStorageType(self):
707 f39a8d14 Helga Velroyen
    storage_type = "invalid_storage_type"
708 f79be8ec Helga Velroyen
    info_fn_orig = backend._STORAGE_TYPE_INFO_FN
709 f39a8d14 Helga Velroyen
    backend._STORAGE_TYPE_INFO_FN = {}
710 f39a8d14 Helga Velroyen
711 f39a8d14 Helga Velroyen
    self.assertRaises(KeyError, backend._ApplyStorageInfoFunction,
712 f39a8d14 Helga Velroyen
                      storage_type, self._STORAGE_KEY, self._SOME_ARGS)
713 f79be8ec Helga Velroyen
    backend._STORAGE_TYPE_INFO_FN = info_fn_orig
714 f39a8d14 Helga Velroyen
715 f39a8d14 Helga Velroyen
  def testApplyNotImplementedStorageType(self):
716 f39a8d14 Helga Velroyen
    storage_type = "not_implemented_storage_type"
717 f79be8ec Helga Velroyen
    info_fn_orig = backend._STORAGE_TYPE_INFO_FN
718 f39a8d14 Helga Velroyen
    backend._STORAGE_TYPE_INFO_FN = {storage_type: None}
719 f39a8d14 Helga Velroyen
720 f39a8d14 Helga Velroyen
    self.assertRaises(NotImplementedError,
721 f39a8d14 Helga Velroyen
                      backend._ApplyStorageInfoFunction,
722 f39a8d14 Helga Velroyen
                      storage_type, self._STORAGE_KEY, self._SOME_ARGS)
723 f79be8ec Helga Velroyen
    backend._STORAGE_TYPE_INFO_FN = info_fn_orig
724 f39a8d14 Helga Velroyen
725 f39a8d14 Helga Velroyen
726 3ae259d3 Helga Velroyen
class TestGetLvmVgSpaceInfo(unittest.TestCase):
727 3ae259d3 Helga Velroyen
728 3ae259d3 Helga Velroyen
  def testValid(self):
729 3ae259d3 Helga Velroyen
    path = "somepath"
730 3ae259d3 Helga Velroyen
    excl_stor = True
731 86e16e3f Helga Velroyen
    orig_fn = backend._GetVgInfo
732 3ae259d3 Helga Velroyen
    backend._GetVgInfo = mock.Mock()
733 3ae259d3 Helga Velroyen
    backend._GetLvmVgSpaceInfo(path, [excl_stor])
734 3ae259d3 Helga Velroyen
    backend._GetVgInfo.assert_called_with(path, excl_stor)
735 86e16e3f Helga Velroyen
    backend._GetVgInfo = orig_fn
736 3ae259d3 Helga Velroyen
737 3ae259d3 Helga Velroyen
  def testNoExclStorageNotBool(self):
738 3ae259d3 Helga Velroyen
    path = "somepath"
739 3ae259d3 Helga Velroyen
    excl_stor = "123"
740 3ae259d3 Helga Velroyen
    self.assertRaises(errors.ProgrammerError, backend._GetLvmVgSpaceInfo,
741 3ae259d3 Helga Velroyen
                      path, [excl_stor])
742 3ae259d3 Helga Velroyen
743 3ae259d3 Helga Velroyen
  def testNoExclStorageNotInList(self):
744 3ae259d3 Helga Velroyen
    path = "somepath"
745 3ae259d3 Helga Velroyen
    excl_stor = "123"
746 3ae259d3 Helga Velroyen
    self.assertRaises(errors.ProgrammerError, backend._GetLvmVgSpaceInfo,
747 3ae259d3 Helga Velroyen
                      path, excl_stor)
748 3ae259d3 Helga Velroyen
749 3c8a599a Helga Velroyen
class TestGetLvmPvSpaceInfo(unittest.TestCase):
750 3c8a599a Helga Velroyen
751 3c8a599a Helga Velroyen
  def testValid(self):
752 3c8a599a Helga Velroyen
    path = "somepath"
753 3c8a599a Helga Velroyen
    excl_stor = True
754 a18ab868 Helga Velroyen
    orig_fn = backend._GetVgSpindlesInfo
755 3c8a599a Helga Velroyen
    backend._GetVgSpindlesInfo = mock.Mock()
756 3c8a599a Helga Velroyen
    backend._GetLvmPvSpaceInfo(path, [excl_stor])
757 3c8a599a Helga Velroyen
    backend._GetVgSpindlesInfo.assert_called_with(path, excl_stor)
758 a18ab868 Helga Velroyen
    backend._GetVgSpindlesInfo = orig_fn
759 3c8a599a Helga Velroyen
760 3ae259d3 Helga Velroyen
761 b01b7a50 Helga Velroyen
class TestCheckStorageParams(unittest.TestCase):
762 b01b7a50 Helga Velroyen
763 b01b7a50 Helga Velroyen
  def testParamsNone(self):
764 b01b7a50 Helga Velroyen
    self.assertRaises(errors.ProgrammerError, backend._CheckStorageParams,
765 b01b7a50 Helga Velroyen
                      None, NotImplemented)
766 b01b7a50 Helga Velroyen
767 b01b7a50 Helga Velroyen
  def testParamsWrongType(self):
768 b01b7a50 Helga Velroyen
    self.assertRaises(errors.ProgrammerError, backend._CheckStorageParams,
769 b01b7a50 Helga Velroyen
                      "string", NotImplemented)
770 b01b7a50 Helga Velroyen
771 b01b7a50 Helga Velroyen
  def testParamsEmpty(self):
772 b01b7a50 Helga Velroyen
    backend._CheckStorageParams([], 0)
773 b01b7a50 Helga Velroyen
774 b01b7a50 Helga Velroyen
  def testParamsValidNumber(self):
775 b01b7a50 Helga Velroyen
    backend._CheckStorageParams(["a", True], 2)
776 b01b7a50 Helga Velroyen
777 b01b7a50 Helga Velroyen
  def testParamsInvalidNumber(self):
778 b01b7a50 Helga Velroyen
    self.assertRaises(errors.ProgrammerError, backend._CheckStorageParams,
779 b01b7a50 Helga Velroyen
                      ["b", False], 3)
780 b01b7a50 Helga Velroyen
781 b01b7a50 Helga Velroyen
782 a18ab868 Helga Velroyen
class TestGetVgSpindlesInfo(unittest.TestCase):
783 a18ab868 Helga Velroyen
784 a18ab868 Helga Velroyen
  def setUp(self):
785 a18ab868 Helga Velroyen
    self.vg_free = 13
786 a18ab868 Helga Velroyen
    self.vg_size = 31
787 a18ab868 Helga Velroyen
    self.mock_fn = mock.Mock(return_value=(self.vg_free, self.vg_size))
788 a18ab868 Helga Velroyen
789 a18ab868 Helga Velroyen
  def testValidInput(self):
790 a18ab868 Helga Velroyen
    name = "myvg"
791 a18ab868 Helga Velroyen
    excl_stor = True
792 a18ab868 Helga Velroyen
    result = backend._GetVgSpindlesInfo(name, excl_stor, info_fn=self.mock_fn)
793 a18ab868 Helga Velroyen
    self.mock_fn.assert_called_with(name)
794 a18ab868 Helga Velroyen
    self.assertEqual(name, result["name"])
795 a18ab868 Helga Velroyen
    self.assertEqual(constants.ST_LVM_PV, result["type"])
796 a18ab868 Helga Velroyen
    self.assertEqual(self.vg_free, result["storage_free"])
797 a18ab868 Helga Velroyen
    self.assertEqual(self.vg_size, result["storage_size"])
798 a18ab868 Helga Velroyen
799 a18ab868 Helga Velroyen
  def testNoExclStor(self):
800 a18ab868 Helga Velroyen
    name = "myvg"
801 a18ab868 Helga Velroyen
    excl_stor = False
802 a18ab868 Helga Velroyen
    result = backend._GetVgSpindlesInfo(name, excl_stor, info_fn=self.mock_fn)
803 a18ab868 Helga Velroyen
    self.mock_fn.assert_not_called()
804 a18ab868 Helga Velroyen
    self.assertEqual(name, result["name"])
805 a18ab868 Helga Velroyen
    self.assertEqual(constants.ST_LVM_PV, result["type"])
806 a18ab868 Helga Velroyen
    self.assertEqual(0, result["storage_free"])
807 a18ab868 Helga Velroyen
    self.assertEqual(0, result["storage_size"])
808 a18ab868 Helga Velroyen
809 a18ab868 Helga Velroyen
810 3f73b3ae Helga Velroyen
class TestGetVgSpindlesInfo(unittest.TestCase):
811 3f73b3ae Helga Velroyen
812 3f73b3ae Helga Velroyen
  def testValidInput(self):
813 3f73b3ae Helga Velroyen
    self.vg_free = 13
814 3f73b3ae Helga Velroyen
    self.vg_size = 31
815 3f73b3ae Helga Velroyen
    self.mock_fn = mock.Mock(return_value=[(self.vg_free, self.vg_size)])
816 3f73b3ae Helga Velroyen
    name = "myvg"
817 3f73b3ae Helga Velroyen
    excl_stor = True
818 3f73b3ae Helga Velroyen
    result = backend._GetVgInfo(name, excl_stor, info_fn=self.mock_fn)
819 3f73b3ae Helga Velroyen
    self.mock_fn.assert_called_with([name], excl_stor)
820 3f73b3ae Helga Velroyen
    self.assertEqual(name, result["name"])
821 3f73b3ae Helga Velroyen
    self.assertEqual(constants.ST_LVM_VG, result["type"])
822 3f73b3ae Helga Velroyen
    self.assertEqual(self.vg_free, result["storage_free"])
823 3f73b3ae Helga Velroyen
    self.assertEqual(self.vg_size, result["storage_size"])
824 3f73b3ae Helga Velroyen
825 3f73b3ae Helga Velroyen
  def testNoExclStor(self):
826 3f73b3ae Helga Velroyen
    name = "myvg"
827 3f73b3ae Helga Velroyen
    excl_stor = True
828 3f73b3ae Helga Velroyen
    self.mock_fn = mock.Mock(return_value=None)
829 3f73b3ae Helga Velroyen
    result = backend._GetVgInfo(name, excl_stor, info_fn=self.mock_fn)
830 3f73b3ae Helga Velroyen
    self.mock_fn.assert_called_with([name], excl_stor)
831 3f73b3ae Helga Velroyen
    self.assertEqual(name, result["name"])
832 3f73b3ae Helga Velroyen
    self.assertEqual(constants.ST_LVM_VG, result["type"])
833 3f73b3ae Helga Velroyen
    self.assertEqual(None, result["storage_free"])
834 3f73b3ae Helga Velroyen
    self.assertEqual(None, result["storage_size"])
835 3f73b3ae Helga Velroyen
836 3f73b3ae Helga Velroyen
837 f39a8d14 Helga Velroyen
class TestGetNodeInfo(unittest.TestCase):
838 f39a8d14 Helga Velroyen
839 f39a8d14 Helga Velroyen
  _SOME_RESULT = None
840 f39a8d14 Helga Velroyen
841 f39a8d14 Helga Velroyen
  def testApplyStorageInfoFunction(self):
842 86e16e3f Helga Velroyen
    orig_fn = backend._ApplyStorageInfoFunction
843 f39a8d14 Helga Velroyen
    backend._ApplyStorageInfoFunction = mock.Mock(
844 f39a8d14 Helga Velroyen
        return_value=self._SOME_RESULT)
845 152759e4 Helga Velroyen
    storage_units = [(st, st + "_key", [st + "_params"]) for st in
846 d8e55568 Helga Velroyen
                     constants.STORAGE_TYPES]
847 f39a8d14 Helga Velroyen
848 152759e4 Helga Velroyen
    backend.GetNodeInfo(storage_units, None)
849 f39a8d14 Helga Velroyen
850 f39a8d14 Helga Velroyen
    call_args_list = backend._ApplyStorageInfoFunction.call_args_list
851 d8e55568 Helga Velroyen
    self.assertEqual(len(constants.STORAGE_TYPES), len(call_args_list))
852 f39a8d14 Helga Velroyen
    for call in call_args_list:
853 152759e4 Helga Velroyen
      storage_type, storage_key, storage_params = call[0]
854 f39a8d14 Helga Velroyen
      self.assertEqual(storage_type + "_key", storage_key)
855 152759e4 Helga Velroyen
      self.assertEqual([storage_type + "_params"], storage_params)
856 d8e55568 Helga Velroyen
      self.assertTrue(storage_type in constants.STORAGE_TYPES)
857 86e16e3f Helga Velroyen
    backend._ApplyStorageInfoFunction = orig_fn
858 f39a8d14 Helga Velroyen
859 f39a8d14 Helga Velroyen
860 f79be8ec Helga Velroyen
class TestSpaceReportingConstants(unittest.TestCase):
861 f79be8ec Helga Velroyen
  """Ensures consistency between STS_REPORT and backend.
862 f79be8ec Helga Velroyen

863 5a904197 Santi Raffa
  These tests ensure, that the constant 'STS_REPORT' is consistent
864 f79be8ec Helga Velroyen
  with the implementation of invoking space reporting functions
865 f79be8ec Helga Velroyen
  in backend.py. Once space reporting is available for all types,
866 f79be8ec Helga Velroyen
  the constant can be removed and these tests as well.
867 f79be8ec Helga Velroyen

868 f79be8ec Helga Velroyen
  """
869 5a904197 Santi Raffa
870 5a904197 Santi Raffa
  REPORTING = set(constants.STS_REPORT)
871 5a904197 Santi Raffa
  NOT_REPORTING = set(constants.STORAGE_TYPES) - REPORTING
872 5a904197 Santi Raffa
873 f79be8ec Helga Velroyen
  def testAllReportingTypesHaveAReportingFunction(self):
874 5a904197 Santi Raffa
    for storage_type in TestSpaceReportingConstants.REPORTING:
875 f79be8ec Helga Velroyen
      self.assertTrue(backend._STORAGE_TYPE_INFO_FN[storage_type] is not None)
876 f79be8ec Helga Velroyen
877 5a904197 Santi Raffa
  def testAllNotReportingTypesDontHaveFunction(self):
878 5a904197 Santi Raffa
    for storage_type in TestSpaceReportingConstants.NOT_REPORTING:
879 f79be8ec Helga Velroyen
      self.assertEqual(None, backend._STORAGE_TYPE_INFO_FN[storage_type])
880 f79be8ec Helga Velroyen
881 f79be8ec Helga Velroyen
882 f942a838 Michael Hanselmann
if __name__ == "__main__":
883 f942a838 Michael Hanselmann
  testutils.GanetiTestProgram()