Commit a4f462bd authored by Klaus Aehlig's avatar Klaus Aehlig

Merge branch 'stable-2.10' into stable-2.11

* stable-2.10
  Add --no-locks option to gnt-debug delay
  Include design-performance-tests.rst in index
  Document the --force-failover option
  Support group evacuation by failover
  Add an option --force-failover
  Extend OpGroupEvacuate by a ForceFailover paramter
  Mark performance tests design as implemented
  openvswitch fix
  Document the --sequential option
  Support sequential evacuation
  Add an option --sequential
  Extend OpGroupEvacuate by a sequential paramter

* stable-2.9
  Improve haskell style
  check-man-warnings: use C.UTF-8 and set LC_ALL
  Fix passing of ispecs in cluster init during QA

Conflicts:
	doc/design-draft.rst
	lib/cmdlib/group.py
	src/Ganeti/JQueue.hs
All trivial.
Signed-off-by: default avatarKlaus Aehlig <aehlig@google.com>
Reviewed-by: default avatarPetr Pudlak <pudlak@google.com>
parents a4aa6d08 c4460a46
......@@ -20,7 +20,13 @@
set -e
! LANG=en_US.UTF-8 MANWIDTH=80 \
if locale -a | grep -qF 'C.UTF-8'; then
loc="C.UTF-8"
else
loc="en_US.UTF-8"
fi
! LANG="$loc" LC_ALL="$loc" MANWIDTH=80 \
man --warnings --encoding=utf8 --local-file "$1" 2>&1 >/dev/null | \
grep -v -e "cannot adjust line" -e "can't break line" | \
grep .
......@@ -7,6 +7,7 @@ The following design documents have been implemented in Ganeti 2.10.
- :doc:`design-cmdlib-unittests`
- :doc:`design-hotplug`
- :doc:`design-openvswitch`
- :doc:`design-performance-tests`
- :doc:`design-storagetypes`
- :doc:`design-upgrade`
......
......@@ -20,7 +20,6 @@ Design document drafts
design-hsqueeze.rst
design-os.rst
design-node-security.rst
design-performance-tests.rst
.. vim: set textwidth=72 :
.. Local Variables:
......
......@@ -116,6 +116,7 @@ Draft designs
design-os.rst
design-ovf-support.rst
design-partitioned
design-performance-tests.rst
design-query2.rst
design-reason-trail.rst
design-restricted-commands.rst
......
......@@ -88,6 +88,7 @@ __all__ = [
"FIELDS_OPT",
"FILESTORE_DIR_OPT",
"FILESTORE_DRIVER_OPT",
"FORCE_FAILOVER_OPT",
"FORCE_FILTER_OPT",
"FORCE_OPT",
"FORCE_VARIANT_OPT",
......@@ -202,6 +203,7 @@ __all__ = [
"IPOLICY_STD_SPECS_OPT",
"IPOLICY_DISK_TEMPLATES",
"IPOLICY_VCPU_RATIO",
"SEQUENTIAL_OPT",
"SPICE_CACERT_OPT",
"SPICE_CERT_OPT",
"SRC_DIR_OPT",
......@@ -850,6 +852,10 @@ PRINT_JOBID_OPT = cli_option("--print-jobid", dest="print_jobid",
help=("Additionally print the job as first line"
" on stdout (for scripting)."))
SEQUENTIAL_OPT = cli_option("--sequential", dest="sequential",
default=False, action="store_true",
help=("Execute all resulting jobs sequentially"))
SYNC_OPT = cli_option("--sync", dest="do_locking",
default=False, action="store_true",
help=("Grab locks while doing the queries"
......@@ -1069,6 +1075,12 @@ ALLOW_FAILOVER_OPT = cli_option("--allow-failover",
help="If migration is not possible fallback to"
" failover")
FORCE_FAILOVER_OPT = cli_option("--force-failover",
dest="force_failover",
action="store_true", default=False,
help="Do not use migration, always use"
" failover")
NONLIVE_OPT = cli_option("--non-live", dest="live",
default=True, action="store_false",
help="Do a non-live migration (this usually means"
......
......@@ -64,7 +64,8 @@ def Delay(opts, args):
op = opcodes.OpTestDelay(duration=delay,
on_master=opts.on_master,
on_nodes=opts.on_nodes,
repeat=opts.repeat)
repeat=opts.repeat,
no_locks=opts.no_locks)
SubmitOrSend(op, opts)
return 0
......@@ -629,6 +630,9 @@ commands = {
action="append", help="Select nodes to sleep on"),
cli_option("-r", "--repeat", type="int", default="0", dest="repeat",
help="Number of times to repeat the sleep"),
cli_option("-l", "--no-locks", default=False, dest="no_locks",
action="store_true",
help="Don't take locks while performing the delay"),
DRY_RUN_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
"[opts...] <duration>", "Executes a TestDelay OpCode"),
"submit-job": (
......
......@@ -242,7 +242,9 @@ def EvacuateGroup(opts, args):
op = opcodes.OpGroupEvacuate(group_name=group_name,
iallocator=opts.iallocator,
target_groups=opts.to,
early_release=opts.early_release)
early_release=opts.early_release,
sequential=opts.sequential,
force_failover=opts.force_failover)
result = SubmitOrSend(op, opts, cl=cl)
# Keep track of submitted jobs
......@@ -358,7 +360,9 @@ commands = {
"[--dry-run] <group-name> <new-name>", "Rename a node group"),
"evacuate": (
EvacuateGroup, [ArgGroup(min=1, max=1)],
[TO_GROUP_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT] + SUBMIT_OPTS,
[TO_GROUP_OPT, IALLOCATOR_OPT, EARLY_RELEASE_OPT, SEQUENTIAL_OPT,
FORCE_FAILOVER_OPT]
+ SUBMIT_OPTS,
"[-I <iallocator>] [--to <group>]",
"Evacuate all instances within a group"),
"list-tags": (
......
......@@ -28,6 +28,7 @@ from ganeti import constants
from ganeti import errors
from ganeti import locking
from ganeti import objects
from ganeti import opcodes
from ganeti import utils
from ganeti.masterd import iallocator
from ganeti.cmdlib.base import LogicalUnit, NoHooksLU, ResultWithJobs
......@@ -731,6 +732,24 @@ class LUGroupEvacuate(LogicalUnit):
return (run_nodes, run_nodes)
@staticmethod
def _MigrateToFailover(op):
"""Return an equivalent failover opcode for a migrate one.
If the argument is not a failover opcode, return it unchanged.
"""
if not isinstance(op, opcodes.OpInstanceMigrate):
return op
else:
return opcodes.OpInstanceFailover(
instance_name=op.instance_name,
instance_uuid=getattr(op, "instance_uuid", None),
target_node=getattr(op, "target_node", None),
target_node_uuid=getattr(op, "target_node_uuid", None),
ignore_ipolicy=op.ignore_ipolicy,
cleanup=op.cleanup)
def Exec(self, feedback_fn):
inst_names = list(self.owned_locks(locking.LEVEL_INSTANCE))
......@@ -753,6 +772,16 @@ class LUGroupEvacuate(LogicalUnit):
self.LogInfo("Iallocator returned %s job(s) for evacuating node group %s",
len(jobs), self.op.group_name)
if self.op.force_failover:
self.LogInfo("Will insist on failovers")
jobs = [[self._MigrateToFailover(op) for op in job] for job in jobs]
if self.op.sequential:
self.LogInfo("Jobs will be submitted to run sequentially")
for job in jobs[1:]:
for op in job:
op.depends = [(-1, ["error", "success"])]
return ResultWithJobs(jobs)
......
......@@ -54,7 +54,7 @@ class LUTestDelay(NoHooksLU):
"""
self.needed_locks = {}
if self.op.on_nodes or self.op.on_master:
if not self.op.no_locks and (self.op.on_nodes or self.op.on_master):
self.needed_locks[locking.LEVEL_NODE] = []
if self.op.on_nodes:
......@@ -63,9 +63,10 @@ class LUTestDelay(NoHooksLU):
# more information.
(self.op.on_node_uuids, self.op.on_nodes) = \
GetWantedNodes(self, self.op.on_nodes)
self.needed_locks[locking.LEVEL_NODE].extend(self.op.on_node_uuids)
if not self.op.no_locks:
self.needed_locks[locking.LEVEL_NODE].extend(self.op.on_node_uuids)
if self.op.on_master:
if not self.op.no_locks and self.op.on_master:
# The node lock should be acquired for the master as well.
self.needed_locks[locking.LEVEL_NODE].append(self.cfg.GetMasterNode())
......
......@@ -878,6 +878,8 @@ class ConfigWriter(object):
link = "bridge:%s" % nic_link
elif nic_mode == constants.NIC_MODE_ROUTED:
link = "route:%s" % nic_link
elif nic_mode == constants.NIC_MODE_OVS:
link = "ovs:%s" % nic_link
else:
raise errors.ProgrammerError("NIC mode '%s' not handled" % nic_mode)
......
......@@ -187,7 +187,7 @@ options.
EVACUATE
~~~~~~~~
| **evacuate** [\--submit] [\--print-job-id]
| **evacuate** [\--submit] [\--print-job-id] [\--sequential] [\--force-failover]
| [\--iallocator *NAME*] [\--to *GROUP*...] {*group*}
This command will move all instances out of the given node group.
......@@ -197,6 +197,14 @@ the command line or as a cluster default.
If no specific destination groups are specified using ``--to``, all
groups except the evacuated group are considered.
The moves of the individual instances are handled as separate jobs
to allow for maximal parallelism. If the ``--sequential`` option is
given, the moves of the individual instances will be executed sequentially.
This can be usefull if the link between the groups is vulnerable to
congestion. If the ``--force-failover`` option is given, no migrations
will be made. This might be necessary if the group being evacuated is
too different from the other groups in the cluster.
See **ganeti**\(7) for a description of ``--submit`` and other common
options.
......
......@@ -4398,6 +4398,10 @@ builtinDataCollectorVersion = "B"
opcodeReason :: String
opcodeReason = "reason"
-- | The reason trail opcode parameter name
opcodeSequential :: String
opcodeSequential = "sequential"
diskstatsFile :: String
diskstatsFile = "/proc/diskstats"
......
......@@ -423,6 +423,7 @@ doRepair client delay instData (rtype, opcodes) =
, opDelayOnNodes = []
, opDelayOnNodeUuids = Nothing
, opDelayRepeat = fromJust $ mkNonNegative 0
, opDelayNoLocks = False
} : opcodes
else
opcodes
......
......@@ -385,7 +385,7 @@ failureReason = show . fst . head
-- | Sorts the failure reasons.
sortReasons :: [(FailMode, Int)] -> [(FailMode, Int)]
sortReasons = reverse . sortBy (comparing snd)
sortReasons = sortBy (flip $ comparing snd)
-- | Runs an allocation algorithm and saves cluster state.
runAllocation :: ClusterData -- ^ Cluster data
......
......@@ -405,7 +405,7 @@ determineJobDirectories rootdir archived = do
-- FIXME: delete this and just use \'sequence\' instead when Lucid compatibility
-- will not be required anymore.
sequencer :: [Either IOError [JobId]] -> Either IOError [[JobId]]
sequencer l = fmap reverse $ foldl seqFolder (Right []) l
sequencer l = reverse <$> foldl seqFolder (Right []) l
-- | Folding function for joining multiple [JobIds] into one list.
seqFolder :: Either IOError [[JobId]]
......
......@@ -211,8 +211,8 @@ error404 = do
-- | Return the report of one collector.
oneReport :: MVar CollectorMap -> Snap ()
oneReport mvar = do
categoryName <- fmap (maybe mzero unpack) $ getParam "category"
collectorName <- fmap (maybe mzero unpack) $ getParam "collector"
categoryName <- maybe mzero unpack <$> getParam "category"
collectorName <- maybe mzero unpack <$> getParam "collector"
category <-
case catFromName categoryName of
BT.Ok cat -> return cat
......
......@@ -726,6 +726,8 @@ $(genOpCode "OpCode"
, pEarlyRelease
, pIallocator
, pTargetGroups
, pSequential
, pForceFailover
],
"group_name")
, ("OpOsDiagnose",
......@@ -812,6 +814,7 @@ $(genOpCode "OpCode"
, pDelayOnNodes
, pDelayOnNodeUuids
, pDelayRepeat
, pDelayNoLocks
],
"duration")
, ("OpTestAllocator",
......
......@@ -215,11 +215,13 @@ module Ganeti.OpParams
, pReplaceDisksMode
, pReplaceDisksList
, pAllowFailover
, pForceFailover
, pDelayDuration
, pDelayOnMaster
, pDelayOnNodes
, pDelayOnNodeUuids
, pDelayRepeat
, pDelayNoLocks
, pIAllocatorDirection
, pIAllocatorMode
, pIAllocatorReqName
......@@ -256,6 +258,7 @@ module Ganeti.OpParams
, pDependencies
, pComment
, pReason
, pSequential
, pEnabledDiskTemplates
) where
......@@ -486,6 +489,11 @@ pReason =
withDoc "Reason trail field" $
simpleField C.opcodeReason [t| ReasonTrail |]
pSequential :: Field
pSequential =
withDoc "Sequential job execution" $
defaultFalse C.opcodeSequential
-- * Parameters
pDebugSimulateErrors :: Field
......@@ -1267,6 +1275,11 @@ pAllowFailover =
withDoc "Whether we can fallback to failover if migration is not possible" $
defaultFalse "allow_failover"
pForceFailover :: Field
pForceFailover =
withDoc "Disallow migration moves and always use failovers" $
defaultFalse "force_failover"
pMoveTargetNode :: Field
pMoveTargetNode =
withDoc "Target node for instance move" .
......@@ -1476,6 +1489,12 @@ pDelayRepeat =
defaultField [| forceNonNeg (0::Int) |] $
simpleField "repeat" [t| NonNegative Int |]
pDelayNoLocks :: Field
pDelayNoLocks =
withDoc "Don't take locks during the delay" .
renameField "DelayNoLocks" $
defaultTrue "no_locks"
pIAllocatorDirection :: Field
pIAllocatorDirection =
withDoc "IAllocator test direction" .
......
......@@ -35,6 +35,7 @@ module Test.Ganeti.HTools.Instance
, Instance.Instance(..)
) where
import Control.Applicative ((<$>))
import Control.Monad (liftM)
import Test.QuickCheck hiding (Result)
......@@ -112,7 +113,7 @@ genInstanceOnNodeList nl = do
genInstanceList :: Gen Instance.Instance -> Gen Instance.List
genInstanceList igen = fmap (snd . Loader.assignIndices) names_instances
where names_instances =
(fmap . map) (\n -> (Instance.name n, n)) $ listOf igen
map (\n -> (Instance.name n, n)) <$> listOf igen
-- let's generate a random instance
instance Arbitrary Instance.Instance where
......
......@@ -125,7 +125,7 @@ instance Arbitrary OpCodes.OpCode where
case op_id of
"OP_TEST_DELAY" ->
OpCodes.OpTestDelay <$> arbitrary <*> arbitrary <*>
genNodeNamesNE <*> return Nothing <*> arbitrary
genNodeNamesNE <*> return Nothing <*> arbitrary <*> arbitrary
"OP_INSTANCE_REPLACE_DISKS" ->
OpCodes.OpInstanceReplaceDisks <$> genFQDN <*> return Nothing <*>
arbitrary <*> arbitrary <*> arbitrary <*> genDiskIndices <*>
......@@ -315,7 +315,7 @@ instance Arbitrary OpCodes.OpCode where
OpCodes.OpGroupRename <$> genNameNE <*> genNameNE
"OP_GROUP_EVACUATE" ->
OpCodes.OpGroupEvacuate <$> genNameNE <*> arbitrary <*>
genMaybe genNameNE <*> genMaybe genNamesNE
genMaybe genNameNE <*> genMaybe genNamesNE <*> arbitrary <*> arbitrary
"OP_OS_DIAGNOSE" ->
OpCodes.OpOsDiagnose <$> genFieldsNE <*> genNamesNE
"OP_EXT_STORAGE_DIAGNOSE" ->
......
......@@ -60,6 +60,11 @@ function setup_bridge {
function setup_ovs {
if [ "$MODE" = "openvswitch" ]; then
# Remove stale port
ovs-vsctl del-port $INTERFACE || true
# Bring interface up
ip link set $INTERFACE up
# Add port
ovs-vsctl add-port ${LINK} $INTERFACE
fi
}
......
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