Commit ba924970 authored by Dimitris Aragiorgis's avatar Dimitris Aragiorgis Committed by Thomas Thrainer
Browse files

Hotplug: cmdlib support



Hotplugging is done by functions invoked by ApplyContainerMods(). In
order hotplugging to take place the --hotplug option must be passed
otherwise the modifications will take place after reboot.

NIC hotplug supports add, remove and modify. The modify is done by removing
the existing NIC and adding a new one in the same pci slot.

Disk hotplug supports add and remove.  Before hotplugging a Disk it
must be assembled. Use blockdev_assemble RPC, get the device link_name
and then call hotplug RPC command.

In order to remove a disk (with blockdev_remove) it must be shutdown. So
after unplugging the disk ShutdownDiskInstanceDisks() must be invoked.

For both device types we use the generic RPC call_hotplug_device.

Also adapt unit tests to follow the change.
Signed-off-by: default avatarDimitris Aragiorgis <dimara@grnet.gr>
Signed-off-by: default avatarThomas Thrainer <thomasth@google.com>
Reviewed-by: default avatarThomas Thrainer <thomasth@google.com>
parent ff5def9b
......@@ -1834,7 +1834,7 @@ class LUInstanceMove(LogicalUnit):
idx, result.fail_msg)
errs.append(result.fail_msg)
break
dev_path = result.payload
dev_path, _ = result.payload
result = self.rpc.call_blockdev_export(source_node.uuid, (disk,
self.instance),
target_node.secondary_ip,
......@@ -3063,7 +3063,8 @@ class LUInstanceSetParams(LogicalUnit):
# Operate on copies as this is still in prereq
nics = [nic.Copy() for nic in self.instance.nics]
_ApplyContainerMods("NIC", nics, self._nic_chgdesc, self.nicmod,
self._CreateNewNic, self._ApplyNicMods, None)
self._CreateNewNic, self._ApplyNicMods,
self._RemoveNic)
# Verify that NIC names are unique and valid
utils.ValidateDeviceNames("NIC", nics)
self._new_nics = nics
......@@ -3233,6 +3234,17 @@ class LUInstanceSetParams(LogicalUnit):
(idx, self.cfg.GetNodeName(pnode_uuid)),
self.LogWarning)
def _HotplugDevice(self, action, dev_type, device, extra, seq):
self.LogInfo("Trying to hotplug device...")
result = self.rpc.call_hotplug_device(self.instance.primary_node,
self.instance, action, dev_type,
device, extra, seq)
if result.fail_msg:
self.LogWarning("Could not hotplug device: %s" % result.fail_msg)
self.LogInfo("Continuing execution..")
else:
self.LogInfo("Hotplug done.")
def _CreateNewDisk(self, idx, params, _):
"""Creates a new disk.
......@@ -3258,6 +3270,19 @@ class LUInstanceSetParams(LogicalUnit):
disks=[(idx, disk, 0)],
cleanup=new_disks)
if self.op.hotplug:
result = self.rpc.call_blockdev_assemble(self.instance.primary_node,
(disk, self.instance),
self.instance.name, True, idx)
if result.fail_msg:
self.LogWarning("Can't assemble newly created disk %d: %s",
idx, result.fail_msg)
else:
_, link_name = result.payload
self._HotplugDevice(constants.HOTPLUG_ACTION_ADD,
constants.HOTPLUG_TARGET_DISK,
disk, link_name, idx)
return (disk, [
("disk/%d" % idx, "add:size=%s,mode=%s" % (disk.size, disk.mode)),
])
......@@ -3294,6 +3319,12 @@ class LUInstanceSetParams(LogicalUnit):
"""Removes a disk.
"""
if self.op.hotplug:
self._HotplugDevice(constants.HOTPLUG_ACTION_REMOVE,
constants.HOTPLUG_TARGET_DISK,
root, None, idx)
ShutdownInstanceDisks(self, self.instance, [root])
(anno_disk,) = AnnotateDiskParams(self.instance, [root], self.cfg)
for node_uuid, disk in anno_disk.ComputeNodeTree(
self.instance.primary_node):
......@@ -3323,13 +3354,19 @@ class LUInstanceSetParams(LogicalUnit):
nicparams=nicparams)
nobj.uuid = self.cfg.GenerateUniqueID(self.proc.GetECId())
return (nobj, [
if self.op.hotplug:
self._HotplugDevice(constants.HOTPLUG_ACTION_ADD,
constants.HOTPLUG_TARGET_NIC,
nobj, None, idx)
desc = [
("nic.%d" % idx,
"add:mac=%s,ip=%s,mode=%s,link=%s,network=%s" %
(mac, ip, private.filled[constants.NIC_MODE],
private.filled[constants.NIC_LINK],
net)),
])
private.filled[constants.NIC_LINK], net)),
]
return (nobj, desc)
def _ApplyNicMods(self, idx, nic, params, private):
"""Modifies a network interface.
......@@ -3354,8 +3391,19 @@ class LUInstanceSetParams(LogicalUnit):
for (key, val) in nic.nicparams.items():
changes.append(("nic.%s/%d" % (key, idx), val))
if self.op.hotplug:
self._HotplugDevice(constants.HOTPLUG_ACTION_MODIFY,
constants.HOTPLUG_TARGET_NIC,
nic, None, idx)
return changes
def _RemoveNic(self, idx, nic, _):
if self.op.hotplug:
self._HotplugDevice(constants.HOTPLUG_ACTION_REMOVE,
constants.HOTPLUG_TARGET_NIC,
nic, None, idx)
def Exec(self, feedback_fn):
"""Modifies an instance.
......
......@@ -1211,8 +1211,11 @@ def ShutdownInstanceDisks(lu, instance, disks=None, ignore_primary=False):
ignored.
"""
lu.cfg.MarkInstanceDisksInactive(instance.uuid)
all_result = True
if disks is None:
# only mark instance disks as inactive if all disks are affected
lu.cfg.MarkInstanceDisksInactive(instance.uuid)
disks = ExpandCheckDisks(instance, disks)
for disk in disks:
......@@ -1240,7 +1243,7 @@ def _SafeShutdownInstanceDisks(lu, instance, disks=None):
def AssembleInstanceDisks(lu, instance, disks=None, ignore_secondaries=False,
ignore_size=False):
ignore_size=False):
"""Prepare the block devices for an instance.
This sets up the block devices on all nodes.
......@@ -1265,6 +1268,11 @@ def AssembleInstanceDisks(lu, instance, disks=None, ignore_secondaries=False,
"""
device_info = []
disks_ok = True
if disks is None:
# only mark instance disks as active if all disks are affected
lu.cfg.MarkInstanceDisksActive(instance.uuid)
disks = ExpandCheckDisks(instance, disks)
# With the two passes mechanism we try to reduce the window of
......@@ -1276,10 +1284,6 @@ def AssembleInstanceDisks(lu, instance, disks=None, ignore_secondaries=False,
# into any other network-connected state (Connected, SyncTarget,
# SyncSource, etc.)
# mark instance disks as active before doing actual work, so watcher does
# not try to shut them down erroneously
lu.cfg.MarkInstanceDisksActive(instance.uuid)
# 1st pass, assemble on all nodes in secondary mode
for idx, inst_disk in enumerate(disks):
for node_uuid, node_disk in inst_disk.ComputeNodeTree(
......@@ -1321,7 +1325,7 @@ def AssembleInstanceDisks(lu, instance, disks=None, ignore_secondaries=False,
inst_disk.iv_name, lu.cfg.GetNodeName(node_uuid), msg)
disks_ok = False
else:
dev_path = result.payload
dev_path, _ = result.payload
device_info.append((lu.cfg.GetNodeName(instance.primary_node),
inst_disk.iv_name, dev_path))
......
......@@ -104,7 +104,8 @@ class TestLUBackupExportBase(CmdlibTestCase):
self.rpc.call_blockdev_assemble.return_value = \
self.RpcResultsBuilder() \
.CreateSuccessfulNodeResult(self.master, None)
.CreateSuccessfulNodeResult(self.master, ("/dev/mock_path",
"/dev/mock_link_name"))
self.rpc.call_blockdev_shutdown.return_value = \
self.RpcResultsBuilder() \
......
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