Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.hypervisor.hv_kvm_unittest.py @ 91c17910

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

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

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

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

301 0ad7f5d8 Guido Trotter
    """
302 0ad7f5d8 Guido Trotter
    boot_re = hv_kvm.KVMHypervisor._BOOT_RE
303 00ef625c Michael Hanselmann
    help_112 = testutils.ReadTestData("kvm_1.1.2_help.txt")
304 00ef625c Michael Hanselmann
    help_10 = testutils.ReadTestData("kvm_1.0_help.txt")
305 00ef625c Michael Hanselmann
    help_01590 = testutils.ReadTestData("kvm_0.15.90_help.txt")
306 00ef625c Michael Hanselmann
    help_0125 = testutils.ReadTestData("kvm_0.12.5_help.txt")
307 00ef625c Michael Hanselmann
    help_091 = testutils.ReadTestData("kvm_0.9.1_help.txt")
308 00ef625c Michael Hanselmann
    help_091_fake = testutils.ReadTestData("kvm_0.9.1_help_boot_test.txt")
309 0ad7f5d8 Guido Trotter
310 0ad7f5d8 Guido Trotter
    self.assertTrue(boot_re.search(help_091))
311 0ad7f5d8 Guido Trotter
    self.assertTrue(boot_re.search(help_0125))
312 eb7a6965 Guido Trotter
    self.assertFalse(boot_re.search(help_091_fake))
313 eb7a6965 Guido Trotter
    self.assertFalse(boot_re.search(help_112))
314 0ad7f5d8 Guido Trotter
    self.assertFalse(boot_re.search(help_10))
315 0ad7f5d8 Guido Trotter
    self.assertFalse(boot_re.search(help_01590))
316 0ad7f5d8 Guido Trotter
317 0ad7f5d8 Guido Trotter
318 748e4b5a Michael Hanselmann
if __name__ == "__main__":
319 748e4b5a Michael Hanselmann
  testutils.GanetiTestProgram()