root / test / py / ganeti.hypervisor.hv_kvm_unittest.py @ 14933c17
History | View | Annotate | Download (13.9 kB)
1 | 748e4b5a | Michael Hanselmann | #!/usr/bin/python
|
---|---|---|---|
2 | 748e4b5a | Michael Hanselmann | #
|
3 | 748e4b5a | Michael Hanselmann | |
4 | 55cc0a44 | Michael Hanselmann | # Copyright (C) 2010, 2011 Google Inc.
|
5 | 748e4b5a | Michael Hanselmann | #
|
6 | 748e4b5a | Michael Hanselmann | # This program is free software; you can redistribute it and/or modify
|
7 | 748e4b5a | Michael Hanselmann | # it under the terms of the GNU General Public License as published by
|
8 | 748e4b5a | Michael Hanselmann | # the Free Software Foundation; either version 2 of the License, or
|
9 | 748e4b5a | Michael Hanselmann | # (at your option) any later version.
|
10 | 748e4b5a | Michael Hanselmann | #
|
11 | 748e4b5a | Michael Hanselmann | # This program is distributed in the hope that it will be useful, but
|
12 | 748e4b5a | Michael Hanselmann | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 748e4b5a | Michael Hanselmann | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 748e4b5a | Michael Hanselmann | # General Public License for more details.
|
15 | 748e4b5a | Michael Hanselmann | #
|
16 | 748e4b5a | Michael Hanselmann | # You should have received a copy of the GNU General Public License
|
17 | 748e4b5a | Michael Hanselmann | # along with this program; if not, write to the Free Software
|
18 | 748e4b5a | Michael Hanselmann | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | 748e4b5a | Michael Hanselmann | # 02110-1301, USA.
|
20 | 748e4b5a | Michael Hanselmann | |
21 | 748e4b5a | Michael Hanselmann | |
22 | 748e4b5a | Michael Hanselmann | """Script for testing the hypervisor.hv_kvm module"""
|
23 | 748e4b5a | Michael Hanselmann | |
24 | 91c10532 | Andrea Spadaccini | import threading |
25 | 91c10532 | Andrea Spadaccini | import tempfile |
26 | 748e4b5a | Michael Hanselmann | import unittest |
27 | 91c10532 | Andrea Spadaccini | import socket |
28 | 91c10532 | Andrea Spadaccini | import os |
29 | ea2bcb82 | Michael Hanselmann | import struct |
30 | fda3d987 | Dimitris Aragiorgis | import re |
31 | 748e4b5a | Michael Hanselmann | |
32 | 91c10532 | Andrea Spadaccini | from ganeti import serializer |
33 | 748e4b5a | Michael Hanselmann | from ganeti import constants |
34 | 748e4b5a | Michael Hanselmann | from ganeti import compat |
35 | 748e4b5a | Michael Hanselmann | from ganeti import objects |
36 | 748e4b5a | Michael Hanselmann | from ganeti import errors |
37 | 585c8187 | Guido Trotter | from ganeti import utils |
38 | a56625a2 | Michael Hanselmann | from ganeti import pathutils |
39 | 748e4b5a | Michael Hanselmann | |
40 | 748e4b5a | Michael Hanselmann | from ganeti.hypervisor import hv_kvm |
41 | 748e4b5a | Michael Hanselmann | |
42 | 748e4b5a | Michael Hanselmann | import testutils |
43 | 748e4b5a | Michael Hanselmann | |
44 | 748e4b5a | Michael Hanselmann | |
45 | 91c10532 | Andrea Spadaccini | class QmpStub(threading.Thread): |
46 | 91c10532 | Andrea Spadaccini | """Stub for a QMP endpoint for a KVM instance
|
47 | 91c10532 | Andrea Spadaccini |
|
48 | 91c10532 | Andrea Spadaccini | """
|
49 | 51129a7f | Michael Hanselmann | _QMP_BANNER_DATA = { |
50 | 51129a7f | Michael Hanselmann | "QMP": {
|
51 | 51129a7f | Michael Hanselmann | "version": {
|
52 | 51129a7f | Michael Hanselmann | "package": "", |
53 | 51129a7f | Michael Hanselmann | "qemu": {
|
54 | 51129a7f | Michael Hanselmann | "micro": 50, |
55 | 51129a7f | Michael Hanselmann | "minor": 13, |
56 | 51129a7f | Michael Hanselmann | "major": 0, |
57 | 51129a7f | Michael Hanselmann | }, |
58 | 51129a7f | Michael Hanselmann | "capabilities": [],
|
59 | 51129a7f | Michael Hanselmann | }, |
60 | 51129a7f | Michael Hanselmann | } |
61 | 51129a7f | Michael Hanselmann | } |
62 | 51129a7f | Michael Hanselmann | _EMPTY_RESPONSE = { |
63 | 51129a7f | Michael Hanselmann | "return": [],
|
64 | 51129a7f | Michael Hanselmann | } |
65 | 91c10532 | Andrea Spadaccini | |
66 | 91c10532 | Andrea Spadaccini | def __init__(self, socket_filename, server_responses): |
67 | 91c10532 | Andrea Spadaccini | """Creates a QMP stub
|
68 | 91c10532 | Andrea Spadaccini |
|
69 | 91c10532 | Andrea Spadaccini | @type socket_filename: string
|
70 | 91c10532 | Andrea Spadaccini | @param socket_filename: filename of the UNIX socket that will be created
|
71 | 91c10532 | Andrea Spadaccini | this class and used for the communication
|
72 | 91c10532 | Andrea Spadaccini | @type server_responses: list
|
73 | 91c10532 | Andrea Spadaccini | @param server_responses: list of responses that the server sends in response
|
74 | 91c10532 | Andrea Spadaccini | to whatever it receives
|
75 | 91c10532 | Andrea Spadaccini | """
|
76 | 91c10532 | Andrea Spadaccini | threading.Thread.__init__(self)
|
77 | 91c10532 | Andrea Spadaccini | self.socket_filename = socket_filename
|
78 | 91c10532 | Andrea Spadaccini | self.script = server_responses
|
79 | 91c10532 | Andrea Spadaccini | |
80 | 91c10532 | Andrea Spadaccini | self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
81 | 91c10532 | Andrea Spadaccini | self.socket.bind(self.socket_filename) |
82 | 91c10532 | Andrea Spadaccini | self.socket.listen(1) |
83 | 91c10532 | Andrea Spadaccini | |
84 | 91c10532 | Andrea Spadaccini | def run(self): |
85 | 91c10532 | Andrea Spadaccini | # Hypothesis: the messages we receive contain only a complete QMP message
|
86 | 91c10532 | Andrea Spadaccini | # encoded in JSON.
|
87 | 91c10532 | Andrea Spadaccini | conn, addr = self.socket.accept()
|
88 | 91c10532 | Andrea Spadaccini | |
89 | 91c10532 | Andrea Spadaccini | # Send the banner as the first thing
|
90 | 91c10532 | Andrea Spadaccini | conn.send(self.encode_string(self._QMP_BANNER_DATA)) |
91 | 91c10532 | Andrea Spadaccini | |
92 | 91c10532 | Andrea Spadaccini | # Expect qmp_capabilities and return an empty response
|
93 | 91c10532 | Andrea Spadaccini | conn.recv(4096)
|
94 | 91c10532 | Andrea Spadaccini | conn.send(self.encode_string(self._EMPTY_RESPONSE)) |
95 | 91c10532 | Andrea Spadaccini | |
96 | 91c10532 | Andrea Spadaccini | while True: |
97 | 91c10532 | Andrea Spadaccini | # We ignore the expected message, as the purpose of this object is not
|
98 | 91c10532 | Andrea Spadaccini | # to verify the correctness of the communication but to act as a
|
99 | 91c10532 | Andrea Spadaccini | # partner for the SUT (System Under Test, that is QmpConnection)
|
100 | 91c10532 | Andrea Spadaccini | msg = conn.recv(4096)
|
101 | 91c10532 | Andrea Spadaccini | if not msg: |
102 | 91c10532 | Andrea Spadaccini | break
|
103 | 91c10532 | Andrea Spadaccini | |
104 | 91c10532 | Andrea Spadaccini | if not self.script: |
105 | 91c10532 | Andrea Spadaccini | break
|
106 | 91c10532 | Andrea Spadaccini | response = self.script.pop(0) |
107 | 91c10532 | Andrea Spadaccini | if isinstance(response, str): |
108 | 91c10532 | Andrea Spadaccini | conn.send(response) |
109 | 91c10532 | Andrea Spadaccini | elif isinstance(response, list): |
110 | 91c10532 | Andrea Spadaccini | for chunk in response: |
111 | 91c10532 | Andrea Spadaccini | conn.send(chunk) |
112 | 91c10532 | Andrea Spadaccini | else:
|
113 | 91c10532 | Andrea Spadaccini | raise errors.ProgrammerError("Unknown response type for %s" % response) |
114 | 91c10532 | Andrea Spadaccini | |
115 | 91c10532 | Andrea Spadaccini | conn.close() |
116 | 91c10532 | Andrea Spadaccini | |
117 | 91c10532 | Andrea Spadaccini | def encode_string(self, message): |
118 | a182a3ed | Michael Hanselmann | return (serializer.DumpJson(message) +
|
119 | 91c10532 | Andrea Spadaccini | hv_kvm.QmpConnection._MESSAGE_END_TOKEN) |
120 | 91c10532 | Andrea Spadaccini | |
121 | 91c10532 | Andrea Spadaccini | |
122 | 91c10532 | Andrea Spadaccini | class TestQmpMessage(testutils.GanetiTestCase): |
123 | 91c10532 | Andrea Spadaccini | def testSerialization(self): |
124 | 51129a7f | Michael Hanselmann | test_data = { |
125 | 51129a7f | Michael Hanselmann | "execute": "command", |
126 | 51129a7f | Michael Hanselmann | "arguments": ["a", "b", "c"], |
127 | 51129a7f | Michael Hanselmann | } |
128 | 91c10532 | Andrea Spadaccini | message = hv_kvm.QmpMessage(test_data) |
129 | 91c10532 | Andrea Spadaccini | |
130 | 91c10532 | Andrea Spadaccini | for k, v in test_data.items(): |
131 | 51129a7f | Michael Hanselmann | self.assertEqual(message[k], v)
|
132 | 91c10532 | Andrea Spadaccini | |
133 | 51129a7f | Michael Hanselmann | serialized = str(message)
|
134 | 51129a7f | Michael Hanselmann | self.assertEqual(len(serialized.splitlines()), 1, |
135 | 51129a7f | Michael Hanselmann | msg="Got multi-line message")
|
136 | 51129a7f | Michael Hanselmann | |
137 | 51129a7f | Michael Hanselmann | rebuilt_message = hv_kvm.QmpMessage.BuildFromJsonString(serialized) |
138 | 51129a7f | Michael Hanselmann | self.assertEqual(rebuilt_message, message)
|
139 | 5e34123e | Michele Tartara | self.assertEqual(len(rebuilt_message), len(test_data)) |
140 | 5e34123e | Michele Tartara | |
141 | 5e34123e | Michele Tartara | def testDelete(self): |
142 | 5e34123e | Michele Tartara | toDelete = "execute"
|
143 | 5e34123e | Michele Tartara | test_data = { |
144 | 5e34123e | Michele Tartara | toDelete: "command",
|
145 | 5e34123e | Michele Tartara | "arguments": ["a", "b", "c"], |
146 | 5e34123e | Michele Tartara | } |
147 | 5e34123e | Michele Tartara | message = hv_kvm.QmpMessage(test_data) |
148 | 5e34123e | Michele Tartara | |
149 | 5e34123e | Michele Tartara | oldLen = len(message)
|
150 | 5e34123e | Michele Tartara | del(message[toDelete])
|
151 | 5e34123e | Michele Tartara | newLen = len(message)
|
152 | 5e34123e | Michele Tartara | self.assertEqual(oldLen - 1, newLen) |
153 | 91c10532 | Andrea Spadaccini | |
154 | 91c10532 | Andrea Spadaccini | |
155 | 91c10532 | Andrea Spadaccini | class TestQmp(testutils.GanetiTestCase): |
156 | 91c10532 | Andrea Spadaccini | def testQmp(self): |
157 | 91c10532 | Andrea Spadaccini | requests = [ |
158 | 91c10532 | Andrea Spadaccini | {"execute": "query-kvm", "arguments": []}, |
159 | 91c10532 | Andrea Spadaccini | {"execute": "eject", "arguments": {"device": "ide1-cd0"}}, |
160 | 91c10532 | Andrea Spadaccini | {"execute": "query-status", "arguments": []}, |
161 | 91c10532 | Andrea Spadaccini | {"execute": "query-name", "arguments": []}, |
162 | 91c10532 | Andrea Spadaccini | ] |
163 | 91c10532 | Andrea Spadaccini | |
164 | 91c10532 | Andrea Spadaccini | server_responses = [ |
165 | 91c10532 | Andrea Spadaccini | # One message, one send()
|
166 | 91c10532 | Andrea Spadaccini | '{"return": {"enabled": true, "present": true}}\r\n',
|
167 | 91c10532 | Andrea Spadaccini | |
168 | 91c10532 | Andrea Spadaccini | # Message sent using multiple send()
|
169 | 91c10532 | Andrea Spadaccini | ['{"retur', 'n": {}}\r\n'], |
170 | 91c10532 | Andrea Spadaccini | |
171 | 91c10532 | Andrea Spadaccini | # Multiple messages sent using one send()
|
172 | 91c10532 | Andrea Spadaccini | '{"return": [{"name": "quit"}, {"name": "eject"}]}\r\n'
|
173 | 91c10532 | Andrea Spadaccini | '{"return": {"running": true, "singlestep": false}}\r\n',
|
174 | 91c10532 | Andrea Spadaccini | ] |
175 | 91c10532 | Andrea Spadaccini | |
176 | 91c10532 | Andrea Spadaccini | expected_responses = [ |
177 | 91c10532 | Andrea Spadaccini | {"return": {"enabled": True, "present": True}}, |
178 | 91c10532 | Andrea Spadaccini | {"return": {}},
|
179 | 91c10532 | Andrea Spadaccini | {"return": [{"name": "quit"}, {"name": "eject"}]}, |
180 | 91c10532 | Andrea Spadaccini | {"return": {"running": True, "singlestep": False}}, |
181 | 91c10532 | Andrea Spadaccini | ] |
182 | 91c10532 | Andrea Spadaccini | |
183 | 91c10532 | Andrea Spadaccini | # Set up the stub
|
184 | 91c10532 | Andrea Spadaccini | socket_file = tempfile.NamedTemporaryFile() |
185 | 91c10532 | Andrea Spadaccini | os.remove(socket_file.name) |
186 | 91c10532 | Andrea Spadaccini | qmp_stub = QmpStub(socket_file.name, server_responses) |
187 | 91c10532 | Andrea Spadaccini | qmp_stub.start() |
188 | 91c10532 | Andrea Spadaccini | |
189 | 91c10532 | Andrea Spadaccini | # Set up the QMP connection
|
190 | 91c10532 | Andrea Spadaccini | qmp_connection = hv_kvm.QmpConnection(socket_file.name) |
191 | 91c10532 | Andrea Spadaccini | qmp_connection.connect() |
192 | 91c10532 | Andrea Spadaccini | |
193 | 91c10532 | Andrea Spadaccini | # Format the script
|
194 | 91c10532 | Andrea Spadaccini | for request, expected_response in zip(requests, expected_responses): |
195 | 91c10532 | Andrea Spadaccini | response = qmp_connection.Execute(request) |
196 | 51129a7f | Michael Hanselmann | msg = hv_kvm.QmpMessage(expected_response) |
197 | 51129a7f | Michael Hanselmann | self.assertEqual(len(str(msg).splitlines()), 1, |
198 | 51129a7f | Michael Hanselmann | msg="Got multi-line message")
|
199 | 51129a7f | Michael Hanselmann | self.assertEqual(response, msg)
|
200 | 91c10532 | Andrea Spadaccini | |
201 | 91c10532 | Andrea Spadaccini | |
202 | 55cc0a44 | Michael Hanselmann | class TestConsole(unittest.TestCase): |
203 | 1c3231aa | Thomas Thrainer | def _Test(self, instance, node, hvparams): |
204 | 1c3231aa | Thomas Thrainer | cons = hv_kvm.KVMHypervisor.GetInstanceConsole(instance, node, hvparams, {}) |
205 | 55cc0a44 | Michael Hanselmann | self.assertTrue(cons.Validate())
|
206 | 55cc0a44 | Michael Hanselmann | return cons
|
207 | 55cc0a44 | Michael Hanselmann | |
208 | 55cc0a44 | Michael Hanselmann | def testSerial(self): |
209 | 55cc0a44 | Michael Hanselmann | instance = objects.Instance(name="kvm.example.com",
|
210 | 1c3231aa | Thomas Thrainer | primary_node="node6017-uuid")
|
211 | 1c3231aa | Thomas Thrainer | node = objects.Node(name="node6017", uuid="node6017-uuid") |
212 | 55cc0a44 | Michael Hanselmann | hvparams = { |
213 | 55cc0a44 | Michael Hanselmann | constants.HV_SERIAL_CONSOLE: True,
|
214 | 55cc0a44 | Michael Hanselmann | constants.HV_VNC_BIND_ADDRESS: None,
|
215 | 4d2cdb5a | Andrea Spadaccini | constants.HV_KVM_SPICE_BIND: None,
|
216 | 55cc0a44 | Michael Hanselmann | } |
217 | 1c3231aa | Thomas Thrainer | cons = self._Test(instance, node, hvparams)
|
218 | 55cc0a44 | Michael Hanselmann | self.assertEqual(cons.kind, constants.CONS_SSH)
|
219 | 1c3231aa | Thomas Thrainer | self.assertEqual(cons.host, node.name)
|
220 | a56625a2 | Michael Hanselmann | self.assertEqual(cons.command[0], pathutils.KVM_CONSOLE_WRAPPER) |
221 | 2f4c951e | Stephen Shirley | self.assertEqual(cons.command[1], constants.SOCAT_PATH) |
222 | 55cc0a44 | Michael Hanselmann | |
223 | 55cc0a44 | Michael Hanselmann | def testVnc(self): |
224 | 55cc0a44 | Michael Hanselmann | instance = objects.Instance(name="kvm.example.com",
|
225 | 1c3231aa | Thomas Thrainer | primary_node="node7235-uuid",
|
226 | 55cc0a44 | Michael Hanselmann | network_port=constants.VNC_BASE_PORT + 10)
|
227 | 1c3231aa | Thomas Thrainer | node = objects.Node(name="node7235", uuid="node7235-uuid") |
228 | 55cc0a44 | Michael Hanselmann | hvparams = { |
229 | 55cc0a44 | Michael Hanselmann | constants.HV_SERIAL_CONSOLE: False,
|
230 | 55cc0a44 | Michael Hanselmann | constants.HV_VNC_BIND_ADDRESS: "192.0.2.1",
|
231 | 4d2cdb5a | Andrea Spadaccini | constants.HV_KVM_SPICE_BIND: None,
|
232 | 55cc0a44 | Michael Hanselmann | } |
233 | 1c3231aa | Thomas Thrainer | cons = self._Test(instance, node, hvparams)
|
234 | 55cc0a44 | Michael Hanselmann | self.assertEqual(cons.kind, constants.CONS_VNC)
|
235 | 55cc0a44 | Michael Hanselmann | self.assertEqual(cons.host, "192.0.2.1") |
236 | 55cc0a44 | Michael Hanselmann | self.assertEqual(cons.port, constants.VNC_BASE_PORT + 10) |
237 | 55cc0a44 | Michael Hanselmann | self.assertEqual(cons.display, 10) |
238 | 55cc0a44 | Michael Hanselmann | |
239 | 4d2cdb5a | Andrea Spadaccini | def testSpice(self): |
240 | 4d2cdb5a | Andrea Spadaccini | instance = objects.Instance(name="kvm.example.com",
|
241 | 4d2cdb5a | Andrea Spadaccini | primary_node="node7235",
|
242 | 4d2cdb5a | Andrea Spadaccini | network_port=11000)
|
243 | 1c3231aa | Thomas Thrainer | node = objects.Node(name="node7235", uuid="node7235-uuid") |
244 | 4d2cdb5a | Andrea Spadaccini | hvparams = { |
245 | 4d2cdb5a | Andrea Spadaccini | constants.HV_SERIAL_CONSOLE: False,
|
246 | 4d2cdb5a | Andrea Spadaccini | constants.HV_VNC_BIND_ADDRESS: None,
|
247 | 4d2cdb5a | Andrea Spadaccini | constants.HV_KVM_SPICE_BIND: "192.0.2.1",
|
248 | 4d2cdb5a | Andrea Spadaccini | } |
249 | 1c3231aa | Thomas Thrainer | cons = self._Test(instance, node, hvparams)
|
250 | 4d2cdb5a | Andrea Spadaccini | self.assertEqual(cons.kind, constants.CONS_SPICE)
|
251 | 4d2cdb5a | Andrea Spadaccini | self.assertEqual(cons.host, "192.0.2.1") |
252 | 4d2cdb5a | Andrea Spadaccini | self.assertEqual(cons.port, 11000) |
253 | 4d2cdb5a | Andrea Spadaccini | |
254 | 55cc0a44 | Michael Hanselmann | def testNoConsole(self): |
255 | 55cc0a44 | Michael Hanselmann | instance = objects.Instance(name="kvm.example.com",
|
256 | 55cc0a44 | Michael Hanselmann | primary_node="node24325",
|
257 | 55cc0a44 | Michael Hanselmann | network_port=0)
|
258 | 1c3231aa | Thomas Thrainer | node = objects.Node(name="node24325", uuid="node24325-uuid") |
259 | 55cc0a44 | Michael Hanselmann | hvparams = { |
260 | 55cc0a44 | Michael Hanselmann | constants.HV_SERIAL_CONSOLE: False,
|
261 | 55cc0a44 | Michael Hanselmann | constants.HV_VNC_BIND_ADDRESS: None,
|
262 | 4d2cdb5a | Andrea Spadaccini | constants.HV_KVM_SPICE_BIND: None,
|
263 | 55cc0a44 | Michael Hanselmann | } |
264 | 1c3231aa | Thomas Thrainer | cons = self._Test(instance, node, hvparams)
|
265 | 55cc0a44 | Michael Hanselmann | self.assertEqual(cons.kind, constants.CONS_MESSAGE)
|
266 | 55cc0a44 | Michael Hanselmann | |
267 | 55cc0a44 | Michael Hanselmann | |
268 | 585c8187 | Guido Trotter | class TestVersionChecking(testutils.GanetiTestCase): |
269 | 585c8187 | Guido Trotter | def testParseVersion(self): |
270 | 585c8187 | Guido Trotter | parse = hv_kvm.KVMHypervisor._ParseKVMVersion |
271 | 00ef625c | Michael Hanselmann | help_112 = testutils.ReadTestData("kvm_1.1.2_help.txt")
|
272 | 00ef625c | Michael Hanselmann | help_10 = testutils.ReadTestData("kvm_1.0_help.txt")
|
273 | 00ef625c | Michael Hanselmann | help_01590 = testutils.ReadTestData("kvm_0.15.90_help.txt")
|
274 | 00ef625c | Michael Hanselmann | help_0125 = testutils.ReadTestData("kvm_0.12.5_help.txt")
|
275 | 00ef625c | Michael Hanselmann | help_091 = testutils.ReadTestData("kvm_0.9.1_help.txt")
|
276 | eb7a6965 | Guido Trotter | self.assertEqual(parse(help_112), ("1.1.2", 1, 1, 2)) |
277 | 585c8187 | Guido Trotter | self.assertEqual(parse(help_10), ("1.0", 1, 0, 0)) |
278 | 585c8187 | Guido Trotter | self.assertEqual(parse(help_01590), ("0.15.90", 0, 15, 90)) |
279 | 585c8187 | Guido Trotter | self.assertEqual(parse(help_0125), ("0.12.5", 0, 12, 5)) |
280 | 585c8187 | Guido Trotter | self.assertEqual(parse(help_091), ("0.9.1", 0, 9, 1)) |
281 | 585c8187 | Guido Trotter | |
282 | 585c8187 | Guido Trotter | |
283 | 141d1489 | Michael Hanselmann | class TestSpiceParameterList(unittest.TestCase): |
284 | 141d1489 | Michael Hanselmann | def test(self): |
285 | daa49d6f | Michael Hanselmann | defaults = constants.HVC_DEFAULTS[constants.HT_KVM] |
286 | daa49d6f | Michael Hanselmann | |
287 | 141d1489 | Michael Hanselmann | params = \ |
288 | 141d1489 | Michael Hanselmann | compat.UniqueFrozenset(getattr(constants, name)
|
289 | 141d1489 | Michael Hanselmann | for name in dir(constants) |
290 | 141d1489 | Michael Hanselmann | if name.startswith("HV_KVM_SPICE_")) |
291 | 141d1489 | Michael Hanselmann | |
292 | daa49d6f | Michael Hanselmann | # Parameters whose default value evaluates to True and don't need to be set
|
293 | daa49d6f | Michael Hanselmann | defaults_true = frozenset(filter(defaults.__getitem__, params)) |
294 | daa49d6f | Michael Hanselmann | |
295 | daa49d6f | Michael Hanselmann | self.assertEqual(defaults_true, frozenset([ |
296 | daa49d6f | Michael Hanselmann | constants.HV_KVM_SPICE_AUDIO_COMPR, |
297 | daa49d6f | Michael Hanselmann | constants.HV_KVM_SPICE_USE_VDAGENT, |
298 | daa49d6f | Michael Hanselmann | constants.HV_KVM_SPICE_TLS_CIPHERS, |
299 | daa49d6f | Michael Hanselmann | ])) |
300 | daa49d6f | Michael Hanselmann | |
301 | daa49d6f | Michael Hanselmann | # HV_KVM_SPICE_BIND decides whether the other parameters must be set if
|
302 | daa49d6f | Michael Hanselmann | # their default evaluates to False
|
303 | daa49d6f | Michael Hanselmann | assert constants.HV_KVM_SPICE_BIND in params |
304 | daa49d6f | Michael Hanselmann | assert constants.HV_KVM_SPICE_BIND not in defaults_true |
305 | daa49d6f | Michael Hanselmann | |
306 | 141d1489 | Michael Hanselmann | # Exclude some parameters
|
307 | daa49d6f | Michael Hanselmann | params -= defaults_true | frozenset([
|
308 | 141d1489 | Michael Hanselmann | constants.HV_KVM_SPICE_BIND, |
309 | 141d1489 | Michael Hanselmann | ]) |
310 | 141d1489 | Michael Hanselmann | |
311 | 141d1489 | Michael Hanselmann | self.assertEqual(hv_kvm._SPICE_ADDITIONAL_PARAMS, params)
|
312 | 141d1489 | Michael Hanselmann | |
313 | 141d1489 | Michael Hanselmann | |
314 | 0ad7f5d8 | Guido Trotter | class TestHelpRegexps(testutils.GanetiTestCase): |
315 | 0ad7f5d8 | Guido Trotter | def testBootRe(self): |
316 | 0ad7f5d8 | Guido Trotter | """Check _BOOT_RE
|
317 | 0ad7f5d8 | Guido Trotter |
|
318 | 0ad7f5d8 | Guido Trotter | It has too match -drive.*boot=on|off except if there is another dash-option
|
319 | 0ad7f5d8 | Guido Trotter | at the beginning of the line.
|
320 | 0ad7f5d8 | Guido Trotter |
|
321 | 0ad7f5d8 | Guido Trotter | """
|
322 | 0ad7f5d8 | Guido Trotter | boot_re = hv_kvm.KVMHypervisor._BOOT_RE |
323 | 00ef625c | Michael Hanselmann | help_112 = testutils.ReadTestData("kvm_1.1.2_help.txt")
|
324 | 00ef625c | Michael Hanselmann | help_10 = testutils.ReadTestData("kvm_1.0_help.txt")
|
325 | 00ef625c | Michael Hanselmann | help_01590 = testutils.ReadTestData("kvm_0.15.90_help.txt")
|
326 | 00ef625c | Michael Hanselmann | help_0125 = testutils.ReadTestData("kvm_0.12.5_help.txt")
|
327 | 00ef625c | Michael Hanselmann | help_091 = testutils.ReadTestData("kvm_0.9.1_help.txt")
|
328 | 00ef625c | Michael Hanselmann | help_091_fake = testutils.ReadTestData("kvm_0.9.1_help_boot_test.txt")
|
329 | 0ad7f5d8 | Guido Trotter | |
330 | 0ad7f5d8 | Guido Trotter | self.assertTrue(boot_re.search(help_091))
|
331 | 0ad7f5d8 | Guido Trotter | self.assertTrue(boot_re.search(help_0125))
|
332 | eb7a6965 | Guido Trotter | self.assertFalse(boot_re.search(help_091_fake))
|
333 | eb7a6965 | Guido Trotter | self.assertFalse(boot_re.search(help_112))
|
334 | 0ad7f5d8 | Guido Trotter | self.assertFalse(boot_re.search(help_10))
|
335 | 0ad7f5d8 | Guido Trotter | self.assertFalse(boot_re.search(help_01590))
|
336 | 0ad7f5d8 | Guido Trotter | |
337 | 0ad7f5d8 | Guido Trotter | |
338 | ea2bcb82 | Michael Hanselmann | class TestGetTunFeatures(unittest.TestCase): |
339 | ea2bcb82 | Michael Hanselmann | def testWrongIoctl(self): |
340 | ea2bcb82 | Michael Hanselmann | tmpfile = tempfile.NamedTemporaryFile() |
341 | ea2bcb82 | Michael Hanselmann | # A file does not have the right ioctls, so this must always fail
|
342 | ea2bcb82 | Michael Hanselmann | result = hv_kvm._GetTunFeatures(tmpfile.fileno()) |
343 | ea2bcb82 | Michael Hanselmann | self.assertTrue(result is None) |
344 | ea2bcb82 | Michael Hanselmann | |
345 | ea2bcb82 | Michael Hanselmann | def _FakeIoctl(self, features, fd, request, buf): |
346 | ea2bcb82 | Michael Hanselmann | self.assertEqual(request, hv_kvm.TUNGETFEATURES)
|
347 | ea2bcb82 | Michael Hanselmann | |
348 | ea2bcb82 | Michael Hanselmann | (reqno, ) = struct.unpack("I", buf)
|
349 | ea2bcb82 | Michael Hanselmann | self.assertEqual(reqno, 0) |
350 | ea2bcb82 | Michael Hanselmann | |
351 | ea2bcb82 | Michael Hanselmann | return struct.pack("I", features) |
352 | ea2bcb82 | Michael Hanselmann | |
353 | ea2bcb82 | Michael Hanselmann | def test(self): |
354 | ea2bcb82 | Michael Hanselmann | tmpfile = tempfile.NamedTemporaryFile() |
355 | ea2bcb82 | Michael Hanselmann | fd = tmpfile.fileno() |
356 | ea2bcb82 | Michael Hanselmann | |
357 | ea2bcb82 | Michael Hanselmann | for features in [0, hv_kvm.IFF_VNET_HDR]: |
358 | ea2bcb82 | Michael Hanselmann | fn = compat.partial(self._FakeIoctl, features)
|
359 | ea2bcb82 | Michael Hanselmann | result = hv_kvm._GetTunFeatures(fd, _ioctl=fn) |
360 | ea2bcb82 | Michael Hanselmann | self.assertEqual(result, features)
|
361 | ea2bcb82 | Michael Hanselmann | |
362 | ea2bcb82 | Michael Hanselmann | |
363 | ea2bcb82 | Michael Hanselmann | class TestProbeTapVnetHdr(unittest.TestCase): |
364 | ea2bcb82 | Michael Hanselmann | def _FakeTunFeatures(self, expected_fd, flags, fd): |
365 | ea2bcb82 | Michael Hanselmann | self.assertEqual(fd, expected_fd)
|
366 | ea2bcb82 | Michael Hanselmann | return flags
|
367 | ea2bcb82 | Michael Hanselmann | |
368 | ea2bcb82 | Michael Hanselmann | def test(self): |
369 | ea2bcb82 | Michael Hanselmann | tmpfile = tempfile.NamedTemporaryFile() |
370 | ea2bcb82 | Michael Hanselmann | fd = tmpfile.fileno() |
371 | ea2bcb82 | Michael Hanselmann | |
372 | ea2bcb82 | Michael Hanselmann | for flags in [0, hv_kvm.IFF_VNET_HDR]: |
373 | ea2bcb82 | Michael Hanselmann | fn = compat.partial(self._FakeTunFeatures, fd, flags)
|
374 | ea2bcb82 | Michael Hanselmann | |
375 | ea2bcb82 | Michael Hanselmann | result = hv_kvm._ProbeTapVnetHdr(fd, _features_fn=fn) |
376 | ea2bcb82 | Michael Hanselmann | if flags == 0: |
377 | ea2bcb82 | Michael Hanselmann | self.assertFalse(result)
|
378 | ea2bcb82 | Michael Hanselmann | else:
|
379 | ea2bcb82 | Michael Hanselmann | self.assertTrue(result)
|
380 | ea2bcb82 | Michael Hanselmann | |
381 | ea2bcb82 | Michael Hanselmann | def testUnsupported(self): |
382 | ea2bcb82 | Michael Hanselmann | tmpfile = tempfile.NamedTemporaryFile() |
383 | ea2bcb82 | Michael Hanselmann | fd = tmpfile.fileno() |
384 | ea2bcb82 | Michael Hanselmann | |
385 | ea2bcb82 | Michael Hanselmann | self.assertFalse(hv_kvm._ProbeTapVnetHdr(fd, _features_fn=lambda _: None)) |
386 | ea2bcb82 | Michael Hanselmann | |
387 | ea2bcb82 | Michael Hanselmann | |
388 | fda3d987 | Dimitris Aragiorgis | class TestGenerateDeviceKVMId(unittest.TestCase): |
389 | fda3d987 | Dimitris Aragiorgis | def test(self): |
390 | fda3d987 | Dimitris Aragiorgis | device = objects.NIC() |
391 | fda3d987 | Dimitris Aragiorgis | target = constants.HOTPLUG_TARGET_NIC |
392 | fda3d987 | Dimitris Aragiorgis | fn = hv_kvm._GenerateDeviceKVMId |
393 | fda3d987 | Dimitris Aragiorgis | self.assertRaises(errors.HotplugError, fn, target, device)
|
394 | fda3d987 | Dimitris Aragiorgis | |
395 | fda3d987 | Dimitris Aragiorgis | device.pci = 5
|
396 | fda3d987 | Dimitris Aragiorgis | device.uuid = "003fc157-66a8-4e6d-8b7e-ec4f69751396"
|
397 | fda3d987 | Dimitris Aragiorgis | self.assertTrue(re.match("hotnic-003fc157-pci-5", fn(target, device))) |
398 | fda3d987 | Dimitris Aragiorgis | |
399 | fda3d987 | Dimitris Aragiorgis | |
400 | fda3d987 | Dimitris Aragiorgis | class TestGetRuntimeInfo(unittest.TestCase): |
401 | fda3d987 | Dimitris Aragiorgis | @classmethod
|
402 | fda3d987 | Dimitris Aragiorgis | def _GetRuntime(cls): |
403 | fda3d987 | Dimitris Aragiorgis | data = testutils.ReadTestData("kvm_runtime.json")
|
404 | fda3d987 | Dimitris Aragiorgis | return hv_kvm._AnalyzeSerializedRuntime(data)
|
405 | fda3d987 | Dimitris Aragiorgis | |
406 | fda3d987 | Dimitris Aragiorgis | def _fail(self, target, device, runtime): |
407 | fda3d987 | Dimitris Aragiorgis | device.uuid = "aaaaaaaa-66a8-4e6d-8b7e-ec4f69751396"
|
408 | fda3d987 | Dimitris Aragiorgis | self.assertRaises(errors.HotplugError,
|
409 | fda3d987 | Dimitris Aragiorgis | hv_kvm._GetExistingDeviceInfo, |
410 | fda3d987 | Dimitris Aragiorgis | target, device, runtime) |
411 | fda3d987 | Dimitris Aragiorgis | |
412 | fda3d987 | Dimitris Aragiorgis | def testNIC(self): |
413 | fda3d987 | Dimitris Aragiorgis | device = objects.NIC() |
414 | fda3d987 | Dimitris Aragiorgis | target = constants.HOTPLUG_TARGET_NIC |
415 | fda3d987 | Dimitris Aragiorgis | runtime = self._GetRuntime()
|
416 | fda3d987 | Dimitris Aragiorgis | |
417 | fda3d987 | Dimitris Aragiorgis | self._fail(target, device, runtime)
|
418 | fda3d987 | Dimitris Aragiorgis | |
419 | fda3d987 | Dimitris Aragiorgis | device.uuid = "003fc157-66a8-4e6d-8b7e-ec4f69751396"
|
420 | fda3d987 | Dimitris Aragiorgis | devinfo = hv_kvm._GetExistingDeviceInfo(target, device, runtime) |
421 | fda3d987 | Dimitris Aragiorgis | self.assertTrue(devinfo.pci==6) |
422 | fda3d987 | Dimitris Aragiorgis | |
423 | fda3d987 | Dimitris Aragiorgis | def testDisk(self): |
424 | fda3d987 | Dimitris Aragiorgis | device = objects.Disk() |
425 | fda3d987 | Dimitris Aragiorgis | target = constants.HOTPLUG_TARGET_DISK |
426 | fda3d987 | Dimitris Aragiorgis | runtime = self._GetRuntime()
|
427 | fda3d987 | Dimitris Aragiorgis | |
428 | fda3d987 | Dimitris Aragiorgis | self._fail(target, device, runtime)
|
429 | fda3d987 | Dimitris Aragiorgis | |
430 | fda3d987 | Dimitris Aragiorgis | device.uuid = "9f5c5bd4-6f60-480b-acdc-9bb1a4b7df79"
|
431 | fda3d987 | Dimitris Aragiorgis | (devinfo, _, __) = hv_kvm._GetExistingDeviceInfo(target, device, runtime) |
432 | fda3d987 | Dimitris Aragiorgis | self.assertTrue(devinfo.pci==5) |
433 | fda3d987 | Dimitris Aragiorgis | |
434 | fda3d987 | Dimitris Aragiorgis | |
435 | 748e4b5a | Michael Hanselmann | if __name__ == "__main__": |
436 | 748e4b5a | Michael Hanselmann | testutils.GanetiTestProgram() |