+def _ConvertNicDiskModifications(mods):
+ """Converts NIC/disk modifications from CLI to opcode.
+
+ When L{opcodes.OpInstanceSetParams} was changed to support adding/removing
+ disks at arbitrary indices, its parameter format changed. This function
+ converts legacy requests (e.g. "--net add" or "--disk add:size=4G") to the
+ newer format and adds support for new-style requests (e.g. "--new 4:add").
+
+ @type mods: list of tuples
+ @param mods: Modifications as given by command line parser
+ @rtype: list of tuples
+ @return: Modifications as understood by L{opcodes.OpInstanceSetParams}
+
+ """
+ result = []
+
+ for (idx, params) in mods:
+ if idx == constants.DDM_ADD:
+ # Add item as last item (legacy interface)
+ action = constants.DDM_ADD
+ idxno = -1
+ elif idx == constants.DDM_REMOVE:
+ # Remove last item (legacy interface)
+ action = constants.DDM_REMOVE
+ idxno = -1
+ else:
+ # Modifications and adding/removing at arbitrary indices
+ try:
+ idxno = int(idx)
+ except (TypeError, ValueError):
+ raise errors.OpPrereqError("Non-numeric index '%s'" % idx,
+ errors.ECODE_INVAL)
+
+ add = params.pop(constants.DDM_ADD, _MISSING)
+ remove = params.pop(constants.DDM_REMOVE, _MISSING)
+ modify = params.pop(constants.DDM_MODIFY, _MISSING)
+
+ if modify is _MISSING:
+ if not (add is _MISSING or remove is _MISSING):
+ raise errors.OpPrereqError("Cannot add and remove at the same time",
+ errors.ECODE_INVAL)
+ elif add is not _MISSING:
+ action = constants.DDM_ADD
+ elif remove is not _MISSING:
+ action = constants.DDM_REMOVE
+ else:
+ action = constants.DDM_MODIFY
+
+ else:
+ if add is _MISSING and remove is _MISSING:
+ action = constants.DDM_MODIFY
+ else:
+ raise errors.OpPrereqError("Cannot modify and add/remove at the"
+ " same time", errors.ECODE_INVAL)
+
+ assert not (constants.DDMS_VALUES_WITH_MODIFY & set(params.keys()))
+
+ if action == constants.DDM_REMOVE and params:
+ raise errors.OpPrereqError("Not accepting parameters on removal",
+ errors.ECODE_INVAL)
+
+ result.append((action, idxno, params))
+
+ return result
+
+
+def _ParseDiskSizes(mods):
+ """Parses disk sizes in parameters.
+
+ """
+ for (action, _, params) in mods:
+ if params and constants.IDISK_SIZE in params:
+ params[constants.IDISK_SIZE] = \
+ utils.ParseUnit(params[constants.IDISK_SIZE])
+ elif action == constants.DDM_ADD:
+ raise errors.OpPrereqError("Missing required parameter 'size'",
+ errors.ECODE_INVAL)
+
+ return mods
+
+