Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hypervisor.hv_kvm_unittest.py @ 6b06efa7

History | View | Annotate | Download (14.4 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 c42be2c0 Petr Pudlak
  def _Test(self, instance, node, group, hvparams):
204 c42be2c0 Petr Pudlak
    cons = hv_kvm.KVMHypervisor.GetInstanceConsole(instance, node, group,
205 c42be2c0 Petr Pudlak
                                                   hvparams, {})
206 55cc0a44 Michael Hanselmann
    self.assertTrue(cons.Validate())
207 55cc0a44 Michael Hanselmann
    return cons
208 55cc0a44 Michael Hanselmann
209 55cc0a44 Michael Hanselmann
  def testSerial(self):
210 55cc0a44 Michael Hanselmann
    instance = objects.Instance(name="kvm.example.com",
211 1c3231aa Thomas Thrainer
                                primary_node="node6017-uuid")
212 c42be2c0 Petr Pudlak
    node = objects.Node(name="node6017", uuid="node6017-uuid",
213 c42be2c0 Petr Pudlak
                        ndparams={})
214 c42be2c0 Petr Pudlak
    group = objects.NodeGroup(name="group6134", ndparams={})
215 55cc0a44 Michael Hanselmann
    hvparams = {
216 55cc0a44 Michael Hanselmann
      constants.HV_SERIAL_CONSOLE: True,
217 55cc0a44 Michael Hanselmann
      constants.HV_VNC_BIND_ADDRESS: None,
218 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: None,
219 55cc0a44 Michael Hanselmann
      }
220 c42be2c0 Petr Pudlak
    cons = self._Test(instance, node, group, hvparams)
221 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.kind, constants.CONS_SSH)
222 1c3231aa Thomas Thrainer
    self.assertEqual(cons.host, node.name)
223 a56625a2 Michael Hanselmann
    self.assertEqual(cons.command[0], pathutils.KVM_CONSOLE_WRAPPER)
224 2f4c951e Stephen Shirley
    self.assertEqual(cons.command[1], constants.SOCAT_PATH)
225 55cc0a44 Michael Hanselmann
226 55cc0a44 Michael Hanselmann
  def testVnc(self):
227 55cc0a44 Michael Hanselmann
    instance = objects.Instance(name="kvm.example.com",
228 1c3231aa Thomas Thrainer
                                primary_node="node7235-uuid",
229 55cc0a44 Michael Hanselmann
                                network_port=constants.VNC_BASE_PORT + 10)
230 c42be2c0 Petr Pudlak
    node = objects.Node(name="node7235", uuid="node7235-uuid",
231 c42be2c0 Petr Pudlak
                        ndparams={})
232 c42be2c0 Petr Pudlak
    group = objects.NodeGroup(name="group3632", ndparams={})
233 55cc0a44 Michael Hanselmann
    hvparams = {
234 55cc0a44 Michael Hanselmann
      constants.HV_SERIAL_CONSOLE: False,
235 55cc0a44 Michael Hanselmann
      constants.HV_VNC_BIND_ADDRESS: "192.0.2.1",
236 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: None,
237 55cc0a44 Michael Hanselmann
      }
238 c42be2c0 Petr Pudlak
    cons = self._Test(instance, node, group, hvparams)
239 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.kind, constants.CONS_VNC)
240 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.host, "192.0.2.1")
241 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.port, constants.VNC_BASE_PORT + 10)
242 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.display, 10)
243 55cc0a44 Michael Hanselmann
244 4d2cdb5a Andrea Spadaccini
  def testSpice(self):
245 4d2cdb5a Andrea Spadaccini
    instance = objects.Instance(name="kvm.example.com",
246 4d2cdb5a Andrea Spadaccini
                                primary_node="node7235",
247 4d2cdb5a Andrea Spadaccini
                                network_port=11000)
248 c42be2c0 Petr Pudlak
    node = objects.Node(name="node7235", uuid="node7235-uuid",
249 c42be2c0 Petr Pudlak
                        ndparams={})
250 c42be2c0 Petr Pudlak
    group = objects.NodeGroup(name="group0132", ndparams={})
251 4d2cdb5a Andrea Spadaccini
    hvparams = {
252 4d2cdb5a Andrea Spadaccini
      constants.HV_SERIAL_CONSOLE: False,
253 4d2cdb5a Andrea Spadaccini
      constants.HV_VNC_BIND_ADDRESS: None,
254 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: "192.0.2.1",
255 4d2cdb5a Andrea Spadaccini
      }
256 c42be2c0 Petr Pudlak
    cons = self._Test(instance, node, group, hvparams)
257 4d2cdb5a Andrea Spadaccini
    self.assertEqual(cons.kind, constants.CONS_SPICE)
258 4d2cdb5a Andrea Spadaccini
    self.assertEqual(cons.host, "192.0.2.1")
259 4d2cdb5a Andrea Spadaccini
    self.assertEqual(cons.port, 11000)
260 4d2cdb5a Andrea Spadaccini
261 55cc0a44 Michael Hanselmann
  def testNoConsole(self):
262 55cc0a44 Michael Hanselmann
    instance = objects.Instance(name="kvm.example.com",
263 55cc0a44 Michael Hanselmann
                                primary_node="node24325",
264 55cc0a44 Michael Hanselmann
                                network_port=0)
265 c42be2c0 Petr Pudlak
    node = objects.Node(name="node24325", uuid="node24325-uuid",
266 c42be2c0 Petr Pudlak
                        ndparams={})
267 c42be2c0 Petr Pudlak
    group = objects.NodeGroup(name="group9184", ndparams={})
268 55cc0a44 Michael Hanselmann
    hvparams = {
269 55cc0a44 Michael Hanselmann
      constants.HV_SERIAL_CONSOLE: False,
270 55cc0a44 Michael Hanselmann
      constants.HV_VNC_BIND_ADDRESS: None,
271 4d2cdb5a Andrea Spadaccini
      constants.HV_KVM_SPICE_BIND: None,
272 55cc0a44 Michael Hanselmann
      }
273 c42be2c0 Petr Pudlak
    cons = self._Test(instance, node, group, hvparams)
274 55cc0a44 Michael Hanselmann
    self.assertEqual(cons.kind, constants.CONS_MESSAGE)
275 55cc0a44 Michael Hanselmann
276 55cc0a44 Michael Hanselmann
277 585c8187 Guido Trotter
class TestVersionChecking(testutils.GanetiTestCase):
278 585c8187 Guido Trotter
  def testParseVersion(self):
279 585c8187 Guido Trotter
    parse = hv_kvm.KVMHypervisor._ParseKVMVersion
280 00ef625c Michael Hanselmann
    help_112 = testutils.ReadTestData("kvm_1.1.2_help.txt")
281 00ef625c Michael Hanselmann
    help_10 = testutils.ReadTestData("kvm_1.0_help.txt")
282 00ef625c Michael Hanselmann
    help_01590 = testutils.ReadTestData("kvm_0.15.90_help.txt")
283 00ef625c Michael Hanselmann
    help_0125 = testutils.ReadTestData("kvm_0.12.5_help.txt")
284 00ef625c Michael Hanselmann
    help_091 = testutils.ReadTestData("kvm_0.9.1_help.txt")
285 eb7a6965 Guido Trotter
    self.assertEqual(parse(help_112), ("1.1.2", 1, 1, 2))
286 585c8187 Guido Trotter
    self.assertEqual(parse(help_10), ("1.0", 1, 0, 0))
287 585c8187 Guido Trotter
    self.assertEqual(parse(help_01590), ("0.15.90", 0, 15, 90))
288 585c8187 Guido Trotter
    self.assertEqual(parse(help_0125), ("0.12.5", 0, 12, 5))
289 585c8187 Guido Trotter
    self.assertEqual(parse(help_091), ("0.9.1", 0, 9, 1))
290 585c8187 Guido Trotter
291 585c8187 Guido Trotter
292 141d1489 Michael Hanselmann
class TestSpiceParameterList(unittest.TestCase):
293 141d1489 Michael Hanselmann
  def test(self):
294 daa49d6f Michael Hanselmann
    defaults = constants.HVC_DEFAULTS[constants.HT_KVM]
295 daa49d6f Michael Hanselmann
296 141d1489 Michael Hanselmann
    params = \
297 141d1489 Michael Hanselmann
      compat.UniqueFrozenset(getattr(constants, name)
298 141d1489 Michael Hanselmann
                             for name in dir(constants)
299 141d1489 Michael Hanselmann
                             if name.startswith("HV_KVM_SPICE_"))
300 141d1489 Michael Hanselmann
301 daa49d6f Michael Hanselmann
    # Parameters whose default value evaluates to True and don't need to be set
302 daa49d6f Michael Hanselmann
    defaults_true = frozenset(filter(defaults.__getitem__, params))
303 daa49d6f Michael Hanselmann
304 daa49d6f Michael Hanselmann
    self.assertEqual(defaults_true, frozenset([
305 daa49d6f Michael Hanselmann
      constants.HV_KVM_SPICE_AUDIO_COMPR,
306 daa49d6f Michael Hanselmann
      constants.HV_KVM_SPICE_USE_VDAGENT,
307 daa49d6f Michael Hanselmann
      constants.HV_KVM_SPICE_TLS_CIPHERS,
308 daa49d6f Michael Hanselmann
      ]))
309 daa49d6f Michael Hanselmann
310 daa49d6f Michael Hanselmann
    # HV_KVM_SPICE_BIND decides whether the other parameters must be set if
311 daa49d6f Michael Hanselmann
    # their default evaluates to False
312 daa49d6f Michael Hanselmann
    assert constants.HV_KVM_SPICE_BIND in params
313 daa49d6f Michael Hanselmann
    assert constants.HV_KVM_SPICE_BIND not in defaults_true
314 daa49d6f Michael Hanselmann
315 141d1489 Michael Hanselmann
    # Exclude some parameters
316 daa49d6f Michael Hanselmann
    params -= defaults_true | frozenset([
317 141d1489 Michael Hanselmann
      constants.HV_KVM_SPICE_BIND,
318 141d1489 Michael Hanselmann
      ])
319 141d1489 Michael Hanselmann
320 141d1489 Michael Hanselmann
    self.assertEqual(hv_kvm._SPICE_ADDITIONAL_PARAMS, params)
321 141d1489 Michael Hanselmann
322 141d1489 Michael Hanselmann
323 0ad7f5d8 Guido Trotter
class TestHelpRegexps(testutils.GanetiTestCase):
324 0ad7f5d8 Guido Trotter
  def testBootRe(self):
325 0ad7f5d8 Guido Trotter
    """Check _BOOT_RE
326 0ad7f5d8 Guido Trotter

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

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