Commit 0c1441eb authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Merge branch 'stable-2.5' into devel-2.5



* stable-2.5:
  htools: rework message display construction
  hbal: handle empty node groups
  Document OpNodeMigrate's result for RAPI
  Fail if node/group evacuation can't evacuate instances
  LUInstanceRename: Compare name with name
  LUClusterRepairDiskSizes: Acquire instance locks in exclusive mode
  Update NEWS for 2.5.0~rc4
  Bump version to 2.5.0~rc4
  jqueue: Allow zero jobs to be submitted at once
  hail: don't select the primary as new secondary
  hail: add an extra safety check in relocate
  Bump version to 2.5.0~rc3

Conflicts:
	configure.ac: Trivial
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parents 05c2e624 bdd8c739
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
-----------------
......
......@@ -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,
......
......@@ -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``
+++++++++++++++++++++++++++++
......
......@@ -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.
......
......@@ -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"
......
......@@ -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",
......
......@@ -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
......
......@@ -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):
......
......@@ -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()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment