Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hypervisor.hv_xen_unittest.py @ 664b392d

History | View | Annotate | Download (17.2 kB)

1 55cc0a44 Michael Hanselmann
#!/usr/bin/python
2 55cc0a44 Michael Hanselmann
#
3 55cc0a44 Michael Hanselmann
4 b255379d Michael Hanselmann
# Copyright (C) 2011, 2013 Google Inc.
5 55cc0a44 Michael Hanselmann
#
6 55cc0a44 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 55cc0a44 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 55cc0a44 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 55cc0a44 Michael Hanselmann
# (at your option) any later version.
10 55cc0a44 Michael Hanselmann
#
11 55cc0a44 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 55cc0a44 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 55cc0a44 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 55cc0a44 Michael Hanselmann
# General Public License for more details.
15 55cc0a44 Michael Hanselmann
#
16 55cc0a44 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 55cc0a44 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 55cc0a44 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 55cc0a44 Michael Hanselmann
# 02110-1301, USA.
20 55cc0a44 Michael Hanselmann
21 55cc0a44 Michael Hanselmann
22 55cc0a44 Michael Hanselmann
"""Script for testing ganeti.hypervisor.hv_lxc"""
23 55cc0a44 Michael Hanselmann
24 d0bb3f24 Michael Hanselmann
import string # pylint: disable=W0402
25 55cc0a44 Michael Hanselmann
import unittest
26 64a66bd2 Michael Hanselmann
import tempfile
27 64a66bd2 Michael Hanselmann
import shutil
28 74a50c46 Michael Hanselmann
import random
29 7610d884 Michael Hanselmann
import os
30 55cc0a44 Michael Hanselmann
31 55cc0a44 Michael Hanselmann
from ganeti import constants
32 55cc0a44 Michael Hanselmann
from ganeti import objects
33 55cc0a44 Michael Hanselmann
from ganeti import hypervisor
34 b255379d Michael Hanselmann
from ganeti import utils
35 b255379d Michael Hanselmann
from ganeti import errors
36 b255379d Michael Hanselmann
from ganeti import compat
37 55cc0a44 Michael Hanselmann
38 55cc0a44 Michael Hanselmann
from ganeti.hypervisor import hv_xen
39 55cc0a44 Michael Hanselmann
40 55cc0a44 Michael Hanselmann
import testutils
41 55cc0a44 Michael Hanselmann
42 55cc0a44 Michael Hanselmann
43 74a50c46 Michael Hanselmann
# Map from hypervisor class to hypervisor name
44 74a50c46 Michael Hanselmann
HVCLASS_TO_HVNAME = utils.InvertDict(hypervisor._HYPERVISOR_MAP)
45 74a50c46 Michael Hanselmann
46 74a50c46 Michael Hanselmann
47 55cc0a44 Michael Hanselmann
class TestConsole(unittest.TestCase):
48 55cc0a44 Michael Hanselmann
  def test(self):
49 55cc0a44 Michael Hanselmann
    for cls in [hv_xen.XenPvmHypervisor, hv_xen.XenHvmHypervisor]:
50 55cc0a44 Michael Hanselmann
      instance = objects.Instance(name="xen.example.com",
51 55cc0a44 Michael Hanselmann
                                  primary_node="node24828")
52 55cc0a44 Michael Hanselmann
      cons = cls.GetInstanceConsole(instance, {}, {})
53 55cc0a44 Michael Hanselmann
      self.assertTrue(cons.Validate())
54 55cc0a44 Michael Hanselmann
      self.assertEqual(cons.kind, constants.CONS_SSH)
55 55cc0a44 Michael Hanselmann
      self.assertEqual(cons.host, instance.primary_node)
56 55cc0a44 Michael Hanselmann
      self.assertEqual(cons.command[-1], instance.name)
57 55cc0a44 Michael Hanselmann
58 55cc0a44 Michael Hanselmann
59 347fa0f1 Michael Hanselmann
class TestCreateConfigCpus(unittest.TestCase):
60 347fa0f1 Michael Hanselmann
  def testEmpty(self):
61 347fa0f1 Michael Hanselmann
    for cpu_mask in [None, ""]:
62 347fa0f1 Michael Hanselmann
      self.assertEqual(hv_xen._CreateConfigCpus(cpu_mask),
63 347fa0f1 Michael Hanselmann
                       "cpus = [  ]")
64 347fa0f1 Michael Hanselmann
65 347fa0f1 Michael Hanselmann
  def testAll(self):
66 347fa0f1 Michael Hanselmann
    self.assertEqual(hv_xen._CreateConfigCpus(constants.CPU_PINNING_ALL),
67 347fa0f1 Michael Hanselmann
                     None)
68 347fa0f1 Michael Hanselmann
69 347fa0f1 Michael Hanselmann
  def testOne(self):
70 347fa0f1 Michael Hanselmann
    self.assertEqual(hv_xen._CreateConfigCpus("9"), "cpu = \"9\"")
71 347fa0f1 Michael Hanselmann
72 347fa0f1 Michael Hanselmann
  def testMultiple(self):
73 347fa0f1 Michael Hanselmann
    self.assertEqual(hv_xen._CreateConfigCpus("0-2,4,5-5:3:all"),
74 347fa0f1 Michael Hanselmann
                     ("cpus = [ \"0,1,2,4,5\", \"3\", \"%s\" ]" %
75 347fa0f1 Michael Hanselmann
                      constants.CPU_PINNING_ALL_XEN))
76 347fa0f1 Michael Hanselmann
77 347fa0f1 Michael Hanselmann
78 b255379d Michael Hanselmann
class TestParseXmList(testutils.GanetiTestCase):
79 b255379d Michael Hanselmann
  def test(self):
80 b255379d Michael Hanselmann
    data = testutils.ReadTestData("xen-xm-list-4.0.1-dom0-only.txt")
81 b255379d Michael Hanselmann
82 b255379d Michael Hanselmann
    # Exclude node
83 b255379d Michael Hanselmann
    self.assertEqual(hv_xen._ParseXmList(data.splitlines(), False), [])
84 b255379d Michael Hanselmann
85 b255379d Michael Hanselmann
    # Include node
86 b255379d Michael Hanselmann
    result = hv_xen._ParseXmList(data.splitlines(), True)
87 b255379d Michael Hanselmann
    self.assertEqual(len(result), 1)
88 b255379d Michael Hanselmann
    self.assertEqual(len(result[0]), 6)
89 b255379d Michael Hanselmann
90 b255379d Michael Hanselmann
    # Name
91 b255379d Michael Hanselmann
    self.assertEqual(result[0][0], hv_xen._DOM0_NAME)
92 b255379d Michael Hanselmann
93 b255379d Michael Hanselmann
    # ID
94 b255379d Michael Hanselmann
    self.assertEqual(result[0][1], 0)
95 b255379d Michael Hanselmann
96 b255379d Michael Hanselmann
    # Memory
97 b255379d Michael Hanselmann
    self.assertEqual(result[0][2], 1023)
98 b255379d Michael Hanselmann
99 b255379d Michael Hanselmann
    # VCPUs
100 b255379d Michael Hanselmann
    self.assertEqual(result[0][3], 1)
101 b255379d Michael Hanselmann
102 b255379d Michael Hanselmann
    # State
103 b255379d Michael Hanselmann
    self.assertEqual(result[0][4], "r-----")
104 b255379d Michael Hanselmann
105 b255379d Michael Hanselmann
    # Time
106 b255379d Michael Hanselmann
    self.assertAlmostEqual(result[0][5], 121152.6)
107 b255379d Michael Hanselmann
108 b255379d Michael Hanselmann
  def testWrongLineFormat(self):
109 b255379d Michael Hanselmann
    tests = [
110 b255379d Michael Hanselmann
      ["three fields only"],
111 b255379d Michael Hanselmann
      ["name InvalidID 128 1 r----- 12345"],
112 b255379d Michael Hanselmann
      ]
113 b255379d Michael Hanselmann
114 b255379d Michael Hanselmann
    for lines in tests:
115 b255379d Michael Hanselmann
      try:
116 b255379d Michael Hanselmann
        hv_xen._ParseXmList(["Header would be here"] + lines, False)
117 b255379d Michael Hanselmann
      except errors.HypervisorError, err:
118 b255379d Michael Hanselmann
        self.assertTrue("Can't parse output of xm list" in str(err))
119 b255379d Michael Hanselmann
      else:
120 b255379d Michael Hanselmann
        self.fail("Exception was not raised")
121 b255379d Michael Hanselmann
122 b255379d Michael Hanselmann
123 b255379d Michael Hanselmann
class TestGetXmList(testutils.GanetiTestCase):
124 b255379d Michael Hanselmann
  def _Fail(self):
125 b255379d Michael Hanselmann
    return utils.RunResult(constants.EXIT_FAILURE, None,
126 b255379d Michael Hanselmann
                           "stdout", "stderr", None,
127 b255379d Michael Hanselmann
                           NotImplemented, NotImplemented)
128 b255379d Michael Hanselmann
129 b255379d Michael Hanselmann
  def testTimeout(self):
130 b255379d Michael Hanselmann
    fn = testutils.CallCounter(self._Fail)
131 b255379d Michael Hanselmann
    try:
132 b255379d Michael Hanselmann
      hv_xen._GetXmList(fn, False, _timeout=0.1)
133 b255379d Michael Hanselmann
    except errors.HypervisorError, err:
134 b255379d Michael Hanselmann
      self.assertTrue("timeout exceeded" in str(err))
135 b255379d Michael Hanselmann
    else:
136 b255379d Michael Hanselmann
      self.fail("Exception was not raised")
137 b255379d Michael Hanselmann
138 b255379d Michael Hanselmann
    self.assertTrue(fn.Count() < 10,
139 b255379d Michael Hanselmann
                    msg="'xm list' was called too many times")
140 b255379d Michael Hanselmann
141 b255379d Michael Hanselmann
  def _Success(self, stdout):
142 b255379d Michael Hanselmann
    return utils.RunResult(constants.EXIT_SUCCESS, None, stdout, "", None,
143 b255379d Michael Hanselmann
                           NotImplemented, NotImplemented)
144 b255379d Michael Hanselmann
145 b255379d Michael Hanselmann
  def testSuccess(self):
146 b255379d Michael Hanselmann
    data = testutils.ReadTestData("xen-xm-list-4.0.1-four-instances.txt")
147 b255379d Michael Hanselmann
148 b255379d Michael Hanselmann
    fn = testutils.CallCounter(compat.partial(self._Success, data))
149 b255379d Michael Hanselmann
150 b255379d Michael Hanselmann
    result = hv_xen._GetXmList(fn, True, _timeout=0.1)
151 b255379d Michael Hanselmann
152 b255379d Michael Hanselmann
    self.assertEqual(len(result), 4)
153 b255379d Michael Hanselmann
154 b255379d Michael Hanselmann
    self.assertEqual(map(compat.fst, result), [
155 b255379d Michael Hanselmann
      "Domain-0",
156 b255379d Michael Hanselmann
      "server01.example.com",
157 b255379d Michael Hanselmann
      "web3106215069.example.com",
158 b255379d Michael Hanselmann
      "testinstance.example.com",
159 b255379d Michael Hanselmann
      ])
160 b255379d Michael Hanselmann
161 b255379d Michael Hanselmann
    self.assertEqual(fn.Count(), 1)
162 b255379d Michael Hanselmann
163 b255379d Michael Hanselmann
164 06c9a520 Michael Hanselmann
class TestParseNodeInfo(testutils.GanetiTestCase):
165 06c9a520 Michael Hanselmann
  def testEmpty(self):
166 06c9a520 Michael Hanselmann
    self.assertEqual(hv_xen._ParseNodeInfo(""), {})
167 06c9a520 Michael Hanselmann
168 06c9a520 Michael Hanselmann
  def testUnknownInput(self):
169 06c9a520 Michael Hanselmann
    data = "\n".join([
170 06c9a520 Michael Hanselmann
      "foo bar",
171 06c9a520 Michael Hanselmann
      "something else goes",
172 06c9a520 Michael Hanselmann
      "here",
173 06c9a520 Michael Hanselmann
      ])
174 06c9a520 Michael Hanselmann
    self.assertEqual(hv_xen._ParseNodeInfo(data), {})
175 06c9a520 Michael Hanselmann
176 06c9a520 Michael Hanselmann
  def testBasicInfo(self):
177 06c9a520 Michael Hanselmann
    data = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
178 06c9a520 Michael Hanselmann
    result = hv_xen._ParseNodeInfo(data)
179 06c9a520 Michael Hanselmann
    self.assertEqual(result, {
180 06c9a520 Michael Hanselmann
      "cpu_nodes": 1,
181 06c9a520 Michael Hanselmann
      "cpu_sockets": 2,
182 06c9a520 Michael Hanselmann
      "cpu_total": 4,
183 06c9a520 Michael Hanselmann
      "hv_version": (4, 0),
184 06c9a520 Michael Hanselmann
      "memory_free": 8004,
185 06c9a520 Michael Hanselmann
      "memory_total": 16378,
186 06c9a520 Michael Hanselmann
      })
187 06c9a520 Michael Hanselmann
188 06c9a520 Michael Hanselmann
189 06c9a520 Michael Hanselmann
class TestMergeInstanceInfo(testutils.GanetiTestCase):
190 06c9a520 Michael Hanselmann
  def testEmpty(self):
191 06c9a520 Michael Hanselmann
    self.assertEqual(hv_xen._MergeInstanceInfo({}, lambda _: []), {})
192 06c9a520 Michael Hanselmann
193 06c9a520 Michael Hanselmann
  def _FakeXmList(self, include_node):
194 06c9a520 Michael Hanselmann
    self.assertTrue(include_node)
195 06c9a520 Michael Hanselmann
    return [
196 06c9a520 Michael Hanselmann
      (hv_xen._DOM0_NAME, NotImplemented, 4096, 7, NotImplemented,
197 06c9a520 Michael Hanselmann
       NotImplemented),
198 06c9a520 Michael Hanselmann
      ("inst1.example.com", NotImplemented, 2048, 4, NotImplemented,
199 06c9a520 Michael Hanselmann
       NotImplemented),
200 06c9a520 Michael Hanselmann
      ]
201 06c9a520 Michael Hanselmann
202 06c9a520 Michael Hanselmann
  def testMissingNodeInfo(self):
203 06c9a520 Michael Hanselmann
    result = hv_xen._MergeInstanceInfo({}, self._FakeXmList)
204 06c9a520 Michael Hanselmann
    self.assertEqual(result, {
205 06c9a520 Michael Hanselmann
      "memory_dom0": 4096,
206 06c9a520 Michael Hanselmann
      "dom0_cpus": 7,
207 06c9a520 Michael Hanselmann
      })
208 06c9a520 Michael Hanselmann
209 06c9a520 Michael Hanselmann
  def testWithNodeInfo(self):
210 06c9a520 Michael Hanselmann
    info = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
211 06c9a520 Michael Hanselmann
    result = hv_xen._GetNodeInfo(info, self._FakeXmList)
212 06c9a520 Michael Hanselmann
    self.assertEqual(result, {
213 06c9a520 Michael Hanselmann
      "cpu_nodes": 1,
214 06c9a520 Michael Hanselmann
      "cpu_sockets": 2,
215 06c9a520 Michael Hanselmann
      "cpu_total": 4,
216 06c9a520 Michael Hanselmann
      "dom0_cpus": 7,
217 06c9a520 Michael Hanselmann
      "hv_version": (4, 0),
218 06c9a520 Michael Hanselmann
      "memory_dom0": 4096,
219 06c9a520 Michael Hanselmann
      "memory_free": 8004,
220 06c9a520 Michael Hanselmann
      "memory_hv": 2230,
221 06c9a520 Michael Hanselmann
      "memory_total": 16378,
222 06c9a520 Michael Hanselmann
      })
223 06c9a520 Michael Hanselmann
224 06c9a520 Michael Hanselmann
225 d0bb3f24 Michael Hanselmann
class TestGetConfigFileDiskData(unittest.TestCase):
226 d0bb3f24 Michael Hanselmann
  def testLetterCount(self):
227 d0bb3f24 Michael Hanselmann
    self.assertEqual(len(hv_xen._DISK_LETTERS), 26)
228 d0bb3f24 Michael Hanselmann
229 d0bb3f24 Michael Hanselmann
  def testNoDisks(self):
230 d0bb3f24 Michael Hanselmann
    self.assertEqual(hv_xen._GetConfigFileDiskData([], "hd"), [])
231 d0bb3f24 Michael Hanselmann
232 d0bb3f24 Michael Hanselmann
  def testManyDisks(self):
233 d0bb3f24 Michael Hanselmann
    for offset in [0, 1, 10]:
234 d0bb3f24 Michael Hanselmann
      disks = [(objects.Disk(dev_type=constants.LD_LV), "/tmp/disk/%s" % idx)
235 d0bb3f24 Michael Hanselmann
               for idx in range(len(hv_xen._DISK_LETTERS) + offset)]
236 d0bb3f24 Michael Hanselmann
237 d0bb3f24 Michael Hanselmann
      if offset == 0:
238 d0bb3f24 Michael Hanselmann
        result = hv_xen._GetConfigFileDiskData(disks, "hd")
239 d0bb3f24 Michael Hanselmann
        self.assertEqual(result, [
240 d0bb3f24 Michael Hanselmann
          "'phy:/tmp/disk/%s,hd%s,r'" % (idx, string.ascii_lowercase[idx])
241 d0bb3f24 Michael Hanselmann
          for idx in range(len(hv_xen._DISK_LETTERS) + offset)
242 d0bb3f24 Michael Hanselmann
          ])
243 d0bb3f24 Michael Hanselmann
      else:
244 d0bb3f24 Michael Hanselmann
        try:
245 d0bb3f24 Michael Hanselmann
          hv_xen._GetConfigFileDiskData(disks, "hd")
246 d0bb3f24 Michael Hanselmann
        except errors.HypervisorError, err:
247 d0bb3f24 Michael Hanselmann
          self.assertEqual(str(err), "Too many disks")
248 d0bb3f24 Michael Hanselmann
        else:
249 d0bb3f24 Michael Hanselmann
          self.fail("Exception was not raised")
250 d0bb3f24 Michael Hanselmann
251 d0bb3f24 Michael Hanselmann
  def testTwoLvDisksWithMode(self):
252 d0bb3f24 Michael Hanselmann
    disks = [
253 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDWR),
254 d0bb3f24 Michael Hanselmann
       "/tmp/diskFirst"),
255 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDONLY),
256 d0bb3f24 Michael Hanselmann
       "/tmp/diskLast"),
257 d0bb3f24 Michael Hanselmann
      ]
258 d0bb3f24 Michael Hanselmann
259 d0bb3f24 Michael Hanselmann
    result = hv_xen._GetConfigFileDiskData(disks, "hd")
260 d0bb3f24 Michael Hanselmann
    self.assertEqual(result, [
261 d0bb3f24 Michael Hanselmann
      "'phy:/tmp/diskFirst,hda,w'",
262 d0bb3f24 Michael Hanselmann
      "'phy:/tmp/diskLast,hdb,r'",
263 d0bb3f24 Michael Hanselmann
      ])
264 d0bb3f24 Michael Hanselmann
265 d0bb3f24 Michael Hanselmann
  def testFileDisks(self):
266 d0bb3f24 Michael Hanselmann
    disks = [
267 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
268 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_LOOP]),
269 d0bb3f24 Michael Hanselmann
       "/tmp/diskFirst"),
270 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDONLY,
271 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_BLKTAP]),
272 d0bb3f24 Michael Hanselmann
       "/tmp/diskTwo"),
273 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
274 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_LOOP]),
275 d0bb3f24 Michael Hanselmann
       "/tmp/diskThree"),
276 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
277 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_BLKTAP]),
278 d0bb3f24 Michael Hanselmann
       "/tmp/diskLast"),
279 d0bb3f24 Michael Hanselmann
      ]
280 d0bb3f24 Michael Hanselmann
281 d0bb3f24 Michael Hanselmann
    result = hv_xen._GetConfigFileDiskData(disks, "sd")
282 d0bb3f24 Michael Hanselmann
    self.assertEqual(result, [
283 d0bb3f24 Michael Hanselmann
      "'file:/tmp/diskFirst,sda,w'",
284 d0bb3f24 Michael Hanselmann
      "'tap:aio:/tmp/diskTwo,sdb,r'",
285 d0bb3f24 Michael Hanselmann
      "'file:/tmp/diskThree,sdc,w'",
286 d0bb3f24 Michael Hanselmann
      "'tap:aio:/tmp/diskLast,sdd,w'",
287 d0bb3f24 Michael Hanselmann
      ])
288 d0bb3f24 Michael Hanselmann
289 d0bb3f24 Michael Hanselmann
  def testInvalidFileDisk(self):
290 d0bb3f24 Michael Hanselmann
    disks = [
291 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
292 d0bb3f24 Michael Hanselmann
                    physical_id=["#unknown#"]),
293 d0bb3f24 Michael Hanselmann
       "/tmp/diskinvalid"),
294 d0bb3f24 Michael Hanselmann
      ]
295 d0bb3f24 Michael Hanselmann
296 d0bb3f24 Michael Hanselmann
    self.assertRaises(KeyError, hv_xen._GetConfigFileDiskData, disks, "sd")
297 d0bb3f24 Michael Hanselmann
298 d0bb3f24 Michael Hanselmann
299 1dee2041 Michael Hanselmann
class TestXenHypervisorUnknownCommand(unittest.TestCase):
300 1dee2041 Michael Hanselmann
  def test(self):
301 1dee2041 Michael Hanselmann
    cmd = "#unknown command#"
302 1dee2041 Michael Hanselmann
    self.assertFalse(cmd in constants.KNOWN_XEN_COMMANDS)
303 1dee2041 Michael Hanselmann
    hv = hv_xen.XenHypervisor(_cfgdir=NotImplemented,
304 1dee2041 Michael Hanselmann
                              _run_cmd_fn=NotImplemented,
305 1dee2041 Michael Hanselmann
                              _cmd=cmd)
306 1dee2041 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, hv._RunXen, [])
307 1dee2041 Michael Hanselmann
308 1dee2041 Michael Hanselmann
309 64a66bd2 Michael Hanselmann
class TestXenHypervisorWriteConfigFile(unittest.TestCase):
310 64a66bd2 Michael Hanselmann
  def setUp(self):
311 64a66bd2 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
312 64a66bd2 Michael Hanselmann
313 64a66bd2 Michael Hanselmann
  def tearDown(self):
314 64a66bd2 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
315 64a66bd2 Michael Hanselmann
316 64a66bd2 Michael Hanselmann
  def testWriteError(self):
317 64a66bd2 Michael Hanselmann
    cfgdir = utils.PathJoin(self.tmpdir, "foobar")
318 64a66bd2 Michael Hanselmann
319 64a66bd2 Michael Hanselmann
    hv = hv_xen.XenHypervisor(_cfgdir=cfgdir,
320 64a66bd2 Michael Hanselmann
                              _run_cmd_fn=NotImplemented,
321 64a66bd2 Michael Hanselmann
                              _cmd=NotImplemented)
322 64a66bd2 Michael Hanselmann
323 64a66bd2 Michael Hanselmann
    self.assertFalse(os.path.exists(cfgdir))
324 64a66bd2 Michael Hanselmann
325 64a66bd2 Michael Hanselmann
    try:
326 64a66bd2 Michael Hanselmann
      hv._WriteConfigFile("name", "data")
327 64a66bd2 Michael Hanselmann
    except errors.HypervisorError, err:
328 64a66bd2 Michael Hanselmann
      self.assertTrue(str(err).startswith("Cannot write Xen instance"))
329 64a66bd2 Michael Hanselmann
    else:
330 64a66bd2 Michael Hanselmann
      self.fail("Exception was not raised")
331 64a66bd2 Michael Hanselmann
332 64a66bd2 Michael Hanselmann
333 74a50c46 Michael Hanselmann
class _TestXenHypervisor(object):
334 74a50c46 Michael Hanselmann
  TARGET = NotImplemented
335 74a50c46 Michael Hanselmann
  CMD = NotImplemented
336 74a50c46 Michael Hanselmann
  HVNAME = NotImplemented
337 74a50c46 Michael Hanselmann
338 74a50c46 Michael Hanselmann
  def setUp(self):
339 74a50c46 Michael Hanselmann
    super(_TestXenHypervisor, self).setUp()
340 74a50c46 Michael Hanselmann
341 74a50c46 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
342 74a50c46 Michael Hanselmann
343 74a50c46 Michael Hanselmann
    self.vncpw = "".join(random.sample(string.ascii_letters, 10))
344 74a50c46 Michael Hanselmann
345 74a50c46 Michael Hanselmann
    self.vncpw_path = utils.PathJoin(self.tmpdir, "vncpw")
346 74a50c46 Michael Hanselmann
    utils.WriteFile(self.vncpw_path, data=self.vncpw)
347 74a50c46 Michael Hanselmann
348 74a50c46 Michael Hanselmann
  def tearDown(self):
349 74a50c46 Michael Hanselmann
    super(_TestXenHypervisor, self).tearDown()
350 74a50c46 Michael Hanselmann
351 74a50c46 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
352 74a50c46 Michael Hanselmann
353 74a50c46 Michael Hanselmann
  def _GetHv(self, run_cmd=NotImplemented):
354 74a50c46 Michael Hanselmann
    return self.TARGET(_cfgdir=self.tmpdir, _run_cmd_fn=run_cmd, _cmd=self.CMD)
355 74a50c46 Michael Hanselmann
356 74a50c46 Michael Hanselmann
  def _SuccessCommand(self, stdout, cmd):
357 74a50c46 Michael Hanselmann
    self.assertEqual(cmd[0], self.CMD)
358 74a50c46 Michael Hanselmann
359 74a50c46 Michael Hanselmann
    return utils.RunResult(constants.EXIT_SUCCESS, None, stdout, "", None,
360 74a50c46 Michael Hanselmann
                           NotImplemented, NotImplemented)
361 74a50c46 Michael Hanselmann
362 74a50c46 Michael Hanselmann
  def _FailingCommand(self, cmd):
363 74a50c46 Michael Hanselmann
    self.assertEqual(cmd[0], self.CMD)
364 74a50c46 Michael Hanselmann
365 74a50c46 Michael Hanselmann
    return utils.RunResult(constants.EXIT_FAILURE, None,
366 74a50c46 Michael Hanselmann
                           "", "This command failed", None,
367 74a50c46 Michael Hanselmann
                           NotImplemented, NotImplemented)
368 74a50c46 Michael Hanselmann
369 57270b2d Michael Hanselmann
  def testReadingNonExistentConfigFile(self):
370 57270b2d Michael Hanselmann
    hv = self._GetHv()
371 57270b2d Michael Hanselmann
372 57270b2d Michael Hanselmann
    try:
373 57270b2d Michael Hanselmann
      hv._ReadConfigFile("inst15780.example.com")
374 57270b2d Michael Hanselmann
    except errors.HypervisorError, err:
375 57270b2d Michael Hanselmann
      self.assertTrue(str(err).startswith("Failed to load Xen config file:"))
376 57270b2d Michael Hanselmann
    else:
377 57270b2d Michael Hanselmann
      self.fail("Exception was not raised")
378 57270b2d Michael Hanselmann
379 7610d884 Michael Hanselmann
  def testRemovingAutoConfigFile(self):
380 7610d884 Michael Hanselmann
    name = "inst8206.example.com"
381 7610d884 Michael Hanselmann
    cfgfile = utils.PathJoin(self.tmpdir, name)
382 7610d884 Michael Hanselmann
    autodir = utils.PathJoin(self.tmpdir, "auto")
383 7610d884 Michael Hanselmann
    autocfgfile = utils.PathJoin(autodir, name)
384 7610d884 Michael Hanselmann
385 7610d884 Michael Hanselmann
    os.mkdir(autodir)
386 7610d884 Michael Hanselmann
387 7610d884 Michael Hanselmann
    utils.WriteFile(autocfgfile, data="")
388 7610d884 Michael Hanselmann
389 7610d884 Michael Hanselmann
    hv = self._GetHv()
390 7610d884 Michael Hanselmann
391 7610d884 Michael Hanselmann
    self.assertTrue(os.path.isfile(autocfgfile))
392 7610d884 Michael Hanselmann
    hv._WriteConfigFile(name, "content")
393 7610d884 Michael Hanselmann
    self.assertFalse(os.path.exists(autocfgfile))
394 7610d884 Michael Hanselmann
    self.assertEqual(utils.ReadFile(cfgfile), "content")
395 7610d884 Michael Hanselmann
396 b666f213 Michael Hanselmann
  def testVerify(self):
397 b666f213 Michael Hanselmann
    output = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
398 b666f213 Michael Hanselmann
    hv = self._GetHv(run_cmd=compat.partial(self._SuccessCommand,
399 b666f213 Michael Hanselmann
                                            output))
400 b666f213 Michael Hanselmann
    self.assertTrue(hv.Verify() is None)
401 b666f213 Michael Hanselmann
402 b666f213 Michael Hanselmann
  def testVerifyFailing(self):
403 b666f213 Michael Hanselmann
    hv = self._GetHv(run_cmd=self._FailingCommand)
404 b666f213 Michael Hanselmann
    self.assertTrue("failed:" in hv.Verify())
405 b666f213 Michael Hanselmann
406 396672cd Michael Hanselmann
  def _StartInstanceCommand(self, inst, paused, failcreate, cmd):
407 396672cd Michael Hanselmann
    if cmd == [self.CMD, "info"]:
408 396672cd Michael Hanselmann
      output = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
409 396672cd Michael Hanselmann
    elif cmd == [self.CMD, "list"]:
410 396672cd Michael Hanselmann
      output = testutils.ReadTestData("xen-xm-list-4.0.1-dom0-only.txt")
411 396672cd Michael Hanselmann
    elif cmd[:2] == [self.CMD, "create"]:
412 396672cd Michael Hanselmann
      args = cmd[2:]
413 396672cd Michael Hanselmann
      cfgfile = utils.PathJoin(self.tmpdir, inst.name)
414 396672cd Michael Hanselmann
415 396672cd Michael Hanselmann
      if paused:
416 396672cd Michael Hanselmann
        self.assertEqual(args, ["-p", cfgfile])
417 396672cd Michael Hanselmann
      else:
418 396672cd Michael Hanselmann
        self.assertEqual(args, [cfgfile])
419 396672cd Michael Hanselmann
420 396672cd Michael Hanselmann
      if failcreate:
421 396672cd Michael Hanselmann
        return self._FailingCommand(cmd)
422 396672cd Michael Hanselmann
423 396672cd Michael Hanselmann
      output = ""
424 396672cd Michael Hanselmann
    else:
425 396672cd Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
426 396672cd Michael Hanselmann
427 396672cd Michael Hanselmann
    return self._SuccessCommand(output, cmd)
428 396672cd Michael Hanselmann
    #return self._FailingCommand(cmd)
429 396672cd Michael Hanselmann
430 396672cd Michael Hanselmann
  def _MakeInstance(self):
431 396672cd Michael Hanselmann
    # Copy default parameters
432 396672cd Michael Hanselmann
    bep = objects.FillDict(constants.BEC_DEFAULTS, {})
433 396672cd Michael Hanselmann
    hvp = objects.FillDict(constants.HVC_DEFAULTS[self.HVNAME], {})
434 396672cd Michael Hanselmann
435 396672cd Michael Hanselmann
    # Override default VNC password file path
436 396672cd Michael Hanselmann
    if constants.HV_VNC_PASSWORD_FILE in hvp:
437 396672cd Michael Hanselmann
      hvp[constants.HV_VNC_PASSWORD_FILE] = self.vncpw_path
438 396672cd Michael Hanselmann
439 396672cd Michael Hanselmann
    disks = [
440 396672cd Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDWR),
441 396672cd Michael Hanselmann
       utils.PathJoin(self.tmpdir, "disk0")),
442 396672cd Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDONLY),
443 396672cd Michael Hanselmann
       utils.PathJoin(self.tmpdir, "disk1")),
444 396672cd Michael Hanselmann
      ]
445 396672cd Michael Hanselmann
446 396672cd Michael Hanselmann
    inst = objects.Instance(name="server01.example.com",
447 396672cd Michael Hanselmann
                            hvparams=hvp, beparams=bep,
448 396672cd Michael Hanselmann
                            osparams={}, nics=[], os="deb1",
449 396672cd Michael Hanselmann
                            disks=map(compat.fst, disks))
450 396672cd Michael Hanselmann
    inst.UpgradeConfig()
451 396672cd Michael Hanselmann
452 396672cd Michael Hanselmann
    return (inst, disks)
453 396672cd Michael Hanselmann
454 396672cd Michael Hanselmann
  def testStartInstance(self):
455 396672cd Michael Hanselmann
    (inst, disks) = self._MakeInstance()
456 396672cd Michael Hanselmann
457 396672cd Michael Hanselmann
    for failcreate in [False, True]:
458 396672cd Michael Hanselmann
      for paused in [False, True]:
459 396672cd Michael Hanselmann
        run_cmd = compat.partial(self._StartInstanceCommand,
460 396672cd Michael Hanselmann
                                 inst, paused, failcreate)
461 396672cd Michael Hanselmann
462 396672cd Michael Hanselmann
        hv = self._GetHv(run_cmd=run_cmd)
463 396672cd Michael Hanselmann
464 396672cd Michael Hanselmann
        # Ensure instance is not listed
465 396672cd Michael Hanselmann
        self.assertTrue(inst.name not in hv.ListInstances())
466 396672cd Michael Hanselmann
467 396672cd Michael Hanselmann
        # Remove configuration
468 396672cd Michael Hanselmann
        cfgfile = utils.PathJoin(self.tmpdir, inst.name)
469 396672cd Michael Hanselmann
        utils.RemoveFile(cfgfile)
470 396672cd Michael Hanselmann
471 396672cd Michael Hanselmann
        if failcreate:
472 396672cd Michael Hanselmann
          self.assertRaises(errors.HypervisorError, hv.StartInstance,
473 396672cd Michael Hanselmann
                            inst, disks, paused)
474 396672cd Michael Hanselmann
        else:
475 396672cd Michael Hanselmann
          hv.StartInstance(inst, disks, paused)
476 396672cd Michael Hanselmann
477 396672cd Michael Hanselmann
        # Check if configuration was updated
478 396672cd Michael Hanselmann
        lines = utils.ReadFile(cfgfile).splitlines()
479 396672cd Michael Hanselmann
480 396672cd Michael Hanselmann
        if constants.HV_VNC_PASSWORD_FILE in inst.hvparams:
481 396672cd Michael Hanselmann
          self.assertTrue(("vncpasswd = '%s'" % self.vncpw) in lines)
482 396672cd Michael Hanselmann
        else:
483 396672cd Michael Hanselmann
          extra = inst.hvparams[constants.HV_KERNEL_ARGS]
484 396672cd Michael Hanselmann
          self.assertTrue(("extra = '%s'" % extra) in lines)
485 396672cd Michael Hanselmann
486 664b392d Michael Hanselmann
  def _StopInstanceCommand(self, instance_name, force, fail, cmd):
487 664b392d Michael Hanselmann
    if ((force and cmd[:2] == [self.CMD, "destroy"]) or
488 664b392d Michael Hanselmann
        (not force and cmd[:2] == [self.CMD, "shutdown"])):
489 664b392d Michael Hanselmann
      self.assertEqual(cmd[2:], [instance_name])
490 664b392d Michael Hanselmann
      output = ""
491 664b392d Michael Hanselmann
    else:
492 664b392d Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
493 664b392d Michael Hanselmann
494 664b392d Michael Hanselmann
    if fail:
495 664b392d Michael Hanselmann
      # Simulate a failing command
496 664b392d Michael Hanselmann
      return self._FailingCommand(cmd)
497 664b392d Michael Hanselmann
    else:
498 664b392d Michael Hanselmann
      return self._SuccessCommand(output, cmd)
499 664b392d Michael Hanselmann
500 664b392d Michael Hanselmann
  def testStopInstance(self):
501 664b392d Michael Hanselmann
    name = "inst4284.example.com"
502 664b392d Michael Hanselmann
    cfgfile = utils.PathJoin(self.tmpdir, name)
503 664b392d Michael Hanselmann
    cfgdata = "config file content\n"
504 664b392d Michael Hanselmann
505 664b392d Michael Hanselmann
    for force in [False, True]:
506 664b392d Michael Hanselmann
      for fail in [False, True]:
507 664b392d Michael Hanselmann
        utils.WriteFile(cfgfile, data=cfgdata)
508 664b392d Michael Hanselmann
509 664b392d Michael Hanselmann
        run_cmd = compat.partial(self._StopInstanceCommand, name, force, fail)
510 664b392d Michael Hanselmann
511 664b392d Michael Hanselmann
        hv = self._GetHv(run_cmd=run_cmd)
512 664b392d Michael Hanselmann
513 664b392d Michael Hanselmann
        self.assertTrue(os.path.isfile(cfgfile))
514 664b392d Michael Hanselmann
515 664b392d Michael Hanselmann
        if fail:
516 664b392d Michael Hanselmann
          try:
517 664b392d Michael Hanselmann
            hv._StopInstance(name, force)
518 664b392d Michael Hanselmann
          except errors.HypervisorError, err:
519 664b392d Michael Hanselmann
            self.assertTrue(str(err).startswith("Failed to stop instance"))
520 664b392d Michael Hanselmann
          else:
521 664b392d Michael Hanselmann
            self.fail("Exception was not raised")
522 664b392d Michael Hanselmann
          self.assertEqual(utils.ReadFile(cfgfile), cfgdata,
523 664b392d Michael Hanselmann
                           msg=("Configuration was removed when stopping"
524 664b392d Michael Hanselmann
                                " instance failed"))
525 664b392d Michael Hanselmann
        else:
526 664b392d Michael Hanselmann
          hv._StopInstance(name, force)
527 664b392d Michael Hanselmann
          self.assertFalse(os.path.exists(cfgfile))
528 664b392d Michael Hanselmann
529 74a50c46 Michael Hanselmann
530 74a50c46 Michael Hanselmann
def _MakeTestClass(cls, cmd):
531 74a50c46 Michael Hanselmann
  """Makes a class for testing.
532 74a50c46 Michael Hanselmann

533 74a50c46 Michael Hanselmann
  The returned class has structure as shown in the following pseudo code:
534 74a50c46 Michael Hanselmann

535 74a50c46 Michael Hanselmann
    class Test{cls.__name__}{cmd}(_TestXenHypervisor, unittest.TestCase):
536 74a50c46 Michael Hanselmann
      TARGET = {cls}
537 74a50c46 Michael Hanselmann
      CMD = {cmd}
538 74a50c46 Michael Hanselmann
      HVNAME = {Hypervisor name retrieved using class}
539 74a50c46 Michael Hanselmann

540 74a50c46 Michael Hanselmann
  @type cls: class
541 74a50c46 Michael Hanselmann
  @param cls: Hypervisor class to be tested
542 74a50c46 Michael Hanselmann
  @type cmd: string
543 74a50c46 Michael Hanselmann
  @param cmd: Hypervisor command
544 74a50c46 Michael Hanselmann
  @rtype: tuple
545 74a50c46 Michael Hanselmann
  @return: Class name and class object (not instance)
546 74a50c46 Michael Hanselmann

547 74a50c46 Michael Hanselmann
  """
548 74a50c46 Michael Hanselmann
  name = "Test%sCmd%s" % (cls.__name__, cmd.title())
549 74a50c46 Michael Hanselmann
  bases = (_TestXenHypervisor, unittest.TestCase)
550 74a50c46 Michael Hanselmann
  hvname = HVCLASS_TO_HVNAME[cls]
551 74a50c46 Michael Hanselmann
552 74a50c46 Michael Hanselmann
  return (name, type(name, bases, dict(TARGET=cls, CMD=cmd, HVNAME=hvname)))
553 74a50c46 Michael Hanselmann
554 74a50c46 Michael Hanselmann
555 74a50c46 Michael Hanselmann
# Create test classes programmatically instead of manually to reduce the risk
556 74a50c46 Michael Hanselmann
# of forgetting some combinations
557 74a50c46 Michael Hanselmann
for cls in [hv_xen.XenPvmHypervisor, hv_xen.XenHvmHypervisor]:
558 74a50c46 Michael Hanselmann
  for cmd in constants.KNOWN_XEN_COMMANDS:
559 74a50c46 Michael Hanselmann
    (name, testcls) = _MakeTestClass(cls, cmd)
560 74a50c46 Michael Hanselmann
561 74a50c46 Michael Hanselmann
    assert name not in locals()
562 74a50c46 Michael Hanselmann
563 74a50c46 Michael Hanselmann
    locals()[name] = testcls
564 74a50c46 Michael Hanselmann
565 74a50c46 Michael Hanselmann
566 55cc0a44 Michael Hanselmann
if __name__ == "__main__":
567 55cc0a44 Michael Hanselmann
  testutils.GanetiTestProgram()