Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hypervisor.hv_kvm_unittest.py @ cd3b4ff4

History | View | Annotate | Download (12.1 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 748e4b5a Michael Hanselmann
31 91c10532 Andrea Spadaccini
from ganeti import serializer
32 748e4b5a Michael Hanselmann
from ganeti import constants
33 748e4b5a Michael Hanselmann
from ganeti import compat
34 748e4b5a Michael Hanselmann
from ganeti import objects
35 748e4b5a Michael Hanselmann
from ganeti import errors
36 585c8187 Guido Trotter
from ganeti import utils
37 a56625a2 Michael Hanselmann
from ganeti import pathutils
38 748e4b5a Michael Hanselmann
39 748e4b5a Michael Hanselmann
from ganeti.hypervisor import hv_kvm
40 748e4b5a Michael Hanselmann
41 748e4b5a Michael Hanselmann
import testutils
42 748e4b5a Michael Hanselmann
43 748e4b5a Michael Hanselmann
44 91c10532 Andrea Spadaccini
class QmpStub(threading.Thread):
45 91c10532 Andrea Spadaccini
  """Stub for a QMP endpoint for a KVM instance
46 91c10532 Andrea Spadaccini

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

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

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

306 0ad7f5d8 Guido Trotter
    """
307 0ad7f5d8 Guido Trotter
    boot_re = hv_kvm.KVMHypervisor._BOOT_RE
308 00ef625c Michael Hanselmann
    help_112 = testutils.ReadTestData("kvm_1.1.2_help.txt")
309 00ef625c Michael Hanselmann
    help_10 = testutils.ReadTestData("kvm_1.0_help.txt")
310 00ef625c Michael Hanselmann
    help_01590 = testutils.ReadTestData("kvm_0.15.90_help.txt")
311 00ef625c Michael Hanselmann
    help_0125 = testutils.ReadTestData("kvm_0.12.5_help.txt")
312 00ef625c Michael Hanselmann
    help_091 = testutils.ReadTestData("kvm_0.9.1_help.txt")
313 00ef625c Michael Hanselmann
    help_091_fake = testutils.ReadTestData("kvm_0.9.1_help_boot_test.txt")
314 0ad7f5d8 Guido Trotter
315 0ad7f5d8 Guido Trotter
    self.assertTrue(boot_re.search(help_091))
316 0ad7f5d8 Guido Trotter
    self.assertTrue(boot_re.search(help_0125))
317 eb7a6965 Guido Trotter
    self.assertFalse(boot_re.search(help_091_fake))
318 eb7a6965 Guido Trotter
    self.assertFalse(boot_re.search(help_112))
319 0ad7f5d8 Guido Trotter
    self.assertFalse(boot_re.search(help_10))
320 0ad7f5d8 Guido Trotter
    self.assertFalse(boot_re.search(help_01590))
321 0ad7f5d8 Guido Trotter
322 0ad7f5d8 Guido Trotter
323 ea2bcb82 Michael Hanselmann
class TestGetTunFeatures(unittest.TestCase):
324 ea2bcb82 Michael Hanselmann
  def testWrongIoctl(self):
325 ea2bcb82 Michael Hanselmann
    tmpfile = tempfile.NamedTemporaryFile()
326 ea2bcb82 Michael Hanselmann
    # A file does not have the right ioctls, so this must always fail
327 ea2bcb82 Michael Hanselmann
    result = hv_kvm._GetTunFeatures(tmpfile.fileno())
328 ea2bcb82 Michael Hanselmann
    self.assertTrue(result is None)
329 ea2bcb82 Michael Hanselmann
330 ea2bcb82 Michael Hanselmann
  def _FakeIoctl(self, features, fd, request, buf):
331 ea2bcb82 Michael Hanselmann
    self.assertEqual(request, hv_kvm.TUNGETFEATURES)
332 ea2bcb82 Michael Hanselmann
333 ea2bcb82 Michael Hanselmann
    (reqno, ) = struct.unpack("I", buf)
334 ea2bcb82 Michael Hanselmann
    self.assertEqual(reqno, 0)
335 ea2bcb82 Michael Hanselmann
336 ea2bcb82 Michael Hanselmann
    return struct.pack("I", features)
337 ea2bcb82 Michael Hanselmann
338 ea2bcb82 Michael Hanselmann
  def test(self):
339 ea2bcb82 Michael Hanselmann
    tmpfile = tempfile.NamedTemporaryFile()
340 ea2bcb82 Michael Hanselmann
    fd = tmpfile.fileno()
341 ea2bcb82 Michael Hanselmann
342 ea2bcb82 Michael Hanselmann
    for features in [0, hv_kvm.IFF_VNET_HDR]:
343 ea2bcb82 Michael Hanselmann
      fn = compat.partial(self._FakeIoctl, features)
344 ea2bcb82 Michael Hanselmann
      result = hv_kvm._GetTunFeatures(fd, _ioctl=fn)
345 ea2bcb82 Michael Hanselmann
      self.assertEqual(result, features)
346 ea2bcb82 Michael Hanselmann
347 ea2bcb82 Michael Hanselmann
348 ea2bcb82 Michael Hanselmann
class TestProbeTapVnetHdr(unittest.TestCase):
349 ea2bcb82 Michael Hanselmann
  def _FakeTunFeatures(self, expected_fd, flags, fd):
350 ea2bcb82 Michael Hanselmann
    self.assertEqual(fd, expected_fd)
351 ea2bcb82 Michael Hanselmann
    return flags
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 flags in [0, hv_kvm.IFF_VNET_HDR]:
358 ea2bcb82 Michael Hanselmann
      fn = compat.partial(self._FakeTunFeatures, fd, flags)
359 ea2bcb82 Michael Hanselmann
360 ea2bcb82 Michael Hanselmann
      result = hv_kvm._ProbeTapVnetHdr(fd, _features_fn=fn)
361 ea2bcb82 Michael Hanselmann
      if flags == 0:
362 ea2bcb82 Michael Hanselmann
        self.assertFalse(result)
363 ea2bcb82 Michael Hanselmann
      else:
364 ea2bcb82 Michael Hanselmann
        self.assertTrue(result)
365 ea2bcb82 Michael Hanselmann
366 ea2bcb82 Michael Hanselmann
  def testUnsupported(self):
367 ea2bcb82 Michael Hanselmann
    tmpfile = tempfile.NamedTemporaryFile()
368 ea2bcb82 Michael Hanselmann
    fd = tmpfile.fileno()
369 ea2bcb82 Michael Hanselmann
370 ea2bcb82 Michael Hanselmann
    self.assertFalse(hv_kvm._ProbeTapVnetHdr(fd, _features_fn=lambda _: None))
371 ea2bcb82 Michael Hanselmann
372 ea2bcb82 Michael Hanselmann
373 748e4b5a Michael Hanselmann
if __name__ == "__main__":
374 748e4b5a Michael Hanselmann
  testutils.GanetiTestProgram()