Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (29.2 kB)

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

842 f79be8ec Helga Velroyen
  These tests ensure, that the constant 'STS_REPORT' is consitent
843 f79be8ec Helga Velroyen
  with the implementation of invoking space reporting functions
844 f79be8ec Helga Velroyen
  in backend.py. Once space reporting is available for all types,
845 f79be8ec Helga Velroyen
  the constant can be removed and these tests as well.
846 f79be8ec Helga Velroyen

847 f79be8ec Helga Velroyen
  """
848 f79be8ec Helga Velroyen
  def testAllReportingTypesHaveAReportingFunction(self):
849 f79be8ec Helga Velroyen
    for storage_type in constants.STS_REPORT:
850 f79be8ec Helga Velroyen
      self.assertTrue(backend._STORAGE_TYPE_INFO_FN[storage_type] is not None)
851 f79be8ec Helga Velroyen
852 f79be8ec Helga Velroyen
  def testAllNotReportingTypesDoneHaveFunction(self):
853 9d0d4f21 Helga Velroyen
    non_reporting_types = set(constants.STORAGE_TYPES)\
854 f79be8ec Helga Velroyen
        - set(constants.STS_REPORT)
855 f79be8ec Helga Velroyen
    for storage_type in non_reporting_types:
856 f79be8ec Helga Velroyen
      self.assertEqual(None, backend._STORAGE_TYPE_INFO_FN[storage_type])
857 f79be8ec Helga Velroyen
858 f79be8ec Helga Velroyen
859 f942a838 Michael Hanselmann
if __name__ == "__main__":
860 f942a838 Michael Hanselmann
  testutils.GanetiTestProgram()