Commit 972a114f authored by Iustin Pop's avatar Iustin Pop
Browse files

Merge branch 'devel-2.3'

* devel-2.3:
  Updates NEWS and for 2.3.0~rc1
  Update NEWS & for the 2.2.2 release
  Fix documentation regarding conversion to drbd
  Fix documentation regarding conversion to drbd
  Reinstall instance: disallow offline secondaries
  QA: check that doubly modifying an OS state is OK
  Fix breakage in OS state modify
  QA: add tests for gnt-cluster modify -B
  LUSetClusterParms: fix validation of beparams
  Add unittests for TemporaryReservationManager
  TempReservationManager: Reserved() doesn't work

	man/gnt-instance.sgml (ported to the RST version)
Signed-off-by: default avatarIustin Pop <>
Reviewed-by: default avatarMichael Hanselmann <>
parents 7f81e2b9 ca6c2dcd
Version 2.3.0 rc1
*(Released Fri, 19 Nov 2010)*
A number of bugfixes and documentation updates:
- Update ganeti-os-interface documentation
- Fixed a bug related to duplicate MACs or similar items which should be
- Fix breakage in OS state modify
- Reinstall instance: disallow offline secondaries (fixes bug related to
OS changing but reinstall failing)
- plus all the other fixes between 2.2.1 and 2.2.2
Version 2.3.0 rc0
......@@ -44,6 +60,20 @@ Version 2.3.0 rc0
- Infrastructure changes for node group support in future versions
Version 2.2.2
*(Released Fri, 19 Nov 2010)*
A few small bugs fixed, and some improvements to the build system:
- Fix documentation regarding conversion to drbd
- Fix validation of parameters in cluster modify (``gnt-cluster modify
- Fix error handling in node modify with multiple changes
- Allow remote imports without checked names
Version 2.2.1
......@@ -234,6 +264,21 @@ Version 2.2.0 beta 0
see the ``ganeti-os-interface(7)`` manpage and look for
Version 2.1.8
*(Released Tue, 16 Nov 2010)*
Some more bugfixes. Unless critical bugs occur, this will be the last
2.1 release:
- Fix case of MAC special-values
- Fix mac checker regex
- backend: Fix typo causing “out of range” error
- Add missing --units in gnt-instance list man page
Version 2.1.7
......@@ -2,7 +2,7 @@
m4_define([gnt_version_major], [2])
m4_define([gnt_version_minor], [3])
m4_define([gnt_version_revision], [0])
m4_define([gnt_version_suffix], [~rc0])
m4_define([gnt_version_suffix], [~rc1])
gnt_version_major, gnt_version_minor,
......@@ -542,7 +542,7 @@ modify`` command::
# later convert it to redundant
gnt-instance stop INSTANCE
gnt-instance modify -t drbd INSTANCE
gnt-instance modify -t drbd -n NEW_SECONDARY INSTANCE
gnt-instance start INSTANCE
# and convert it back
......@@ -593,17 +593,19 @@ def _CheckGlobalHvParams(params):
raise errors.OpPrereqError(msg, errors.ECODE_INVAL)
def _CheckNodeOnline(lu, node):
def _CheckNodeOnline(lu, node, msg=None):
"""Ensure that a given node is online.
@param lu: the LU on behalf of which we make the check
@param node: the node to check
@param msg: if passed, should be a message to replace the default one
@raise errors.OpPrereqError: if the node is offline
if msg is None:
msg = "Can't use offline node"
if lu.cfg.GetNodeInfo(node).offline:
raise errors.OpPrereqError("Can't use offline node %s" % node,
raise errors.OpPrereqError("%s: %s" % (msg, node), errors.ECODE_STATE)
def _CheckNodeNotDrained(lu, node):
......@@ -2575,8 +2577,7 @@ class LUSetClusterParams(LogicalUnit):
("hvparams", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
("beparams", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
("beparams", None, ht.TOr(ht.TDict, ht.TNone)),
("os_hvp", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
("osparams", None, ht.TOr(ht.TDictOf(ht.TNonEmptyString, ht.TDict),
......@@ -2883,14 +2884,14 @@ class LUSetClusterParams(LogicalUnit):
for key, val in mods:
if key == constants.DDM_ADD:
if val in lst:
feedback_fn("OS %s already in %s, ignoring", val, desc)
feedback_fn("OS %s already in %s, ignoring" % (val, desc))
elif key == constants.DDM_REMOVE:
if val in lst:
feedback_fn("OS %s not found in %s, ignoring", val, desc)
feedback_fn("OS %s not found in %s, ignoring" % (val, desc))
raise errors.ProgrammerError("Invalid modification '%s'" % key)
......@@ -5009,7 +5010,11 @@ class LUReinstallInstance(LogicalUnit):
instance = self.cfg.GetInstanceInfo(self.op.instance_name)
assert instance is not None, \
"Cannot retrieve locked instance %s" % self.op.instance_name
_CheckNodeOnline(self, instance.primary_node)
_CheckNodeOnline(self, instance.primary_node, "Instance primary node"
" offline, cannot reinstall")
for node in instance.secondary_nodes:
_CheckNodeOnline(self, node, "Instance secondary node offline,"
" cannot reinstall")
if instance.disk_template == constants.DT_DISKLESS:
raise errors.OpPrereqError("Instance '%s' has no disks" %
......@@ -81,15 +81,15 @@ class TemporaryReservationManager:
self._ec_reserved = {}
def Reserved(self, resource):
for holder_reserved in self._ec_reserved.items():
for holder_reserved in self._ec_reserved.values():
if resource in holder_reserved:
return True
return False
def Reserve(self, ec_id, resource):
if self.Reserved(resource):
raise errors.ReservationError("Duplicate reservation for resource: %s." %
raise errors.ReservationError("Duplicate reservation for resource '%s'"
% str(resource))
if ec_id not in self._ec_reserved:
self._ec_reserved[ec_id] = set([resource])
......@@ -834,7 +834,7 @@ MODIFY
| [--net add*[:options]* \| --net remove \| --net *N:options*]
| [--disk add:size=*SIZE* \| --disk remove \| --disk *N*:mode=*MODE*]
| [-t {plain \| drbd}]
| [-t plain | -t drbd -n *new_secondary*]
| [--os-name=*OS* [--force-variant]]
| [--submit]
| {*instance*}
......@@ -849,9 +849,10 @@ name=value[,...]. For details which options can be specified, see
the **add** command.
The ``-t`` option will change the disk template of the instance.
Currently only conversions between the plain and drbd disk
templates are supported, and the instance must be stopped before
attempting the conversion.
Currently only conversions between the plain and drbd disk templates
are supported, and the instance must be stopped before attempting the
conversion. When changing from the plain to the drbd disk template, a
new secondary node must be specified via the ``-n`` option.
The ``--disk add:size=``*SIZE* option adds a disk to the instance. The
``--disk remove`` option will remove the last disk of the
......@@ -128,6 +128,10 @@ def RunClusterTests():
if qa_config.TestEnabled('cluster-reserved-lvs'):
if qa_config.TestEnabled("cluster-modify"):
# TODO: add more cluster modify tests
if qa_config.TestEnabled('cluster-rename'):
......@@ -51,6 +51,7 @@
"cluster-destroy": true,
"cluster-rename": true,
"cluster-reserved-lvs": true,
"cluster-modify": true,
"node-info": true,
"node-volumes": true,
......@@ -171,6 +171,34 @@ def TestClusterReservedLvs():
utils.ShellQuoteArgs(cmd)).wait(), rcode)
def TestClusterModifyBe():
"""gnt-cluster modify -B"""
master = qa_config.GetMasterNode()
for rcode, cmd in [
# mem
(0, ["gnt-cluster", "modify", "-B", "memory=256"]),
(0, ["sh", "-c", "gnt-cluster info|grep '^ *memory: 256$'"]),
(1, ["gnt-cluster", "modify", "-B", "memory=a"]),
(0, ["gnt-cluster", "modify", "-B", "memory=128"]),
(0, ["sh", "-c", "gnt-cluster info|grep '^ *memory: 128$'"]),
# vcpus
(0, ["gnt-cluster", "modify", "-B", "vcpus=4"]),
(0, ["sh", "-c", "gnt-cluster info|grep '^ *vcpus: 4$'"]),
(1, ["gnt-cluster", "modify", "-B", "vcpus=a"]),
(0, ["gnt-cluster", "modify", "-B", "vcpus=1"]),
(0, ["sh", "-c", "gnt-cluster info|grep '^ *vcpus: 1$'"]),
# auto_balance
(0, ["gnt-cluster", "modify", "-B", "auto_balance=False"]),
(0, ["sh", "-c", "gnt-cluster info|grep '^ *auto_balance: False$'"]),
(1, ["gnt-cluster", "modify", "-B", "auto_balance=1"]),
(0, ["gnt-cluster", "modify", "-B", "auto_balance=True"]),
(0, ["sh", "-c", "gnt-cluster info|grep '^ *auto_balance: True$'"]),
utils.ShellQuoteArgs(cmd)).wait(), rcode)
def TestClusterInfo():
"""gnt-cluster info"""
master = qa_config.GetMasterNode()
......@@ -86,6 +86,9 @@ def _TestOsStates():
new_cmd = cmd + ["--%s" % param, val, _TEMP_OS_NAME]
utils.ShellQuoteArgs(new_cmd)).wait(), 0)
# check that double-running the command is OK
utils.ShellQuoteArgs(new_cmd)).wait(), 0)
def _SetupTempOs(node, dir, valid):
......@@ -37,6 +37,8 @@ from ganeti import objects
from ganeti import utils
from ganeti import netutils
from ganeti.config import TemporaryReservationManager
import testutils
import mocks
......@@ -186,5 +188,23 @@ class TestConfigRunner(unittest.TestCase):
CheckSyntax, {mode: m_bridged, link: ''})
class TestTRM(unittest.TestCase):
EC_ID = 1
def testEmpty(self):
t = TemporaryReservationManager()
t.Reserve(self.EC_ID, "a")
self.assertEqual(len(t.GetReserved()), 1)
def testDuplicate(self):
t = TemporaryReservationManager()
t.Reserve(self.EC_ID, "a")
self.assertRaises(errors.ReservationError, t.Reserve, 2, "a")
if __name__ == '__main__':
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