Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.backend_unittest.py @ 69809ae3

History | View | Annotate | Download (32.7 kB)

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

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

928 f79be8ec Helga Velroyen
  """
929 5a904197 Santi Raffa
930 5a904197 Santi Raffa
  REPORTING = set(constants.STS_REPORT)
931 5a904197 Santi Raffa
  NOT_REPORTING = set(constants.STORAGE_TYPES) - REPORTING
932 5a904197 Santi Raffa
933 f79be8ec Helga Velroyen
  def testAllReportingTypesHaveAReportingFunction(self):
934 5a904197 Santi Raffa
    for storage_type in TestSpaceReportingConstants.REPORTING:
935 f79be8ec Helga Velroyen
      self.assertTrue(backend._STORAGE_TYPE_INFO_FN[storage_type] is not None)
936 f79be8ec Helga Velroyen
937 5a904197 Santi Raffa
  def testAllNotReportingTypesDontHaveFunction(self):
938 5a904197 Santi Raffa
    for storage_type in TestSpaceReportingConstants.NOT_REPORTING:
939 f79be8ec Helga Velroyen
      self.assertEqual(None, backend._STORAGE_TYPE_INFO_FN[storage_type])
940 f79be8ec Helga Velroyen
941 f79be8ec Helga Velroyen
942 f942a838 Michael Hanselmann
if __name__ == "__main__":
943 f942a838 Michael Hanselmann
  testutils.GanetiTestProgram()