Commit 6a74f584 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Merge branch 'devel-2.6'



* devel-2.6:
  verify-disks: Explicitely state nothing has to be done
  Add list of design documents implemented in version 2.6
  Better list of replace-disks arguments + typos fixed
  jqueue: Look at archived jobs when watching
  Show old primary/secondary node on disk replacement
  gnt-instance reinstall: Don't always exit with success
  LUClusterVerify: Ignore /proc/drbd if DRBD is disabled
  Fixed typos in devnotes.rst
  Always_failover doesn't require --allow-failover anymore
  bash_completion: Enable extglob while parsing file
  rpc: Remove duplicated logic, fix unittests
  Annotate disk params on instance_start
  cmdlib: Handle locking.ALL_SET correctly when copying locks

Conflicts:
	Makefile.am: Sorted file lists
	autotools/build-bash-completion: Compact output
	lib/rpc_defs.py: instance_start changed on both sides
	qa/qa_instance.py: Modified on both sides
	test/ganeti.cmdlib_unittest.py: Tests added on both sides
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parents 43d51ef2 c44356fd
......@@ -341,6 +341,7 @@ docrst = \
doc/design-2.3.rst \
doc/design-2.4.rst \
doc/design-2.5.rst \
doc/design-2.6.rst \
doc/design-autorepair.rst \
doc/design-bulk-create.rst \
doc/design-chained-jobs.rst \
......
......@@ -767,6 +767,11 @@ def main():
sw.Write("gnt_shopt_extglob=$(shopt -p extglob || :)")
sw.Write("shopt -s extglob")
# Remember original state of extglob and enable it (required for pattern
# matching; must be enabled while parsing script)
sw.Write("gnt_shopt_extglob=$(shopt -p extglob || :)")
sw.Write("shopt -s extglob")
WritePreamble(sw, not options.compact)
# gnt-* scripts
......
=================
Ganeti 2.6 design
=================
The following design documents have been implemented in Ganeti 2.6:
- :doc:`design-cpu-pinning`
- :doc:`design-ovf-support`
.. vim: set textwidth=72 :
.. Local Variables:
.. mode: rst
.. fill-column: 72
.. End:
......@@ -8,8 +8,6 @@ Design document drafts
design-x509-ca.rst
design-http-server.rst
design-impexp2.rst
design-cpu-pinning.rst
design-ovf-support.rst
design-network.rst
design-node-state-cache.rst
design-resource-model.rst
......
......@@ -136,9 +136,9 @@ documentation, the second one with profiling enabled.
Packaging notes
===============
Ganeti is mostly developped and tested on `Debian
Ganeti is mostly developed and tested on `Debian
<http://www.debian.org/>`_-based distributions, while still keeping
adoptability to other Linux distributions in mind.
adaptability to other Linux distributions in mind.
The ``doc/examples/`` directory contains a number of potentially useful
scripts and configuration files. Some of them might need adjustment
......
......@@ -22,6 +22,7 @@ Contents:
design-htools-2.3.rst
design-2.4.rst
design-2.5.rst
design-2.6.rst
design-draft.rst
cluster-merge.rst
locking.rst
......@@ -45,6 +46,8 @@ Contents:
design-chained-jobs.rst
design-multi-reloc.rst
design-shared-storage.rst
design-cpu-pinning.rst
design-ovf-support.rst
Also see the :ref:`search`.
......
......@@ -671,6 +671,8 @@ def VerifyDisks(opts, args):
ToStdout("You need to replace or recreate disks for all the above"
" instances if this message persists after fixing broken nodes.")
retcode = constants.EXIT_FAILURE
elif not instances:
ToStdout("No disks need to be activated.")
return retcode
......
......@@ -397,8 +397,12 @@ def ReinstallInstance(opts, args):
osparams=opts.osparams)
jex.QueueJob(instance_name, op)
jex.WaitOrShow(not opts.submit_only)
return 0
results = jex.WaitOrShow(not opts.submit_only)
if compat.all(map(compat.fst, results)):
return constants.EXIT_SUCCESS
else:
return constants.EXIT_FAILURE
def RemoveInstance(opts, args):
......@@ -1513,8 +1517,8 @@ commands = {
[AUTO_REPLACE_OPT, DISKIDX_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT,
NEW_SECONDARY_OPT, ON_PRIMARY_OPT, ON_SECONDARY_OPT, SUBMIT_OPT,
DRY_RUN_OPT, PRIORITY_OPT, IGNORE_IPOLICY_OPT],
"[-s|-p|-n NODE|-I NAME] <instance>",
"Replaces all disks for the instance"),
"[-s|-p|-a|-n NODE|-I NAME] <instance>",
"Replaces disks for the instance"),
"modify": (
SetInstanceParams, ARGS_ONE_INSTANCE,
[BACKEND_OPT, DISK_OPT, FORCE_OPT, HVOPTS_OPT, NET_OPT, SUBMIT_OPT,
......
......@@ -690,6 +690,18 @@ def _SupportsOob(cfg, node):
return cfg.GetNdParams(node)[constants.ND_OOB_PROGRAM]
 
 
def _CopyLockList(names):
"""Makes a copy of a list of lock names.
Handles L{locking.ALL_SET} correctly.
"""
if names == locking.ALL_SET:
return locking.ALL_SET
else:
return names[:]
def _GetWantedNodes(lu, nodes):
"""Returns list of checked and expanded node names.
 
......@@ -7210,7 +7222,7 @@ class LUInstanceRecreateDisks(LogicalUnit):
elif level == locking.LEVEL_NODE_RES:
# Copy node locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.needed_locks[locking.LEVEL_NODE][:]
_CopyLockList(self.needed_locks[locking.LEVEL_NODE])
 
def BuildHooksEnv(self):
"""Build hooks env.
......@@ -7498,7 +7510,7 @@ class LUInstanceRemove(LogicalUnit):
elif level == locking.LEVEL_NODE_RES:
# Copy node locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.needed_locks[locking.LEVEL_NODE][:]
_CopyLockList(self.needed_locks[locking.LEVEL_NODE])
 
def BuildHooksEnv(self):
"""Build hooks env.
......@@ -7651,7 +7663,7 @@ class LUInstanceFailover(LogicalUnit):
elif level == locking.LEVEL_NODE_RES:
# Copy node locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.needed_locks[locking.LEVEL_NODE][:]
_CopyLockList(self.needed_locks[locking.LEVEL_NODE])
 
def BuildHooksEnv(self):
"""Build hooks env.
......@@ -7735,7 +7747,7 @@ class LUInstanceMigrate(LogicalUnit):
elif level == locking.LEVEL_NODE_RES:
# Copy node locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.needed_locks[locking.LEVEL_NODE][:]
_CopyLockList(self.needed_locks[locking.LEVEL_NODE])
 
def BuildHooksEnv(self):
"""Build hooks env.
......@@ -7794,7 +7806,7 @@ class LUInstanceMove(LogicalUnit):
elif level == locking.LEVEL_NODE_RES:
# Copy node locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.needed_locks[locking.LEVEL_NODE][:]
_CopyLockList(self.needed_locks[locking.LEVEL_NODE])
 
def BuildHooksEnv(self):
"""Build hooks env.
......@@ -11061,11 +11073,15 @@ class TLReplaceDisks(Tasklet):
"Should not own any node group lock at this point"
 
if not self.disks:
feedback_fn("No disks need replacement")
feedback_fn("No disks need replacement for instance '%s'" %
self.instance.name)
return
 
feedback_fn("Replacing disk(s) %s for %s" %
feedback_fn("Replacing disk(s) %s for instance '%s'" %
(utils.CommaJoin(self.disks), self.instance.name))
feedback_fn("Current primary node: %s", self.instance.primary_node)
feedback_fn("Current seconary node: %s",
utils.CommaJoin(self.instance.secondary_nodes))
 
activate_disks = (self.instance.admin_state != constants.ADMINST_UP)
 
......@@ -11892,7 +11908,7 @@ class LUInstanceGrowDisk(LogicalUnit):
elif level == locking.LEVEL_NODE_RES:
# Copy node locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.needed_locks[locking.LEVEL_NODE][:]
_CopyLockList(self.needed_locks[locking.LEVEL_NODE])
 
def BuildHooksEnv(self):
"""Build hooks env.
......@@ -12587,7 +12603,7 @@ class LUInstanceSetParams(LogicalUnit):
elif level == locking.LEVEL_NODE_RES and self.op.disk_template:
# Copy node locks
self.needed_locks[locking.LEVEL_NODE_RES] = \
self.needed_locks[locking.LEVEL_NODE][:]
_CopyLockList(self.needed_locks[locking.LEVEL_NODE])
 
def BuildHooksEnv(self):
"""Build hooks env.
......
......@@ -664,7 +664,7 @@ class RpcRunner(_RpcClientBase,
encoders.update({
# Encoders requiring configuration object
rpc_defs.ED_INST_DICT: self._InstDict,
rpc_defs.ED_INST_DICT_HVP_BEP: self._InstDictHvpBep,
rpc_defs.ED_INST_DICT_HVP_BEP_DP: self._InstDictHvpBepDp,
rpc_defs.ED_INST_DICT_OSP_DP: self._InstDictOspDp,
# Encoders annotating disk parameters
......@@ -725,9 +725,10 @@ class RpcRunner(_RpcClientBase,
nic["nicparams"] = objects.FillDict(
cluster.nicparams[constants.PP_DEFAULT],
nic["nicparams"])
idict["disks"] = self._DisksDictDP((instance.disks, instance))
return idict
def _InstDictHvpBep(self, (instance, hvp, bep)):
def _InstDictHvpBepDp(self, (instance, hvp, bep)):
"""Wrapper for L{_InstDict}.
"""
......@@ -737,9 +738,7 @@ class RpcRunner(_RpcClientBase,
"""Wrapper for L{_InstDict}.
"""
updated_inst = self._InstDict(instance, osp=osparams)
updated_inst["disks"] = self._DisksDictDP((instance.disks, instance))
return updated_inst
return self._InstDict(instance, osp=osparams)
def _DisksDictDP(self, (disks, instance)):
"""Wrapper for L{AnnotateDiskParams}.
......
......@@ -61,7 +61,7 @@ ACCEPT_OFFLINE_NODE = object()
(ED_OBJECT_DICT,
ED_OBJECT_DICT_LIST,
ED_INST_DICT,
ED_INST_DICT_HVP_BEP,
ED_INST_DICT_HVP_BEP_DP,
ED_NODE_TO_DISK_DICT,
ED_INST_DICT_OSP_DP,
ED_IMPEXP_IO,
......@@ -263,7 +263,7 @@ _INSTANCE_CALLS = [
("instance", ED_INST_DICT, "Instance object"),
], None, _MigrationStatusPostProc, "Report migration status"),
("instance_start", SINGLE, None, constants.RPC_TMO_NORMAL, [
("instance_hvp_bep", ED_INST_DICT_HVP_BEP, None),
("instance_hvp_bep", ED_INST_DICT_HVP_BEP_DP, None),
("startup_paused", None, None),
], None, None, "Starts an instance"),
("instance_os_add", SINGLE, None, constants.RPC_TMO_1DAY, [
......
......@@ -84,7 +84,7 @@ the resolver (e.g. in DNS or /etc/hosts, depending on your setup).
Since the name check is used to compute the IP address, if you pass
this option you must also pass the ``--no-ip-check`` option.
If you don't wat the instance to automatically start after
If you don't want the instance to automatically start after
creation, this is possible via the ``--no-start`` option. This will
leave the instance down until a subsequent **gnt-instance start**
command.
......@@ -258,7 +258,7 @@ cdrom\_disk\_type
This parameter determines the way the cdroms disks are presented
to the instance. The default behavior is to get the same value of
the eariler parameter (disk_type). The possible options are:
the earlier parameter (disk_type). The possible options are:
- paravirtual
- ide
......@@ -522,7 +522,7 @@ mem\_path
use\_chroot
Valid for the KVM hypervisor.
This boolean option determines wether to run the KVM instance in a
This boolean option determines whether to run the KVM instance in a
chroot directory.
If it is set to ``true``, an empty directory is created before
......@@ -728,7 +728,7 @@ hypervisor
mac, ip, mode, link
Specifications for the one NIC that will be created for the
instance. 'bridge' is also accepted as a backwards compatibile
instance. 'bridge' is also accepted as a backwards compatible
key.
nics
......@@ -1266,10 +1266,10 @@ REPLACE-DISKS
[\--disks *idx*] {*instance*}
**replace-disks** [\--submit] [\--early-release] [\--ignore-ipolicy]
{{-I\|\--iallocator} *name* \| \--node *node* } {*instance*}
{{-I\|\--iallocator} *name* \| {{-n|\--new-secondary} *node* } {*instance*}
**replace-disks** [\--submit] [\--early-release] [\--ignore-ipolicy]
{\--auto} {*instance*}
{-a\|\--auto} {*instance*}
This command is a generalized form for replacing disks. It is
currently only valid for the mirrored (DRBD) disk template.
......@@ -1557,7 +1557,7 @@ viewed with the **gnt-cluster info** command).
If the ``--cleanup`` option is passed, the operation changes from
migration to attempting recovery from a failed previous migration. In
this mode, Ganeti checks if the instance runs on the correct node (and
updates its configuration if not) and ensures the instances's disks
updates its configuration if not) and ensures the instances' disks
are configured correctly. In this mode, the ``--non-live`` option is
ignored.
......
......@@ -220,7 +220,7 @@ listing fast if only fields from this set are selected), whereas the
other fields are "live" fields and require a query to the cluster nodes.
Depending on the virtualization type and implementation details, the
``mtotal``, ``mnode`` and ``mfree`` fields may have slighly varying
``mtotal``, ``mnode`` and ``mfree`` fields may have slightly varying
meanings. For example, some solutions share the node memory with the
pool of memory used for instances (KVM), whereas others have separate
memory for the node and for the instances (Xen).
......@@ -295,8 +295,8 @@ As for the **gnt-instance migrate** command, the options
``--no-live``, ``--migration-mode`` and ``--no-runtime-changes``
can be given to influence the migration type.
If ``--ignore-ipolicy`` is given any instance policy violations occuring
during this operation are ignored.
If ``--ignore-ipolicy`` is given any instance policy violations
occurring during this operation are ignored.
See **ganeti(7)** for a description of ``--submit`` and other common
options.
......@@ -580,7 +580,7 @@ POWER
This command calls out to out-of-band management to change the power
state of given node. With ``status`` you get the power status as reported
by the out-of-band managment script.
by the out-of-band management script.
Note that this command will only work if the out-of-band functionality
is configured and enabled on the cluster. If this is not the case,
......
......@@ -106,7 +106,7 @@ INI_MEM_INST, FIN_MEM_INST
INI_MEM_OVERHEAD, FIN_MEM_OVERHEAD
The initial and final memory overhead, i.e. memory used for the node
itself and unacounted memory (e.g. due to hypervisor overhead).
itself and unaccounted memory (e.g. due to hypervisor overhead).
INI_MEM_EFF, HTS_INI_MEM_EFF
The initial and final memory efficiency, represented as instance
......
......@@ -220,6 +220,12 @@ def TestInstanceReinstall(instance):
"""gnt-instance reinstall"""
AssertCommand(["gnt-instance", "reinstall", "-f", instance["name"]])
# Test with non-existant OS definition
AssertCommand(["gnt-instance", "reinstall", "-f",
"--os-type=NonExistantOsForQa",
instance["name"]],
fail=True)
def _ReadSsconfInstanceList():
"""Reads ssconf_instance_list from the master node.
......@@ -323,6 +329,25 @@ def TestInstanceMigrate(instance, toggle_always_failover=True):
AssertCommand(["gnt-instance", "start", instance["name"]])
AssertCommand(cmd)
# @InstanceCheck enforces the check that the instance is running
qa_utils.RunInstanceCheck(instance, True)
AssertCommand(["gnt-instance", "modify", "-B",
("%s=%s" %
(constants.BE_ALWAYS_FAILOVER, constants.VALUE_TRUE)),
instance["name"]])
AssertCommand(cmd)
qa_utils.RunInstanceCheck(instance, True)
# TODO: Verify that a failover has been done instead of a migration
# TODO: Verify whether the default value is restored here (not hardcoded)
AssertCommand(["gnt-instance", "modify", "-B",
("%s=%s" %
(constants.BE_ALWAYS_FAILOVER, constants.VALUE_FALSE)),
instance["name"]])
AssertCommand(cmd)
qa_utils.RunInstanceCheck(instance, True)
def TestInstanceInfo(instance):
......
......@@ -42,6 +42,7 @@ from ganeti import ht
from ganeti import objects
from ganeti import compat
from ganeti import rpc
from ganeti import locking
from ganeti import pathutils
from ganeti.masterd import iallocator
from ganeti.hypervisor import hv_xen
......@@ -1488,5 +1489,17 @@ class TestDiskSizeInBytesToMebibytes(unittest.TestCase):
self.assertEqual(warnsize, (1024 * 1024) - j)
class TestCopyLockList(unittest.TestCase):
def test(self):
self.assertEqual(cmdlib._CopyLockList([]), [])
self.assertEqual(cmdlib._CopyLockList(None), None)
self.assertEqual(cmdlib._CopyLockList(locking.ALL_SET), locking.ALL_SET)
names = ["foo", "bar"]
output = cmdlib._CopyLockList(names)
self.assertEqual(names, output)
self.assertNotEqual(id(names), id(output), msg="List was not copied")
if __name__ == "__main__":
testutils.GanetiTestProgram()
......@@ -800,8 +800,13 @@ class TestRpcRunner(unittest.TestCase):
constants.NIC_MODE: "mymode",
}),
],
disk_template=constants.DT_DISKLESS,
disks=[])
disk_template=constants.DT_PLAIN,
disks=[
objects.Disk(dev_type=constants.LD_LV, size=4096,
logical_id=("vg", "disk6120")),
objects.Disk(dev_type=constants.LD_LV, size=1024,
logical_id=("vg", "disk8508")),
])
inst.UpgradeConfig()
cfg = _FakeConfigForRpcRunner(cluster=cluster)
......@@ -854,7 +859,7 @@ class TestRpcRunner(unittest.TestCase):
})
# Instance with hypervisor and backend parameters
result = runner._encoder((rpc_defs.ED_INST_DICT_HVP_BEP, (inst, {
result = runner._encoder((rpc_defs.ED_INST_DICT_HVP_BEP_DP, (inst, {
constants.HT_KVM: {
constants.HV_BOOT_ORDER: "xyz",
},
......@@ -868,6 +873,20 @@ class TestRpcRunner(unittest.TestCase):
self.assertEqual(result["hvparams"][constants.HT_KVM], {
constants.HV_BOOT_ORDER: "xyz",
})
self.assertEqual(result["disks"], [{
"dev_type": constants.LD_LV,
"size": 4096,
"logical_id": ("vg", "disk6120"),
"params": constants.DISK_DT_DEFAULTS[inst.disk_template],
}, {
"dev_type": constants.LD_LV,
"size": 1024,
"logical_id": ("vg", "disk8508"),
"params": constants.DISK_DT_DEFAULTS[inst.disk_template],
}])
self.assertTrue(compat.all(disk.params == {} for disk in inst.disks),
msg="Configuration objects were modified")
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