Commit c8872a0b authored by Iustin Pop's avatar Iustin Pop
Browse files

Merge remote branch 'origin/master' into mogu



* origin/master:
  Fix burnin's verbose mode
  Final NEWS update and version increase for 2.0.4
  Encode the actual exception raised by LU execution
  Move the luxi error handling into errors.py
  Fix the confusing ssh/hostname message in node add
  Add man page for ganeti-cleaner
  Update NEWS file for version 2.0.4
  Automatically cleanup _temporary_ids at save
  Separate the computation of all config IDs
  Change config upgrade to be explicit
  Fix unittest breakage due to new test file
  Fix /proc/drbd parsing in presence of gaps
  repair-size: ensure child disks have sane sizes
  Fix yet another bug in LURepairDiskSizes
  Fix a bug in LURepairDiskSizes

Conflicts:
	NEWS          (trivial, the RST change)
	lib/cmdlib.py (trivial, some small change in 2.0)
	lib/config.py (due to the cherry-picks and UUID changes in 2.1)
Signed-off-by: default avatarIustin Pop <iustin@google.com>
parents e73a5804 88d31e5c
......@@ -235,6 +235,7 @@ EXTRA_DIST = \
man_MANS = \
man/ganeti.7 \
man/ganeti-cleaner.8 \
man/ganeti-masterd.8 \
man/ganeti-noded.8 \
man/ganeti-os-interface.7 \
......@@ -258,6 +259,7 @@ TEST_FILES = \
test/data/bdev-disk.txt \
test/data/bdev-net.txt \
test/data/proc_drbd8.txt \
test/data/proc_drbd80-emptyline.txt \
test/data/proc_drbd83.txt
dist_TESTS = \
......
News
====
Version 2.0.4
-------------
- Fixed many wrong messages
- Fixed a few bugs related to the locking library
- Fixed MAC checking at instance creation time
- Fixed a DRBD parsing bug related to gaps in /proc/drbd
- Fixed a few issues related to signal handling in both daemons and
scripts
- Fixed the example startup script provided
- Fixed insserv dependencies in the example startup script (patch from
Debian)
- Fixed handling of drained nodes in the iallocator framework
- Fixed handling of KERNEL_PATH parameter for xen-hvm (Debian bug
#528618)
- Fixed error related to invalid job IDs in job polling
- Fixed job/opcode persistence on unclean master shutdown
- Fixed handling of partial job processing after unclean master
shutdown
- Fixed error reporting from LUs, previously all errors were converted
into execution errors
- Fixed error reporting from burnin
- Decreased significantly the memory usage of the job queue
- Optimised slightly multi-job submission
- Optimised slightly opcode loading
- Backported the multi-job submit framework from the development
branch; multi-instance start and stop should be faster
- Added script to clean archived jobs after 21 days; this will reduce
the size of the queue directory
- Added some extra checks in disk size tracking
- Added an example ethers hook script
- Added a cluster parameter that prevents Ganeti from modifying of
/etc/hosts
- Added more node information to RAPI responses
- Added a “gnt-job watch” command that allows following the ouput of a
job
- Added a bind-address option to ganeti-rapi
- Added more checks to the configuration verify
- Enhanced the burnin script such that some operations can be retried
automatically
- Converted instance reinstall to multi-instance model
Version 2.0.3
-------------
......
# Configure script for Ganeti
m4_define([gnt_version_major], [2])
m4_define([gnt_version_minor], [0])
m4_define([gnt_version_revision], [3])
m4_define([gnt_version_revision], [4])
m4_define([gnt_version_suffix], [])
m4_define([gnt_version_full],
m4_format([%d.%d.%d%s],
......
......@@ -803,6 +803,8 @@ class BaseDRBD(BlockDev):
results = {}
old_minor = old_line = None
for line in data:
if not line: # completely empty lines, as can be returned by drbd8.0+
continue
lresult = lmatch.match(line)
if lresult is not None:
if old_minor is not None:
......
......@@ -1594,7 +1594,6 @@ class LURepairDiskSizes(NoHooksLU):
if full_name is None:
raise errors.OpPrereqError("Instance '%s' not known" % name)
self.wanted_names.append(full_name)
self.needed_locks[locking.LEVEL_INSTANCE] = self.wanted_names
self.needed_locks = {
locking.LEVEL_NODE: [],
locking.LEVEL_INSTANCE: self.wanted_names,
......@@ -1624,6 +1623,29 @@ class LURepairDiskSizes(NoHooksLU):
self.wanted_instances = [self.cfg.GetInstanceInfo(name) for name
in self.wanted_names]
def _EnsureChildSizes(self, disk):
"""Ensure children of the disk have the needed disk size.
This is valid mainly for DRBD8 and fixes an issue where the
children have smaller disk size.
@param disk: an L{ganeti.objects.Disk} object
"""
if disk.dev_type == constants.LD_DRBD8:
assert disk.children, "Empty children for DRBD8?"
fchild = disk.children[0]
mismatch = fchild.size < disk.size
if mismatch:
self.LogInfo("Child disk has size %d, parent %d, fixing",
fchild.size, disk.size)
fchild.size = disk.size
# and we recurse on this child only, not on the metadev
return self._EnsureChildSizes(fchild) or mismatch
else:
return False
def Exec(self, feedback_fn):
"""Verify the size of cluster disks.
......@@ -1640,7 +1662,10 @@ class LURepairDiskSizes(NoHooksLU):
changed = []
for node, dskl in per_node_disks.items():
result = self.rpc.call_blockdev_getsizes(node, [v[2] for v in dskl])
newl = [v[2].Copy() for v in dskl]
for dsk in newl:
self.cfg.SetDiskID(dsk, node)
result = self.rpc.call_blockdev_getsizes(node, newl)
if result.fail_msg:
self.LogWarning("Failure in blockdev_getsizes call to node"
" %s, ignoring", node)
......@@ -1666,6 +1691,9 @@ class LURepairDiskSizes(NoHooksLU):
disk.size = size
self.cfg.Update(instance)
changed.append((instance.name, idx, size))
if self._EnsureChildSizes(disk):
self.cfg.Update(instance)
changed.append((instance.name, idx, disk.size))
return changed
......@@ -2861,7 +2889,8 @@ class LUAddNode(LogicalUnit):
nl_payload = result[verifier].payload[constants.NV_NODELIST]
if nl_payload:
for failed in nl_payload:
feedback_fn("ssh/hostname verification failed %s -> %s" %
feedback_fn("ssh/hostname verification failed"
" (checking from %s): %s" %
(verifier, nl_payload[failed]))
raise errors.OpExecError("ssh/hostname verification failed.")
......
......@@ -227,7 +227,12 @@ class SshRunner:
remotehostname = retval.stdout.strip()
if not remotehostname or remotehostname != node:
return False, "hostname mismatch, got %s" % remotehostname
if node.startswith(remotehostname + "."):
msg = "hostname not FQDN"
else:
msg = "hostname mistmatch"
return False, ("%s: expected %s but got %s" %
(msg, node, remotehostname))
return True, "host matches"
......
......@@ -59,6 +59,10 @@
<refentrytitle>ganeti-watcher</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry> (automatic instance restarter),
<citerefentry>
<refentrytitle>ganeti-cleaner</refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry> (job queue cleaner),
<citerefentry>
<refentrytitle>ganeti-noded</refentrytitle>
<manvolnum>8</manvolnum>
......
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
<!-- Please adjust the date whenever revising the manpage. -->
<!ENTITY dhdate "<date>February 11, 2009</date>">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1). -->
<!ENTITY dhsection "<manvolnum>8</manvolnum>">
<!ENTITY dhucpackage "<refentrytitle>ganeti-cleaner</refentrytitle>">
<!ENTITY dhpackage "ganeti-cleaner">
<!ENTITY debian "<productname>Debian</productname>">
<!ENTITY gnu "<acronym>GNU</acronym>">
<!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
<!ENTITY footer SYSTEM "footer.sgml">
]>
<refentry>
<refentryinfo>
<copyright>
<year>2009</year>
<holder>Google Inc.</holder>
</copyright>
&dhdate;
</refentryinfo>
<refmeta>
&dhucpackage;
&dhsection;
<refmiscinfo>ganeti 2.0</refmiscinfo>
</refmeta>
<refnamediv>
<refname>&dhpackage;</refname>
<refpurpose>ganeti job queue cleaner</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>&dhpackage;</command>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>
The <command>&dhpackage;</command> is a periodically run script to clean
old job files from the job queue archive.
</para>
<para>
<command>&dhpackage;</command> automatically removes all files older than
21 days from
<filename>@LOCALSTATEDIR@/lib/ganeti/queue/archive</filename>.
</para>
</refsect1>
&footer;
</refentry>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:2
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:nil
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
-->
GIT-hash: 5c9f89594553e32adb87d9638dce591782f947e3 build by root@node1.example.com, 2009-05-22 12:47:52
0: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r---
ns:78728316 nr:0 dw:77675644 dr:1277039 al:254 bm:270 lo:0 pe:0 ua:0 ap:0
resync: used:0/61 hits:65657 misses:135 starving:0 dirty:0 changed:135
act_log: used:0/257 hits:11378843 misses:254 starving:0 dirty:0 changed:254
1: cs:Unconfigured
2: cs:Unconfigured
5: cs:Unconfigured
6: cs:Unconfigured
......@@ -114,10 +114,13 @@ class TestDRBD8Status(testutils.GanetiTestCase):
"""Read in txt data"""
testutils.GanetiTestCase.setUp(self)
proc_data = self._TestDataFilename("proc_drbd8.txt")
proc80e_data = self._TestDataFilename("proc_drbd80-emptyline.txt")
proc83_data = self._TestDataFilename("proc_drbd83.txt")
self.proc_data = bdev.DRBD8._GetProcData(filename=proc_data)
self.proc80e_data = bdev.DRBD8._GetProcData(filename=proc80e_data)
self.proc83_data = bdev.DRBD8._GetProcData(filename=proc83_data)
self.mass_data = bdev.DRBD8._MassageProcData(self.proc_data)
self.mass80e_data = bdev.DRBD8._MassageProcData(self.proc80e_data)
self.mass83_data = bdev.DRBD8._MassageProcData(self.proc83_data)
def testIOErrors(self):
......@@ -131,6 +134,7 @@ class TestDRBD8Status(testutils.GanetiTestCase):
"""Test not-found-minor in /proc"""
self.failUnless(9 not in self.mass_data)
self.failUnless(9 not in self.mass83_data)
self.failUnless(3 not in self.mass80e_data)
def testLineNotMatch(self):
"""Test wrong line passed to DRBD8Status"""
......@@ -154,7 +158,7 @@ class TestDRBD8Status(testutils.GanetiTestCase):
def testMinor2(self):
"""Test unconfigured device"""
for data in [self.mass_data, self.mass83_data]:
for data in [self.mass_data, self.mass83_data, self.mass80e_data]:
stats = bdev.DRBD8Status(data[2])
self.failIf(stats.is_in_use)
......
......@@ -229,10 +229,10 @@ class Burner(object):
def Feedback(self, msg):
"""Acumulate feedback in our buffer."""
self._feed_buf.write("%s %s\n" % (time.ctime(utils.MergeTime(msg[0])),
msg[2]))
formatted_msg = "%s %s" % (time.ctime(utils.MergeTime(msg[0])), msg[2])
self._feed_buf.write(formatted_msg + "\n")
if self.opts.verbose:
Log(msg, indent=3)
Log(formatted_msg, indent=3)
def MaybeRetry(self, retry_count, msg, fn, *args):
"""Possibly retry a given function execution.
......
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