from ganeti import compat
from ganeti import netutils
from ganeti import qlang
+from ganeti import objects
from optparse import (OptionParser, TitledHelpFormatter,
Option, OptionValueError)
__all__ = [
# Command line options
+ "ABSOLUTE_OPT",
"ADD_UIDS_OPT",
"ALLOCATABLE_OPT",
"ALLOC_POLICY_OPT",
"INSTANCE_POLICY_OPTS",
# Generic functions for CLI programs
"ConfirmOperation",
+ "CreateIPolicyFromOpts",
"GenericMain",
"GenericInstanceCreate",
"GenericList",
_CHOOSE_BATCH = 25
+# constants used to create InstancePolicy dictionary
+TISPECS_GROUP_TYPES = {
+ constants.ISPECS_MIN: constants.VTYPE_INT,
+ constants.ISPECS_MAX: constants.VTYPE_INT,
+ }
+
+TISPECS_CLUSTER_TYPES = {
+ constants.ISPECS_MIN: constants.VTYPE_INT,
+ constants.ISPECS_MAX: constants.VTYPE_INT,
+ constants.ISPECS_STD: constants.VTYPE_INT,
+ }
+
+
class _Argument:
def __init__(self, min=0, max=None): # pylint: disable=W0622
self.min = min
return utils.UnescapeAndSplit(value)
+def check_maybefloat(option, opt, value): # pylint: disable=W0613
+ """Custom parser for float numbers which might be also defaults.
+
+ """
+ value = value.lower()
+
+ if value == constants.VALUE_DEFAULT:
+ return value
+ else:
+ return float(value)
+
+
# completion_suggestion is normally a list. Using numeric values not evaluating
# to False for dynamic completion.
(OPT_COMPL_MANY_NODES,
"unit",
"bool",
"list",
+ "maybefloat",
)
TYPE_CHECKER = Option.TYPE_CHECKER.copy()
TYPE_CHECKER["identkeyval"] = check_ident_key_val
TYPE_CHECKER["unit"] = check_unit
TYPE_CHECKER["bool"] = check_bool
TYPE_CHECKER["list"] = check_list
+ TYPE_CHECKER["maybefloat"] = check_maybefloat
# optparse.py sets make_option, so we do it for our own option class, too
DRY_RUN_OPT = cli_option("--dry-run", default=False,
action="store_true",
help=("Do not execute the operation, just run the"
- " check steps and verify it it could be"
+ " check steps and verify if it could be"
" executed"))
VERBOSE_OPT = cli_option("-v", "--verbose", default=False,
SPECS_MEM_SIZE_OPT = cli_option("--specs-mem-size", dest="ispecs_mem_size",
type="keyval", default={},
- help="Memory count specs: min, max, std"
- " (in MB)")
+ help="Memory size specs: list of key=value,"
+ " where key is one of min, max, std"
+ " (in MB or using a unit)")
SPECS_CPU_COUNT_OPT = cli_option("--specs-cpu-count", dest="ispecs_cpu_count",
type="keyval", default={},
- help="CPU count specs: min, max, std")
+ help="CPU count specs: list of key=value,"
+ " where key is one of min, max, std")
SPECS_DISK_COUNT_OPT = cli_option("--specs-disk-count",
dest="ispecs_disk_count",
type="keyval", default={},
- help="Disk count specs: min, max, std")
+ help="Disk count specs: list of key=value,"
+ " where key is one of min, max, std")
SPECS_DISK_SIZE_OPT = cli_option("--specs-disk-size", dest="ispecs_disk_size",
type="keyval", default={},
- help="Disk size specs: min, max, std (in MB)")
+ help="Disk size specs: list of key=value,"
+ " where key is one of min, max, std"
+ " (in MB or using a unit)")
SPECS_NIC_COUNT_OPT = cli_option("--specs-nic-count", dest="ispecs_nic_count",
type="keyval", default={},
- help="NIC count specs: min, max, std")
+ help="NIC count specs: list of key=value,"
+ " where key is one of min, max, std")
IPOLICY_DISK_TEMPLATES = cli_option("--ipolicy-disk-templates",
dest="ipolicy_disk_templates",
IPOLICY_VCPU_RATIO = cli_option("--ipolicy-vcpu-ratio",
dest="ipolicy_vcpu_ratio",
- type="float", default=None,
+ type="maybefloat", default=None,
help="The maximum allowed vcpu-to-cpu ratio")
+IPOLICY_SPINDLE_RATIO = cli_option("--ipolicy-spindle-ratio",
+ dest="ipolicy_spindle_ratio",
+ type="maybefloat", default=None,
+ help=("The maximum allowed instances to"
+ " spindle ratio"))
+
HYPERVISOR_OPT = cli_option("-H", "--hypervisor-parameters", dest="hypervisor",
help="Hypervisor and hypervisor options, in the"
" format hypervisor:option=value,option=value,...",
DISK_STATE_OPT = cli_option("--disk-state", default=[], dest="disk_state",
action="append",
- help=("Specify disk state information in the format"
- " storage_type/identifier:option=value,..."),
+ help=("Specify disk state information in the"
+ " format"
+ " storage_type/identifier:option=value,...;"
+ " note this is unused for now"),
type="identkeyval")
HV_STATE_OPT = cli_option("--hypervisor-state", default=[], dest="hv_state",
action="append",
help=("Specify hypervisor state information in the"
- " format hypervisor:option=value,..."),
+ " format hypervisor:option=value,...;"
+ " note this is unused for now"),
type="identkeyval")
IGNORE_IPOLICY_OPT = cli_option("--ignore-ipolicy", dest="ignore_ipolicy",
" ballooning it up or down to the new value",
default=None, type="unit", metavar="<size>")
+ABSOLUTE_OPT = cli_option("--absolute", dest="absolute",
+ action="store_true", default=False,
+ help="Marks the grow as absolute instead of the"
+ " (default) relative mode")
+
#: Options provided by all commands
COMMON_OPTS = [DEBUG_OPT]
SPECS_NIC_COUNT_OPT,
IPOLICY_DISK_TEMPLATES,
IPOLICY_VCPU_RATIO,
+ IPOLICY_SPINDLE_RATIO,
]
"""
indent = " " * level
+
for key in sorted(actual):
- val = param_dict.get(key, "default (%s)" % actual[key])
- buf.write("%s- %s: %s\n" % (indent, key, val))
+ data = actual[key]
+ buf.write("%s- %s:" % (indent, key))
+
+ if isinstance(data, dict) and data:
+ buf.write("\n")
+ FormatParameterDict(buf, param_dict.get(key, {}), data,
+ level=level + 1)
+ else:
+ val = param_dict.get(key, "default (%s)" % data)
+ buf.write(" %s\n" % val)
def ConfirmOperation(names, list_type, text, extra=""):
choices.pop(1)
choice = AskUser(msg + affected, choices)
return choice
+
+
+def _MaybeParseUnit(elements):
+ """Parses and returns an array of potential values with units.
+
+ """
+ parsed = {}
+ for k, v in elements.items():
+ if v == constants.VALUE_DEFAULT:
+ parsed[k] = v
+ else:
+ parsed[k] = utils.ParseUnit(v)
+ return parsed
+
+
+def CreateIPolicyFromOpts(ispecs_mem_size=None,
+ ispecs_cpu_count=None,
+ ispecs_disk_count=None,
+ ispecs_disk_size=None,
+ ispecs_nic_count=None,
+ ipolicy_disk_templates=None,
+ ipolicy_vcpu_ratio=None,
+ ipolicy_spindle_ratio=None,
+ group_ipolicy=False,
+ allowed_values=None,
+ fill_all=False):
+ """Creation of instance policy based on command line options.
+
+ @param fill_all: whether for cluster policies we should ensure that
+ all values are filled
+
+
+ """
+ try:
+ if ispecs_mem_size:
+ ispecs_mem_size = _MaybeParseUnit(ispecs_mem_size)
+ if ispecs_disk_size:
+ ispecs_disk_size = _MaybeParseUnit(ispecs_disk_size)
+ except (TypeError, ValueError, errors.UnitParseError), err:
+ raise errors.OpPrereqError("Invalid disk (%s) or memory (%s) size"
+ " in policy: %s" %
+ (ispecs_disk_size, ispecs_mem_size, err),
+ errors.ECODE_INVAL)
+
+ # prepare ipolicy dict
+ ipolicy_transposed = {
+ constants.ISPEC_MEM_SIZE: ispecs_mem_size,
+ constants.ISPEC_CPU_COUNT: ispecs_cpu_count,
+ constants.ISPEC_DISK_COUNT: ispecs_disk_count,
+ constants.ISPEC_DISK_SIZE: ispecs_disk_size,
+ constants.ISPEC_NIC_COUNT: ispecs_nic_count,
+ }
+
+ # first, check that the values given are correct
+ if group_ipolicy:
+ forced_type = TISPECS_GROUP_TYPES
+ else:
+ forced_type = TISPECS_CLUSTER_TYPES
+
+ for specs in ipolicy_transposed.values():
+ utils.ForceDictType(specs, forced_type, allowed_values=allowed_values)
+
+ # then transpose
+ ipolicy_out = objects.MakeEmptyIPolicy()
+ for name, specs in ipolicy_transposed.iteritems():
+ assert name in constants.ISPECS_PARAMETERS
+ for key, val in specs.items(): # {min: .. ,max: .., std: ..}
+ ipolicy_out[key][name] = val
+
+ # no filldict for non-dicts
+ if not group_ipolicy and fill_all:
+ if ipolicy_disk_templates is None:
+ ipolicy_disk_templates = constants.DISK_TEMPLATES
+ if ipolicy_vcpu_ratio is None:
+ ipolicy_vcpu_ratio = \
+ constants.IPOLICY_DEFAULTS[constants.IPOLICY_VCPU_RATIO]
+ if ipolicy_spindle_ratio is None:
+ ipolicy_spindle_ratio = \
+ constants.IPOLICY_DEFAULTS[constants.IPOLICY_SPINDLE_RATIO]
+ if ipolicy_disk_templates is not None:
+ ipolicy_out[constants.IPOLICY_DTS] = list(ipolicy_disk_templates)
+ if ipolicy_vcpu_ratio is not None:
+ ipolicy_out[constants.IPOLICY_VCPU_RATIO] = ipolicy_vcpu_ratio
+ if ipolicy_spindle_ratio is not None:
+ ipolicy_out[constants.IPOLICY_SPINDLE_RATIO] = ipolicy_spindle_ratio
+
+ assert not (frozenset(ipolicy_out.keys()) - constants.IPOLICY_ALL_KEYS)
+
+ return ipolicy_out