From e7323b5e55c623198ecfdb74acaf77a7f0d1ff11 Mon Sep 17 00:00:00 2001 From: Manuel Franceschini <livewire@google.com> Date: Mon, 2 Aug 2010 19:26:07 +0200 Subject: [PATCH] Support IPv6 cluster init Signed-off-by: Manuel Franceschini <livewire@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- lib/backend.py | 23 ++++++++++++++++++----- lib/cli.py | 8 ++++++++ lib/cmdlib.py | 9 ++++++++- lib/daemon.py | 13 ++++++++++++- scripts/gnt-cluster | 11 +++++++++-- 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/lib/backend.py b/lib/backend.py index b8725912e..a4105dbba 100644 --- a/lib/backend.py +++ b/lib/backend.py @@ -287,7 +287,12 @@ def StartMaster(start_daemons, no_voting): logging.error(msg) err_msgs.append(msg) else: - result = utils.RunCmd(["ip", "address", "add", "%s/32" % master_ip, + netmask = 32 + if netutils.IP6Address.IsValid(master_ip): + netmask = 128 + + result = utils.RunCmd(["ip", "address", "add", + "%s/%d" % (master_ip, netmask), "dev", master_netdev, "label", "%s:0" % master_netdev]) if result.failed: @@ -295,9 +300,12 @@ def StartMaster(start_daemons, no_voting): logging.error(msg) err_msgs.append(msg) - result = utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev, - "-s", master_ip, master_ip]) - # we'll ignore the exit code of arping + # we ignore the exit code of the following cmds + if netutils.IP4Address.IsValid(master_ip): + utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev, "-s", + master_ip, master_ip]) + elif netutils.IP6Address.IsValid(master_ip): + utils.RunCmd(["ndisc6", "-q", "-r 3", master_ip, master_netdev]) if err_msgs: _Fail("; ".join(err_msgs)) @@ -322,7 +330,12 @@ def StopMaster(stop_daemons): # GetMasterInfo will raise an exception if not able to return data master_netdev, master_ip, _ = GetMasterInfo() - result = utils.RunCmd(["ip", "address", "del", "%s/32" % master_ip, + netmask = 32 + if netutils.IP6Address.IsValid(master_ip): + netmask = 128 + + result = utils.RunCmd(["ip", "address", "del", + "%s/%d" % (master_ip, netmask), "dev", master_netdev]) if result.failed: logging.error("Can't remove the master IP, error: %s", result.output) diff --git a/lib/cli.py b/lib/cli.py index 9d865555f..a314ce445 100644 --- a/lib/cli.py +++ b/lib/cli.py @@ -119,6 +119,7 @@ __all__ = [ "OSPARAMS_OPT", "OS_OPT", "OS_SIZE_OPT", + "PRIMARY_IP_VERSION_OPT", "RAPI_CERT_OPT", "READD_OPT", "REBOOT_TYPE_OPT", @@ -1021,6 +1022,13 @@ NODRBD_STORAGE_OPT = cli_option("--no-drbd-storage", dest="drbd_storage", action="store_false", default=True, help="Disable support for DRBD") +PRIMARY_IP_VERSION_OPT = \ + cli_option("--primary-ip-version", default=constants.IP4_VERSION, + action="store", dest="primary_ip_version", + metavar="%d|%d" % (constants.IP4_VERSION, + constants.IP6_VERSION), + help="Cluster-wide IP version for primary IP") + def _ParseArgs(argv, commands, aliases): """Parser for the command line arguments. diff --git a/lib/cmdlib.py b/lib/cmdlib.py index c092cceb1..6870f172f 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -2527,7 +2527,8 @@ class LURenameCluster(LogicalUnit): """Verify that the passed name is a valid one. """ - hostname = netutils.GetHostname(name=self.op.name) + hostname = netutils.GetHostname(name=self.op.name, + family=self.cfg.GetPrimaryIPFamily()) new_name = hostname.name self.ip = new_ip = hostname.ip @@ -4117,6 +4118,11 @@ class LUQueryClusterInfo(NoHooksLU): if hv_name in cluster.enabled_hypervisors: os_hvp[os_name][hv_name] = hv_params + # Convert ip_family to ip_version + primary_ip_version = constants.IP4_VERSION + if cluster.primary_ip_family == netutils.IP6Address.family: + primary_ip_version = constants.IP6_VERSION + result = { "software_version": constants.RELEASE_VERSION, "protocol_version": constants.PROTOCOL_VERSION, @@ -4147,6 +4153,7 @@ class LUQueryClusterInfo(NoHooksLU): "uid_pool": cluster.uid_pool, "default_iallocator": cluster.default_iallocator, "reserved_lvs": cluster.reserved_lvs, + "primary_ip_version": primary_ip_version, } return result diff --git a/lib/daemon.py b/lib/daemon.py index 86e6c02da..5346e47da 100644 --- a/lib/daemon.py +++ b/lib/daemon.py @@ -40,6 +40,7 @@ from ganeti import utils from ganeti import constants from ganeti import errors from ganeti import netutils +from ganeti import ssconf _DEFAULT_RUN_USER = "root" @@ -542,6 +543,16 @@ def GenericMain(daemon_name, optionparser, dirs, check_fn, exec_fn, if daemon_name in constants.DAEMONS_PORTS: default_bind_address = constants.IP4_ADDRESS_ANY + try: + family = ssconf.SimpleStore().GetPrimaryIPFamily() + if family == netutils.IP6Address.family: + default_bind_address = constants.IP6_ADDRESS_ANY + except errors.ConfigurationError: + # This case occurs when adding a node, as there is no ssconf available + # when noded is first started. In that case, however, the correct + # bind_address must be passed + pass + default_port = netutils.GetDaemonPort(daemon_name) # For networked daemons we allow choosing the port and bind address @@ -549,7 +560,7 @@ def GenericMain(daemon_name, optionparser, dirs, check_fn, exec_fn, help="Network port (default: %s)" % default_port, default=default_port, type="int") optionparser.add_option("-b", "--bind", dest="bind_address", - help=("Bind address (default: %s)" % + help=("Bind address (default: '%s')" % default_bind_address), default=default_bind_address, metavar="ADDRESS") diff --git a/scripts/gnt-cluster b/scripts/gnt-cluster index 2da37fdcd..ab505b8ec 100755 --- a/scripts/gnt-cluster +++ b/scripts/gnt-cluster @@ -105,6 +105,12 @@ def InitCluster(opts, args): if uid_pool is not None: uid_pool = uidpool.ParseUidPool(uid_pool) + try: + primary_ip_version = int(opts.primary_ip_version) + except (ValueError, TypeError), err: + ToStderr("Invalid primary ip version value: %s" % str(err)) + return 1 + bootstrap.InitCluster(cluster_name=args[0], secondary_ip=opts.secondary_ip, vg_name=vg_name, @@ -122,7 +128,7 @@ def InitCluster(opts, args): drbd_helper=drbd_helper, uid_pool=uid_pool, default_iallocator=opts.default_iallocator, - primary_ip_version=constants.IP4_VERSION, + primary_ip_version=primary_ip_version, ) op = opcodes.OpPostInitCluster() SubmitOpCode(op, opts=opts) @@ -318,6 +324,7 @@ def ShowClusterConfig(opts, args): uidpool.FormatUidPool(result["uid_pool"], roman=opts.roman_integers)) ToStdout(" - default instance allocator: %s", result["default_iallocator"]) + ToStdout(" - primary ip version: %d", result["primary_ip_version"]) ToStdout("Default instance parameters:") _PrintGroupedParams(result["beparams"], roman=opts.roman_integers) @@ -849,7 +856,7 @@ commands = { NOLVM_STORAGE_OPT, NOMODIFY_ETCHOSTS_OPT, NOMODIFY_SSH_SETUP_OPT, SECONDARY_IP_OPT, VG_NAME_OPT, MAINTAIN_NODE_HEALTH_OPT, UIDPOOL_OPT, DRBD_HELPER_OPT, NODRBD_STORAGE_OPT, - DEFAULT_IALLOCATOR_OPT], + DEFAULT_IALLOCATOR_OPT, PRIMARY_IP_VERSION_OPT], "[opts...] <cluster_name>", "Initialises a new cluster configuration"), 'destroy': ( DestroyCluster, ARGS_NONE, [YES_DOIT_OPT], -- GitLab