Commit 8729e0d7 authored by Iustin Pop's avatar Iustin Pop
Browse files

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
parent acec9d51
......@@ -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.
......
......@@ -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
......
......@@ -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."""
......
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