Statistics
| Branch: | Tag: | Revision:

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

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

797 f79be8ec Helga Velroyen
  These tests ensure, that the constant 'STS_REPORT' is consitent
798 f79be8ec Helga Velroyen
  with the implementation of invoking space reporting functions
799 f79be8ec Helga Velroyen
  in backend.py. Once space reporting is available for all types,
800 f79be8ec Helga Velroyen
  the constant can be removed and these tests as well.
801 f79be8ec Helga Velroyen

802 f79be8ec Helga Velroyen
  """
803 f79be8ec Helga Velroyen
  def testAllReportingTypesHaveAReportingFunction(self):
804 f79be8ec Helga Velroyen
    for storage_type in constants.STS_REPORT:
805 f79be8ec Helga Velroyen
      self.assertTrue(backend._STORAGE_TYPE_INFO_FN[storage_type] is not None)
806 f79be8ec Helga Velroyen
807 f79be8ec Helga Velroyen
  def testAllNotReportingTypesDoneHaveFunction(self):
808 9d0d4f21 Helga Velroyen
    non_reporting_types = set(constants.STORAGE_TYPES)\
809 f79be8ec Helga Velroyen
        - set(constants.STS_REPORT)
810 f79be8ec Helga Velroyen
    for storage_type in non_reporting_types:
811 f79be8ec Helga Velroyen
      self.assertEqual(None, backend._STORAGE_TYPE_INFO_FN[storage_type])
812 f79be8ec Helga Velroyen
813 f79be8ec Helga Velroyen
814 f942a838 Michael Hanselmann
if __name__ == "__main__":
815 f942a838 Michael Hanselmann
  testutils.GanetiTestProgram()