From: Dimitris Aragiorgis Date: Tue, 19 Nov 2013 13:34:21 +0000 (+0200) Subject: Introduce --hotplug-if-possible option X-Git-Tag: debian/2.8.2+snapshot1+b64v1+hotplug2+ippoolfix+rapifix-1wheezy~1^2 X-Git-Url: https://code.grnet.gr/git/ganeti-local/commitdiff_plain/7cfe1eb620722322a602b24a3a57ad7abeaf65ae Introduce --hotplug-if-possible option This will be useful for an external entity using RAPI that wants to modify devices of instances. The common use case for that is: "I want to add a NIC/disk to an instance. If it is running then try to hotplug the device. If not, then just add it to config." Another use case is that if we are unaware of the instance's hypervisor: "I want do add a NIC/disk to an instance and if its hypervisor is KVM try to hotplug it." For all those cases just print a warning in CheckPrereq() and disable any further hotplug related actions (and let modifications take place after reboot). Signed-off-by: Dimitris Aragiorgis --- diff --git a/lib/cli.py b/lib/cli.py index 3b1cf51..28e345e 100644 --- a/lib/cli.py +++ b/lib/cli.py @@ -96,6 +96,7 @@ __all__ = [ "HID_OS_OPT", "GLOBAL_SHARED_FILEDIR_OPT", "HOTPLUG_OPT", + "HOTPLUG_IF_POSSIBLE_OPT", "KEEPDISKS_OPT", "HVLIST_OPT", "HVOPTS_OPT", @@ -1648,6 +1649,12 @@ KEEPDISKS_OPT = cli_option("--keep-disks", dest="keep_disks", action="store_true", default=False, help="Do not remove disks") +HOTPLUG_IF_POSSIBLE_OPT = cli_option("--hotplug-if-possible", + dest="hotplug_if_possible", + action="store_true", default=False, + help="Hotplug devices in case" + " hotplug is supported") + #: Options provided by all commands COMMON_OPTS = [DEBUG_OPT, REASON_OPT] diff --git a/lib/client/gnt_instance.py b/lib/client/gnt_instance.py index 9febee3..e71c0da 100644 --- a/lib/client/gnt_instance.py +++ b/lib/client/gnt_instance.py @@ -1372,6 +1372,7 @@ def SetInstanceParams(opts, args): nics=nics, disks=disks, hotplug=opts.hotplug, + hotplug_if_possible=opts.hotplug_if_possible, keep_disks=opts.keep_disks, disk_template=opts.disk_template, remote_node=opts.node, @@ -1581,7 +1582,8 @@ commands = { DISK_TEMPLATE_OPT, SINGLE_NODE_OPT, OS_OPT, FORCE_VARIANT_OPT, OSPARAMS_OPT, DRY_RUN_OPT, PRIORITY_OPT, NWSYNC_OPT, OFFLINE_INST_OPT, ONLINE_INST_OPT, IGNORE_IPOLICY_OPT, RUNTIME_MEM_OPT, - NOCONFLICTSCHECK_OPT, NEW_PRIMARY_OPT, HOTPLUG_OPT, KEEPDISKS_OPT], + NOCONFLICTSCHECK_OPT, NEW_PRIMARY_OPT, HOTPLUG_OPT, KEEPDISKS_OPT, + HOTPLUG_IF_POSSIBLE_OPT], "", "Alters the parameters of an instance"), "shutdown": ( GenericManyOps("shutdown", _ShutdownInstance), [ArgInstance()], diff --git a/lib/cmdlib/instance.py b/lib/cmdlib/instance.py index 8229fb5..a340bc0 100644 --- a/lib/cmdlib/instance.py +++ b/lib/cmdlib/instance.py @@ -2665,14 +2665,19 @@ class LUInstanceSetParams(LogicalUnit): # dictionary with instance information after the modification ispec = {} - if self.op.hotplug: + if self.op.hotplug or self.op.hotplug_if_possible: result = self.rpc.call_hotplug_supported(self.instance.primary_node, self.instance) - # result.Raise("Hotplug is not supported.") if result.fail_msg: - self.LogWarning(result.fail_msg) - self.op.hotplug = False - self.LogInfo("Continuing execution..") + if self.op.hotplug: + result.Raise("Hotplug is not possible: %s" % result.fail_msg, + prereq=True) + else: + self.LogWarning(result.fail_msg) + self.op.hotplug = False + self.LogInfo("Modification will take place without hotplugging.") + else: + self.op.hotplug = True # Check disk modifications. This is done here and not in CheckArguments # (as with NICs), because we need to know the instance's disk template diff --git a/lib/hypervisor/hv_kvm.py b/lib/hypervisor/hv_kvm.py index 8ffb2dc..dfdd6df 100644 --- a/lib/hypervisor/hv_kvm.py +++ b/lib/hypervisor/hv_kvm.py @@ -1991,13 +1991,14 @@ class KVMHypervisor(hv_base.BaseHypervisor): """ try: output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD) - except errors.HypervisorError, err: - raise errors.HotplugError("Cannot hotplug on a stopped VM.") + except errors.HypervisorError: + raise errors.HotplugError("Instance is probably down") # TODO: search for netdev_add, drive_add, device_add..... match = self._INFO_VERSION_RE.search(output.stdout) if not match: - raise errors.HotplugError("Cannot parse qemu version via monitor.") + raise errors.HotplugError("Cannot parse qemu version via monitor") + v_major, v_min, _, _ = match.groups() if (int(v_major), int(v_min)) < (1, 0): raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0") diff --git a/man/gnt-instance.rst b/man/gnt-instance.rst index c854e35..4f296dc 100644 --- a/man/gnt-instance.rst +++ b/man/gnt-instance.rst @@ -1109,6 +1109,7 @@ MODIFY | [\--submit] | [\--ignore-ipolicy] | [\--hotplug] +| [\--hotplug-if-possible] | {*instance*} Modifies the memory size, number of vcpus, ip address, MAC address @@ -1189,6 +1190,11 @@ effect without the need of actual reboot. Please note that this feature is currently supported only for KVM hypervisor and for versions greater than 1.0. +If ``--hotplug-if-possible`` is given then ganeti won't abort in case +hotplug is not supported. It will continue execution and modification +will take place after reboot. This covers use cases where instances are +not running or hypervisor is not KVM. + See **ganeti**\(7) for a description of ``--submit`` and other common options. diff --git a/src/Ganeti/OpCodes.hs b/src/Ganeti/OpCodes.hs index 41a4371..c679f1d 100644 --- a/src/Ganeti/OpCodes.hs +++ b/src/Ganeti/OpCodes.hs @@ -403,6 +403,7 @@ $(genOpCode "OpCode" , pOffline , pIpConflictsCheck , pHotplug + , pHotplugIfPossible , pKeepDisks ]) , ("OpInstanceGrowDisk", diff --git a/src/Ganeti/OpParams.hs b/src/Ganeti/OpParams.hs index 46bd949..80b7746 100644 --- a/src/Ganeti/OpParams.hs +++ b/src/Ganeti/OpParams.hs @@ -97,6 +97,7 @@ module Ganeti.OpParams , pDiskState , pIgnoreIpolicy , pHotplug + , pHotplugIfPossible , pKeepDisks , pAllowRuntimeChgs , pInstDisks @@ -733,6 +734,9 @@ pDiskParams = optionalField $ pHotplug :: Field pHotplug = defaultFalse "hotplug" +pHotplugIfPossible :: Field +pHotplugIfPossible = defaultFalse "hotplug_if_possible" + -- | Whether to remove disks. pKeepDisks :: Field pKeepDisks = defaultFalse "keep_disks"