Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hypervisor.hv_kvm_unittest.py @ 595149d5

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

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

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