#
#
-# Copyright (C) 2006, 2007, 2010, 2011, 2012 Google Inc.
+# Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# W0614: Unused import %s from wildcard import (since we need cli)
# C0103: Invalid name gnt-cluster
+from cStringIO import StringIO
import os.path
import time
import OpenSSL
_EPO_REACHABLE_TIMEOUT = 15 * 60 # 15 minutes
+def _CheckNoLvmStorageOptDeprecated(opts):
+ """Checks if the legacy option '--no-lvm-storage' is used.
+
+ """
+ if not opts.lvm_storage:
+ ToStderr("The option --no-lvm-storage is no longer supported. If you want"
+ " to disable lvm-based storage cluster-wide, use the option"
+ " --enabled-disk-templates to disable all of these lvm-base disk "
+ " templates: %s" %
+ utils.CommaJoin(utils.GetLvmDiskTemplates()))
+ return 1
+
+
@UsesRPC
def InitCluster(opts, args):
"""Initialize the cluster.
@return: the desired exit code
"""
- if not opts.lvm_storage and opts.vg_name:
- ToStderr("Options --no-lvm-storage and --vg-name conflict.")
+ if _CheckNoLvmStorageOptDeprecated(opts):
return 1
-
- vg_name = opts.vg_name
- if opts.lvm_storage and not opts.vg_name:
- vg_name = constants.DEFAULT_VG
+ enabled_disk_templates = opts.enabled_disk_templates
+ if enabled_disk_templates:
+ enabled_disk_templates = enabled_disk_templates.split(",")
+ else:
+ enabled_disk_templates = constants.DEFAULT_ENABLED_DISK_TEMPLATES
+
+ vg_name = None
+ if opts.vg_name is not None:
+ vg_name = opts.vg_name
+ if vg_name:
+ if not utils.IsLvmEnabled(enabled_disk_templates):
+ ToStdout("You specified a volume group with --vg-name, but you did not"
+ " enable any disk template that uses lvm.")
+ else:
+ if utils.IsLvmEnabled(enabled_disk_templates):
+ ToStderr("LVM disk templates are enabled, but vg name not set.")
+ return 1
+ else:
+ if utils.IsLvmEnabled(enabled_disk_templates):
+ vg_name = constants.DEFAULT_VG
if not opts.drbd_storage and opts.drbd_helper:
ToStderr("Options --no-drbd-storage and --drbd-usermode-helper conflict.")
utils.ForceDictType(diskparams[templ], constants.DISK_DT_TYPES)
# prepare ipolicy dict
- ipolicy_raw = CreateIPolicyFromOpts(
+ ipolicy = CreateIPolicyFromOpts(
ispecs_mem_size=opts.ispecs_mem_size,
ispecs_cpu_count=opts.ispecs_cpu_count,
ispecs_disk_count=opts.ispecs_disk_count,
ispecs_disk_size=opts.ispecs_disk_size,
ispecs_nic_count=opts.ispecs_nic_count,
+ minmax_ispecs=opts.ipolicy_bounds_specs,
+ std_ispecs=opts.ipolicy_std_specs,
ipolicy_disk_templates=opts.ipolicy_disk_templates,
ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio,
ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio,
fill_all=True)
- ipolicy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, ipolicy_raw)
if opts.candidate_pool_size is None:
opts.candidate_pool_size = constants.MASTER_POOL_SIZE_DEFAULT
use_external_mip_script=external_ip_setup_script,
hv_state=hv_state,
disk_state=disk_state,
+ enabled_disk_templates=enabled_disk_templates,
)
op = opcodes.OpClusterPostInit()
SubmitOpCode(op, opts=opts)
return 1
op = opcodes.OpClusterDestroy()
- master = SubmitOpCode(op, opts=opts)
+ master_uuid = SubmitOpCode(op, opts=opts)
# if we reached this, the opcode didn't fail; we can proceed to
# shutdown all the daemons
- bootstrap.FinalizeClusterDestroy(master)
+ bootstrap.FinalizeClusterDestroy(master_uuid)
return 0
ToStdout("Configuration format: %s", result["config_version"])
ToStdout("OS api version: %s", result["os_api_version"])
ToStdout("Export interface: %s", result["export_version"])
+ ToStdout("VCS version: %s", result["vcs_version"])
return 0
return 0
-def _PrintGroupedParams(paramsdict, level=1, roman=False):
- """Print Grouped parameters (be, nic, disk) by group.
+def _FormatGroupedParams(paramsdict, roman=False):
+ """Format Grouped parameters (be, nic, disk) by group.
@type paramsdict: dict of dicts
@param paramsdict: {group: {param: value, ...}, ...}
- @type level: int
- @param level: Level of indention
+ @rtype: dict of dicts
+ @return: copy of the input dictionaries with strings as values
"""
- indent = " " * level
- for item, val in sorted(paramsdict.items()):
+ ret = {}
+ for (item, val) in paramsdict.items():
if isinstance(val, dict):
- ToStdout("%s- %s:", indent, item)
- _PrintGroupedParams(val, level=level + 1, roman=roman)
+ ret[item] = _FormatGroupedParams(val, roman=roman)
elif roman and isinstance(val, int):
- ToStdout("%s %s: %s", indent, item, compat.TryToRoman(val))
+ ret[item] = compat.TryToRoman(val)
else:
- ToStdout("%s %s: %s", indent, item, val)
+ ret[item] = str(val)
+ return ret
def ShowClusterConfig(opts, args):
cl = GetClient(query=True)
result = cl.QueryClusterInfo()
- ToStdout("Cluster name: %s", result["name"])
- ToStdout("Cluster UUID: %s", result["uuid"])
-
- ToStdout("Creation time: %s", utils.FormatTime(result["ctime"]))
- ToStdout("Modification time: %s", utils.FormatTime(result["mtime"]))
-
- ToStdout("Master node: %s", result["master"])
-
- ToStdout("Architecture (this node): %s (%s)",
- result["architecture"][0], result["architecture"][1])
-
if result["tags"]:
tags = utils.CommaJoin(utils.NiceSort(result["tags"]))
else:
tags = "(none)"
+ if result["reserved_lvs"]:
+ reserved_lvs = utils.CommaJoin(result["reserved_lvs"])
+ else:
+ reserved_lvs = "(none)"
- ToStdout("Tags: %s", tags)
+ enabled_hv = result["enabled_hypervisors"]
+ hvparams = dict((k, v) for k, v in result["hvparams"].iteritems()
+ if k in enabled_hv)
- ToStdout("Default hypervisor: %s", result["default_hypervisor"])
- ToStdout("Enabled hypervisors: %s",
- utils.CommaJoin(result["enabled_hypervisors"]))
+ info = [
+ ("Cluster name", result["name"]),
+ ("Cluster UUID", result["uuid"]),
- ToStdout("Hypervisor parameters:")
- _PrintGroupedParams(result["hvparams"])
+ ("Creation time", utils.FormatTime(result["ctime"])),
+ ("Modification time", utils.FormatTime(result["mtime"])),
- ToStdout("OS-specific hypervisor parameters:")
- _PrintGroupedParams(result["os_hvp"])
+ ("Master node", result["master"]),
- ToStdout("OS parameters:")
- _PrintGroupedParams(result["osparams"])
+ ("Architecture (this node)",
+ "%s (%s)" % (result["architecture"][0], result["architecture"][1])),
- ToStdout("Hidden OSes: %s", utils.CommaJoin(result["hidden_os"]))
- ToStdout("Blacklisted OSes: %s", utils.CommaJoin(result["blacklisted_os"]))
+ ("Tags", tags),
- ToStdout("Cluster parameters:")
- ToStdout(" - candidate pool size: %s",
- compat.TryToRoman(result["candidate_pool_size"],
- convert=opts.roman_integers))
- ToStdout(" - master netdev: %s", result["master_netdev"])
- ToStdout(" - master netmask: %s", result["master_netmask"])
- ToStdout(" - use external master IP address setup script: %s",
- result["use_external_mip_script"])
- ToStdout(" - lvm volume group: %s", result["volume_group_name"])
- if result["reserved_lvs"]:
- reserved_lvs = utils.CommaJoin(result["reserved_lvs"])
- else:
- reserved_lvs = "(none)"
- ToStdout(" - lvm reserved volumes: %s", reserved_lvs)
- ToStdout(" - drbd usermode helper: %s", result["drbd_usermode_helper"])
- ToStdout(" - file storage path: %s", result["file_storage_dir"])
- ToStdout(" - shared file storage path: %s",
- result["shared_file_storage_dir"])
- ToStdout(" - maintenance of node health: %s",
- result["maintain_node_health"])
- ToStdout(" - uid pool: %s", uidpool.FormatUidPool(result["uid_pool"]))
- ToStdout(" - default instance allocator: %s", result["default_iallocator"])
- ToStdout(" - primary ip version: %d", result["primary_ip_version"])
- ToStdout(" - preallocation wipe disks: %s", result["prealloc_wipe_disks"])
- ToStdout(" - OS search path: %s", utils.CommaJoin(pathutils.OS_SEARCH_PATH))
- ToStdout(" - ExtStorage Providers search path: %s",
- utils.CommaJoin(pathutils.ES_SEARCH_PATH))
- ToStdout(" - enabled storage types: %s",
- utils.CommaJoin(result["enabled_storage_types"]))
-
- ToStdout("Default node parameters:")
- _PrintGroupedParams(result["ndparams"], roman=opts.roman_integers)
-
- ToStdout("Default instance parameters:")
- _PrintGroupedParams(result["beparams"], roman=opts.roman_integers)
-
- ToStdout("Default nic parameters:")
- _PrintGroupedParams(result["nicparams"], roman=opts.roman_integers)
-
- ToStdout("Default disk parameters:")
- _PrintGroupedParams(result["diskparams"], roman=opts.roman_integers)
-
- ToStdout("Instance policy - limits for instances:")
- for key in constants.IPOLICY_ISPECS:
- ToStdout(" - %s", key)
- _PrintGroupedParams(result["ipolicy"][key], roman=opts.roman_integers)
- ToStdout(" - enabled disk templates: %s",
- utils.CommaJoin(result["ipolicy"][constants.IPOLICY_DTS]))
- for key in constants.IPOLICY_PARAMETERS:
- ToStdout(" - %s: %s", key, result["ipolicy"][key])
+ ("Default hypervisor", result["default_hypervisor"]),
+ ("Enabled hypervisors", utils.CommaJoin(enabled_hv)),
+
+ ("Hypervisor parameters", _FormatGroupedParams(hvparams)),
+
+ ("OS-specific hypervisor parameters",
+ _FormatGroupedParams(result["os_hvp"])),
+
+ ("OS parameters", _FormatGroupedParams(result["osparams"])),
+ ("Hidden OSes", utils.CommaJoin(result["hidden_os"])),
+ ("Blacklisted OSes", utils.CommaJoin(result["blacklisted_os"])),
+
+ ("Cluster parameters", [
+ ("candidate pool size",
+ compat.TryToRoman(result["candidate_pool_size"],
+ convert=opts.roman_integers)),
+ ("master netdev", result["master_netdev"]),
+ ("master netmask", result["master_netmask"]),
+ ("use external master IP address setup script",
+ result["use_external_mip_script"]),
+ ("lvm volume group", result["volume_group_name"]),
+ ("lvm reserved volumes", reserved_lvs),
+ ("drbd usermode helper", result["drbd_usermode_helper"]),
+ ("file storage path", result["file_storage_dir"]),
+ ("shared file storage path", result["shared_file_storage_dir"]),
+ ("maintenance of node health", result["maintain_node_health"]),
+ ("uid pool", uidpool.FormatUidPool(result["uid_pool"])),
+ ("default instance allocator", result["default_iallocator"]),
+ ("primary ip version", result["primary_ip_version"]),
+ ("preallocation wipe disks", result["prealloc_wipe_disks"]),
+ ("OS search path", utils.CommaJoin(pathutils.OS_SEARCH_PATH)),
+ ("ExtStorage Providers search path",
+ utils.CommaJoin(pathutils.ES_SEARCH_PATH)),
+ ("enabled disk templates",
+ utils.CommaJoin(result["enabled_disk_templates"])),
+ ]),
+
+ ("Default node parameters",
+ _FormatGroupedParams(result["ndparams"], roman=opts.roman_integers)),
+
+ ("Default instance parameters",
+ _FormatGroupedParams(result["beparams"], roman=opts.roman_integers)),
+
+ ("Default nic parameters",
+ _FormatGroupedParams(result["nicparams"], roman=opts.roman_integers)),
+
+ ("Default disk parameters",
+ _FormatGroupedParams(result["diskparams"], roman=opts.roman_integers)),
+
+ ("Instance policy - limits for instances",
+ FormatPolicyInfo(result["ipolicy"], None, True)),
+ ]
+
+ PrintGenericInfo(info)
return 0
"""
filename = args[0]
+ filename = os.path.abspath(filename)
+
if not os.path.exists(filename):
raise errors.OpPrereqError("No such filename '%s'" % filename,
errors.ECODE_INVAL)
@return: the desired exit code
"""
- if not (not opts.lvm_storage or opts.vg_name or
- not opts.drbd_storage or opts.drbd_helper or
+ if not (opts.vg_name is not None or opts.drbd_helper or
opts.enabled_hypervisors or opts.hvparams or
opts.beparams or opts.nicparams or
opts.ndparams or opts.diskparams or
opts.use_external_mip_script is not None or
opts.prealloc_wipe_disks is not None or
opts.hv_state or
- opts.enabled_storage_types or
+ opts.enabled_disk_templates or
opts.disk_state or
- opts.ispecs_mem_size or
- opts.ispecs_cpu_count or
- opts.ispecs_disk_count or
- opts.ispecs_disk_size or
- opts.ispecs_nic_count or
+ opts.ipolicy_bounds_specs is not None or
+ opts.ipolicy_std_specs is not None or
opts.ipolicy_disk_templates is not None or
opts.ipolicy_vcpu_ratio is not None or
- opts.ipolicy_spindle_ratio is not None):
+ opts.ipolicy_spindle_ratio is not None or
+ opts.modify_etc_hosts is not None or
+ opts.file_storage_dir is not None):
ToStderr("Please give at least one of the parameters.")
return 1
- vg_name = opts.vg_name
- if not opts.lvm_storage and opts.vg_name:
- ToStderr("Options --no-lvm-storage and --vg-name conflict.")
+ if _CheckNoLvmStorageOptDeprecated(opts):
return 1
- if not opts.lvm_storage:
- vg_name = ""
+ enabled_disk_templates = None
+ if opts.enabled_disk_templates:
+ enabled_disk_templates = opts.enabled_disk_templates.split(",")
+
+ # consistency between vg name and enabled disk templates
+ vg_name = None
+ if opts.vg_name is not None:
+ vg_name = opts.vg_name
+ if enabled_disk_templates:
+ if vg_name and not utils.IsLvmEnabled(enabled_disk_templates):
+ ToStdout("You specified a volume group with --vg-name, but you did not"
+ " enable any of the following lvm-based disk templates: %s" %
+ utils.CommaJoin(utils.GetLvmDiskTemplates()))
drbd_helper = opts.drbd_helper
if not opts.drbd_storage and opts.drbd_helper:
if hvlist is not None:
hvlist = hvlist.split(",")
- enabled_storage_types = opts.enabled_storage_types
- if enabled_storage_types is not None:
- enabled_storage_types = enabled_storage_types.split(",")
-
# a list of (name, dict) we can pass directly to dict() (or [])
hvparams = dict(opts.hvparams)
for hv_params in hvparams.values():
utils.ForceDictType(ndparams, constants.NDS_PARAMETER_TYPES)
ipolicy = CreateIPolicyFromOpts(
- ispecs_mem_size=opts.ispecs_mem_size,
- ispecs_cpu_count=opts.ispecs_cpu_count,
- ispecs_disk_count=opts.ispecs_disk_count,
- ispecs_disk_size=opts.ispecs_disk_size,
- ispecs_nic_count=opts.ispecs_nic_count,
+ minmax_ispecs=opts.ipolicy_bounds_specs,
+ std_ispecs=opts.ipolicy_std_specs,
ipolicy_disk_templates=opts.ipolicy_disk_templates,
ipolicy_vcpu_ratio=opts.ipolicy_vcpu_ratio,
ipolicy_spindle_ratio=opts.ipolicy_spindle_ratio,
ipolicy=ipolicy,
candidate_pool_size=opts.candidate_pool_size,
maintain_node_health=mnh,
+ modify_etc_hosts=opts.modify_etc_hosts,
uid_pool=uid_pool,
add_uids=add_uids,
remove_uids=remove_uids,
use_external_mip_script=ext_ip_script,
hv_state=hv_state,
disk_state=disk_state,
- enabled_storage_types=enabled_storage_types,
+ enabled_disk_templates=enabled_disk_templates,
+ force=opts.force,
+ file_storage_dir=opts.file_storage_dir,
)
SubmitOrSend(op, opts)
return 0
return _off_fn(opts, node_list, inst_map)
+def _GetCreateCommand(info):
+ buf = StringIO()
+ buf.write("gnt-cluster init")
+ PrintIPolicyCommand(buf, info["ipolicy"], False)
+ buf.write(" ")
+ buf.write(info["name"])
+ return buf.getvalue()
+
+
+def ShowCreateCommand(opts, args):
+ """Shows the command that can be used to re-create the cluster.
+
+ Currently it works only for ipolicy specs.
+
+ """
+ cl = GetClient(query=True)
+ result = cl.QueryClusterInfo()
+ ToStdout(_GetCreateCommand(result))
+
+
commands = {
"init": (
InitCluster, [ArgHost(min=1, max=1)],
MAINTAIN_NODE_HEALTH_OPT, UIDPOOL_OPT, DRBD_HELPER_OPT, NODRBD_STORAGE_OPT,
DEFAULT_IALLOCATOR_OPT, PRIMARY_IP_VERSION_OPT, PREALLOC_WIPE_DISKS_OPT,
NODE_PARAMS_OPT, GLOBAL_SHARED_FILEDIR_OPT, USE_EXTERNAL_MIP_SCRIPT,
- DISK_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT] + INSTANCE_POLICY_OPTS,
+ DISK_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT, ENABLED_DISK_TEMPLATES_OPT,
+ IPOLICY_STD_SPECS_OPT] + INSTANCE_POLICY_OPTS + SPLIT_ISPECS_OPTS,
"[opts...] <cluster_name>", "Initialises a new cluster configuration"),
"destroy": (
DestroyCluster, ARGS_NONE, [YES_DOIT_OPT],
"<new_name>",
"Renames the cluster"),
"redist-conf": (
- RedistributeConfig, ARGS_NONE, [SUBMIT_OPT, DRY_RUN_OPT, PRIORITY_OPT],
+ RedistributeConfig, ARGS_NONE, SUBMIT_OPTS + [DRY_RUN_OPT, PRIORITY_OPT],
"", "Forces a push of the configuration file and ssconf files"
" to the nodes in the cluster"),
"verify": (
"list-tags": (
ListTags, ARGS_NONE, [], "", "List the tags of the cluster"),
"add-tags": (
- AddTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
+ AddTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
"tag...", "Add tags to the cluster"),
"remove-tags": (
- RemoveTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT, SUBMIT_OPT],
+ RemoveTags, [ArgUnknown()], [TAG_SRC_OPT, PRIORITY_OPT] + SUBMIT_OPTS,
"tag...", "Remove tags from the cluster"),
"search-tags": (
SearchTags, [ArgUnknown(min=1, max=1)], [PRIORITY_OPT], "",
"{pause <timespec>|continue|info}", "Change watcher properties"),
"modify": (
SetClusterParams, ARGS_NONE,
- [BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, HVLIST_OPT, MASTER_NETDEV_OPT,
+ [FORCE_OPT,
+ BACKEND_OPT, CP_SIZE_OPT, ENABLED_HV_OPT, HVLIST_OPT, MASTER_NETDEV_OPT,
MASTER_NETMASK_OPT, NIC_PARAMS_OPT, NOLVM_STORAGE_OPT, VG_NAME_OPT,
MAINTAIN_NODE_HEALTH_OPT, UIDPOOL_OPT, ADD_UIDS_OPT, REMOVE_UIDS_OPT,
DRBD_HELPER_OPT, NODRBD_STORAGE_OPT, DEFAULT_IALLOCATOR_OPT,
RESERVED_LVS_OPT, DRY_RUN_OPT, PRIORITY_OPT, PREALLOC_WIPE_DISKS_OPT,
NODE_PARAMS_OPT, USE_EXTERNAL_MIP_SCRIPT, DISK_PARAMS_OPT, HV_STATE_OPT,
- DISK_STATE_OPT, SUBMIT_OPT, ENABLED_STORAGE_TYPES_OPT] +
- INSTANCE_POLICY_OPTS,
+ DISK_STATE_OPT] + SUBMIT_OPTS +
+ [ENABLED_DISK_TEMPLATES_OPT, IPOLICY_STD_SPECS_OPT, MODIFY_ETCHOSTS_OPT] +
+ INSTANCE_POLICY_OPTS + [GLOBAL_FILEDIR_OPT],
"[opts...]",
"Alters the parameters of the cluster"),
"renew-crypto": (
"deactivate-master-ip": (
DeactivateMasterIp, ARGS_NONE, [CONFIRM_OPT], "",
"Deactivates the master IP"),
+ "show-ispecs-cmd": (
+ ShowCreateCommand, ARGS_NONE, [], "",
+ "Show the command line to re-create the cluster"),
}