Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hypervisor.hv_xen_unittest.py @ 3eb073a6

History | View | Annotate | Download (24.9 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 b44af065 Helga Velroyen
"""Script for testing ganeti.hypervisor.hv_xen"""
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 48bba9de Balazs Lecz
from ganeti import pathutils
34 55cc0a44 Michael Hanselmann
from ganeti import hypervisor
35 b255379d Michael Hanselmann
from ganeti import utils
36 b255379d Michael Hanselmann
from ganeti import errors
37 b255379d Michael Hanselmann
from ganeti import compat
38 55cc0a44 Michael Hanselmann
39 55cc0a44 Michael Hanselmann
from ganeti.hypervisor import hv_xen
40 55cc0a44 Michael Hanselmann
41 55cc0a44 Michael Hanselmann
import testutils
42 55cc0a44 Michael Hanselmann
43 55cc0a44 Michael Hanselmann
44 74a50c46 Michael Hanselmann
# Map from hypervisor class to hypervisor name
45 74a50c46 Michael Hanselmann
HVCLASS_TO_HVNAME = utils.InvertDict(hypervisor._HYPERVISOR_MAP)
46 74a50c46 Michael Hanselmann
47 74a50c46 Michael Hanselmann
48 55cc0a44 Michael Hanselmann
class TestConsole(unittest.TestCase):
49 55cc0a44 Michael Hanselmann
  def test(self):
50 55cc0a44 Michael Hanselmann
    for cls in [hv_xen.XenPvmHypervisor, hv_xen.XenHvmHypervisor]:
51 55cc0a44 Michael Hanselmann
      instance = objects.Instance(name="xen.example.com",
52 55cc0a44 Michael Hanselmann
                                  primary_node="node24828")
53 55cc0a44 Michael Hanselmann
      cons = cls.GetInstanceConsole(instance, {}, {})
54 55cc0a44 Michael Hanselmann
      self.assertTrue(cons.Validate())
55 55cc0a44 Michael Hanselmann
      self.assertEqual(cons.kind, constants.CONS_SSH)
56 55cc0a44 Michael Hanselmann
      self.assertEqual(cons.host, instance.primary_node)
57 55cc0a44 Michael Hanselmann
      self.assertEqual(cons.command[-1], instance.name)
58 55cc0a44 Michael Hanselmann
59 55cc0a44 Michael Hanselmann
60 347fa0f1 Michael Hanselmann
class TestCreateConfigCpus(unittest.TestCase):
61 347fa0f1 Michael Hanselmann
  def testEmpty(self):
62 347fa0f1 Michael Hanselmann
    for cpu_mask in [None, ""]:
63 347fa0f1 Michael Hanselmann
      self.assertEqual(hv_xen._CreateConfigCpus(cpu_mask),
64 347fa0f1 Michael Hanselmann
                       "cpus = [  ]")
65 347fa0f1 Michael Hanselmann
66 347fa0f1 Michael Hanselmann
  def testAll(self):
67 347fa0f1 Michael Hanselmann
    self.assertEqual(hv_xen._CreateConfigCpus(constants.CPU_PINNING_ALL),
68 347fa0f1 Michael Hanselmann
                     None)
69 347fa0f1 Michael Hanselmann
70 347fa0f1 Michael Hanselmann
  def testOne(self):
71 347fa0f1 Michael Hanselmann
    self.assertEqual(hv_xen._CreateConfigCpus("9"), "cpu = \"9\"")
72 347fa0f1 Michael Hanselmann
73 347fa0f1 Michael Hanselmann
  def testMultiple(self):
74 347fa0f1 Michael Hanselmann
    self.assertEqual(hv_xen._CreateConfigCpus("0-2,4,5-5:3:all"),
75 347fa0f1 Michael Hanselmann
                     ("cpus = [ \"0,1,2,4,5\", \"3\", \"%s\" ]" %
76 347fa0f1 Michael Hanselmann
                      constants.CPU_PINNING_ALL_XEN))
77 347fa0f1 Michael Hanselmann
78 347fa0f1 Michael Hanselmann
79 3eb073a6 Helga Velroyen
class TestGetCommand(testutils.GanetiTestCase):
80 3eb073a6 Helga Velroyen
  def testDefault(self):
81 3eb073a6 Helga Velroyen
    expected_cmd = "xm"
82 3eb073a6 Helga Velroyen
    hv = hv_xen.XenHypervisor()
83 3eb073a6 Helga Velroyen
    self.assertEqual(hv._GetCommand(), expected_cmd)
84 3eb073a6 Helga Velroyen
85 3eb073a6 Helga Velroyen
  def testCommandExplicit(self):
86 3eb073a6 Helga Velroyen
    """Test the case when the command is given as class parameter explicitly.
87 3eb073a6 Helga Velroyen

88 3eb073a6 Helga Velroyen
    """
89 3eb073a6 Helga Velroyen
    expected_cmd = "xl"
90 3eb073a6 Helga Velroyen
    hv = hv_xen.XenHypervisor(_cmd=constants.XEN_CMD_XL)
91 3eb073a6 Helga Velroyen
    self.assertEqual(hv._GetCommand(), expected_cmd)
92 3eb073a6 Helga Velroyen
93 3eb073a6 Helga Velroyen
  def testCommandInvalid(self):
94 3eb073a6 Helga Velroyen
    """Test the case an invalid command is given as class parameter explicitly.
95 3eb073a6 Helga Velroyen

96 3eb073a6 Helga Velroyen
    """
97 3eb073a6 Helga Velroyen
    hv = hv_xen.XenHypervisor(_cmd="invalidcommand")
98 3eb073a6 Helga Velroyen
    self.assertRaises(errors.ProgrammerError, hv._GetCommand, None)
99 3eb073a6 Helga Velroyen
100 3eb073a6 Helga Velroyen
101 b255379d Michael Hanselmann
class TestParseXmList(testutils.GanetiTestCase):
102 b255379d Michael Hanselmann
  def test(self):
103 b255379d Michael Hanselmann
    data = testutils.ReadTestData("xen-xm-list-4.0.1-dom0-only.txt")
104 b255379d Michael Hanselmann
105 b255379d Michael Hanselmann
    # Exclude node
106 b255379d Michael Hanselmann
    self.assertEqual(hv_xen._ParseXmList(data.splitlines(), False), [])
107 b255379d Michael Hanselmann
108 b255379d Michael Hanselmann
    # Include node
109 b255379d Michael Hanselmann
    result = hv_xen._ParseXmList(data.splitlines(), True)
110 b255379d Michael Hanselmann
    self.assertEqual(len(result), 1)
111 b255379d Michael Hanselmann
    self.assertEqual(len(result[0]), 6)
112 b255379d Michael Hanselmann
113 b255379d Michael Hanselmann
    # Name
114 b255379d Michael Hanselmann
    self.assertEqual(result[0][0], hv_xen._DOM0_NAME)
115 b255379d Michael Hanselmann
116 b255379d Michael Hanselmann
    # ID
117 b255379d Michael Hanselmann
    self.assertEqual(result[0][1], 0)
118 b255379d Michael Hanselmann
119 b255379d Michael Hanselmann
    # Memory
120 b255379d Michael Hanselmann
    self.assertEqual(result[0][2], 1023)
121 b255379d Michael Hanselmann
122 b255379d Michael Hanselmann
    # VCPUs
123 b255379d Michael Hanselmann
    self.assertEqual(result[0][3], 1)
124 b255379d Michael Hanselmann
125 b255379d Michael Hanselmann
    # State
126 b255379d Michael Hanselmann
    self.assertEqual(result[0][4], "r-----")
127 b255379d Michael Hanselmann
128 b255379d Michael Hanselmann
    # Time
129 b255379d Michael Hanselmann
    self.assertAlmostEqual(result[0][5], 121152.6)
130 b255379d Michael Hanselmann
131 b255379d Michael Hanselmann
  def testWrongLineFormat(self):
132 b255379d Michael Hanselmann
    tests = [
133 b255379d Michael Hanselmann
      ["three fields only"],
134 b255379d Michael Hanselmann
      ["name InvalidID 128 1 r----- 12345"],
135 b255379d Michael Hanselmann
      ]
136 b255379d Michael Hanselmann
137 b255379d Michael Hanselmann
    for lines in tests:
138 b255379d Michael Hanselmann
      try:
139 b255379d Michael Hanselmann
        hv_xen._ParseXmList(["Header would be here"] + lines, False)
140 b255379d Michael Hanselmann
      except errors.HypervisorError, err:
141 b255379d Michael Hanselmann
        self.assertTrue("Can't parse output of xm list" in str(err))
142 b255379d Michael Hanselmann
      else:
143 b255379d Michael Hanselmann
        self.fail("Exception was not raised")
144 b255379d Michael Hanselmann
145 b255379d Michael Hanselmann
146 b255379d Michael Hanselmann
class TestGetXmList(testutils.GanetiTestCase):
147 b255379d Michael Hanselmann
  def _Fail(self):
148 b255379d Michael Hanselmann
    return utils.RunResult(constants.EXIT_FAILURE, None,
149 b255379d Michael Hanselmann
                           "stdout", "stderr", None,
150 b255379d Michael Hanselmann
                           NotImplemented, NotImplemented)
151 b255379d Michael Hanselmann
152 b255379d Michael Hanselmann
  def testTimeout(self):
153 b255379d Michael Hanselmann
    fn = testutils.CallCounter(self._Fail)
154 b255379d Michael Hanselmann
    try:
155 b255379d Michael Hanselmann
      hv_xen._GetXmList(fn, False, _timeout=0.1)
156 b255379d Michael Hanselmann
    except errors.HypervisorError, err:
157 b255379d Michael Hanselmann
      self.assertTrue("timeout exceeded" in str(err))
158 b255379d Michael Hanselmann
    else:
159 b255379d Michael Hanselmann
      self.fail("Exception was not raised")
160 b255379d Michael Hanselmann
161 b255379d Michael Hanselmann
    self.assertTrue(fn.Count() < 10,
162 b255379d Michael Hanselmann
                    msg="'xm list' was called too many times")
163 b255379d Michael Hanselmann
164 b255379d Michael Hanselmann
  def _Success(self, stdout):
165 b255379d Michael Hanselmann
    return utils.RunResult(constants.EXIT_SUCCESS, None, stdout, "", None,
166 b255379d Michael Hanselmann
                           NotImplemented, NotImplemented)
167 b255379d Michael Hanselmann
168 b255379d Michael Hanselmann
  def testSuccess(self):
169 b255379d Michael Hanselmann
    data = testutils.ReadTestData("xen-xm-list-4.0.1-four-instances.txt")
170 b255379d Michael Hanselmann
171 b255379d Michael Hanselmann
    fn = testutils.CallCounter(compat.partial(self._Success, data))
172 b255379d Michael Hanselmann
173 b255379d Michael Hanselmann
    result = hv_xen._GetXmList(fn, True, _timeout=0.1)
174 b255379d Michael Hanselmann
175 b255379d Michael Hanselmann
    self.assertEqual(len(result), 4)
176 b255379d Michael Hanselmann
177 b255379d Michael Hanselmann
    self.assertEqual(map(compat.fst, result), [
178 b255379d Michael Hanselmann
      "Domain-0",
179 b255379d Michael Hanselmann
      "server01.example.com",
180 b255379d Michael Hanselmann
      "web3106215069.example.com",
181 b255379d Michael Hanselmann
      "testinstance.example.com",
182 b255379d Michael Hanselmann
      ])
183 b255379d Michael Hanselmann
184 b255379d Michael Hanselmann
    self.assertEqual(fn.Count(), 1)
185 b255379d Michael Hanselmann
186 b255379d Michael Hanselmann
187 06c9a520 Michael Hanselmann
class TestParseNodeInfo(testutils.GanetiTestCase):
188 06c9a520 Michael Hanselmann
  def testEmpty(self):
189 06c9a520 Michael Hanselmann
    self.assertEqual(hv_xen._ParseNodeInfo(""), {})
190 06c9a520 Michael Hanselmann
191 06c9a520 Michael Hanselmann
  def testUnknownInput(self):
192 06c9a520 Michael Hanselmann
    data = "\n".join([
193 06c9a520 Michael Hanselmann
      "foo bar",
194 06c9a520 Michael Hanselmann
      "something else goes",
195 06c9a520 Michael Hanselmann
      "here",
196 06c9a520 Michael Hanselmann
      ])
197 06c9a520 Michael Hanselmann
    self.assertEqual(hv_xen._ParseNodeInfo(data), {})
198 06c9a520 Michael Hanselmann
199 06c9a520 Michael Hanselmann
  def testBasicInfo(self):
200 06c9a520 Michael Hanselmann
    data = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
201 06c9a520 Michael Hanselmann
    result = hv_xen._ParseNodeInfo(data)
202 06c9a520 Michael Hanselmann
    self.assertEqual(result, {
203 06c9a520 Michael Hanselmann
      "cpu_nodes": 1,
204 06c9a520 Michael Hanselmann
      "cpu_sockets": 2,
205 06c9a520 Michael Hanselmann
      "cpu_total": 4,
206 06c9a520 Michael Hanselmann
      "hv_version": (4, 0),
207 06c9a520 Michael Hanselmann
      "memory_free": 8004,
208 06c9a520 Michael Hanselmann
      "memory_total": 16378,
209 06c9a520 Michael Hanselmann
      })
210 06c9a520 Michael Hanselmann
211 06c9a520 Michael Hanselmann
212 06c9a520 Michael Hanselmann
class TestMergeInstanceInfo(testutils.GanetiTestCase):
213 06c9a520 Michael Hanselmann
  def testEmpty(self):
214 06c9a520 Michael Hanselmann
    self.assertEqual(hv_xen._MergeInstanceInfo({}, lambda _: []), {})
215 06c9a520 Michael Hanselmann
216 06c9a520 Michael Hanselmann
  def _FakeXmList(self, include_node):
217 06c9a520 Michael Hanselmann
    self.assertTrue(include_node)
218 06c9a520 Michael Hanselmann
    return [
219 06c9a520 Michael Hanselmann
      (hv_xen._DOM0_NAME, NotImplemented, 4096, 7, NotImplemented,
220 06c9a520 Michael Hanselmann
       NotImplemented),
221 06c9a520 Michael Hanselmann
      ("inst1.example.com", NotImplemented, 2048, 4, NotImplemented,
222 06c9a520 Michael Hanselmann
       NotImplemented),
223 06c9a520 Michael Hanselmann
      ]
224 06c9a520 Michael Hanselmann
225 06c9a520 Michael Hanselmann
  def testMissingNodeInfo(self):
226 06c9a520 Michael Hanselmann
    result = hv_xen._MergeInstanceInfo({}, self._FakeXmList)
227 06c9a520 Michael Hanselmann
    self.assertEqual(result, {
228 06c9a520 Michael Hanselmann
      "memory_dom0": 4096,
229 06c9a520 Michael Hanselmann
      "dom0_cpus": 7,
230 06c9a520 Michael Hanselmann
      })
231 06c9a520 Michael Hanselmann
232 06c9a520 Michael Hanselmann
  def testWithNodeInfo(self):
233 06c9a520 Michael Hanselmann
    info = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
234 06c9a520 Michael Hanselmann
    result = hv_xen._GetNodeInfo(info, self._FakeXmList)
235 06c9a520 Michael Hanselmann
    self.assertEqual(result, {
236 06c9a520 Michael Hanselmann
      "cpu_nodes": 1,
237 06c9a520 Michael Hanselmann
      "cpu_sockets": 2,
238 06c9a520 Michael Hanselmann
      "cpu_total": 4,
239 06c9a520 Michael Hanselmann
      "dom0_cpus": 7,
240 06c9a520 Michael Hanselmann
      "hv_version": (4, 0),
241 06c9a520 Michael Hanselmann
      "memory_dom0": 4096,
242 06c9a520 Michael Hanselmann
      "memory_free": 8004,
243 06c9a520 Michael Hanselmann
      "memory_hv": 2230,
244 06c9a520 Michael Hanselmann
      "memory_total": 16378,
245 06c9a520 Michael Hanselmann
      })
246 06c9a520 Michael Hanselmann
247 06c9a520 Michael Hanselmann
248 d0bb3f24 Michael Hanselmann
class TestGetConfigFileDiskData(unittest.TestCase):
249 d0bb3f24 Michael Hanselmann
  def testLetterCount(self):
250 d0bb3f24 Michael Hanselmann
    self.assertEqual(len(hv_xen._DISK_LETTERS), 26)
251 d0bb3f24 Michael Hanselmann
252 d0bb3f24 Michael Hanselmann
  def testNoDisks(self):
253 d0bb3f24 Michael Hanselmann
    self.assertEqual(hv_xen._GetConfigFileDiskData([], "hd"), [])
254 d0bb3f24 Michael Hanselmann
255 d0bb3f24 Michael Hanselmann
  def testManyDisks(self):
256 d0bb3f24 Michael Hanselmann
    for offset in [0, 1, 10]:
257 d0bb3f24 Michael Hanselmann
      disks = [(objects.Disk(dev_type=constants.LD_LV), "/tmp/disk/%s" % idx)
258 d0bb3f24 Michael Hanselmann
               for idx in range(len(hv_xen._DISK_LETTERS) + offset)]
259 d0bb3f24 Michael Hanselmann
260 d0bb3f24 Michael Hanselmann
      if offset == 0:
261 d0bb3f24 Michael Hanselmann
        result = hv_xen._GetConfigFileDiskData(disks, "hd")
262 d0bb3f24 Michael Hanselmann
        self.assertEqual(result, [
263 d0bb3f24 Michael Hanselmann
          "'phy:/tmp/disk/%s,hd%s,r'" % (idx, string.ascii_lowercase[idx])
264 d0bb3f24 Michael Hanselmann
          for idx in range(len(hv_xen._DISK_LETTERS) + offset)
265 d0bb3f24 Michael Hanselmann
          ])
266 d0bb3f24 Michael Hanselmann
      else:
267 d0bb3f24 Michael Hanselmann
        try:
268 d0bb3f24 Michael Hanselmann
          hv_xen._GetConfigFileDiskData(disks, "hd")
269 d0bb3f24 Michael Hanselmann
        except errors.HypervisorError, err:
270 d0bb3f24 Michael Hanselmann
          self.assertEqual(str(err), "Too many disks")
271 d0bb3f24 Michael Hanselmann
        else:
272 d0bb3f24 Michael Hanselmann
          self.fail("Exception was not raised")
273 d0bb3f24 Michael Hanselmann
274 d0bb3f24 Michael Hanselmann
  def testTwoLvDisksWithMode(self):
275 d0bb3f24 Michael Hanselmann
    disks = [
276 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDWR),
277 d0bb3f24 Michael Hanselmann
       "/tmp/diskFirst"),
278 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDONLY),
279 d0bb3f24 Michael Hanselmann
       "/tmp/diskLast"),
280 d0bb3f24 Michael Hanselmann
      ]
281 d0bb3f24 Michael Hanselmann
282 d0bb3f24 Michael Hanselmann
    result = hv_xen._GetConfigFileDiskData(disks, "hd")
283 d0bb3f24 Michael Hanselmann
    self.assertEqual(result, [
284 d0bb3f24 Michael Hanselmann
      "'phy:/tmp/diskFirst,hda,w'",
285 d0bb3f24 Michael Hanselmann
      "'phy:/tmp/diskLast,hdb,r'",
286 d0bb3f24 Michael Hanselmann
      ])
287 d0bb3f24 Michael Hanselmann
288 d0bb3f24 Michael Hanselmann
  def testFileDisks(self):
289 d0bb3f24 Michael Hanselmann
    disks = [
290 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
291 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_LOOP]),
292 d0bb3f24 Michael Hanselmann
       "/tmp/diskFirst"),
293 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDONLY,
294 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_BLKTAP]),
295 d0bb3f24 Michael Hanselmann
       "/tmp/diskTwo"),
296 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
297 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_LOOP]),
298 d0bb3f24 Michael Hanselmann
       "/tmp/diskThree"),
299 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
300 d0bb3f24 Michael Hanselmann
                    physical_id=[constants.FD_BLKTAP]),
301 d0bb3f24 Michael Hanselmann
       "/tmp/diskLast"),
302 d0bb3f24 Michael Hanselmann
      ]
303 d0bb3f24 Michael Hanselmann
304 d0bb3f24 Michael Hanselmann
    result = hv_xen._GetConfigFileDiskData(disks, "sd")
305 d0bb3f24 Michael Hanselmann
    self.assertEqual(result, [
306 d0bb3f24 Michael Hanselmann
      "'file:/tmp/diskFirst,sda,w'",
307 d0bb3f24 Michael Hanselmann
      "'tap:aio:/tmp/diskTwo,sdb,r'",
308 d0bb3f24 Michael Hanselmann
      "'file:/tmp/diskThree,sdc,w'",
309 d0bb3f24 Michael Hanselmann
      "'tap:aio:/tmp/diskLast,sdd,w'",
310 d0bb3f24 Michael Hanselmann
      ])
311 d0bb3f24 Michael Hanselmann
312 d0bb3f24 Michael Hanselmann
  def testInvalidFileDisk(self):
313 d0bb3f24 Michael Hanselmann
    disks = [
314 d0bb3f24 Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR,
315 d0bb3f24 Michael Hanselmann
                    physical_id=["#unknown#"]),
316 d0bb3f24 Michael Hanselmann
       "/tmp/diskinvalid"),
317 d0bb3f24 Michael Hanselmann
      ]
318 d0bb3f24 Michael Hanselmann
319 d0bb3f24 Michael Hanselmann
    self.assertRaises(KeyError, hv_xen._GetConfigFileDiskData, disks, "sd")
320 d0bb3f24 Michael Hanselmann
321 d0bb3f24 Michael Hanselmann
322 1dee2041 Michael Hanselmann
class TestXenHypervisorUnknownCommand(unittest.TestCase):
323 1dee2041 Michael Hanselmann
  def test(self):
324 1dee2041 Michael Hanselmann
    cmd = "#unknown command#"
325 1dee2041 Michael Hanselmann
    self.assertFalse(cmd in constants.KNOWN_XEN_COMMANDS)
326 1dee2041 Michael Hanselmann
    hv = hv_xen.XenHypervisor(_cfgdir=NotImplemented,
327 1dee2041 Michael Hanselmann
                              _run_cmd_fn=NotImplemented,
328 1dee2041 Michael Hanselmann
                              _cmd=cmd)
329 1dee2041 Michael Hanselmann
    self.assertRaises(errors.ProgrammerError, hv._RunXen, [])
330 1dee2041 Michael Hanselmann
331 1dee2041 Michael Hanselmann
332 64a66bd2 Michael Hanselmann
class TestXenHypervisorWriteConfigFile(unittest.TestCase):
333 64a66bd2 Michael Hanselmann
  def setUp(self):
334 64a66bd2 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
335 64a66bd2 Michael Hanselmann
336 64a66bd2 Michael Hanselmann
  def tearDown(self):
337 64a66bd2 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
338 64a66bd2 Michael Hanselmann
339 64a66bd2 Michael Hanselmann
  def testWriteError(self):
340 64a66bd2 Michael Hanselmann
    cfgdir = utils.PathJoin(self.tmpdir, "foobar")
341 64a66bd2 Michael Hanselmann
342 64a66bd2 Michael Hanselmann
    hv = hv_xen.XenHypervisor(_cfgdir=cfgdir,
343 64a66bd2 Michael Hanselmann
                              _run_cmd_fn=NotImplemented,
344 64a66bd2 Michael Hanselmann
                              _cmd=NotImplemented)
345 64a66bd2 Michael Hanselmann
346 64a66bd2 Michael Hanselmann
    self.assertFalse(os.path.exists(cfgdir))
347 64a66bd2 Michael Hanselmann
348 64a66bd2 Michael Hanselmann
    try:
349 64a66bd2 Michael Hanselmann
      hv._WriteConfigFile("name", "data")
350 64a66bd2 Michael Hanselmann
    except errors.HypervisorError, err:
351 64a66bd2 Michael Hanselmann
      self.assertTrue(str(err).startswith("Cannot write Xen instance"))
352 64a66bd2 Michael Hanselmann
    else:
353 64a66bd2 Michael Hanselmann
      self.fail("Exception was not raised")
354 64a66bd2 Michael Hanselmann
355 64a66bd2 Michael Hanselmann
356 74a50c46 Michael Hanselmann
class _TestXenHypervisor(object):
357 74a50c46 Michael Hanselmann
  TARGET = NotImplemented
358 74a50c46 Michael Hanselmann
  CMD = NotImplemented
359 74a50c46 Michael Hanselmann
  HVNAME = NotImplemented
360 74a50c46 Michael Hanselmann
361 74a50c46 Michael Hanselmann
  def setUp(self):
362 74a50c46 Michael Hanselmann
    super(_TestXenHypervisor, self).setUp()
363 74a50c46 Michael Hanselmann
364 74a50c46 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
365 74a50c46 Michael Hanselmann
366 74a50c46 Michael Hanselmann
    self.vncpw = "".join(random.sample(string.ascii_letters, 10))
367 74a50c46 Michael Hanselmann
368 74a50c46 Michael Hanselmann
    self.vncpw_path = utils.PathJoin(self.tmpdir, "vncpw")
369 74a50c46 Michael Hanselmann
    utils.WriteFile(self.vncpw_path, data=self.vncpw)
370 74a50c46 Michael Hanselmann
371 74a50c46 Michael Hanselmann
  def tearDown(self):
372 74a50c46 Michael Hanselmann
    super(_TestXenHypervisor, self).tearDown()
373 74a50c46 Michael Hanselmann
374 74a50c46 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
375 74a50c46 Michael Hanselmann
376 74a50c46 Michael Hanselmann
  def _GetHv(self, run_cmd=NotImplemented):
377 74a50c46 Michael Hanselmann
    return self.TARGET(_cfgdir=self.tmpdir, _run_cmd_fn=run_cmd, _cmd=self.CMD)
378 74a50c46 Michael Hanselmann
379 74a50c46 Michael Hanselmann
  def _SuccessCommand(self, stdout, cmd):
380 74a50c46 Michael Hanselmann
    self.assertEqual(cmd[0], self.CMD)
381 74a50c46 Michael Hanselmann
382 74a50c46 Michael Hanselmann
    return utils.RunResult(constants.EXIT_SUCCESS, None, stdout, "", None,
383 74a50c46 Michael Hanselmann
                           NotImplemented, NotImplemented)
384 74a50c46 Michael Hanselmann
385 74a50c46 Michael Hanselmann
  def _FailingCommand(self, cmd):
386 74a50c46 Michael Hanselmann
    self.assertEqual(cmd[0], self.CMD)
387 74a50c46 Michael Hanselmann
388 74a50c46 Michael Hanselmann
    return utils.RunResult(constants.EXIT_FAILURE, None,
389 74a50c46 Michael Hanselmann
                           "", "This command failed", None,
390 74a50c46 Michael Hanselmann
                           NotImplemented, NotImplemented)
391 74a50c46 Michael Hanselmann
392 d8784f7d Michael Hanselmann
  def _FakeTcpPing(self, expected, result, target, port, **kwargs):
393 d8784f7d Michael Hanselmann
    self.assertEqual((target, port), expected)
394 d8784f7d Michael Hanselmann
    return result
395 d8784f7d Michael Hanselmann
396 57270b2d Michael Hanselmann
  def testReadingNonExistentConfigFile(self):
397 57270b2d Michael Hanselmann
    hv = self._GetHv()
398 57270b2d Michael Hanselmann
399 57270b2d Michael Hanselmann
    try:
400 57270b2d Michael Hanselmann
      hv._ReadConfigFile("inst15780.example.com")
401 57270b2d Michael Hanselmann
    except errors.HypervisorError, err:
402 57270b2d Michael Hanselmann
      self.assertTrue(str(err).startswith("Failed to load Xen config file:"))
403 57270b2d Michael Hanselmann
    else:
404 57270b2d Michael Hanselmann
      self.fail("Exception was not raised")
405 57270b2d Michael Hanselmann
406 7610d884 Michael Hanselmann
  def testRemovingAutoConfigFile(self):
407 7610d884 Michael Hanselmann
    name = "inst8206.example.com"
408 7610d884 Michael Hanselmann
    cfgfile = utils.PathJoin(self.tmpdir, name)
409 7610d884 Michael Hanselmann
    autodir = utils.PathJoin(self.tmpdir, "auto")
410 7610d884 Michael Hanselmann
    autocfgfile = utils.PathJoin(autodir, name)
411 7610d884 Michael Hanselmann
412 7610d884 Michael Hanselmann
    os.mkdir(autodir)
413 7610d884 Michael Hanselmann
414 7610d884 Michael Hanselmann
    utils.WriteFile(autocfgfile, data="")
415 7610d884 Michael Hanselmann
416 7610d884 Michael Hanselmann
    hv = self._GetHv()
417 7610d884 Michael Hanselmann
418 7610d884 Michael Hanselmann
    self.assertTrue(os.path.isfile(autocfgfile))
419 7610d884 Michael Hanselmann
    hv._WriteConfigFile(name, "content")
420 7610d884 Michael Hanselmann
    self.assertFalse(os.path.exists(autocfgfile))
421 7610d884 Michael Hanselmann
    self.assertEqual(utils.ReadFile(cfgfile), "content")
422 7610d884 Michael Hanselmann
423 2edc1c79 Michael Hanselmann
  def _XenList(self, cmd):
424 2edc1c79 Michael Hanselmann
    self.assertEqual(cmd, [self.CMD, "list"])
425 2edc1c79 Michael Hanselmann
426 2edc1c79 Michael Hanselmann
    # TODO: Use actual data from "xl" command
427 2edc1c79 Michael Hanselmann
    output = testutils.ReadTestData("xen-xm-list-4.0.1-four-instances.txt")
428 2edc1c79 Michael Hanselmann
429 2edc1c79 Michael Hanselmann
    return self._SuccessCommand(output, cmd)
430 2edc1c79 Michael Hanselmann
431 2edc1c79 Michael Hanselmann
  def testGetInstanceInfo(self):
432 2edc1c79 Michael Hanselmann
    hv = self._GetHv(run_cmd=self._XenList)
433 2edc1c79 Michael Hanselmann
434 2edc1c79 Michael Hanselmann
    (name, instid, memory, vcpus, state, runtime) = \
435 2edc1c79 Michael Hanselmann
      hv.GetInstanceInfo("server01.example.com")
436 2edc1c79 Michael Hanselmann
437 2edc1c79 Michael Hanselmann
    self.assertEqual(name, "server01.example.com")
438 2edc1c79 Michael Hanselmann
    self.assertEqual(instid, 1)
439 2edc1c79 Michael Hanselmann
    self.assertEqual(memory, 1024)
440 2edc1c79 Michael Hanselmann
    self.assertEqual(vcpus, 1)
441 2edc1c79 Michael Hanselmann
    self.assertEqual(state, "-b----")
442 2edc1c79 Michael Hanselmann
    self.assertAlmostEqual(runtime, 167643.2)
443 2edc1c79 Michael Hanselmann
444 2edc1c79 Michael Hanselmann
  def testGetInstanceInfoDom0(self):
445 2edc1c79 Michael Hanselmann
    hv = self._GetHv(run_cmd=self._XenList)
446 2edc1c79 Michael Hanselmann
447 2edc1c79 Michael Hanselmann
    # TODO: Not sure if this is actually used anywhere (can't find it), but the
448 2edc1c79 Michael Hanselmann
    # code supports querying for Dom0
449 2edc1c79 Michael Hanselmann
    (name, instid, memory, vcpus, state, runtime) = \
450 2edc1c79 Michael Hanselmann
      hv.GetInstanceInfo(hv_xen._DOM0_NAME)
451 2edc1c79 Michael Hanselmann
452 2edc1c79 Michael Hanselmann
    self.assertEqual(name, "Domain-0")
453 2edc1c79 Michael Hanselmann
    self.assertEqual(instid, 0)
454 2edc1c79 Michael Hanselmann
    self.assertEqual(memory, 1023)
455 2edc1c79 Michael Hanselmann
    self.assertEqual(vcpus, 1)
456 2edc1c79 Michael Hanselmann
    self.assertEqual(state, "r-----")
457 2edc1c79 Michael Hanselmann
    self.assertAlmostEqual(runtime, 154706.1)
458 2edc1c79 Michael Hanselmann
459 2edc1c79 Michael Hanselmann
  def testGetInstanceInfoUnknown(self):
460 2edc1c79 Michael Hanselmann
    hv = self._GetHv(run_cmd=self._XenList)
461 2edc1c79 Michael Hanselmann
462 2edc1c79 Michael Hanselmann
    result = hv.GetInstanceInfo("unknown.example.com")
463 2edc1c79 Michael Hanselmann
    self.assertTrue(result is None)
464 2edc1c79 Michael Hanselmann
465 2edc1c79 Michael Hanselmann
  def testGetAllInstancesInfo(self):
466 2edc1c79 Michael Hanselmann
    hv = self._GetHv(run_cmd=self._XenList)
467 2edc1c79 Michael Hanselmann
468 2edc1c79 Michael Hanselmann
    result = hv.GetAllInstancesInfo()
469 2edc1c79 Michael Hanselmann
470 2edc1c79 Michael Hanselmann
    self.assertEqual(map(compat.fst, result), [
471 2edc1c79 Michael Hanselmann
      "server01.example.com",
472 2edc1c79 Michael Hanselmann
      "web3106215069.example.com",
473 2edc1c79 Michael Hanselmann
      "testinstance.example.com",
474 2edc1c79 Michael Hanselmann
      ])
475 2edc1c79 Michael Hanselmann
476 2edc1c79 Michael Hanselmann
  def testListInstances(self):
477 2edc1c79 Michael Hanselmann
    hv = self._GetHv(run_cmd=self._XenList)
478 2edc1c79 Michael Hanselmann
479 2edc1c79 Michael Hanselmann
    self.assertEqual(hv.ListInstances(), [
480 2edc1c79 Michael Hanselmann
      "server01.example.com",
481 2edc1c79 Michael Hanselmann
      "web3106215069.example.com",
482 2edc1c79 Michael Hanselmann
      "testinstance.example.com",
483 2edc1c79 Michael Hanselmann
      ])
484 2edc1c79 Michael Hanselmann
485 b666f213 Michael Hanselmann
  def testVerify(self):
486 b666f213 Michael Hanselmann
    output = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
487 b666f213 Michael Hanselmann
    hv = self._GetHv(run_cmd=compat.partial(self._SuccessCommand,
488 b666f213 Michael Hanselmann
                                            output))
489 b666f213 Michael Hanselmann
    self.assertTrue(hv.Verify() is None)
490 b666f213 Michael Hanselmann
491 b666f213 Michael Hanselmann
  def testVerifyFailing(self):
492 b666f213 Michael Hanselmann
    hv = self._GetHv(run_cmd=self._FailingCommand)
493 b666f213 Michael Hanselmann
    self.assertTrue("failed:" in hv.Verify())
494 b666f213 Michael Hanselmann
495 396672cd Michael Hanselmann
  def _StartInstanceCommand(self, inst, paused, failcreate, cmd):
496 396672cd Michael Hanselmann
    if cmd == [self.CMD, "info"]:
497 396672cd Michael Hanselmann
      output = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
498 396672cd Michael Hanselmann
    elif cmd == [self.CMD, "list"]:
499 396672cd Michael Hanselmann
      output = testutils.ReadTestData("xen-xm-list-4.0.1-dom0-only.txt")
500 396672cd Michael Hanselmann
    elif cmd[:2] == [self.CMD, "create"]:
501 396672cd Michael Hanselmann
      args = cmd[2:]
502 396672cd Michael Hanselmann
      cfgfile = utils.PathJoin(self.tmpdir, inst.name)
503 396672cd Michael Hanselmann
504 396672cd Michael Hanselmann
      if paused:
505 396672cd Michael Hanselmann
        self.assertEqual(args, ["-p", cfgfile])
506 396672cd Michael Hanselmann
      else:
507 396672cd Michael Hanselmann
        self.assertEqual(args, [cfgfile])
508 396672cd Michael Hanselmann
509 396672cd Michael Hanselmann
      if failcreate:
510 396672cd Michael Hanselmann
        return self._FailingCommand(cmd)
511 396672cd Michael Hanselmann
512 396672cd Michael Hanselmann
      output = ""
513 396672cd Michael Hanselmann
    else:
514 396672cd Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
515 396672cd Michael Hanselmann
516 396672cd Michael Hanselmann
    return self._SuccessCommand(output, cmd)
517 396672cd Michael Hanselmann
518 396672cd Michael Hanselmann
  def _MakeInstance(self):
519 396672cd Michael Hanselmann
    # Copy default parameters
520 396672cd Michael Hanselmann
    bep = objects.FillDict(constants.BEC_DEFAULTS, {})
521 396672cd Michael Hanselmann
    hvp = objects.FillDict(constants.HVC_DEFAULTS[self.HVNAME], {})
522 396672cd Michael Hanselmann
523 396672cd Michael Hanselmann
    # Override default VNC password file path
524 396672cd Michael Hanselmann
    if constants.HV_VNC_PASSWORD_FILE in hvp:
525 396672cd Michael Hanselmann
      hvp[constants.HV_VNC_PASSWORD_FILE] = self.vncpw_path
526 396672cd Michael Hanselmann
527 396672cd Michael Hanselmann
    disks = [
528 396672cd Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDWR),
529 396672cd Michael Hanselmann
       utils.PathJoin(self.tmpdir, "disk0")),
530 396672cd Michael Hanselmann
      (objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDONLY),
531 396672cd Michael Hanselmann
       utils.PathJoin(self.tmpdir, "disk1")),
532 396672cd Michael Hanselmann
      ]
533 396672cd Michael Hanselmann
534 396672cd Michael Hanselmann
    inst = objects.Instance(name="server01.example.com",
535 396672cd Michael Hanselmann
                            hvparams=hvp, beparams=bep,
536 396672cd Michael Hanselmann
                            osparams={}, nics=[], os="deb1",
537 396672cd Michael Hanselmann
                            disks=map(compat.fst, disks))
538 396672cd Michael Hanselmann
    inst.UpgradeConfig()
539 396672cd Michael Hanselmann
540 396672cd Michael Hanselmann
    return (inst, disks)
541 396672cd Michael Hanselmann
542 396672cd Michael Hanselmann
  def testStartInstance(self):
543 396672cd Michael Hanselmann
    (inst, disks) = self._MakeInstance()
544 48bba9de Balazs Lecz
    pathutils.LOG_XEN_DIR = self.tmpdir
545 396672cd Michael Hanselmann
546 396672cd Michael Hanselmann
    for failcreate in [False, True]:
547 396672cd Michael Hanselmann
      for paused in [False, True]:
548 396672cd Michael Hanselmann
        run_cmd = compat.partial(self._StartInstanceCommand,
549 396672cd Michael Hanselmann
                                 inst, paused, failcreate)
550 396672cd Michael Hanselmann
551 396672cd Michael Hanselmann
        hv = self._GetHv(run_cmd=run_cmd)
552 396672cd Michael Hanselmann
553 396672cd Michael Hanselmann
        # Ensure instance is not listed
554 396672cd Michael Hanselmann
        self.assertTrue(inst.name not in hv.ListInstances())
555 396672cd Michael Hanselmann
556 396672cd Michael Hanselmann
        # Remove configuration
557 396672cd Michael Hanselmann
        cfgfile = utils.PathJoin(self.tmpdir, inst.name)
558 396672cd Michael Hanselmann
        utils.RemoveFile(cfgfile)
559 396672cd Michael Hanselmann
560 396672cd Michael Hanselmann
        if failcreate:
561 396672cd Michael Hanselmann
          self.assertRaises(errors.HypervisorError, hv.StartInstance,
562 396672cd Michael Hanselmann
                            inst, disks, paused)
563 48bba9de Balazs Lecz
          # Check whether a stale config file is left behind
564 48bba9de Balazs Lecz
          self.assertFalse(os.path.exists(cfgfile))
565 396672cd Michael Hanselmann
        else:
566 396672cd Michael Hanselmann
          hv.StartInstance(inst, disks, paused)
567 48bba9de Balazs Lecz
          # Check if configuration was updated
568 48bba9de Balazs Lecz
          lines = utils.ReadFile(cfgfile).splitlines()
569 396672cd Michael Hanselmann
570 396672cd Michael Hanselmann
        if constants.HV_VNC_PASSWORD_FILE in inst.hvparams:
571 396672cd Michael Hanselmann
          self.assertTrue(("vncpasswd = '%s'" % self.vncpw) in lines)
572 396672cd Michael Hanselmann
        else:
573 396672cd Michael Hanselmann
          extra = inst.hvparams[constants.HV_KERNEL_ARGS]
574 396672cd Michael Hanselmann
          self.assertTrue(("extra = '%s'" % extra) in lines)
575 396672cd Michael Hanselmann
576 664b392d Michael Hanselmann
  def _StopInstanceCommand(self, instance_name, force, fail, cmd):
577 664b392d Michael Hanselmann
    if ((force and cmd[:2] == [self.CMD, "destroy"]) or
578 664b392d Michael Hanselmann
        (not force and cmd[:2] == [self.CMD, "shutdown"])):
579 664b392d Michael Hanselmann
      self.assertEqual(cmd[2:], [instance_name])
580 664b392d Michael Hanselmann
      output = ""
581 664b392d Michael Hanselmann
    else:
582 664b392d Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
583 664b392d Michael Hanselmann
584 664b392d Michael Hanselmann
    if fail:
585 664b392d Michael Hanselmann
      # Simulate a failing command
586 664b392d Michael Hanselmann
      return self._FailingCommand(cmd)
587 664b392d Michael Hanselmann
    else:
588 664b392d Michael Hanselmann
      return self._SuccessCommand(output, cmd)
589 664b392d Michael Hanselmann
590 664b392d Michael Hanselmann
  def testStopInstance(self):
591 664b392d Michael Hanselmann
    name = "inst4284.example.com"
592 664b392d Michael Hanselmann
    cfgfile = utils.PathJoin(self.tmpdir, name)
593 664b392d Michael Hanselmann
    cfgdata = "config file content\n"
594 664b392d Michael Hanselmann
595 664b392d Michael Hanselmann
    for force in [False, True]:
596 664b392d Michael Hanselmann
      for fail in [False, True]:
597 664b392d Michael Hanselmann
        utils.WriteFile(cfgfile, data=cfgdata)
598 664b392d Michael Hanselmann
599 664b392d Michael Hanselmann
        run_cmd = compat.partial(self._StopInstanceCommand, name, force, fail)
600 664b392d Michael Hanselmann
601 664b392d Michael Hanselmann
        hv = self._GetHv(run_cmd=run_cmd)
602 664b392d Michael Hanselmann
603 664b392d Michael Hanselmann
        self.assertTrue(os.path.isfile(cfgfile))
604 664b392d Michael Hanselmann
605 664b392d Michael Hanselmann
        if fail:
606 664b392d Michael Hanselmann
          try:
607 664b392d Michael Hanselmann
            hv._StopInstance(name, force)
608 664b392d Michael Hanselmann
          except errors.HypervisorError, err:
609 664b392d Michael Hanselmann
            self.assertTrue(str(err).startswith("Failed to stop instance"))
610 664b392d Michael Hanselmann
          else:
611 664b392d Michael Hanselmann
            self.fail("Exception was not raised")
612 664b392d Michael Hanselmann
          self.assertEqual(utils.ReadFile(cfgfile), cfgdata,
613 664b392d Michael Hanselmann
                           msg=("Configuration was removed when stopping"
614 664b392d Michael Hanselmann
                                " instance failed"))
615 664b392d Michael Hanselmann
        else:
616 664b392d Michael Hanselmann
          hv._StopInstance(name, force)
617 664b392d Michael Hanselmann
          self.assertFalse(os.path.exists(cfgfile))
618 664b392d Michael Hanselmann
619 d8784f7d Michael Hanselmann
  def _MigrateNonRunningInstCmd(self, cmd):
620 d8784f7d Michael Hanselmann
    if cmd == [self.CMD, "list"]:
621 d8784f7d Michael Hanselmann
      output = testutils.ReadTestData("xen-xm-list-4.0.1-dom0-only.txt")
622 d8784f7d Michael Hanselmann
    else:
623 d8784f7d Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
624 d8784f7d Michael Hanselmann
625 d8784f7d Michael Hanselmann
    return self._SuccessCommand(output, cmd)
626 d8784f7d Michael Hanselmann
627 d8784f7d Michael Hanselmann
  def testMigrateInstanceNotRunning(self):
628 d8784f7d Michael Hanselmann
    name = "nonexistinginstance.example.com"
629 d8784f7d Michael Hanselmann
    target = constants.IP4_ADDRESS_LOCALHOST
630 d8784f7d Michael Hanselmann
    port = 14618
631 d8784f7d Michael Hanselmann
632 d8784f7d Michael Hanselmann
    hv = self._GetHv(run_cmd=self._MigrateNonRunningInstCmd)
633 d8784f7d Michael Hanselmann
634 d8784f7d Michael Hanselmann
    for live in [False, True]:
635 d8784f7d Michael Hanselmann
      try:
636 d8784f7d Michael Hanselmann
        hv._MigrateInstance(NotImplemented, name, target, port, live,
637 d8784f7d Michael Hanselmann
                            _ping_fn=NotImplemented)
638 d8784f7d Michael Hanselmann
      except errors.HypervisorError, err:
639 d8784f7d Michael Hanselmann
        self.assertEqual(str(err), "Instance not running, cannot migrate")
640 d8784f7d Michael Hanselmann
      else:
641 d8784f7d Michael Hanselmann
        self.fail("Exception was not raised")
642 d8784f7d Michael Hanselmann
643 d8784f7d Michael Hanselmann
  def _MigrateInstTargetUnreachCmd(self, cmd):
644 d8784f7d Michael Hanselmann
    if cmd == [self.CMD, "list"]:
645 d8784f7d Michael Hanselmann
      output = testutils.ReadTestData("xen-xm-list-4.0.1-four-instances.txt")
646 d8784f7d Michael Hanselmann
    else:
647 d8784f7d Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
648 d8784f7d Michael Hanselmann
649 d8784f7d Michael Hanselmann
    return self._SuccessCommand(output, cmd)
650 d8784f7d Michael Hanselmann
651 d8784f7d Michael Hanselmann
  def testMigrateTargetUnreachable(self):
652 d8784f7d Michael Hanselmann
    name = "server01.example.com"
653 d8784f7d Michael Hanselmann
    target = constants.IP4_ADDRESS_LOCALHOST
654 d8784f7d Michael Hanselmann
    port = 28349
655 d8784f7d Michael Hanselmann
656 d8784f7d Michael Hanselmann
    hv = self._GetHv(run_cmd=self._MigrateInstTargetUnreachCmd)
657 d8784f7d Michael Hanselmann
658 d8784f7d Michael Hanselmann
    for live in [False, True]:
659 d8784f7d Michael Hanselmann
      if self.CMD == constants.XEN_CMD_XL:
660 d8784f7d Michael Hanselmann
        # TODO: Detect unreachable targets
661 d8784f7d Michael Hanselmann
        pass
662 d8784f7d Michael Hanselmann
      else:
663 d8784f7d Michael Hanselmann
        try:
664 d8784f7d Michael Hanselmann
          hv._MigrateInstance(NotImplemented, name, target, port, live,
665 d8784f7d Michael Hanselmann
                              _ping_fn=compat.partial(self._FakeTcpPing,
666 d8784f7d Michael Hanselmann
                                                      (target, port), False))
667 d8784f7d Michael Hanselmann
        except errors.HypervisorError, err:
668 d8784f7d Michael Hanselmann
          wanted = "Remote host %s not" % target
669 d8784f7d Michael Hanselmann
          self.assertTrue(str(err).startswith(wanted))
670 d8784f7d Michael Hanselmann
        else:
671 d8784f7d Michael Hanselmann
          self.fail("Exception was not raised")
672 d8784f7d Michael Hanselmann
673 d8784f7d Michael Hanselmann
  def _MigrateInstanceCmd(self, cluster_name, instance_name, target, port,
674 d8784f7d Michael Hanselmann
                          live, fail, cmd):
675 d8784f7d Michael Hanselmann
    if cmd == [self.CMD, "list"]:
676 d8784f7d Michael Hanselmann
      output = testutils.ReadTestData("xen-xm-list-4.0.1-four-instances.txt")
677 d8784f7d Michael Hanselmann
    elif cmd[:2] == [self.CMD, "migrate"]:
678 d8784f7d Michael Hanselmann
      if self.CMD == constants.XEN_CMD_XM:
679 d8784f7d Michael Hanselmann
        args = ["-p", str(port)]
680 d8784f7d Michael Hanselmann
681 d8784f7d Michael Hanselmann
        if live:
682 d8784f7d Michael Hanselmann
          args.append("-l")
683 d8784f7d Michael Hanselmann
684 d8784f7d Michael Hanselmann
      elif self.CMD == constants.XEN_CMD_XL:
685 d8784f7d Michael Hanselmann
        args = [
686 d8784f7d Michael Hanselmann
          "-s", constants.XL_SSH_CMD % cluster_name,
687 d8784f7d Michael Hanselmann
          "-C", utils.PathJoin(self.tmpdir, instance_name),
688 d8784f7d Michael Hanselmann
          ]
689 d8784f7d Michael Hanselmann
690 d8784f7d Michael Hanselmann
      else:
691 d8784f7d Michael Hanselmann
        self.fail("Unknown Xen command '%s'" % self.CMD)
692 d8784f7d Michael Hanselmann
693 d8784f7d Michael Hanselmann
      args.extend([instance_name, target])
694 d8784f7d Michael Hanselmann
      self.assertEqual(cmd[2:], args)
695 d8784f7d Michael Hanselmann
696 d8784f7d Michael Hanselmann
      if fail:
697 d8784f7d Michael Hanselmann
        return self._FailingCommand(cmd)
698 d8784f7d Michael Hanselmann
699 d8784f7d Michael Hanselmann
      output = ""
700 d8784f7d Michael Hanselmann
    else:
701 d8784f7d Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
702 d8784f7d Michael Hanselmann
703 d8784f7d Michael Hanselmann
    return self._SuccessCommand(output, cmd)
704 d8784f7d Michael Hanselmann
705 d8784f7d Michael Hanselmann
  def testMigrateInstance(self):
706 d8784f7d Michael Hanselmann
    clustername = "cluster.example.com"
707 d8784f7d Michael Hanselmann
    instname = "server01.example.com"
708 d8784f7d Michael Hanselmann
    target = constants.IP4_ADDRESS_LOCALHOST
709 d8784f7d Michael Hanselmann
    port = 22364
710 d8784f7d Michael Hanselmann
711 d8784f7d Michael Hanselmann
    for live in [False, True]:
712 d8784f7d Michael Hanselmann
      for fail in [False, True]:
713 d8784f7d Michael Hanselmann
        ping_fn = \
714 d8784f7d Michael Hanselmann
          testutils.CallCounter(compat.partial(self._FakeTcpPing,
715 d8784f7d Michael Hanselmann
                                               (target, port), True))
716 d8784f7d Michael Hanselmann
717 d8784f7d Michael Hanselmann
        run_cmd = \
718 d8784f7d Michael Hanselmann
          compat.partial(self._MigrateInstanceCmd,
719 d8784f7d Michael Hanselmann
                         clustername, instname, target, port, live,
720 d8784f7d Michael Hanselmann
                         fail)
721 d8784f7d Michael Hanselmann
722 d8784f7d Michael Hanselmann
        hv = self._GetHv(run_cmd=run_cmd)
723 d8784f7d Michael Hanselmann
724 d8784f7d Michael Hanselmann
        if fail:
725 d8784f7d Michael Hanselmann
          try:
726 d8784f7d Michael Hanselmann
            hv._MigrateInstance(clustername, instname, target, port, live,
727 d8784f7d Michael Hanselmann
                                _ping_fn=ping_fn)
728 d8784f7d Michael Hanselmann
          except errors.HypervisorError, err:
729 d8784f7d Michael Hanselmann
            self.assertTrue(str(err).startswith("Failed to migrate instance"))
730 d8784f7d Michael Hanselmann
          else:
731 d8784f7d Michael Hanselmann
            self.fail("Exception was not raised")
732 d8784f7d Michael Hanselmann
        else:
733 d8784f7d Michael Hanselmann
          hv._MigrateInstance(clustername, instname, target, port, live,
734 d8784f7d Michael Hanselmann
                              _ping_fn=ping_fn)
735 d8784f7d Michael Hanselmann
736 d8784f7d Michael Hanselmann
        if self.CMD == constants.XEN_CMD_XM:
737 d8784f7d Michael Hanselmann
          expected_pings = 1
738 d8784f7d Michael Hanselmann
        else:
739 d8784f7d Michael Hanselmann
          expected_pings = 0
740 d8784f7d Michael Hanselmann
741 d8784f7d Michael Hanselmann
        self.assertEqual(ping_fn.Count(), expected_pings)
742 d8784f7d Michael Hanselmann
743 1b9e1f42 Michael Hanselmann
  def _GetNodeInfoCmd(self, fail, cmd):
744 1b9e1f42 Michael Hanselmann
    if cmd == [self.CMD, "info"]:
745 1b9e1f42 Michael Hanselmann
      if fail:
746 1b9e1f42 Michael Hanselmann
        return self._FailingCommand(cmd)
747 1b9e1f42 Michael Hanselmann
      else:
748 1b9e1f42 Michael Hanselmann
        output = testutils.ReadTestData("xen-xm-info-4.0.1.txt")
749 1b9e1f42 Michael Hanselmann
    elif cmd == [self.CMD, "list"]:
750 1b9e1f42 Michael Hanselmann
      if fail:
751 1b9e1f42 Michael Hanselmann
        self.fail("'xm list' shouldn't be called when 'xm info' failed")
752 1b9e1f42 Michael Hanselmann
      else:
753 1b9e1f42 Michael Hanselmann
        output = testutils.ReadTestData("xen-xm-list-4.0.1-four-instances.txt")
754 1b9e1f42 Michael Hanselmann
    else:
755 1b9e1f42 Michael Hanselmann
      self.fail("Unhandled command: %s" % (cmd, ))
756 1b9e1f42 Michael Hanselmann
757 1b9e1f42 Michael Hanselmann
    return self._SuccessCommand(output, cmd)
758 1b9e1f42 Michael Hanselmann
759 1b9e1f42 Michael Hanselmann
  def testGetNodeInfo(self):
760 1b9e1f42 Michael Hanselmann
    run_cmd = compat.partial(self._GetNodeInfoCmd, False)
761 1b9e1f42 Michael Hanselmann
    hv = self._GetHv(run_cmd=run_cmd)
762 1b9e1f42 Michael Hanselmann
    result = hv.GetNodeInfo()
763 1b9e1f42 Michael Hanselmann
764 1b9e1f42 Michael Hanselmann
    self.assertEqual(result["hv_version"], (4, 0))
765 1b9e1f42 Michael Hanselmann
    self.assertEqual(result["memory_free"], 8004)
766 1b9e1f42 Michael Hanselmann
767 1b9e1f42 Michael Hanselmann
  def testGetNodeInfoFailing(self):
768 1b9e1f42 Michael Hanselmann
    run_cmd = compat.partial(self._GetNodeInfoCmd, True)
769 1b9e1f42 Michael Hanselmann
    hv = self._GetHv(run_cmd=run_cmd)
770 1b9e1f42 Michael Hanselmann
    self.assertTrue(hv.GetNodeInfo() is None)
771 1b9e1f42 Michael Hanselmann
772 74a50c46 Michael Hanselmann
773 74a50c46 Michael Hanselmann
def _MakeTestClass(cls, cmd):
774 74a50c46 Michael Hanselmann
  """Makes a class for testing.
775 74a50c46 Michael Hanselmann

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

778 74a50c46 Michael Hanselmann
    class Test{cls.__name__}{cmd}(_TestXenHypervisor, unittest.TestCase):
779 74a50c46 Michael Hanselmann
      TARGET = {cls}
780 74a50c46 Michael Hanselmann
      CMD = {cmd}
781 74a50c46 Michael Hanselmann
      HVNAME = {Hypervisor name retrieved using class}
782 74a50c46 Michael Hanselmann

783 74a50c46 Michael Hanselmann
  @type cls: class
784 74a50c46 Michael Hanselmann
  @param cls: Hypervisor class to be tested
785 74a50c46 Michael Hanselmann
  @type cmd: string
786 74a50c46 Michael Hanselmann
  @param cmd: Hypervisor command
787 74a50c46 Michael Hanselmann
  @rtype: tuple
788 74a50c46 Michael Hanselmann
  @return: Class name and class object (not instance)
789 74a50c46 Michael Hanselmann

790 74a50c46 Michael Hanselmann
  """
791 74a50c46 Michael Hanselmann
  name = "Test%sCmd%s" % (cls.__name__, cmd.title())
792 74a50c46 Michael Hanselmann
  bases = (_TestXenHypervisor, unittest.TestCase)
793 74a50c46 Michael Hanselmann
  hvname = HVCLASS_TO_HVNAME[cls]
794 74a50c46 Michael Hanselmann
795 74a50c46 Michael Hanselmann
  return (name, type(name, bases, dict(TARGET=cls, CMD=cmd, HVNAME=hvname)))
796 74a50c46 Michael Hanselmann
797 74a50c46 Michael Hanselmann
798 74a50c46 Michael Hanselmann
# Create test classes programmatically instead of manually to reduce the risk
799 74a50c46 Michael Hanselmann
# of forgetting some combinations
800 74a50c46 Michael Hanselmann
for cls in [hv_xen.XenPvmHypervisor, hv_xen.XenHvmHypervisor]:
801 74a50c46 Michael Hanselmann
  for cmd in constants.KNOWN_XEN_COMMANDS:
802 74a50c46 Michael Hanselmann
    (name, testcls) = _MakeTestClass(cls, cmd)
803 74a50c46 Michael Hanselmann
804 74a50c46 Michael Hanselmann
    assert name not in locals()
805 74a50c46 Michael Hanselmann
806 74a50c46 Michael Hanselmann
    locals()[name] = testcls
807 74a50c46 Michael Hanselmann
808 74a50c46 Michael Hanselmann
809 55cc0a44 Michael Hanselmann
if __name__ == "__main__":
810 55cc0a44 Michael Hanselmann
  testutils.GanetiTestProgram()