Statistics
| Branch: | Tag: | Revision:

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

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

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

919 f79be8ec Helga Velroyen
  """
920 5a904197 Santi Raffa
921 5a904197 Santi Raffa
  REPORTING = set(constants.STS_REPORT)
922 5a904197 Santi Raffa
  NOT_REPORTING = set(constants.STORAGE_TYPES) - REPORTING
923 5a904197 Santi Raffa
924 f79be8ec Helga Velroyen
  def testAllReportingTypesHaveAReportingFunction(self):
925 5a904197 Santi Raffa
    for storage_type in TestSpaceReportingConstants.REPORTING:
926 f79be8ec Helga Velroyen
      self.assertTrue(backend._STORAGE_TYPE_INFO_FN[storage_type] is not None)
927 f79be8ec Helga Velroyen
928 5a904197 Santi Raffa
  def testAllNotReportingTypesDontHaveFunction(self):
929 5a904197 Santi Raffa
    for storage_type in TestSpaceReportingConstants.NOT_REPORTING:
930 f79be8ec Helga Velroyen
      self.assertEqual(None, backend._STORAGE_TYPE_INFO_FN[storage_type])
931 f79be8ec Helga Velroyen
932 f79be8ec Helga Velroyen
933 f942a838 Michael Hanselmann
if __name__ == "__main__":
934 f942a838 Michael Hanselmann
  testutils.GanetiTestProgram()