Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hypervisor.hv_kvm_unittest.py @ 14933c17

History | View | Annotate | Download (13.9 kB)

1 748e4b5a Michael Hanselmann
#!/usr/bin/python
2 748e4b5a Michael Hanselmann
#
3 748e4b5a Michael Hanselmann
4 55cc0a44 Michael Hanselmann
# Copyright (C) 2010, 2011 Google Inc.
5 748e4b5a Michael Hanselmann
#
6 748e4b5a Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 748e4b5a Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 748e4b5a Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 748e4b5a Michael Hanselmann
# (at your option) any later version.
10 748e4b5a Michael Hanselmann
#
11 748e4b5a Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 748e4b5a Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 748e4b5a Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 748e4b5a Michael Hanselmann
# General Public License for more details.
15 748e4b5a Michael Hanselmann
#
16 748e4b5a Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 748e4b5a Michael Hanselmann
# along with this program; if not, write to the Free Software
18 748e4b5a Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 748e4b5a Michael Hanselmann
# 02110-1301, USA.
20 748e4b5a Michael Hanselmann
21 748e4b5a Michael Hanselmann
22 748e4b5a Michael Hanselmann
"""Script for testing the hypervisor.hv_kvm module"""
23 748e4b5a Michael Hanselmann
24 91c10532 Andrea Spadaccini
import threading
25 91c10532 Andrea Spadaccini
import tempfile
26 748e4b5a Michael Hanselmann
import unittest
27 91c10532 Andrea Spadaccini
import socket
28 91c10532 Andrea Spadaccini
import os
29 ea2bcb82 Michael Hanselmann
import struct
30 fda3d987 Dimitris Aragiorgis
import re
31 748e4b5a Michael Hanselmann
32 91c10532 Andrea Spadaccini
from ganeti import serializer
33 748e4b5a Michael Hanselmann
from ganeti import constants
34 748e4b5a Michael Hanselmann
from ganeti import compat
35 748e4b5a Michael Hanselmann
from ganeti import objects
36 748e4b5a Michael Hanselmann
from ganeti import errors
37 585c8187 Guido Trotter
from ganeti import utils
38 a56625a2 Michael Hanselmann
from ganeti import pathutils
39 748e4b5a Michael Hanselmann
40 748e4b5a Michael Hanselmann
from ganeti.hypervisor import hv_kvm
41 748e4b5a Michael Hanselmann
42 748e4b5a Michael Hanselmann
import testutils
43 748e4b5a Michael Hanselmann
44 748e4b5a Michael Hanselmann
45 91c10532 Andrea Spadaccini
class QmpStub(threading.Thread):
46 91c10532 Andrea Spadaccini
  """Stub for a QMP endpoint for a KVM instance
47 91c10532 Andrea Spadaccini

48 91c10532 Andrea Spadaccini
  """
49 51129a7f Michael Hanselmann
  _QMP_BANNER_DATA = {
50 51129a7f Michael Hanselmann
    "QMP": {
51 51129a7f Michael Hanselmann
      "version": {
52 51129a7f Michael Hanselmann
        "package": "",
53 51129a7f Michael Hanselmann
        "qemu": {
54 51129a7f Michael Hanselmann
          "micro": 50,
55 51129a7f Michael Hanselmann
          "minor": 13,
56 51129a7f Michael Hanselmann
          "major": 0,
57 51129a7f Michael Hanselmann
          },
58 51129a7f Michael Hanselmann
        "capabilities": [],
59 51129a7f Michael Hanselmann
        },
60 51129a7f Michael Hanselmann
      }
61 51129a7f Michael Hanselmann
    }
62 51129a7f Michael Hanselmann
  _EMPTY_RESPONSE = {
63 51129a7f Michael Hanselmann
    "return": [],
64 51129a7f Michael Hanselmann
    }
65 91c10532 Andrea Spadaccini
66 91c10532 Andrea Spadaccini
  def __init__(self, socket_filename, server_responses):
67 91c10532 Andrea Spadaccini
    """Creates a QMP stub
68 91c10532 Andrea Spadaccini

69 91c10532 Andrea Spadaccini
    @type socket_filename: string
70 91c10532 Andrea Spadaccini
    @param socket_filename: filename of the UNIX socket that will be created
71 91c10532 Andrea Spadaccini
                            this class and used for the communication
72 91c10532 Andrea Spadaccini
    @type server_responses: list
73 91c10532 Andrea Spadaccini
    @param server_responses: list of responses that the server sends in response
74 91c10532 Andrea Spadaccini
                             to whatever it receives
75 91c10532 Andrea Spadaccini
    """
76 91c10532 Andrea Spadaccini
    threading.Thread.__init__(self)
77 91c10532 Andrea Spadaccini
    self.socket_filename = socket_filename
78 91c10532 Andrea Spadaccini
    self.script = server_responses
79 91c10532 Andrea Spadaccini
80 91c10532 Andrea Spadaccini
    self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
81 91c10532 Andrea Spadaccini
    self.socket.bind(self.socket_filename)
82 91c10532 Andrea Spadaccini
    self.socket.listen(1)
83 91c10532 Andrea Spadaccini
84 91c10532 Andrea Spadaccini
  def run(self):
85 91c10532 Andrea Spadaccini
    # Hypothesis: the messages we receive contain only a complete QMP message
86 91c10532 Andrea Spadaccini
    # encoded in JSON.
87 91c10532 Andrea Spadaccini
    conn, addr = self.socket.accept()
88 91c10532 Andrea Spadaccini
89 91c10532 Andrea Spadaccini
    # Send the banner as the first thing
90 91c10532 Andrea Spadaccini
    conn.send(self.encode_string(self._QMP_BANNER_DATA))
91 91c10532 Andrea Spadaccini
92 91c10532 Andrea Spadaccini
    # Expect qmp_capabilities and return an empty response
93 91c10532 Andrea Spadaccini
    conn.recv(4096)
94 91c10532 Andrea Spadaccini
    conn.send(self.encode_string(self._EMPTY_RESPONSE))
95 91c10532 Andrea Spadaccini
96 91c10532 Andrea Spadaccini
    while True:
97 91c10532 Andrea Spadaccini
      # We ignore the expected message, as the purpose of this object is not
98 91c10532 Andrea Spadaccini
      # to verify the correctness of the communication but to act as a
99 91c10532 Andrea Spadaccini
      # partner for the SUT (System Under Test, that is QmpConnection)
100 91c10532 Andrea Spadaccini
      msg = conn.recv(4096)
101 91c10532 Andrea Spadaccini
      if not msg:
102 91c10532 Andrea Spadaccini
        break
103 91c10532 Andrea Spadaccini
104 91c10532 Andrea Spadaccini
      if not self.script:
105 91c10532 Andrea Spadaccini
        break
106 91c10532 Andrea Spadaccini
      response = self.script.pop(0)
107 91c10532 Andrea Spadaccini
      if isinstance(response, str):
108 91c10532 Andrea Spadaccini
        conn.send(response)
109 91c10532 Andrea Spadaccini
      elif isinstance(response, list):
110 91c10532 Andrea Spadaccini
        for chunk in response:
111 91c10532 Andrea Spadaccini
          conn.send(chunk)
112 91c10532 Andrea Spadaccini
      else:
113 91c10532 Andrea Spadaccini
        raise errors.ProgrammerError("Unknown response type for %s" % response)
114 91c10532 Andrea Spadaccini
115 91c10532 Andrea Spadaccini
    conn.close()
116 91c10532 Andrea Spadaccini
117 91c10532 Andrea Spadaccini
  def encode_string(self, message):
118 a182a3ed Michael Hanselmann
    return (serializer.DumpJson(message) +
119 91c10532 Andrea Spadaccini
            hv_kvm.QmpConnection._MESSAGE_END_TOKEN)
120 91c10532 Andrea Spadaccini
121 91c10532 Andrea Spadaccini
122 91c10532 Andrea Spadaccini
class TestQmpMessage(testutils.GanetiTestCase):
123 91c10532 Andrea Spadaccini
  def testSerialization(self):
124 51129a7f Michael Hanselmann
    test_data = {
125 51129a7f Michael Hanselmann
      "execute": "command",
126 51129a7f Michael Hanselmann
      "arguments": ["a", "b", "c"],
127 51129a7f Michael Hanselmann
      }
128 91c10532 Andrea Spadaccini
    message = hv_kvm.QmpMessage(test_data)
129 91c10532 Andrea Spadaccini
130 91c10532 Andrea Spadaccini
    for k, v in test_data.items():
131 51129a7f Michael Hanselmann
      self.assertEqual(message[k], v)
132 91c10532 Andrea Spadaccini
133 51129a7f Michael Hanselmann
    serialized = str(message)
134 51129a7f Michael Hanselmann
    self.assertEqual(len(serialized.splitlines()), 1,
135 51129a7f Michael Hanselmann
                     msg="Got multi-line message")
136 51129a7f Michael Hanselmann
137 51129a7f Michael Hanselmann
    rebuilt_message = hv_kvm.QmpMessage.BuildFromJsonString(serialized)
138 51129a7f Michael Hanselmann
    self.assertEqual(rebuilt_message, message)
139 5e34123e Michele Tartara
    self.assertEqual(len(rebuilt_message), len(test_data))
140 5e34123e Michele Tartara
141 5e34123e Michele Tartara
  def testDelete(self):
142 5e34123e Michele Tartara
    toDelete = "execute"
143 5e34123e Michele Tartara
    test_data = {
144 5e34123e Michele Tartara
      toDelete: "command",
145 5e34123e Michele Tartara
      "arguments": ["a", "b", "c"],
146 5e34123e Michele Tartara
      }
147 5e34123e Michele Tartara
    message = hv_kvm.QmpMessage(test_data)
148 5e34123e Michele Tartara
149 5e34123e Michele Tartara
    oldLen = len(message)
150 5e34123e Michele Tartara
    del(message[toDelete])
151 5e34123e Michele Tartara
    newLen = len(message)
152 5e34123e Michele Tartara
    self.assertEqual(oldLen - 1, newLen)
153 91c10532 Andrea Spadaccini
154 91c10532 Andrea Spadaccini
155 91c10532 Andrea Spadaccini
class TestQmp(testutils.GanetiTestCase):
156 91c10532 Andrea Spadaccini
  def testQmp(self):
157 91c10532 Andrea Spadaccini
    requests = [
158 91c10532 Andrea Spadaccini
      {"execute": "query-kvm", "arguments": []},
159 91c10532 Andrea Spadaccini
      {"execute": "eject", "arguments": {"device": "ide1-cd0"}},
160 91c10532 Andrea Spadaccini
      {"execute": "query-status", "arguments": []},
161 91c10532 Andrea Spadaccini
      {"execute": "query-name", "arguments": []},
162 91c10532 Andrea Spadaccini
      ]
163 91c10532 Andrea Spadaccini
164 91c10532 Andrea Spadaccini
    server_responses = [
165 91c10532 Andrea Spadaccini
      # One message, one send()
166 91c10532 Andrea Spadaccini
      '{"return": {"enabled": true, "present": true}}\r\n',
167 91c10532 Andrea Spadaccini
168 91c10532 Andrea Spadaccini
      # Message sent using multiple send()
169 91c10532 Andrea Spadaccini
      ['{"retur', 'n": {}}\r\n'],
170 91c10532 Andrea Spadaccini
171 91c10532 Andrea Spadaccini
      # Multiple messages sent using one send()
172 91c10532 Andrea Spadaccini
      '{"return": [{"name": "quit"}, {"name": "eject"}]}\r\n'
173 91c10532 Andrea Spadaccini
      '{"return": {"running": true, "singlestep": false}}\r\n',
174 91c10532 Andrea Spadaccini
      ]
175 91c10532 Andrea Spadaccini
176 91c10532 Andrea Spadaccini
    expected_responses = [
177 91c10532 Andrea Spadaccini
      {"return": {"enabled": True, "present": True}},
178 91c10532 Andrea Spadaccini
      {"return": {}},
179 91c10532 Andrea Spadaccini
      {"return": [{"name": "quit"}, {"name": "eject"}]},
180 91c10532 Andrea Spadaccini
      {"return": {"running": True, "singlestep": False}},
181 91c10532 Andrea Spadaccini
      ]
182 91c10532 Andrea Spadaccini
183 91c10532 Andrea Spadaccini
    # Set up the stub
184 91c10532 Andrea Spadaccini
    socket_file = tempfile.NamedTemporaryFile()
185 91c10532 Andrea Spadaccini
    os.remove(socket_file.name)
186 91c10532 Andrea Spadaccini
    qmp_stub = QmpStub(socket_file.name, server_responses)
187 91c10532 Andrea Spadaccini
    qmp_stub.start()
188 91c10532 Andrea Spadaccini
189 91c10532 Andrea Spadaccini
    # Set up the QMP connection
190 91c10532 Andrea Spadaccini
    qmp_connection = hv_kvm.QmpConnection(socket_file.name)
191 91c10532 Andrea Spadaccini
    qmp_connection.connect()
192 91c10532 Andrea Spadaccini
193 91c10532 Andrea Spadaccini
    # Format the script
194 91c10532 Andrea Spadaccini
    for request, expected_response in zip(requests, expected_responses):
195 91c10532 Andrea Spadaccini
      response = qmp_connection.Execute(request)
196 51129a7f Michael Hanselmann
      msg = hv_kvm.QmpMessage(expected_response)
197 51129a7f Michael Hanselmann
      self.assertEqual(len(str(msg).splitlines()), 1,
198 51129a7f Michael Hanselmann
                       msg="Got multi-line message")
199 51129a7f Michael Hanselmann
      self.assertEqual(response, msg)
200 91c10532 Andrea Spadaccini
201 91c10532 Andrea Spadaccini
202 55cc0a44 Michael Hanselmann
class TestConsole(unittest.TestCase):
203 1c3231aa Thomas Thrainer
  def _Test(self, instance, node, hvparams):
204 1c3231aa Thomas Thrainer
    cons = hv_kvm.KVMHypervisor.GetInstanceConsole(instance, node, hvparams, {})
205 55cc0a44 Michael Hanselmann
    self.assertTrue(cons.Validate())
206 55cc0a44 Michael Hanselmann
    return cons
207 55cc0a44 Michael Hanselmann
208 55cc0a44 Michael Hanselmann
  def testSerial(self):
209 55cc0a44 Michael Hanselmann
    instance = objects.Instance(name="kvm.example.com",
210 1c3231aa Thomas Thrainer
                                primary_node="node6017-uuid")
211 1c3231aa Thomas Thrainer
    node = objects.Node(name="node6017", uuid="node6017-uuid")
212 55cc0a44 Michael Hanselmann
    hvparams = {
213 55cc0a44 Michael Hanselmann
      constants.HV_SERIAL_CONSOLE: True,
214 55cc0a44 Michael Hanselmann
      constants.HV_VNC_BIND_ADDRESS: None,
215 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: None,
216 55cc0a44 Michael Hanselmann
      }
217 1c3231aa Thomas Thrainer
    cons = self._Test(instance, node, hvparams)
218 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.kind, constants.CONS_SSH)
219 1c3231aa Thomas Thrainer
    self.assertEqual(cons.host, node.name)
220 a56625a2 Michael Hanselmann
    self.assertEqual(cons.command[0], pathutils.KVM_CONSOLE_WRAPPER)
221 2f4c951e Stephen Shirley
    self.assertEqual(cons.command[1], constants.SOCAT_PATH)
222 55cc0a44 Michael Hanselmann
223 55cc0a44 Michael Hanselmann
  def testVnc(self):
224 55cc0a44 Michael Hanselmann
    instance = objects.Instance(name="kvm.example.com",
225 1c3231aa Thomas Thrainer
                                primary_node="node7235-uuid",
226 55cc0a44 Michael Hanselmann
                                network_port=constants.VNC_BASE_PORT + 10)
227 1c3231aa Thomas Thrainer
    node = objects.Node(name="node7235", uuid="node7235-uuid")
228 55cc0a44 Michael Hanselmann
    hvparams = {
229 55cc0a44 Michael Hanselmann
      constants.HV_SERIAL_CONSOLE: False,
230 55cc0a44 Michael Hanselmann
      constants.HV_VNC_BIND_ADDRESS: "192.0.2.1",
231 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: None,
232 55cc0a44 Michael Hanselmann
      }
233 1c3231aa Thomas Thrainer
    cons = self._Test(instance, node, hvparams)
234 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.kind, constants.CONS_VNC)
235 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.host, "192.0.2.1")
236 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.port, constants.VNC_BASE_PORT + 10)
237 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.display, 10)
238 55cc0a44 Michael Hanselmann
239 4d2cdb5a Andrea Spadaccini
  def testSpice(self):
240 4d2cdb5a Andrea Spadaccini
    instance = objects.Instance(name="kvm.example.com",
241 4d2cdb5a Andrea Spadaccini
                                primary_node="node7235",
242 4d2cdb5a Andrea Spadaccini
                                network_port=11000)
243 1c3231aa Thomas Thrainer
    node = objects.Node(name="node7235", uuid="node7235-uuid")
244 4d2cdb5a Andrea Spadaccini
    hvparams = {
245 4d2cdb5a Andrea Spadaccini
      constants.HV_SERIAL_CONSOLE: False,
246 4d2cdb5a Andrea Spadaccini
      constants.HV_VNC_BIND_ADDRESS: None,
247 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: "192.0.2.1",
248 4d2cdb5a Andrea Spadaccini
      }
249 1c3231aa Thomas Thrainer
    cons = self._Test(instance, node, hvparams)
250 4d2cdb5a Andrea Spadaccini
    self.assertEqual(cons.kind, constants.CONS_SPICE)
251 4d2cdb5a Andrea Spadaccini
    self.assertEqual(cons.host, "192.0.2.1")
252 4d2cdb5a Andrea Spadaccini
    self.assertEqual(cons.port, 11000)
253 4d2cdb5a Andrea Spadaccini
254 55cc0a44 Michael Hanselmann
  def testNoConsole(self):
255 55cc0a44 Michael Hanselmann
    instance = objects.Instance(name="kvm.example.com",
256 55cc0a44 Michael Hanselmann
                                primary_node="node24325",
257 55cc0a44 Michael Hanselmann
                                network_port=0)
258 1c3231aa Thomas Thrainer
    node = objects.Node(name="node24325", uuid="node24325-uuid")
259 55cc0a44 Michael Hanselmann
    hvparams = {
260 55cc0a44 Michael Hanselmann
      constants.HV_SERIAL_CONSOLE: False,
261 55cc0a44 Michael Hanselmann
      constants.HV_VNC_BIND_ADDRESS: None,
262 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: None,
263 55cc0a44 Michael Hanselmann
      }
264 1c3231aa Thomas Thrainer
    cons = self._Test(instance, node, hvparams)
265 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.kind, constants.CONS_MESSAGE)
266 55cc0a44 Michael Hanselmann
267 55cc0a44 Michael Hanselmann
268 585c8187 Guido Trotter
class TestVersionChecking(testutils.GanetiTestCase):
269 585c8187 Guido Trotter
  def testParseVersion(self):
270 585c8187 Guido Trotter
    parse = hv_kvm.KVMHypervisor._ParseKVMVersion
271 00ef625c Michael Hanselmann
    help_112 = testutils.ReadTestData("kvm_1.1.2_help.txt")
272 00ef625c Michael Hanselmann
    help_10 = testutils.ReadTestData("kvm_1.0_help.txt")
273 00ef625c Michael Hanselmann
    help_01590 = testutils.ReadTestData("kvm_0.15.90_help.txt")
274 00ef625c Michael Hanselmann
    help_0125 = testutils.ReadTestData("kvm_0.12.5_help.txt")
275 00ef625c Michael Hanselmann
    help_091 = testutils.ReadTestData("kvm_0.9.1_help.txt")
276 eb7a6965 Guido Trotter
    self.assertEqual(parse(help_112), ("1.1.2", 1, 1, 2))
277 585c8187 Guido Trotter
    self.assertEqual(parse(help_10), ("1.0", 1, 0, 0))
278 585c8187 Guido Trotter
    self.assertEqual(parse(help_01590), ("0.15.90", 0, 15, 90))
279 585c8187 Guido Trotter
    self.assertEqual(parse(help_0125), ("0.12.5", 0, 12, 5))
280 585c8187 Guido Trotter
    self.assertEqual(parse(help_091), ("0.9.1", 0, 9, 1))
281 585c8187 Guido Trotter
282 585c8187 Guido Trotter
283 141d1489 Michael Hanselmann
class TestSpiceParameterList(unittest.TestCase):
284 141d1489 Michael Hanselmann
  def test(self):
285 daa49d6f Michael Hanselmann
    defaults = constants.HVC_DEFAULTS[constants.HT_KVM]
286 daa49d6f Michael Hanselmann
287 141d1489 Michael Hanselmann
    params = \
288 141d1489 Michael Hanselmann
      compat.UniqueFrozenset(getattr(constants, name)
289 141d1489 Michael Hanselmann
                             for name in dir(constants)
290 141d1489 Michael Hanselmann
                             if name.startswith("HV_KVM_SPICE_"))
291 141d1489 Michael Hanselmann
292 daa49d6f Michael Hanselmann
    # Parameters whose default value evaluates to True and don't need to be set
293 daa49d6f Michael Hanselmann
    defaults_true = frozenset(filter(defaults.__getitem__, params))
294 daa49d6f Michael Hanselmann
295 daa49d6f Michael Hanselmann
    self.assertEqual(defaults_true, frozenset([
296 daa49d6f Michael Hanselmann
      constants.HV_KVM_SPICE_AUDIO_COMPR,
297 daa49d6f Michael Hanselmann
      constants.HV_KVM_SPICE_USE_VDAGENT,
298 daa49d6f Michael Hanselmann
      constants.HV_KVM_SPICE_TLS_CIPHERS,
299 daa49d6f Michael Hanselmann
      ]))
300 daa49d6f Michael Hanselmann
301 daa49d6f Michael Hanselmann
    # HV_KVM_SPICE_BIND decides whether the other parameters must be set if
302 daa49d6f Michael Hanselmann
    # their default evaluates to False
303 daa49d6f Michael Hanselmann
    assert constants.HV_KVM_SPICE_BIND in params
304 daa49d6f Michael Hanselmann
    assert constants.HV_KVM_SPICE_BIND not in defaults_true
305 daa49d6f Michael Hanselmann
306 141d1489 Michael Hanselmann
    # Exclude some parameters
307 daa49d6f Michael Hanselmann
    params -= defaults_true | frozenset([
308 141d1489 Michael Hanselmann
      constants.HV_KVM_SPICE_BIND,
309 141d1489 Michael Hanselmann
      ])
310 141d1489 Michael Hanselmann
311 141d1489 Michael Hanselmann
    self.assertEqual(hv_kvm._SPICE_ADDITIONAL_PARAMS, params)
312 141d1489 Michael Hanselmann
313 141d1489 Michael Hanselmann
314 0ad7f5d8 Guido Trotter
class TestHelpRegexps(testutils.GanetiTestCase):
315 0ad7f5d8 Guido Trotter
  def testBootRe(self):
316 0ad7f5d8 Guido Trotter
    """Check _BOOT_RE
317 0ad7f5d8 Guido Trotter

318 0ad7f5d8 Guido Trotter
    It has too match -drive.*boot=on|off except if there is another dash-option
319 0ad7f5d8 Guido Trotter
    at the beginning of the line.
320 0ad7f5d8 Guido Trotter

321 0ad7f5d8 Guido Trotter
    """
322 0ad7f5d8 Guido Trotter
    boot_re = hv_kvm.KVMHypervisor._BOOT_RE
323 00ef625c Michael Hanselmann
    help_112 = testutils.ReadTestData("kvm_1.1.2_help.txt")
324 00ef625c Michael Hanselmann
    help_10 = testutils.ReadTestData("kvm_1.0_help.txt")
325 00ef625c Michael Hanselmann
    help_01590 = testutils.ReadTestData("kvm_0.15.90_help.txt")
326 00ef625c Michael Hanselmann
    help_0125 = testutils.ReadTestData("kvm_0.12.5_help.txt")
327 00ef625c Michael Hanselmann
    help_091 = testutils.ReadTestData("kvm_0.9.1_help.txt")
328 00ef625c Michael Hanselmann
    help_091_fake = testutils.ReadTestData("kvm_0.9.1_help_boot_test.txt")
329 0ad7f5d8 Guido Trotter
330 0ad7f5d8 Guido Trotter
    self.assertTrue(boot_re.search(help_091))
331 0ad7f5d8 Guido Trotter
    self.assertTrue(boot_re.search(help_0125))
332 eb7a6965 Guido Trotter
    self.assertFalse(boot_re.search(help_091_fake))
333 eb7a6965 Guido Trotter
    self.assertFalse(boot_re.search(help_112))
334 0ad7f5d8 Guido Trotter
    self.assertFalse(boot_re.search(help_10))
335 0ad7f5d8 Guido Trotter
    self.assertFalse(boot_re.search(help_01590))
336 0ad7f5d8 Guido Trotter
337 0ad7f5d8 Guido Trotter
338 ea2bcb82 Michael Hanselmann
class TestGetTunFeatures(unittest.TestCase):
339 ea2bcb82 Michael Hanselmann
  def testWrongIoctl(self):
340 ea2bcb82 Michael Hanselmann
    tmpfile = tempfile.NamedTemporaryFile()
341 ea2bcb82 Michael Hanselmann
    # A file does not have the right ioctls, so this must always fail
342 ea2bcb82 Michael Hanselmann
    result = hv_kvm._GetTunFeatures(tmpfile.fileno())
343 ea2bcb82 Michael Hanselmann
    self.assertTrue(result is None)
344 ea2bcb82 Michael Hanselmann
345 ea2bcb82 Michael Hanselmann
  def _FakeIoctl(self, features, fd, request, buf):
346 ea2bcb82 Michael Hanselmann
    self.assertEqual(request, hv_kvm.TUNGETFEATURES)
347 ea2bcb82 Michael Hanselmann
348 ea2bcb82 Michael Hanselmann
    (reqno, ) = struct.unpack("I", buf)
349 ea2bcb82 Michael Hanselmann
    self.assertEqual(reqno, 0)
350 ea2bcb82 Michael Hanselmann
351 ea2bcb82 Michael Hanselmann
    return struct.pack("I", features)
352 ea2bcb82 Michael Hanselmann
353 ea2bcb82 Michael Hanselmann
  def test(self):
354 ea2bcb82 Michael Hanselmann
    tmpfile = tempfile.NamedTemporaryFile()
355 ea2bcb82 Michael Hanselmann
    fd = tmpfile.fileno()
356 ea2bcb82 Michael Hanselmann
357 ea2bcb82 Michael Hanselmann
    for features in [0, hv_kvm.IFF_VNET_HDR]:
358 ea2bcb82 Michael Hanselmann
      fn = compat.partial(self._FakeIoctl, features)
359 ea2bcb82 Michael Hanselmann
      result = hv_kvm._GetTunFeatures(fd, _ioctl=fn)
360 ea2bcb82 Michael Hanselmann
      self.assertEqual(result, features)
361 ea2bcb82 Michael Hanselmann
362 ea2bcb82 Michael Hanselmann
363 ea2bcb82 Michael Hanselmann
class TestProbeTapVnetHdr(unittest.TestCase):
364 ea2bcb82 Michael Hanselmann
  def _FakeTunFeatures(self, expected_fd, flags, fd):
365 ea2bcb82 Michael Hanselmann
    self.assertEqual(fd, expected_fd)
366 ea2bcb82 Michael Hanselmann
    return flags
367 ea2bcb82 Michael Hanselmann
368 ea2bcb82 Michael Hanselmann
  def test(self):
369 ea2bcb82 Michael Hanselmann
    tmpfile = tempfile.NamedTemporaryFile()
370 ea2bcb82 Michael Hanselmann
    fd = tmpfile.fileno()
371 ea2bcb82 Michael Hanselmann
372 ea2bcb82 Michael Hanselmann
    for flags in [0, hv_kvm.IFF_VNET_HDR]:
373 ea2bcb82 Michael Hanselmann
      fn = compat.partial(self._FakeTunFeatures, fd, flags)
374 ea2bcb82 Michael Hanselmann
375 ea2bcb82 Michael Hanselmann
      result = hv_kvm._ProbeTapVnetHdr(fd, _features_fn=fn)
376 ea2bcb82 Michael Hanselmann
      if flags == 0:
377 ea2bcb82 Michael Hanselmann
        self.assertFalse(result)
378 ea2bcb82 Michael Hanselmann
      else:
379 ea2bcb82 Michael Hanselmann
        self.assertTrue(result)
380 ea2bcb82 Michael Hanselmann
381 ea2bcb82 Michael Hanselmann
  def testUnsupported(self):
382 ea2bcb82 Michael Hanselmann
    tmpfile = tempfile.NamedTemporaryFile()
383 ea2bcb82 Michael Hanselmann
    fd = tmpfile.fileno()
384 ea2bcb82 Michael Hanselmann
385 ea2bcb82 Michael Hanselmann
    self.assertFalse(hv_kvm._ProbeTapVnetHdr(fd, _features_fn=lambda _: None))
386 ea2bcb82 Michael Hanselmann
387 ea2bcb82 Michael Hanselmann
388 fda3d987 Dimitris Aragiorgis
class TestGenerateDeviceKVMId(unittest.TestCase):
389 fda3d987 Dimitris Aragiorgis
  def test(self):
390 fda3d987 Dimitris Aragiorgis
    device = objects.NIC()
391 fda3d987 Dimitris Aragiorgis
    target = constants.HOTPLUG_TARGET_NIC
392 fda3d987 Dimitris Aragiorgis
    fn = hv_kvm._GenerateDeviceKVMId
393 fda3d987 Dimitris Aragiorgis
    self.assertRaises(errors.HotplugError, fn, target, device)
394 fda3d987 Dimitris Aragiorgis
395 fda3d987 Dimitris Aragiorgis
    device.pci = 5
396 fda3d987 Dimitris Aragiorgis
    device.uuid = "003fc157-66a8-4e6d-8b7e-ec4f69751396"
397 fda3d987 Dimitris Aragiorgis
    self.assertTrue(re.match("hotnic-003fc157-pci-5", fn(target, device)))
398 fda3d987 Dimitris Aragiorgis
399 fda3d987 Dimitris Aragiorgis
400 fda3d987 Dimitris Aragiorgis
class TestGetRuntimeInfo(unittest.TestCase):
401 fda3d987 Dimitris Aragiorgis
  @classmethod
402 fda3d987 Dimitris Aragiorgis
  def _GetRuntime(cls):
403 fda3d987 Dimitris Aragiorgis
    data = testutils.ReadTestData("kvm_runtime.json")
404 fda3d987 Dimitris Aragiorgis
    return hv_kvm._AnalyzeSerializedRuntime(data)
405 fda3d987 Dimitris Aragiorgis
406 fda3d987 Dimitris Aragiorgis
  def _fail(self, target, device, runtime):
407 fda3d987 Dimitris Aragiorgis
    device.uuid = "aaaaaaaa-66a8-4e6d-8b7e-ec4f69751396"
408 fda3d987 Dimitris Aragiorgis
    self.assertRaises(errors.HotplugError,
409 fda3d987 Dimitris Aragiorgis
                      hv_kvm._GetExistingDeviceInfo,
410 fda3d987 Dimitris Aragiorgis
                      target, device, runtime)
411 fda3d987 Dimitris Aragiorgis
412 fda3d987 Dimitris Aragiorgis
  def testNIC(self):
413 fda3d987 Dimitris Aragiorgis
    device = objects.NIC()
414 fda3d987 Dimitris Aragiorgis
    target = constants.HOTPLUG_TARGET_NIC
415 fda3d987 Dimitris Aragiorgis
    runtime = self._GetRuntime()
416 fda3d987 Dimitris Aragiorgis
417 fda3d987 Dimitris Aragiorgis
    self._fail(target, device, runtime)
418 fda3d987 Dimitris Aragiorgis
419 fda3d987 Dimitris Aragiorgis
    device.uuid = "003fc157-66a8-4e6d-8b7e-ec4f69751396"
420 fda3d987 Dimitris Aragiorgis
    devinfo = hv_kvm._GetExistingDeviceInfo(target, device, runtime)
421 fda3d987 Dimitris Aragiorgis
    self.assertTrue(devinfo.pci==6)
422 fda3d987 Dimitris Aragiorgis
423 fda3d987 Dimitris Aragiorgis
  def testDisk(self):
424 fda3d987 Dimitris Aragiorgis
    device = objects.Disk()
425 fda3d987 Dimitris Aragiorgis
    target = constants.HOTPLUG_TARGET_DISK
426 fda3d987 Dimitris Aragiorgis
    runtime = self._GetRuntime()
427 fda3d987 Dimitris Aragiorgis
428 fda3d987 Dimitris Aragiorgis
    self._fail(target, device, runtime)
429 fda3d987 Dimitris Aragiorgis
430 fda3d987 Dimitris Aragiorgis
    device.uuid = "9f5c5bd4-6f60-480b-acdc-9bb1a4b7df79"
431 fda3d987 Dimitris Aragiorgis
    (devinfo, _, __) = hv_kvm._GetExistingDeviceInfo(target, device, runtime)
432 fda3d987 Dimitris Aragiorgis
    self.assertTrue(devinfo.pci==5)
433 fda3d987 Dimitris Aragiorgis
434 fda3d987 Dimitris Aragiorgis
435 748e4b5a Michael Hanselmann
if __name__ == "__main__":
436 748e4b5a Michael Hanselmann
  testutils.GanetiTestProgram()