Revision d0bb3f24
b/lib/hypervisor/hv_xen.py | ||
---|---|---|
24 | 24 |
""" |
25 | 25 |
|
26 | 26 |
import logging |
27 |
import string # pylint: disable=W0402 |
|
27 | 28 |
from cStringIO import StringIO |
28 | 29 |
|
29 | 30 |
from ganeti import constants |
... | ... | |
41 | 42 |
VIF_BRIDGE_SCRIPT = utils.PathJoin(pathutils.XEN_CONFIG_DIR, |
42 | 43 |
"scripts/vif-bridge") |
43 | 44 |
_DOM0_NAME = "Domain-0" |
45 |
_DISK_LETTERS = string.ascii_lowercase |
|
46 |
|
|
47 |
_FILE_DRIVER_MAP = { |
|
48 |
constants.FD_LOOP: "file", |
|
49 |
constants.FD_BLKTAP: "tap:aio", |
|
50 |
} |
|
44 | 51 |
|
45 | 52 |
|
46 | 53 |
def _CreateConfigCpus(cpu_mask): |
... | ... | |
254 | 261 |
return _MergeInstanceInfo(_ParseNodeInfo(info), fn) |
255 | 262 |
|
256 | 263 |
|
264 |
def _GetConfigFileDiskData(block_devices, blockdev_prefix, |
|
265 |
_letters=_DISK_LETTERS): |
|
266 |
"""Get disk directives for Xen config file. |
|
267 |
|
|
268 |
This method builds the xen config disk directive according to the |
|
269 |
given disk_template and block_devices. |
|
270 |
|
|
271 |
@param block_devices: list of tuples (cfdev, rldev): |
|
272 |
- cfdev: dict containing ganeti config disk part |
|
273 |
- rldev: ganeti.bdev.BlockDev object |
|
274 |
@param blockdev_prefix: a string containing blockdevice prefix, |
|
275 |
e.g. "sd" for /dev/sda |
|
276 |
|
|
277 |
@return: string containing disk directive for xen instance config file |
|
278 |
|
|
279 |
""" |
|
280 |
if len(block_devices) > len(_letters): |
|
281 |
raise errors.HypervisorError("Too many disks") |
|
282 |
|
|
283 |
disk_data = [] |
|
284 |
|
|
285 |
for sd_suffix, (cfdev, dev_path) in zip(_letters, block_devices): |
|
286 |
sd_name = blockdev_prefix + sd_suffix |
|
287 |
|
|
288 |
if cfdev.mode == constants.DISK_RDWR: |
|
289 |
mode = "w" |
|
290 |
else: |
|
291 |
mode = "r" |
|
292 |
|
|
293 |
if cfdev.dev_type == constants.LD_FILE: |
|
294 |
driver = _FILE_DRIVER_MAP[cfdev.physical_id[0]] |
|
295 |
else: |
|
296 |
driver = "phy" |
|
297 |
|
|
298 |
disk_data.append("'%s:%s,%s,%s'" % (driver, dev_path, sd_name, mode)) |
|
299 |
|
|
300 |
return disk_data |
|
301 |
|
|
302 |
|
|
257 | 303 |
class XenHypervisor(hv_base.BaseHypervisor): |
258 | 304 |
"""Xen generic hypervisor interface |
259 | 305 |
|
... | ... | |
506 | 552 |
|
507 | 553 |
return None |
508 | 554 |
|
509 |
@staticmethod |
|
510 |
def _GetConfigFileDiskData(block_devices, blockdev_prefix): |
|
511 |
"""Get disk directive for xen config file. |
|
512 |
|
|
513 |
This method builds the xen config disk directive according to the |
|
514 |
given disk_template and block_devices. |
|
515 |
|
|
516 |
@param block_devices: list of tuples (cfdev, rldev): |
|
517 |
- cfdev: dict containing ganeti config disk part |
|
518 |
- rldev: ganeti.bdev.BlockDev object |
|
519 |
@param blockdev_prefix: a string containing blockdevice prefix, |
|
520 |
e.g. "sd" for /dev/sda |
|
521 |
|
|
522 |
@return: string containing disk directive for xen instance config file |
|
523 |
|
|
524 |
""" |
|
525 |
FILE_DRIVER_MAP = { |
|
526 |
constants.FD_LOOP: "file", |
|
527 |
constants.FD_BLKTAP: "tap:aio", |
|
528 |
} |
|
529 |
disk_data = [] |
|
530 |
if len(block_devices) > 24: |
|
531 |
# 'z' - 'a' = 24 |
|
532 |
raise errors.HypervisorError("Too many disks") |
|
533 |
namespace = [blockdev_prefix + chr(i + ord("a")) for i in range(24)] |
|
534 |
for sd_name, (cfdev, dev_path) in zip(namespace, block_devices): |
|
535 |
if cfdev.mode == constants.DISK_RDWR: |
|
536 |
mode = "w" |
|
537 |
else: |
|
538 |
mode = "r" |
|
539 |
if cfdev.dev_type == constants.LD_FILE: |
|
540 |
line = "'%s:%s,%s,%s'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]], |
|
541 |
dev_path, sd_name, mode) |
|
542 |
else: |
|
543 |
line = "'phy:%s,%s,%s'" % (dev_path, sd_name, mode) |
|
544 |
disk_data.append(line) |
|
545 |
|
|
546 |
return disk_data |
|
547 |
|
|
548 | 555 |
def MigrationInfo(self, instance): |
549 | 556 |
"""Get instance information to perform a migration. |
550 | 557 |
|
... | ... | |
765 | 772 |
nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK] |
766 | 773 |
vif_data.append("'%s'" % nic_str) |
767 | 774 |
|
768 |
disk_data = cls._GetConfigFileDiskData(block_devices,
|
|
769 |
hvp[constants.HV_BLOCKDEV_PREFIX])
|
|
775 |
disk_data = \
|
|
776 |
_GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
|
|
770 | 777 |
|
771 | 778 |
config.write("vif = [%s]\n" % ",".join(vif_data)) |
772 | 779 |
config.write("disk = [%s]\n" % ",".join(disk_data)) |
... | ... | |
918 | 925 |
|
919 | 926 |
config.write("vif = [%s]\n" % ",".join(vif_data)) |
920 | 927 |
|
921 |
disk_data = cls._GetConfigFileDiskData(block_devices,
|
|
922 |
hvp[constants.HV_BLOCKDEV_PREFIX])
|
|
928 |
disk_data = \
|
|
929 |
_GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
|
|
923 | 930 |
|
924 | 931 |
iso_path = hvp[constants.HV_CDROM_IMAGE_PATH] |
925 | 932 |
if iso_path: |
b/test/py/ganeti.hypervisor.hv_xen_unittest.py | ||
---|---|---|
21 | 21 |
|
22 | 22 |
"""Script for testing ganeti.hypervisor.hv_lxc""" |
23 | 23 |
|
24 |
import string # pylint: disable=W0402 |
|
24 | 25 |
import unittest |
25 | 26 |
|
26 | 27 |
from ganeti import constants |
... | ... | |
213 | 214 |
}) |
214 | 215 |
|
215 | 216 |
|
217 |
class TestGetConfigFileDiskData(unittest.TestCase): |
|
218 |
def testLetterCount(self): |
|
219 |
self.assertEqual(len(hv_xen._DISK_LETTERS), 26) |
|
220 |
|
|
221 |
def testNoDisks(self): |
|
222 |
self.assertEqual(hv_xen._GetConfigFileDiskData([], "hd"), []) |
|
223 |
|
|
224 |
def testManyDisks(self): |
|
225 |
for offset in [0, 1, 10]: |
|
226 |
disks = [(objects.Disk(dev_type=constants.LD_LV), "/tmp/disk/%s" % idx) |
|
227 |
for idx in range(len(hv_xen._DISK_LETTERS) + offset)] |
|
228 |
|
|
229 |
if offset == 0: |
|
230 |
result = hv_xen._GetConfigFileDiskData(disks, "hd") |
|
231 |
self.assertEqual(result, [ |
|
232 |
"'phy:/tmp/disk/%s,hd%s,r'" % (idx, string.ascii_lowercase[idx]) |
|
233 |
for idx in range(len(hv_xen._DISK_LETTERS) + offset) |
|
234 |
]) |
|
235 |
else: |
|
236 |
try: |
|
237 |
hv_xen._GetConfigFileDiskData(disks, "hd") |
|
238 |
except errors.HypervisorError, err: |
|
239 |
self.assertEqual(str(err), "Too many disks") |
|
240 |
else: |
|
241 |
self.fail("Exception was not raised") |
|
242 |
|
|
243 |
def testTwoLvDisksWithMode(self): |
|
244 |
disks = [ |
|
245 |
(objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDWR), |
|
246 |
"/tmp/diskFirst"), |
|
247 |
(objects.Disk(dev_type=constants.LD_LV, mode=constants.DISK_RDONLY), |
|
248 |
"/tmp/diskLast"), |
|
249 |
] |
|
250 |
|
|
251 |
result = hv_xen._GetConfigFileDiskData(disks, "hd") |
|
252 |
self.assertEqual(result, [ |
|
253 |
"'phy:/tmp/diskFirst,hda,w'", |
|
254 |
"'phy:/tmp/diskLast,hdb,r'", |
|
255 |
]) |
|
256 |
|
|
257 |
def testFileDisks(self): |
|
258 |
disks = [ |
|
259 |
(objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR, |
|
260 |
physical_id=[constants.FD_LOOP]), |
|
261 |
"/tmp/diskFirst"), |
|
262 |
(objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDONLY, |
|
263 |
physical_id=[constants.FD_BLKTAP]), |
|
264 |
"/tmp/diskTwo"), |
|
265 |
(objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR, |
|
266 |
physical_id=[constants.FD_LOOP]), |
|
267 |
"/tmp/diskThree"), |
|
268 |
(objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR, |
|
269 |
physical_id=[constants.FD_BLKTAP]), |
|
270 |
"/tmp/diskLast"), |
|
271 |
] |
|
272 |
|
|
273 |
result = hv_xen._GetConfigFileDiskData(disks, "sd") |
|
274 |
self.assertEqual(result, [ |
|
275 |
"'file:/tmp/diskFirst,sda,w'", |
|
276 |
"'tap:aio:/tmp/diskTwo,sdb,r'", |
|
277 |
"'file:/tmp/diskThree,sdc,w'", |
|
278 |
"'tap:aio:/tmp/diskLast,sdd,w'", |
|
279 |
]) |
|
280 |
|
|
281 |
def testInvalidFileDisk(self): |
|
282 |
disks = [ |
|
283 |
(objects.Disk(dev_type=constants.LD_FILE, mode=constants.DISK_RDWR, |
|
284 |
physical_id=["#unknown#"]), |
|
285 |
"/tmp/diskinvalid"), |
|
286 |
] |
|
287 |
|
|
288 |
self.assertRaises(KeyError, hv_xen._GetConfigFileDiskData, disks, "sd") |
|
289 |
|
|
290 |
|
|
216 | 291 |
if __name__ == "__main__": |
217 | 292 |
testutils.GanetiTestProgram() |
Also available in: Unified diff