From 8729e0d78bc231321adbcd80d8782546f391a67f Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Tue, 17 Jun 2008 06:50:51 +0000 Subject: [PATCH] Implement disk grow at LU level This patch adds a new opcode and LU for growing an instance's disk. The opcode allows growing only one disk at time, and will throw an error if the operation fails midway (e.g. on the primary node after it has been increased on the secondary node). As such, it might actually leave different sized LVs on different nodes, but this will not create problems. Reviewed-by: imsnah --- lib/cmdlib.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/mcpu.py | 1 + lib/opcodes.py | 6 ++++ 3 files changed, 89 insertions(+) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 596b0deef..4cc1f41c3 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -3937,6 +3937,88 @@ class LUReplaceDisks(LogicalUnit): return ret +class LUGrowDisk(LogicalUnit): + """Grow a disk of an instance. + + """ + HPATH = "disk-grow" + HTYPE = constants.HTYPE_INSTANCE + _OP_REQP = ["instance_name", "disk", "amount"] + + def BuildHooksEnv(self): + """Build hooks env. + + This runs on the master, the primary and all the secondaries. + + """ + env = { + "DISK": self.op.disk, + "AMOUNT": self.op.amount, + } + env.update(_BuildInstanceHookEnvByObject(self.instance)) + nl = [ + self.sstore.GetMasterNode(), + self.instance.primary_node, + ] + return env, nl, nl + + def CheckPrereq(self): + """Check prerequisites. + + This checks that the instance is in the cluster. + + """ + instance = self.cfg.GetInstanceInfo( + self.cfg.ExpandInstanceName(self.op.instance_name)) + if instance is None: + raise errors.OpPrereqError("Instance '%s' not known" % + self.op.instance_name) + self.instance = instance + self.op.instance_name = instance.name + + if instance.disk_template not in (constants.DT_PLAIN, constants.DT_DRBD8): + raise errors.OpPrereqError("Instance's disk layout does not support" + " growing.") + + if instance.FindDisk(self.op.disk) is None: + raise errors.OpPrereqError("Disk '%s' not found for instance '%s'" % + (name, instance.name)) + + nodenames = [instance.primary_node] + list(instance.secondary_nodes) + nodeinfo = rpc.call_node_info(nodenames, self.cfg.GetVGName()) + for node in nodenames: + info = nodeinfo.get(node, None) + if not info: + raise errors.OpPrereqError("Cannot get current information" + " from node '%s'" % node) + vg_free = info.get('vg_free', None) + if not isinstance(vg_free, int): + raise errors.OpPrereqError("Can't compute free disk space on" + " node %s" % node) + if self.op.amount > info['vg_free']: + raise errors.OpPrereqError("Not enough disk space on target node %s:" + " %d MiB available, %d MiB required" % + (node, info['vg_free'], self.op.amount)) + + def Exec(self, feedback_fn): + """Execute disk grow. + + """ + instance = self.instance + disk = instance.FindDisk(self.op.disk) + for node in (instance.secondary_nodes + (instance.primary_node,)): + self.cfg.SetDiskID(disk, node) + result = rpc.call_blockdev_grow(node, disk, self.op.amount) + if not result or not isinstance(result, tuple) or len(result) != 2: + raise errors.OpExecError("grow request failed to node %s" % node) + elif not result[0]: + raise errors.OpExecError("grow request failed to node %s: %s" % + (node, result[1])) + disk.RecordGrow(self.op.amount) + self.cfg.Update(instance) + return + + class LUQueryInstanceData(NoHooksLU): """Query runtime instance data. diff --git a/lib/mcpu.py b/lib/mcpu.py index b9b06f631..2e7f3039c 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -74,6 +74,7 @@ class Processor(object): opcodes.OpQueryInstances: cmdlib.LUQueryInstances, opcodes.OpQueryInstanceData: cmdlib.LUQueryInstanceData, opcodes.OpSetInstanceParams: cmdlib.LUSetInstanceParams, + opcodes.OpGrowDisk: cmdlib.LUGrowDisk, # os lu opcodes.OpDiagnoseOS: cmdlib.LUDiagnoseOS, # exports lu diff --git a/lib/opcodes.py b/lib/opcodes.py index 094d0858e..11385c013 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -370,6 +370,12 @@ class OpSetInstanceParams(OpCode): ] +class OpGrowDisk(OpCode): + """Grow a disk of an instance.""" + OP_ID = "OP_INSTANCE_GROW_DISK" + __slots__ = ["instance_name", "disk", "amount"] + + # OS opcodes class OpDiagnoseOS(OpCode): """Compute the list of guest operating systems.""" -- GitLab