Revision 398fd4f6
b/lib/hypervisor/hv_xen.py | ||
---|---|---|
339 | 339 |
|
340 | 340 |
self._cmd = _cmd |
341 | 341 |
|
342 |
def _GetCommand(self, hvparams=None):
|
|
342 |
def _GetCommand(self, hvparams): |
|
343 | 343 |
"""Returns Xen command to use. |
344 | 344 |
|
345 | 345 |
@type hvparams: dict of strings |
... | ... | |
347 | 347 |
|
348 | 348 |
""" |
349 | 349 |
if self._cmd is None: |
350 |
if hvparams is not None:
|
|
351 |
cmd = hvparams[constants.HV_XEN_CMD]
|
|
350 |
if hvparams is None or constants.HV_XEN_CMD not in hvparams:
|
|
351 |
raise errors.HypervisorError("Cannot determine xen command.")
|
|
352 | 352 |
else: |
353 |
# TODO: Remove autoconf option once retrieving the command from |
|
354 |
# the hvparams is fully implemented. |
|
355 |
cmd = constants.XEN_CMD |
|
353 |
cmd = hvparams[constants.HV_XEN_CMD] |
|
356 | 354 |
else: |
357 | 355 |
cmd = self._cmd |
358 | 356 |
|
... | ... | |
361 | 359 |
|
362 | 360 |
return cmd |
363 | 361 |
|
364 |
def _RunXen(self, args, hvparams=None):
|
|
362 |
def _RunXen(self, args, hvparams): |
|
365 | 363 |
"""Wrapper around L{utils.process.RunCmd} to run Xen command. |
366 | 364 |
|
367 | 365 |
@type hvparams: dict of strings |
... | ... | |
369 | 367 |
@see: L{utils.process.RunCmd} |
370 | 368 |
|
371 | 369 |
""" |
372 |
cmd = [self._GetCommand(hvparams=hvparams)]
|
|
370 |
cmd = [self._GetCommand(hvparams)] |
|
373 | 371 |
cmd.extend(args) |
374 | 372 |
|
375 | 373 |
return self._run_cmd_fn(cmd) |
... | ... | |
438 | 436 |
utils.RenameFile(old_filename, new_filename) |
439 | 437 |
return new_filename |
440 | 438 |
|
441 |
def _GetInstanceList(self, include_node, hvparams=None):
|
|
439 |
def _GetInstanceList(self, include_node, hvparams): |
|
442 | 440 |
"""Wrapper around module level L{_GetInstanceList}. |
443 | 441 |
|
442 |
@type hvparams: dict of strings |
|
443 |
@param hvparams: hypervisor parameters to be used on this node |
|
444 |
|
|
444 | 445 |
""" |
445 |
return _GetInstanceList(lambda: self._RunXen(["list"], hvparams=hvparams),
|
|
446 |
return _GetInstanceList(lambda: self._RunXen(["list"], hvparams), |
|
446 | 447 |
include_node) |
447 | 448 |
|
448 | 449 |
def ListInstances(self, hvparams=None): |
449 | 450 |
"""Get the list of running instances. |
450 | 451 |
|
451 | 452 |
""" |
452 |
instance_list = self._GetInstanceList(False, hvparams=hvparams)
|
|
453 |
instance_list = self._GetInstanceList(False, hvparams) |
|
453 | 454 |
names = [info[0] for info in instance_list] |
454 | 455 |
return names |
455 | 456 |
|
... | ... | |
464 | 465 |
@return: tuple (name, id, memory, vcpus, stat, times) |
465 | 466 |
|
466 | 467 |
""" |
467 |
instance_list = self._GetInstanceList(instance_name == _DOM0_NAME, |
|
468 |
hvparams=hvparams) |
|
468 |
instance_list = self._GetInstanceList(instance_name == _DOM0_NAME, hvparams) |
|
469 | 469 |
result = None |
470 | 470 |
for data in instance_list: |
471 | 471 |
if data[0] == instance_name: |
... | ... | |
481 | 481 |
@return: list of tuples (name, id, memory, vcpus, stat, times) |
482 | 482 |
|
483 | 483 |
""" |
484 |
return self._GetInstanceList(False, hvparams=hvparams)
|
|
484 |
return self._GetInstanceList(False, hvparams) |
|
485 | 485 |
|
486 | 486 |
def _MakeConfigFile(self, instance, startup_memory, block_devices): |
487 | 487 |
"""Gather configuration details and write to disk. |
... | ... | |
511 | 511 |
cmd.append("-p") |
512 | 512 |
cmd.append(self._ConfigFileName(instance.name)) |
513 | 513 |
|
514 |
result = self._RunXen(cmd, hvparams=instance.hvparams)
|
|
514 |
result = self._RunXen(cmd, instance.hvparams) |
|
515 | 515 |
if result.failed: |
516 | 516 |
# Move the Xen configuration file to the log directory to avoid |
517 | 517 |
# leaving a stale config file behind. |
... | ... | |
546 | 546 |
else: |
547 | 547 |
action = "shutdown" |
548 | 548 |
|
549 |
result = self._RunXen([action, name], hvparams=hvparams)
|
|
549 |
result = self._RunXen([action, name], hvparams) |
|
550 | 550 |
if result.failed: |
551 | 551 |
raise errors.HypervisorError("Failed to stop instance %s: %s, %s" % |
552 | 552 |
(name, result.fail_reason, result.output)) |
... | ... | |
564 | 564 |
raise errors.HypervisorError("Failed to reboot instance %s," |
565 | 565 |
" not running" % instance.name) |
566 | 566 |
|
567 |
result = self._RunXen(["reboot", instance.name], hvparams=instance.hvparams)
|
|
567 |
result = self._RunXen(["reboot", instance.name], instance.hvparams) |
|
568 | 568 |
if result.failed: |
569 | 569 |
raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" % |
570 | 570 |
(instance.name, result.fail_reason, |
... | ... | |
597 | 597 |
@param mem: actual memory size to use for instance runtime |
598 | 598 |
|
599 | 599 |
""" |
600 |
result = self._RunXen(["mem-set", instance.name, mem], |
|
601 |
hvparams=instance.hvparams) |
|
600 |
result = self._RunXen(["mem-set", instance.name, mem], instance.hvparams) |
|
602 | 601 |
if result.failed: |
603 | 602 |
raise errors.HypervisorError("Failed to balloon instance %s: %s (%s)" % |
604 | 603 |
(instance.name, result.fail_reason, |
... | ... | |
620 | 619 |
@see: L{_GetNodeInfo} and L{_ParseNodeInfo} |
621 | 620 |
|
622 | 621 |
""" |
623 |
result = self._RunXen(["info"], hvparams=hvparams)
|
|
622 |
result = self._RunXen(["info"], hvparams) |
|
624 | 623 |
if result.failed: |
625 | 624 |
logging.error("Can't retrieve xen hypervisor information (%s): %s", |
626 | 625 |
result.fail_reason, result.output) |
627 | 626 |
return None |
628 | 627 |
|
629 |
instance_list = self._GetInstanceList(True, hvparams=hvparams)
|
|
628 |
instance_list = self._GetInstanceList(True, hvparams) |
|
630 | 629 |
return _GetNodeInfo(result.stdout, instance_list) |
631 | 630 |
|
632 | 631 |
@classmethod |
... | ... | |
664 | 663 |
return "The configured xen toolstack '%s' is not available on this" \ |
665 | 664 |
" node." % xen_cmd |
666 | 665 |
|
667 |
result = self._RunXen(["info"], hvparams=hvparams)
|
|
666 |
result = self._RunXen(["info"], hvparams) |
|
668 | 667 |
if result.failed: |
669 | 668 |
return "Retrieving information from xen failed: %s, %s" % \ |
670 | 669 |
(result.fail_reason, result.output) |
... | ... | |
747 | 746 |
if self.GetInstanceInfo(instance_name, hvparams=hvparams) is None: |
748 | 747 |
raise errors.HypervisorError("Instance not running, cannot migrate") |
749 | 748 |
|
750 |
cmd = self._GetCommand(hvparams=hvparams)
|
|
749 |
cmd = self._GetCommand(hvparams) |
|
751 | 750 |
|
752 | 751 |
if (cmd == constants.XEN_CMD_XM and |
753 | 752 |
not _ping_fn(target, port, live_port_needed=True)): |
... | ... | |
772 | 771 |
|
773 | 772 |
args.extend([instance_name, target]) |
774 | 773 |
|
775 |
result = self._RunXen(args, hvparams=hvparams)
|
|
774 |
result = self._RunXen(args, hvparams) |
|
776 | 775 |
if result.failed: |
777 | 776 |
raise errors.HypervisorError("Failed to migrate instance %s: %s" % |
778 | 777 |
(instance_name, result.output)) |
b/test/py/ganeti.hypervisor.hv_xen_unittest.py | ||
---|---|---|
78 | 78 |
|
79 | 79 |
|
80 | 80 |
class TestGetCommand(testutils.GanetiTestCase): |
81 |
def testDefault(self): |
|
82 |
expected_cmd = "xm" |
|
83 |
hv = hv_xen.XenHypervisor() |
|
84 |
self.assertEqual(hv._GetCommand(), expected_cmd) |
|
85 |
|
|
86 | 81 |
def testCommandExplicit(self): |
87 | 82 |
"""Test the case when the command is given as class parameter explicitly. |
88 | 83 |
|
89 | 84 |
""" |
90 | 85 |
expected_cmd = "xl" |
91 | 86 |
hv = hv_xen.XenHypervisor(_cmd=constants.XEN_CMD_XL) |
92 |
self.assertEqual(hv._GetCommand(), expected_cmd) |
|
87 |
self.assertEqual(hv._GetCommand(None), expected_cmd)
|
|
93 | 88 |
|
94 | 89 |
def testCommandInvalid(self): |
95 | 90 |
"""Test the case an invalid command is given as class parameter explicitly. |
... | ... | |
102 | 97 |
expected_cmd = "xl" |
103 | 98 |
test_hvparams = {constants.HV_XEN_CMD: constants.XEN_CMD_XL} |
104 | 99 |
hv = hv_xen.XenHypervisor() |
105 |
self.assertEqual(hv._GetCommand(hvparams=test_hvparams), expected_cmd)
|
|
100 |
self.assertEqual(hv._GetCommand(test_hvparams), expected_cmd) |
|
106 | 101 |
|
107 | 102 |
def testCommandHvparamsInvalid(self): |
108 | 103 |
test_hvparams = {} |
109 | 104 |
hv = hv_xen.XenHypervisor() |
110 |
self.assertRaises(KeyError, hv._GetCommand, test_hvparams)
|
|
105 |
self.assertRaises(errors.HypervisorError, hv._GetCommand, test_hvparams)
|
|
111 | 106 |
|
112 | 107 |
def testCommandHvparamsCmdInvalid(self): |
113 | 108 |
test_hvparams = {constants.HV_XEN_CMD: "invalidcommand"} |
... | ... | |
347 | 342 |
hv = hv_xen.XenHypervisor(_cfgdir=NotImplemented, |
348 | 343 |
_run_cmd_fn=NotImplemented, |
349 | 344 |
_cmd=cmd) |
350 |
self.assertRaises(errors.ProgrammerError, hv._RunXen, []) |
|
345 |
self.assertRaises(errors.ProgrammerError, hv._RunXen, [], None)
|
|
351 | 346 |
|
352 |
def testCommandValid(self): |
|
353 |
xen_cmd = "xm" |
|
354 |
mock_run_cmd = mock.Mock() |
|
347 |
def testCommandNoHvparams(self): |
|
355 | 348 |
hv = hv_xen.XenHypervisor(_cfgdir=NotImplemented, |
356 |
_run_cmd_fn=mock_run_cmd) |
|
357 |
hv._RunXen([self.XEN_SUB_CMD]) |
|
358 |
mock_run_cmd.assert_called_with([xen_cmd, self.XEN_SUB_CMD]) |
|
349 |
_run_cmd_fn=NotImplemented) |
|
350 |
hvparams = None |
|
351 |
self.assertRaises(errors.HypervisorError, hv._RunXen, [self.XEN_SUB_CMD], |
|
352 |
hvparams) |
|
359 | 353 |
|
360 | 354 |
def testCommandFromHvparams(self): |
361 | 355 |
expected_xen_cmd = "xl" |
... | ... | |
372 | 366 |
RESULT_OK = utils.RunResult(0, None, "", "", "", None, None) |
373 | 367 |
XEN_LIST = "list" |
374 | 368 |
|
375 |
def testOk(self):
|
|
369 |
def testNoHvparams(self):
|
|
376 | 370 |
expected_xen_cmd = "xm" |
377 | 371 |
mock_run_cmd = mock.Mock( return_value=self.RESULT_OK ) |
378 | 372 |
hv = hv_xen.XenHypervisor(_cfgdir=NotImplemented, |
379 | 373 |
_run_cmd_fn=mock_run_cmd) |
380 |
hv._GetInstanceList(True) |
|
381 |
mock_run_cmd.assert_called_with([expected_xen_cmd, self.XEN_LIST]) |
|
374 |
self.assertRaises(errors.HypervisorError, hv._GetInstanceList, True, None) |
|
382 | 375 |
|
383 | 376 |
def testFromHvparams(self): |
384 | 377 |
expected_xen_cmd = "xl" |
... | ... | |
386 | 379 |
mock_run_cmd = mock.Mock( return_value=self.RESULT_OK ) |
387 | 380 |
hv = hv_xen.XenHypervisor(_cfgdir=NotImplemented, |
388 | 381 |
_run_cmd_fn=mock_run_cmd) |
389 |
hv._GetInstanceList(True, hvparams=hvparams)
|
|
382 |
hv._GetInstanceList(True, hvparams) |
|
390 | 383 |
mock_run_cmd.assert_called_with([expected_xen_cmd, self.XEN_LIST]) |
391 | 384 |
|
392 | 385 |
|
... | ... | |
395 | 388 |
RESULT_OK = utils.RunResult(0, None, "", "", "", None, None) |
396 | 389 |
XEN_LIST = "list" |
397 | 390 |
|
398 |
def testDefaultXm(self):
|
|
391 |
def testNoHvparams(self):
|
|
399 | 392 |
expected_xen_cmd = "xm" |
400 | 393 |
mock_run_cmd = mock.Mock( return_value=self.RESULT_OK ) |
401 | 394 |
hv = hv_xen.XenHypervisor(_cfgdir=NotImplemented, |
402 | 395 |
_run_cmd_fn=mock_run_cmd) |
403 |
hv.ListInstances() |
|
404 |
mock_run_cmd.assert_called_with([expected_xen_cmd, self.XEN_LIST]) |
|
396 |
self.assertRaises(errors.HypervisorError, hv.ListInstances) |
|
405 | 397 |
|
406 | 398 |
def testHvparamsXl(self): |
407 | 399 |
expected_xen_cmd = "xl" |
Also available in: Unified diff