Commit dd6514c9 authored by Hrvoje Ribicic's avatar Hrvoje Ribicic
Browse files

Merge branch 'stable-2.11' into master



* stable-2.11
  (no changes)

* stable-2.10
  Revision bump for 2.10.3
  Update NEWS file for 2.10.3
  Warn in UPGRADE about not tar'ing exported insts
  Fix non-running test and remove custom_nicparams rename
  Acccount for NODE_RES lock in opportunistic locking
  Fix request flooding of noded during disk sync

* stable-2.9
  Allow QA asserts to produce more messages
  Add messages about skipped QA disk template tests
  Fix list-drbd QA test
  Update installation guide wrt to DRBD version
  Update NEWS for 2.9.6
  Revision bump for 2.9.6

Conflicts:
	qa/qa_utils.py: Taken more generic 2.10 functions
Signed-off-by: default avatarHrvoje Ribicic <riba@google.com>
Reviewed-by: default avatarKlaus Aehlig <aehlig@google.com>
parents 3cb014b3 7ddbfbaa
......@@ -128,6 +128,30 @@ This was the first beta release of the 2.11 series. All important changes
are listed in the latest 2.11 entry.
Version 2.10.3
--------------
*(Released Mon, 14 Apr 2014)*
- Fix filtering of pending jobs with -o id (issue 778)
- Make RAPI API calls more symmetric (issue 770)
- Make parsing of old cluster configuration more robust (issue 783)
- Fix wrong output of gnt-instance info after migrations
- Fix reserved PCI slots for KVM hotplugging
- Use runtime hypervisor parameters to calculate bockdevice options for KVM
- Fix high node daemon load during disk sync if the sync is paused manually
(issue 792)
- Improve opportunistic locking during instance creation (issue 791)
Inherited from the 2.9 branch:
- Make watcher submit queries low priority (issue 772)
- Add reason parameter to RAPI client functions (issue 776)
- Fix failing gnt-node list-drbd command (issue 777)
- Properly display fake job locks in gnt-debug.
- small fixes in documentation
Version 2.10.2
--------------
......@@ -354,6 +378,21 @@ before rc1.
- Issue 623: IPv6 Masterd <-> Luxid communication error
Version 2.9.6
-------------
*(Released Mon, 7 Apr 2014)*
- Improve RAPI detection of the watcher (Issue 752)
- gnt-cluster copyfile: accept relative paths (Issue 754)
- Make watcher submit queries low priority (Issue 772)
- Add reason parameter to RAPI client functions (Issue 776)
- Fix failing gnt-node list-drbd command (Issue 777)
- Properly display fake job locks in gnt-debug.
- Enable timeout for instance shutdown
- small fixes in documentation
Version 2.9.5
-------------
......
......@@ -72,6 +72,10 @@ To run commands on all nodes, the `distributed shell (dsh)
$ tar czf /var/lib/ganeti-$(date +\%FT\%T).tar.gz -C /var/lib ganeti
(``/var/lib/ganeti`` can also contain exported instances, so make sure to
backup only files you are interested in. Use ``--exclude export`` for
example)
#. Install new Ganeti version on all nodes
#. Run cfgupgrade on the master node::
......
......@@ -248,7 +248,7 @@ your instances to DRBD to take advantage of the new features.
.. _DRBD: http://www.drbd.org/
Supported DRBD versions: 8.0-8.3. It's recommended to have at least
Supported DRBD versions: 8.0-8.4. It's recommended to have at least
version 8.0.12. Note that for version 8.2 and newer it is needed to pass
the ``usermode_helper=/bin/true`` parameter to the module, either by
configuring ``/etc/modules`` or when inserting it manually.
......
......@@ -582,6 +582,7 @@ class LUInstanceCreate(LogicalUnit):
if self.op.opportunistic_locking:
self.opportunistic_locks[locking.LEVEL_NODE] = True
self.opportunistic_locks[locking.LEVEL_NODE_RES] = True
else:
(self.op.pnode_uuid, self.op.pnode) = \
ExpandNodeUuidAndName(self.cfg, self.op.pnode_uuid, self.op.pnode)
......@@ -636,14 +637,6 @@ class LUInstanceCreate(LogicalUnit):
self.needed_locks[locking.LEVEL_NODE]))
self.share_locks[locking.LEVEL_NODEGROUP] = 1
def DeclareLocks(self, level):
if level == locking.LEVEL_NODE_RES and \
self.opportunistic_locks[locking.LEVEL_NODE]:
# Even when using opportunistic locking, we require the same set of
# NODE_RES locks as we got NODE locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.owned_locks(locking.LEVEL_NODE)
def _RunAllocator(self):
"""Run the allocator based on input opcode.
......@@ -651,7 +644,8 @@ class LUInstanceCreate(LogicalUnit):
if self.op.opportunistic_locking:
# Only consider nodes for which a lock is held
node_name_whitelist = self.cfg.GetNodeNames(
self.owned_locks(locking.LEVEL_NODE))
set(self.owned_locks(locking.LEVEL_NODE)) &
set(self.owned_locks(locking.LEVEL_NODE_RES)))
else:
node_name_whitelist = None
......@@ -2110,6 +2104,7 @@ class LUInstanceMultiAlloc(NoHooksLU):
if self.op.opportunistic_locking:
self.opportunistic_locks[locking.LEVEL_NODE] = True
self.opportunistic_locks[locking.LEVEL_NODE_RES] = True
else:
nodeslist = []
for inst in self.op.instances:
......@@ -2126,14 +2121,6 @@ class LUInstanceMultiAlloc(NoHooksLU):
# prevent accidential modification)
self.needed_locks[locking.LEVEL_NODE_RES] = list(nodeslist)
def DeclareLocks(self, level):
if level == locking.LEVEL_NODE_RES and \
self.opportunistic_locks[locking.LEVEL_NODE]:
# Even when using opportunistic locking, we require the same set of
# NODE_RES locks as we got NODE locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.owned_locks(locking.LEVEL_NODE)
def CheckPrereq(self):
"""Check prerequisite.
......@@ -2146,7 +2133,8 @@ class LUInstanceMultiAlloc(NoHooksLU):
if self.op.opportunistic_locking:
# Only consider nodes for which a lock is held
node_whitelist = self.cfg.GetNodeNames(
list(self.owned_locks(locking.LEVEL_NODE)))
set(self.owned_locks(locking.LEVEL_NODE)) &
set(self.owned_locks(locking.LEVEL_NODE_RES)))
else:
node_whitelist = None
......
......@@ -1247,6 +1247,7 @@ def WaitForSync(lu, instance, disks=None, oneshot=False):
max_time = mstat.estimated_time
else:
rem_time = "no time estimate"
max_time = 5 # sleep at least a bit between retries
lu.LogInfo("- device %s: %5.2f%% done, %s",
disks[i].iv_name, mstat.sync_percent, rem_time)
......
......@@ -1362,7 +1362,6 @@ class R_2_instances_name_modify(baserlib.OpcodeResource):
PUT_RENAME = {
"custom_beparams": "beparams",
"custom_hvparams": "hvparams",
"custom_nicparams": "nicparams",
}
def GetPutOpInput(self):
......
......@@ -111,6 +111,23 @@ def RunTest(fn, *args, **kwargs):
color=colors.MAGENTA, mark=">")
def ReportTestSkip(desc, testnames):
"""Reports that tests have been skipped.
@type desc: string
@param desc: string
@type testnames: string or list of string
@param testnames: either a single test name in the configuration
file, or a list of testnames (which will be AND-ed together)
"""
tstart = datetime.datetime.now()
# TODO: Formatting test names when non-string names are involved
print _FormatHeader("%s skipping %s, test(s) %s disabled" %
(tstart, desc, testnames),
color=colors.BLUE, mark="*")
def RunTestIf(testnames, fn, *args, **kwargs):
"""Runs a test conditionally.
......@@ -121,12 +138,8 @@ def RunTestIf(testnames, fn, *args, **kwargs):
if qa_config.TestEnabled(testnames):
RunTest(fn, *args, **kwargs)
else:
tstart = datetime.datetime.now()
desc = _DescriptionOf(fn)
# TODO: Formatting test names when non-string names are involved
print _FormatHeader("%s skipping %s, test(s) %s disabled" %
(tstart, desc, testnames),
color=colors.BLUE, mark="*")
ReportTestSkip(desc, testnames)
def RunTestBlock(fn, *args, **kwargs):
......@@ -825,6 +838,12 @@ def RunInstanceTests():
finally:
qa_config.ReleaseManyNodes(inodes)
qa_cluster.AssertClusterVerify()
else:
test_desc = "Creating instances of template %s" % templ
if not qa_config.TestEnabled(test_name):
ReportTestSkip(test_desc, test_name)
else:
ReportTestSkip(test_desc, "disk template %s" % templ)
def RunMonitoringTests():
......
......@@ -462,8 +462,17 @@ def TestNodeListDrbd(node, is_drbd):
# primary or one of the secondaries
if is_drbd:
# Invoked for both primary and secondary
drbd_node, _, _, _, _, drbd_peer = result_output.split()
AssertIn(node.primary, [drbd_node, drbd_peer])
per_disk_info = result_output.splitlines()
for line in per_disk_info:
try:
drbd_node, _, _, _, _, drbd_peer = line.split()
except ValueError:
raise qa_error.Error("Could not examine list-drbd output: expected a"
" single row of 6 entries, found the following:"
" %s" % line)
AssertIn(node.primary, [drbd_node, drbd_peer],
msg="The output %s does not contain the node" % line)
else:
# Output should be empty, barring newlines
AssertEqual(result_output.strip(), "")
......
......@@ -69,42 +69,47 @@ _QA_OUTPUT = pathutils.GetLogFilename("qa-output")
RETURN_VALUE) = range(1000, 1002)
def AssertIn(item, sequence, msg=""):
def _RaiseWithInfo(msg, error_desc):
"""Raises a QA error with the given content, and adds a message if present.
"""
if msg:
output = "%s: %s" % (msg, error_desc)
else:
output = error_desc
raise qa_error.Error(output)
def AssertIn(item, sequence, msg=None):
"""Raises an error when item is not in sequence.
"""
if item not in sequence:
if msg:
raise qa_error.Error("%s: %r not in %r" % (msg, item, sequence))
else:
raise qa_error.Error("%r not in %r" % (item, sequence))
_RaiseWithInfo(msg, "%r not in %r" % (item, sequence))
def AssertNotIn(item, sequence):
def AssertNotIn(item, sequence, msg=None):
"""Raises an error when item is in sequence.
"""
if item in sequence:
raise qa_error.Error("%r in %r" % (item, sequence))
_RaiseWithInfo(msg, "%r in %r" % (item, sequence))
def AssertEqual(first, second, msg=""):
def AssertEqual(first, second, msg=None):
"""Raises an error when values aren't equal.
"""
if not first == second:
if msg:
raise qa_error.Error("%s: %r == %r" % (msg, first, second))
else:
raise qa_error.Error("%r == %r" % (first, second))
_RaiseWithInfo(msg, "%r == %r" % (first, second))
def AssertMatch(string, pattern):
def AssertMatch(string, pattern, msg=None):
"""Raises an error when string doesn't match regexp pattern.
"""
if not re.match(pattern, string):
raise qa_error.Error("%r doesn't match /%r/" % (string, pattern))
_RaiseWithInfo(msg, "%r doesn't match /%r/" % (string, pattern))
def _GetName(entity, fn):
......
......@@ -558,7 +558,7 @@ class TestInstanceDiskGrow(unittest.TestCase):
self.assertRaises(IndexError, cl.GetNextSubmittedJob)
class TestInstanceModify():
class TestInstanceModify(unittest.TestCase):
def testCustomParamRename(self):
clfactory = _FakeClientFactory(_FakeClient)
......@@ -566,7 +566,6 @@ class TestInstanceModify():
data = {
"custom_beparams": {},
"custom_hvparams": {},
"custom_nicparams": {},
}
handler = _CreateHandler(rlib2.R_2_instances_name_modify, [name], {}, data,
......@@ -582,7 +581,6 @@ class TestInstanceModify():
self.assertTrue(isinstance(op, opcodes.OpInstanceSetParams))
self.assertEqual(op.beparams, {})
self.assertEqual(op.hvparams, {})
self.assertEqual(op.nicparams, {})
self.assertRaises(IndexError, cl.GetNextSubmittedJob)
......
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