Hi, first of all thanks for the patch and sorry for the late response.
I walked through the code and I have the following comments: 1) You eliminate HotplugSupported() in the backend. It was used as a preliminary check so that we fail early in case the Hypervisor does not support hotplug at all (i.e. for all Hypervisors other than kvm) or in case the instance is not running. So I guess this should not be removed. 2) Ganeti usually has for each RPC the equivalent backend method (see lib/server/noded.py). Here you keep hotplug_supported RPC and invoke VerifyHotplugSupport(). This is inconsistent. VerifyHotplugSupport is a more fine-grained check that should be done inside HoptlugDevice() just before actually doing the hotplug action. 3) Is there a reason for introducing _CheckDisksNicsHotplug() and practically replacing _CheckHotplug()? Besides that it does too many RPCs, it has a bug since if a check for a NIC fails and all checks for DISKs succeed it does not abort. 4) In general this patch should be mainly additions. You removed HotplugSupported(), practically rewrote VerifyHotplugSupport() by moving code around and changed _CheckHotplug(). All these introduced lots of deleted lines in the patch which makes it hard to read/understand/review. 5) Just a minor coding style comment: I think the docstring of the functions should have a one-line title, an empty line and then a more verbose text. So I suggest we keep the HotplugSupported() backend method and hotplug_supported RPC as it was previously. _CheckHotplug() in cmdlib should not change at all. The patch should extend VerfifyHotplugSupport() with CheckDiskHotResizeSupport() and HotModDevice() with HotResizeDisk() that will end up using the new QMP helper methods. Please note that these are my personal comments so it would be wise to get some feedback from the core team too, e.g., Hrvoje [Cc: ed]. dimara * Yoann Laissus <yoann.lais...@gmail.com> [2015-06-28 21:13:17 +0200]: > Here is the second revision of my patch. > > As you have suggested, I now use existing hotplug methods instead of > creating new ones. (except the _VerifyHotResizeCommand special case) > > For GetBlockDevices, I choose to keep it because it returns different > informations than PCI devices (eg : disk size) so it would be difficult to > merge them together. > > For the integration of "grow-disk" in "modify", I'll probably do that in a > separate patch. > > 2015-06-28 20:59 GMT+02:00 Yoann Laissus <yoann.lais...@gmail.com>: > > > This patch adds support for disk hot resizing when using a KVM > > hypervisor. It's done by calling the "block_resize" QMP command. > > It can be enabled via the new '--hot-resize' option of gnt-instance > > grow-disk but it remains disabled by default. > > > > Signed-off-by: Yoann Laissus <yoann.lais...@gmail.com> > > --- > > lib/backend.py | 15 ++++++-- > > lib/cli_opts.py | 6 +++ > > lib/client/gnt_instance.py | 5 ++- > > lib/cmdlib/instance_set_params.py | 43 +++++++++++++++++++-- > > lib/cmdlib/instance_storage.py | 49 ++++++++++++++++++++++-- > > lib/hypervisor/hv_base.py | 8 ---- > > lib/hypervisor/hv_kvm/__init__.py | 79 > > ++++++++++++++++++++++++--------------- > > lib/hypervisor/hv_kvm/monitor.py | 53 ++++++++++++++++++++++++++ > > lib/rapi/client.py | 3 +- > > lib/rpc_defs.py | 2 + > > lib/server/noded.py | 5 ++- > > src/Ganeti/OpCodes.hs | 1 + > > src/Ganeti/OpParams.hs | 4 ++ > > test/hs/Test/Ganeti/OpCodes.hs | 1 + > > 14 files changed, 218 insertions(+), 56 deletions(-) > > > > diff --git a/lib/backend.py b/lib/backend.py > > index f80fc20..8021301 100644 > > --- a/lib/backend.py > > +++ b/lib/backend.py > > @@ -2993,17 +2993,24 @@ def HotplugDevice(instance, action, dev_type, > > device, extra, seq): > > return fn(instance, dev_type, device, extra, seq) > > > > > > -def HotplugSupported(instance): > > - """Checks if hotplug is generally supported. > > +def VerifyHotplugSupport(instance, action, dev_type): > > + """Checks if hotplug is supported on the specified device type > > + > > + @type instance: L{objects.Instance} > > + @param instance: the instance to which we want to hotplug a device > > + @type action: string > > + @param action: the hotplug action to perform > > + @type dev_type: string > > + @param dev_type: the device type to hotplug > > + @raise RPCFail: in case instance does not have KVM hypervisor > > > > """ > > hyper = hypervisor.GetHypervisor(instance.hypervisor) > > try: > > - hyper.HotplugSupported(instance) > > + hyper.VerifyHotplugSupport(instance, action, dev_type) > > except errors.HotplugError, err: > > _Fail("Hotplug is not supported: %s", err) > > > > - > > def ModifyInstanceMetadata(metadata): > > """Sends instance data to the metadata daemon. > > > > diff --git a/lib/cli_opts.py b/lib/cli_opts.py > > index a6126e9..3f8677f 100644 > > --- a/lib/cli_opts.py > > +++ b/lib/cli_opts.py > > @@ -104,6 +104,7 @@ __all__ = [ > > "HELPER_SHUTDOWN_TIMEOUT_OPT", > > "HELPER_STARTUP_TIMEOUT_OPT", > > "HID_OS_OPT", > > + "HOT_RESIZE_OPT", > > "HOTPLUG_IF_POSSIBLE_OPT", > > "HOTPLUG_OPT", > > "HV_STATE_OPT", > > @@ -1513,6 +1514,11 @@ INCLUDEDEFAULTS_OPT = > > cli_option("--include-defaults", dest="include_defaults", > > default=False, action="store_true", > > help="Include default values") > > > > +HOT_RESIZE_OPT = cli_option("--hot-resize", dest="hot_resize", > > + action="store_true", default=False, > > + help="Make the extra space available for the" > > + "running instance without rebooting.") > > + > > HOTPLUG_OPT = cli_option("--hotplug", dest="hotplug", > > action="store_true", default=False, > > help="Hotplug supported devices (NICs and > > Disks)") > > diff --git a/lib/client/gnt_instance.py b/lib/client/gnt_instance.py > > index 224ee44..c2931a5 100644 > > --- a/lib/client/gnt_instance.py > > +++ b/lib/client/gnt_instance.py > > @@ -609,7 +609,8 @@ def GrowDisk(opts, args): > > disk=disk, amount=amount, > > wait_for_sync=opts.wait_for_sync, > > absolute=opts.absolute, > > - ignore_ipolicy=opts.ignore_ipolicy > > + ignore_ipolicy=opts.ignore_ipolicy, > > + hot_resize=opts.hot_resize > > ) > > SubmitOrSend(op, opts) > > return 0 > > @@ -1705,7 +1706,7 @@ commands = { > > [ArgInstance(min=1, max=1), ArgUnknown(min=1, max=1), > > ArgUnknown(min=1, max=1)], > > SUBMIT_OPTS + > > - [NWSYNC_OPT, DRY_RUN_OPT, PRIORITY_OPT, ABSOLUTE_OPT, > > IGNORE_IPOLICY_OPT], > > + [NWSYNC_OPT, DRY_RUN_OPT, PRIORITY_OPT, ABSOLUTE_OPT, > > IGNORE_IPOLICY_OPT, HOT_RESIZE_OPT], > > "<instance> <disk> <size>", "Grow an instance's disk"), > > "change-group": ( > > ChangeGroup, ARGS_ONE_INSTANCE, > > diff --git a/lib/cmdlib/instance_set_params.py > > b/lib/cmdlib/instance_set_params.py > > index 12d573a..f200df3 100644 > > --- a/lib/cmdlib/instance_set_params.py > > +++ b/lib/cmdlib/instance_set_params.py > > @@ -883,10 +883,45 @@ class LUInstanceSetParams(LogicalUnit): > > cluster_hvparams) > > return instance_info > > > > - def _CheckHotplug(self): > > + def _CheckDeviceHotplug(self, device_type, action): > > + """_CheckDeviceHotplug checks if an hotplug action is possible on the > > + specified device type. > > + > > + @type device_type: string > > + @param device_type: the device type to hotplug > > + @type action: string > > + @param action: the hotplug action to perform > > + > > + """ > > + if action in (constants.DDM_ADD, constants.DDM_ATTACH): > > + hotplug_action = constants.HOTPLUG_ACTION_ADD > > + elif action in (constants.DDM_REMOVE, constants.DDM_DETACH): > > + hotplug_action = constants.HOTPLUG_ACTION_REMOVE > > + else: > > + hotplug_action = constants.HOTPLUG_ACTION_MODIFY > > + > > + return self.rpc.call_hotplug_supported(self.instance.primary_node, > > + self.instance, > > + hotplug_action, > > + device_type) > > + > > + def _CheckDisksNicsHotplug(self): > > + """_CheckDisksNicsHotplug checks if hotplug is available for each > > disk and > > + NIC of the request. > > + If one check fail, hotplug will be globally unavailable. > > + > > + """ > > if self.op.hotplug or self.op.hotplug_if_possible: > > - result = self.rpc.call_hotplug_supported(self.instance.primary_node, > > - self.instance) > > + for op, _, _ in self.op.nics: > > + result = self._CheckDeviceHotplug(constants.HOTPLUG_TARGET_NIC, > > op) > > + if result.fail_msg: > > + break > > + > > + for op, _, _ in self.op.disks: > > + result = self._CheckDeviceHotplug(constants.HOTPLUG_TARGET_DISK, > > op) > > + if result.fail_msg: > > + break > > + > > if result.fail_msg: > > if self.op.hotplug: > > result.Raise("Hotplug is not possible: %s" % result.fail_msg, > > @@ -1148,7 +1183,7 @@ class LUInstanceSetParams(LogicalUnit): > > # dictionary with instance information after the modification > > ispec = {} > > > > - self._CheckHotplug() > > + self._CheckDisksNicsHotplug() > > > > self._PrepareNicCommunication() > > > > diff --git a/lib/cmdlib/instance_storage.py > > b/lib/cmdlib/instance_storage.py > > index 3f609d6..1a2a2a0 100644 > > --- a/lib/cmdlib/instance_storage.py > > +++ b/lib/cmdlib/instance_storage.py > > @@ -1710,6 +1710,7 @@ class LUInstanceGrowDisk(LogicalUnit): > > "DISK": self.op.disk, > > "AMOUNT": self.op.amount, > > "ABSOLUTE": self.op.absolute, > > + "HOT_RESIZE": self.op.hot_resize, > > } > > env.update(BuildInstanceHookEnvByObject(self, self.instance)) > > return env > > @@ -1764,6 +1765,8 @@ class LUInstanceGrowDisk(LogicalUnit): > > > > self._CheckIPolicy(self.target) > > > > + self._CheckDiskHotResize() > > + > > def _CheckDiskSpace(self, node_uuids, req_vgspace): > > template = self.disk.dev_type > > if (template not in constants.DTS_NO_FREE_SPACE_CHECK and > > @@ -1798,6 +1801,30 @@ class LUInstanceGrowDisk(LogicalUnit): > > else: > > raise errors.OpPrereqError(msg, errors.ECODE_INVAL) > > > > + def _CheckDiskHotResize(self): > > + if self.op.hot_resize: > > + result = self.rpc.call_hotplug_supported(self.instance.primary_node, > > + self.instance, > > + > > constants.HOTPLUG_ACTION_MODIFY, > > + > > constants.HOTPLUG_TARGET_DISK) > > + if result.fail_msg: > > + result.Raise("Hot resizing is not possible: %s" % result.fail_msg, > > + prereq=True, ecode=errors.ECODE_STATE) > > + else: > > + self.LogInfo("Modification will take place without hot resizing.") > > + > > + def _HotResizeDisk(self, device, size): > > + result = self.rpc.call_hotplug_device(self.instance.primary_node, > > + self.instance, > > constants.HOTPLUG_ACTION_MODIFY, > > + constants.HOTPLUG_TARGET_DISK, > > + (device, self.instance), > > + (size,), device.logical_id) > > + if result.fail_msg: > > + self.LogWarning("Could not hot resize disk: %s" % result.fail_msg) > > + self.LogInfo("Continuing execution..") > > + else: > > + self.LogInfo("Hot resize successful") > > + > > def Exec(self, feedback_fn): > > """Execute disk grow. > > > > @@ -1835,14 +1862,14 @@ class LUInstanceGrowDisk(LogicalUnit): > > result.Raise("Failed to retrieve disk size from node '%s'" % > > self.instance.primary_node) > > > > - (disk_dimensions, ) = result.payload > > + (old_disk_dimensions, ) = result.payload > > > > - if disk_dimensions is None: > > + if old_disk_dimensions is None: > > raise errors.OpExecError("Failed to retrieve disk size from > > primary" > > " node '%s'" % > > self.instance.primary_node) > > - (disk_size_in_bytes, _) = disk_dimensions > > + (old_disk_size_in_bytes, _) = old_disk_dimensions > > > > - old_disk_size = _DiskSizeInBytesToMebibytes(self, > > disk_size_in_bytes) > > + old_disk_size = _DiskSizeInBytesToMebibytes(self, > > old_disk_size_in_bytes) > > > > assert old_disk_size >= self.disk.size, \ > > ("Retrieved disk size too small (got %s, should be at least %s)" % > > @@ -1889,6 +1916,20 @@ class LUInstanceGrowDisk(LogicalUnit): > > WipeDisks(self, self.instance, > > disks=[(self.op.disk, self.disk, old_disk_size)]) > > > > + if self.op.hot_resize: > > + result = self.rpc.call_blockdev_getdimensions( > > + self.instance.primary_node, [([self.disk], > > self.instance)]) > > + result.Raise("Failed to retrieve disk size from node '%s'" % > > + self.instance.primary_node) > > + > > + (new_disk_dimensions, ) = result.payload > > + > > + if new_disk_dimensions is None: > > + raise errors.OpExecError("Failed to retrieve disk size from > > primary" > > + " node '%s'" % > > self.instance.primary_node) > > + (new_disk_size_in_bytes, _) = new_disk_dimensions > > + self._HotResizeDisk(self.disk, new_disk_size_in_bytes) > > + > > if self.op.wait_for_sync: > > disk_abort = not WaitForSync(self, self.instance, disks=[self.disk]) > > if disk_abort: > > diff --git a/lib/hypervisor/hv_base.py b/lib/hypervisor/hv_base.py > > index 8aaa062..ba669d0 100644 > > --- a/lib/hypervisor/hv_base.py > > +++ b/lib/hypervisor/hv_base.py > > @@ -773,11 +773,3 @@ class BaseHypervisor(object): > > > > """ > > raise errors.HotplugError("Hotplug is not supported.") > > - > > - def HotplugSupported(self, instance): > > - """Checks if hotplug is supported. > > - > > - By default is not. Currently only KVM hypervisor supports it. > > - > > - """ > > - raise errors.HotplugError("Hotplug is not supported by this > > hypervisor") > > diff --git a/lib/hypervisor/hv_kvm/__init__.py > > b/lib/hypervisor/hv_kvm/__init__.py > > index 340ddb1..b08de59 100644 > > --- a/lib/hypervisor/hv_kvm/__init__.py > > +++ b/lib/hypervisor/hv_kvm/__init__.py > > @@ -1830,36 +1830,18 @@ class KVMHypervisor(hv_base.BaseHypervisor): > > @raise errors.HypervisorError: in one of the previous cases > > > > """ > > - if dev_type == constants.HOTPLUG_TARGET_DISK: > > - if action == constants.HOTPLUG_ACTION_ADD: > > - self.qmp.CheckDiskHotAddSupport() > > - if dev_type == constants.HOTPLUG_TARGET_NIC: > > - if action == constants.HOTPLUG_ACTION_ADD: > > - self.qmp.CheckNicHotAddSupport() > > - > > - def HotplugSupported(self, instance): > > - """Checks if hotplug is generally supported. > > - > > - Hotplug is *not* supported in case of: > > - - qemu versions < 1.7 (where all qmp related commands are supported) > > - - for stopped instances > > - > > - @raise errors.HypervisorError: in one of the previous cases > > - > > - """ > > - try: > > - output = self._CallMonitorCommand(instance.name, > > self._INFO_VERSION_CMD) > > - except errors.HypervisorError: > > - raise errors.HotplugError("Instance is probably down") > > - > > - match = self._INFO_VERSION_RE.search(output.stdout) > > - if not match: > > - raise errors.HotplugError("Cannot parse qemu version via monitor") > > - > > - #TODO: delegate more fine-grained checks to VerifyHotplugSupport > > - v_major, v_min, _, _ = match.groups() > > - if (int(v_major), int(v_min)) < (1, 7): > > - raise errors.HotplugError("Hotplug not supported for qemu versions > > < 1.7") > > + if action == constants.HOTPLUG_ACTION_ADD: > > + if dev_type == constants.HOTPLUG_TARGET_DISK: > > + self.qmp.CheckDiskHotAddSupport() > > + elif dev_type == constants.HOTPLUG_TARGET_NIC: > > + self.qmp.CheckNicHotAddSupport() > > + elif action == constants.HOTPLUG_ACTION_MODIFY: > > + if dev_type == constants.HOTPLUG_TARGET_DISK: > > + # Currently, it's the only modification supported on disks > > + self.qmp.CheckDiskHotResizeSupport() > > + elif dev_type == constants.HOTPLUG_TARGET_NIC: > > + # It consists of removing the NIC and adding it again > > + self.qmp.CheckNicHotAddSupport() > > > > @_with_qmp > > def _VerifyHotplugCommand(self, _instance, > > @@ -1952,17 +1934,52 @@ class KVMHypervisor(hv_base.BaseHypervisor): > > > > return kvm_device.pci > > > > - def HotModDevice(self, instance, dev_type, device, _, seq): > > + def HotModDevice(self, instance, dev_type, device, extra, seq): > > """ Helper method for hot-mod device > > > > It gets device info from runtime file, generates the device name and > > invokes the device specific method. Currently only NICs support > > hot-mod > > > > """ > > + runtime = self._LoadKVMRuntime(instance) > > + entry = _GetExistingDeviceInfo(dev_type, device, runtime) > > + kvm_device = _RUNTIME_DEVICE[dev_type](entry) > > + kvm_devid = _GenerateDeviceKVMId(dev_type, kvm_device) > > + > > if dev_type == constants.HOTPLUG_TARGET_NIC: > > # putting it back in the same pci slot > > device.pci = self.HotDelDevice(instance, dev_type, device, _, seq) > > self.HotAddDevice(instance, dev_type, device, _, seq) > > + elif dev_type == constants.HOTPLUG_TARGET_DISK: > > + new_size = extra[0] > > + self.qmp.HotResizeDisk(kvm_devid, new_size) > > + self._VerifyHotResizeCommand(kvm_devid, new_size) > > + > > + @_with_qmp > > + def _VerifyHotResizeCommand(self, kvm_devid, size): > > + """Checks if a previous disk hot resize command was successful. > > + > > + The current block device size is retrieved and compared to the > > specified > > + size. > > + > > + @raise errors.HypervisorError: if result is not the expected one > > + > > + """ > > + for i in range(5): > > + found_size = self.qmp.GetBlockDeviceSize(kvm_devid) > > + logging.info("Verifying hotplug command (retry %s): %s", i, > > found_size) > > + if found_size == size: > > + break > > + time.sleep(1) > > + > > + if found_size != size: > > + msg = ("Device %s should have been resized to %s but its size is > > still " > > + "%s" % (kvm_devid, size, found_size)) > > + raise errors.HypervisorError(msg) > > + > > + logging.info("Device %s has been correctly hot resized to %s", > > + kvm_devid, > > + size) > > > > @classmethod > > def _ParseKVMVersion(cls, text): > > diff --git a/lib/hypervisor/hv_kvm/monitor.py > > b/lib/hypervisor/hv_kvm/monitor.py > > index f2b7d02..0db8318 100644 > > --- a/lib/hypervisor/hv_kvm/monitor.py > > +++ b/lib/hypervisor/hv_kvm/monitor.py > > @@ -579,6 +579,45 @@ class QmpConnection(MonitorSocket): > > #TODO: uncomment when drive_del gets implemented in upstream qemu > > # self.Execute("drive_del", {"id": devid}) > > > > + @_ensure_connection > > + def HotResizeDisk(self, devid, size): > > + """Hot resize a Disk to the specified size > > + > > + This command is available since QEMU 0.12. > > + > > + """ > > + arguments = { > > + "device": devid, > > + "size": size, > > + } > > + self.Execute("block_resize", arguments) > > + > > + def _GetBlockDevices(self): > > + """Get the block devices of a running instance. > > + > > + """ > > + self._check_connection() > > + devices = self.Execute("query-block") > > + return devices > > + > > + def _GetBlockDevice(self, devid): > > + """Get the block device JSON object of the specified id > > + > > + """ > > + for d in self._GetBlockDevices(): > > + if d["device"] == devid: > > + return d > > + > > + return False > > + > > + @_ensure_connection > > + def GetBlockDeviceSize(self, devid): > > + """Get the size of the specified block device > > + > > + """ > > + device = self._GetBlockDevice(devid) > > + return device["inserted"]["image"]["virtual-size"] > > + > > def _GetPCIDevices(self): > > """Get the devices of the first PCI bus of a running instance. > > > > @@ -617,6 +656,20 @@ class QmpConnection(MonitorSocket): > > return utils.GetFreeSlot(slots) > > > > @_ensure_connection > > + def CheckDiskHotResizeSupport(self): > > + """Check if disk hot resizing is possible > > + block_resize and query-block qmp commands need to be available. > > + > > + """ > > + def _raise(reason): > > + raise errors.HotplugError("Cannot hot resize disk: %s." % reason) > > + > > + if "block_resize" not in self.supported_commands: > > + _raise("block_resize qmp command is not supported") > > + if "query-block" not in self.supported_commands: > > + _raise("query-block qmp command is not supported") > > + > > + @_ensure_connection > > def CheckDiskHotAddSupport(self): > > """Check if disk hotplug is possible > > > > diff --git a/lib/rapi/client.py b/lib/rapi/client.py > > index 65f82ab..7439ef6 100644 > > --- a/lib/rapi/client.py > > +++ b/lib/rapi/client.py > > @@ -1012,7 +1012,7 @@ class GanetiRapiClient(object): # pylint: > > disable=R0904 > > (GANETI_RAPI_VERSION, instance)), query, > > body) > > > > def GrowInstanceDisk(self, instance, disk, amount, wait_for_sync=None, > > - reason=None): > > + reason=None, hot_resize=None): > > """Grows a disk of an instance. > > > > More details for parameters can be found in the RAPI documentation. > > @@ -1036,6 +1036,7 @@ class GanetiRapiClient(object): # pylint: > > disable=R0904 > > } > > > > _SetItemIf(body, wait_for_sync is not None, "wait_for_sync", > > wait_for_sync) > > + _SetItemIf(body, hot_resize is not None, "hot_resize", hot_resize) > > > > query = [] > > _AppendReason(query, reason) > > diff --git a/lib/rpc_defs.py b/lib/rpc_defs.py > > index dfdc5de..3c25a71 100644 > > --- a/lib/rpc_defs.py > > +++ b/lib/rpc_defs.py > > @@ -304,6 +304,8 @@ _INSTANCE_CALLS = [ > > ], None, None, "Hoplug a device to a running instance"), > > ("hotplug_supported", SINGLE, None, constants.RPC_TMO_NORMAL, [ > > ("instance", ED_INST_DICT, "Instance object"), > > + ("action", None, "Hotplug Action"), > > + ("dev_type", None, "Device type"), > > ], None, None, "Check if hotplug is supported"), > > ("instance_metadata_modify", SINGLE, None, constants.RPC_TMO_URGENT, [ > > ("instance", None, "Instance object"), > > diff --git a/lib/server/noded.py b/lib/server/noded.py > > index fe1be33..6910abb 100644 > > --- a/lib/server/noded.py > > +++ b/lib/server/noded.py > > @@ -666,8 +666,9 @@ class > > NodeRequestHandler(http.server.HttpServerHandler): > > """Checks if hotplug is supported. > > > > """ > > - instance = objects.Instance.FromDict(params[0]) > > - return backend.HotplugSupported(instance) > > + (idict, action, dev_type) = params > > + instance = objects.Instance.FromDict(idict) > > + return backend.VerifyHotplugSupport(instance, action, dev_type) > > > > @staticmethod > > def perspective_instance_metadata_modify(params): > > diff --git a/src/Ganeti/OpCodes.hs b/src/Ganeti/OpCodes.hs > > index 271b409..cf38673 100644 > > --- a/src/Ganeti/OpCodes.hs > > +++ b/src/Ganeti/OpCodes.hs > > @@ -710,6 +710,7 @@ $(genOpCode "OpCode" > > , pDiskChgAmount > > , pDiskChgAbsolute > > , pIgnoreIpolicy > > + , pHotResize > > ], > > "instance_name") > > , ("OpInstanceChangeGroup", > > diff --git a/src/Ganeti/OpParams.hs b/src/Ganeti/OpParams.hs > > index 63bf34b..5aba89c 100644 > > --- a/src/Ganeti/OpParams.hs > > +++ b/src/Ganeti/OpParams.hs > > @@ -111,6 +111,7 @@ module Ganeti.OpParams > > , pIgnoreIpolicy > > , pHotplug > > , pHotplugIfPossible > > + , pHotResize > > , pAllowRuntimeChgs > > , pInstDisks > > , pDiskTemplate > > @@ -589,6 +590,9 @@ pHotplug = defaultFalse "hotplug" > > pHotplugIfPossible :: Field > > pHotplugIfPossible = defaultFalse "hotplug_if_possible" > > > > +pHotResize :: Field > > +pHotResize = defaultFalse "hot_resize" > > + > > pInstances :: Field > > pInstances = > > withDoc "List of instances" . > > diff --git a/test/hs/Test/Ganeti/OpCodes.hs > > b/test/hs/Test/Ganeti/OpCodes.hs > > index dfcb483..b5a433c 100644 > > --- a/test/hs/Test/Ganeti/OpCodes.hs > > +++ b/test/hs/Test/Ganeti/OpCodes.hs > > @@ -427,6 +427,7 @@ instance Arbitrary OpCodes.OpCode where > > "OP_INSTANCE_GROW_DISK" -> > > OpCodes.OpInstanceGrowDisk <$> genFQDN <*> return Nothing <*> > > arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> > > arbitrary > > + <*> arbitrary > > "OP_INSTANCE_CHANGE_GROUP" -> > > OpCodes.OpInstanceChangeGroup <$> genFQDN <*> return Nothing <*> > > arbitrary <*> genMaybe genNameNE <*> > > -- > > 2.1.4 > > > > > > > -- > Yoann Laissus
signature.asc
Description: Digital signature