diff --git a/NEWS b/NEWS index 3d8229288333e55d90dc33b1a31dd2861d884ea7..1e1cd6c8f1ec03327846a063179c5a9b71ad8390 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,10 @@ News ==== -Version 2.5.0 rc2 +Version 2.5.0 rc4 ----------------- -*(Released Tue, 18 Oct 2011)* +*(Released Thu, 27 Oct 2011)* Incompatible/important changes and bugfixes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -119,6 +119,8 @@ Misc - :doc:`RAPI <rapi>` documentation now has detailed parameter descriptions. + - Some opcode/job results are now also documented, see :doc:`RAPI + <rapi>`. - A lockset's internal lock is now also visible in lock monitor. - Log messages from job queue workers now contain information about the @@ -129,6 +131,22 @@ Misc - DRBD metadata volumes are overwritten with zeros during disk creation. +Version 2.5.0 rc3 +----------------- + +*(Released Wed, 26 Oct 2011)* + +This was the third release candidate of the 2.5 series. + + +Version 2.5.0 rc2 +----------------- + +*(Released Tue, 18 Oct 2011)* + +This was the second release candidate of the 2.5 series. + + Version 2.5.0 rc1 ----------------- diff --git a/configure.ac b/configure.ac index 4234b467b282e257a72adccc7775681019499321..dbad2efbd679c85e232c1c78eb6508dc2956721b 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ m4_define([gnt_version_major], [2]) m4_define([gnt_version_minor], [5]) m4_define([gnt_version_revision], [0]) -m4_define([gnt_version_suffix], [~rc2]) +m4_define([gnt_version_suffix], [~rc4]) m4_define([gnt_version_full], m4_format([%d.%d.%d%s], gnt_version_major, gnt_version_minor, diff --git a/doc/rapi.rst b/doc/rapi.rst index 6dea27c617d191dd111ba466e4e2604053bf6a54..79373211ccf91e4122bf43124f25938adcb78571 100644 --- a/doc/rapi.rst +++ b/doc/rapi.rst @@ -1287,6 +1287,10 @@ The query arguments used up to and including Ganeti 2.4 are deprecated and should no longer be used. The new request format can be detected by the presence of the :pyeval:`rlib2._NODE_MIGRATE_REQV1` feature string. +Job result: + +.. opcode_result:: OP_NODE_MIGRATE + ``/2/nodes/[node_name]/role`` +++++++++++++++++++++++++++++ diff --git a/htools/Ganeti/HTools/Loader.hs b/htools/Ganeti/HTools/Loader.hs index 58ad010c963ae946880844b66e0af4a16af4dbfb..db08d73a5464a35d7ead2defd16f4a4ea9812783 100644 --- a/htools/Ganeti/HTools/Loader.hs +++ b/htools/Ganeti/HTools/Loader.hs @@ -318,11 +318,14 @@ checkData nl il = - nodeIdsk node il newn = Node.setFmem (Node.setXmem node delta_mem) (Node.fMem node - adj_mem) - umsg1 = [printf "node %s is missing %d MB ram \ - \and %d GB disk" - nname delta_mem (delta_dsk `div` 1024) | - delta_mem > 512 || delta_dsk > 1024]::[String] - in (msgs ++ umsg1, newn) + umsg1 = + if delta_mem > 512 || delta_dsk > 1024 + then (printf "node %s is missing %d MB ram \ + \and %d GB disk" + nname delta_mem (delta_dsk `div` 1024)): + msgs + else msgs + in (umsg1, newn) ) [] nl -- | Compute the amount of memory used by primary instances on a node. diff --git a/htools/Ganeti/HTools/Program/Hbal.hs b/htools/Ganeti/HTools/Program/Hbal.hs index 424ff88edc0decaeb876e8c2073d73d7d1281342..77d38340fc0f2a82521e85d33ba75c71f217ad46 100644 --- a/htools/Ganeti/HTools/Program/Hbal.hs +++ b/htools/Ganeti/HTools/Program/Hbal.hs @@ -308,10 +308,9 @@ main = do Just grp -> case lookup (Group.idx grp) ngroups of Nothing -> do - -- TODO: while this is unlikely to happen, log here the - -- actual group data to help debugging - hPutStrLn stderr "Internal failure, missing group idx" - exitWith $ ExitFailure 1 + -- This will only happen if there are no nodes assigned + -- to this group + return (Group.name grp, (Container.empty, Container.empty)) Just cdata -> return (Group.name grp, cdata) unless oneline $ printf "Group size %d nodes, %d instances\n" diff --git a/lib/cmdlib.py b/lib/cmdlib.py index a3d9fc9d82681c82ec0a8a99aa02a7717876e900..4297b8a0dc48c4ad127994805196833846c1c690 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -3187,7 +3187,10 @@ class LUClusterRepairDiskSizes(NoHooksLU): locking.LEVEL_NODE: locking.ALL_SET, locking.LEVEL_INSTANCE: locking.ALL_SET, } - self.share_locks = _ShareAll() + self.share_locks = { + locking.LEVEL_NODE: 1, + locking.LEVEL_INSTANCE: 0, + } def DeclareLocks(self, level): if level == locking.LEVEL_NODE and self.wanted_names is not None: @@ -6466,7 +6469,7 @@ class LUInstanceRename(LogicalUnit): new_name = self.op.new_name if self.op.name_check: hostname = netutils.GetHostname(name=new_name) - if hostname != new_name: + if hostname.name != new_name: self.LogInfo("Resolved given name '%s' to '%s'", new_name, hostname.name) if not utils.MatchNameComponent(self.op.new_name, [hostname.name]): @@ -10340,9 +10343,10 @@ def _LoadNodeEvacResult(lu, alloc_result, early_release, use_nodes): (moved, failed, jobs) = alloc_result if failed: - lu.LogWarning("Unable to evacuate instances %s", - utils.CommaJoin("%s (%s)" % (name, reason) - for (name, reason) in failed)) + failreason = utils.CommaJoin("%s (%s)" % (name, reason) + for (name, reason) in failed) + lu.LogWarning("Unable to evacuate instances %s", failreason) + raise errors.OpExecError("Unable to evacuate instances %s" % failreason) if moved: lu.LogInfo("Instances to be moved: %s", diff --git a/lib/jqueue.py b/lib/jqueue.py index 3cf3b428762be1b26b4e509fc63fb34c2e819d33..d5ea3cb79b81d5bc7e8d36a5079227d6605d9724 100644 --- a/lib/jqueue.py +++ b/lib/jqueue.py @@ -1798,7 +1798,8 @@ class JobQueue(object): @return: a string representing the job identifier. """ - assert count > 0 + assert ht.TPositiveInt(count) + # New number serial = self._last_serial + count diff --git a/lib/opcodes.py b/lib/opcodes.py index f00044a3b5bfc4fea279818460152a172d01f2ba..ed017cc1674b9d8f3b97d7911cfe28b919ae1582 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -1003,6 +1003,7 @@ class OpNodeMigrate(OpCode): ("iallocator", None, ht.TMaybeString, "Iallocator for deciding the target node for shared-storage instances"), ] + OP_RESULT = TJobIdListOnly class OpNodeEvacuate(OpCode): diff --git a/test/ganeti.cmdlib_unittest.py b/test/ganeti.cmdlib_unittest.py index 6d06200e7942c08516dcd556636abb3f97a2b151..522fe8b9f9660b327da673b741cd7cbe06be7590 100755 --- a/test/ganeti.cmdlib_unittest.py +++ b/test/ganeti.cmdlib_unittest.py @@ -28,6 +28,7 @@ import time import tempfile import shutil import operator +import itertools from ganeti import constants from ganeti import mcpu @@ -380,5 +381,71 @@ class TestClusterVerifyFiles(unittest.TestCase): ])) +class _FakeLU: + def __init__(self): + self.warning_log = [] + self.info_log = [] + + def LogWarning(self, text, *args): + self.warning_log.append((text, args)) + + def LogInfo(self, text, *args): + self.info_log.append((text, args)) + + +class TestLoadNodeEvacResult(unittest.TestCase): + def testSuccess(self): + for moved in [[], [ + ("inst20153.example.com", "grp2", ["nodeA4509", "nodeB2912"]), + ]]: + for early_release in [False, True]: + for use_nodes in [False, True]: + jobs = [ + [opcodes.OpInstanceReplaceDisks().__getstate__()], + [opcodes.OpInstanceMigrate().__getstate__()], + ] + + alloc_result = (moved, [], jobs) + assert cmdlib.IAllocator._NEVAC_RESULT(alloc_result) + + lu = _FakeLU() + result = cmdlib._LoadNodeEvacResult(lu, alloc_result, + early_release, use_nodes) + + if moved: + (_, (info_args, )) = lu.info_log.pop(0) + for (instname, instgroup, instnodes) in moved: + self.assertTrue(instname in info_args) + if use_nodes: + for i in instnodes: + self.assertTrue(i in info_args) + else: + self.assertTrue(instgroup in info_args) + + self.assertFalse(lu.info_log) + self.assertFalse(lu.warning_log) + + for op in itertools.chain(*result): + if hasattr(op.__class__, "early_release"): + self.assertEqual(op.early_release, early_release) + else: + self.assertFalse(hasattr(op, "early_release")) + + def testFailed(self): + alloc_result = ([], [ + ("inst5191.example.com", "errormsg21178"), + ], []) + assert cmdlib.IAllocator._NEVAC_RESULT(alloc_result) + + lu = _FakeLU() + self.assertRaises(errors.OpExecError, cmdlib._LoadNodeEvacResult, + lu, alloc_result, False, False) + self.assertFalse(lu.info_log) + (_, (args, )) = lu.warning_log.pop(0) + self.assertTrue("inst5191.example.com" in args) + self.assertTrue("errormsg21178" in args) + self.assertFalse(lu.warning_log) + + if __name__ == "__main__": testutils.GanetiTestProgram()