]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Add zgenhostid utility script
authorOlaf Faaland <faaland1@llnl.gov>
Wed, 19 Jul 2017 01:11:08 +0000 (18:11 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 25 Jul 2017 17:22:03 +0000 (13:22 -0400)
Turning the multihost property on requires that a hostid be set to allow
ZFS to determine when a foreign system is attemping to import a pool.
The error message instructing the user to set a hostid refers to
genhostid(1).

Genhostid(1) is not available on SUSE Linux.  This commit adds a script
modeled after genhostid(1) for those users.

Zgenhostid checks for an /etc/hostid file; if it does not exist, it
creates one and stores a value.  If the user has provided a hostid as an
argument, that value is used.  Otherwise, a random hostid is generated
and stored.

This differs from the CENTOS 6/7 versions of genhostid, which overwrite
the /etc/hostid file even though their manpages state otherwise.

A man page for zgenhostid is added. The one for genhostid is in (1), but
I put zgenhostid in (8) because I believe it's more appropriate.

The mmp tests are modified to use zgenhostid to set the hostid instead
of using the spl_hostid module parameter.  zgenhostid will not replace
an existing /etc/hostid file, so new mmp_clear_hostid calls are
required.

Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #6358
Closes #6379

14 files changed:
cmd/Makefile.am
cmd/zgenhostid/Makefile.am [new file with mode: 0644]
cmd/zgenhostid/zgenhostid [new file with mode: 0755]
cmd/zpool/zpool_main.c
configure.ac
lib/libzfs/libzfs_pool.c
man/man8/Makefile.am
man/man8/zgenhostid.8 [new file with mode: 0644]
man/man8/zpool.8
tests/zfs-tests/include/commands.cfg
tests/zfs-tests/tests/functional/mmp/mmp.kshlib
tests/zfs-tests/tests/functional/mmp/mmp_active_import.ksh
tests/zfs-tests/tests/functional/mmp/mmp_exported_import.ksh
tests/zfs-tests/tests/functional/mmp/mmp_inactive_import.ksh

index 04aa7c6333daa3b5d5220cd12eda6a10dbedd053..f7d7db68cef0bb77b3a311d8c6c0729abbc496e8 100644 (file)
@@ -1,3 +1,3 @@
 SUBDIRS  = zfs zpool zdb zhack zinject zstreamdump ztest zpios
 SUBDIRS += mount_zfs fsck_zfs zvol_id vdev_id arcstat dbufstat zed
-SUBDIRS += arc_summary raidz_test
+SUBDIRS += arc_summary raidz_test zgenhostid
diff --git a/cmd/zgenhostid/Makefile.am b/cmd/zgenhostid/Makefile.am
new file mode 100644 (file)
index 0000000..69c99ca
--- /dev/null
@@ -0,0 +1 @@
+dist_bin_SCRIPTS = zgenhostid
diff --git a/cmd/zgenhostid/zgenhostid b/cmd/zgenhostid/zgenhostid
new file mode 100755 (executable)
index 0000000..db690ec
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+# Emulate genhostid(1) available on RHEL/CENTOS, for use on distros
+# which do not provide that utility.
+#
+# Usage:
+#    zgenhostid
+#    zgenhostid <value>
+#
+# If /etc/hostid already exists and is size > 0, the script exits immediately
+# and changes nothing.  Unlike genhostid, this generates an error message.
+#
+# The first form generates a random hostid and stores it in /etc/hostid.
+# The second form checks that the provided value is between 0x1 and 0xFFFFFFFF
+# and if so, stores it in /etc/hostid.  This form is not supported by
+# genhostid(1).
+
+hostid_file=/etc/hostid
+
+function usage {
+       echo "$0 [value]"
+       echo "If $hostid_file is not present, store a hostid in it." >&2
+       echo "The optional value must be an 8-digit hex number between" >&2
+       echo "1 and 2^32-1.  If no value is provided, a random one will" >&2
+       echo "be generated.  The value must be unique among your systems." >&2
+}
+
+# hostid(1) ignores contents of /etc/hostid if size < 4 bytes.  It would
+# be better if this checked size >= 4 bytes but it the method must be
+# widely portable.
+if [ -s $hostid_file ]; then
+       echo "$hostid_file already exists.  No change made." >&2
+       exit 1
+fi
+
+if [ -n "$1" ]; then
+       host_id=$1
+else
+       # $RANDOM goes from 0..32k-1
+       number=$((((RANDOM % 4) * 32768 + RANDOM) * 32768 + RANDOM))
+       host_id=$(printf "%08x" $number)
+fi
+
+if egrep -o '^0{8}$' <<< $host_id >/dev/null 2>&1; then
+       usage
+       exit 2
+fi
+
+if ! egrep -o '^[a-fA-F0-9]{8}$' <<< $host_id >/dev/null 2>&1; then
+       usage
+       exit 3
+fi
+
+a=${host_id:6:2}
+b=${host_id:4:2}
+c=${host_id:2:2}
+d=${host_id:0:2}
+
+echo -ne \\x$a\\x$b\\x$c\\x$d > $hostid_file
+
+exit 0
index 8d04f772580021e2da09890725a30e74780784cb..f597109d2a28d5906ee03633afa834c77b8ae116 100644 (file)
@@ -2177,7 +2177,7 @@ show_import(nvlist_t *config)
                        break;
                case ZPOOL_STATUS_HOSTID_REQUIRED:
                        (void) printf(gettext(" action: Set a unique system "
-                           "hostid with the genhostid(1) command.\n"));
+                           "hostid with the zgenhostid(8) command.\n"));
                        break;
                default:
                        (void) printf(gettext(" action: The pool cannot be "
@@ -2304,7 +2304,7 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
                        (void) fprintf(stderr, gettext("Cannot import '%s': "
                            "pool has the multihost property on and the\n"
                            "system's hostid is not set. Set a unique hostid "
-                           "with the genhostid(1) command.\n"), name);
+                           "with the zgenhostid(8) command.\n"), name);
                } else {
                        char *hostname = "<unknown>";
                        uint64_t timestamp = 0;
index 514fcd98e1a93bbed4cdf67f0b7c82a6de0b6308..0c7977ef80ea23d1a67a56c8245c28bdbb98d9f5 100644 (file)
@@ -113,6 +113,7 @@ AC_CONFIG_FILES([
        cmd/arc_summary/Makefile
        cmd/zed/Makefile
        cmd/raidz_test/Makefile
+       cmd/zgenhostid/Makefile
        contrib/Makefile
        contrib/bash_completion.d/Makefile
        contrib/dracut/Makefile
index 58d91c8f4bb656cc89678c9dfa6d9236c94078ce..73af75f9d3d8c2b27dd4b71c3bcfe87bee3a2cfb 100644 (file)
@@ -1865,7 +1865,7 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
                                            "the multihost property on and "
                                            "the\nsystem's hostid is not set. "
                                            "Set a unique system hostid with "
-                                           "the genhostid(1) command.\n"));
+                                           "the zgenhostid(8) command.\n"));
                                }
 
                                (void) zfs_error_aux(hdl, aux);
index b89e34dfd4fe3a6d0af7a3bf5811bf60e451d2e4..fa58a628d03e7787451855e2bd531c3827744a66 100644 (file)
@@ -4,6 +4,7 @@ dist_man_MANS = \
        vdev_id.8 \
        zdb.8 \
        zfs.8 \
+       zgenhostid.8
        zinject.8 \
        zpool.8 \
        zstreamdump.8
diff --git a/man/man8/zgenhostid.8 b/man/man8/zgenhostid.8
new file mode 100644 (file)
index 0000000..2c86b8e
--- /dev/null
@@ -0,0 +1,72 @@
+.\"
+.\" CDDL HEADER START
+.\"
+.\" The contents of this file are subject to the terms of the
+.\" Common Development and Distribution License (the "License").
+.\" You may not use this file except in compliance with the License.
+.\"
+.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+.\" or http://www.opensolaris.org/os/licensing.
+.\" See the License for the specific language governing permissions
+.\" and limitations under the License.
+.\"
+.\" When distributing Covered Code, include this CDDL HEADER in each
+.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+.\" If applicable, add the following below this CDDL HEADER, with the
+.\" fields enclosed by brackets "[]" replaced with your own identifying
+.\" information: Portions Copyright [yyyy] [name of copyright owner]
+.\"
+.\" CDDL HEADER END
+.\"
+.\"
+.\" Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
+.\"
+.Dd July 24, 2017
+.Dt ZGENHOSTID 8 SMM
+.Os Linux
+.Sh NAME
+.Nm zgenhostid
+.Nd generate and store a hostid in
+.Em /etc/hostid
+.Sh SYNOPSIS
+.Nm
+.Op Ar hostid
+.Sh DESCRIPTION
+If
+.Em /etc/hostid
+does not exist, create it and store a hostid in it.  If the user provides
+.Op Ar hostid
+on the command line, store that value.  Otherwise, randomly generate a
+value to store.
+.Pp
+This emulates the
+.Xr genhostid 1
+utility and is provided for use on systems which do not include the utility.
+.Pp
+.Sh OPTIONS
+.Op Ar hostid
+Specifies the value to be placed in
+.Em /etc/hostid .
+It must be a number with a value between 1 and 2^32-1.  This value
+.Sy must
+be unique among your systems.  It must be expressed in hexadecimal and be
+exactly 8 digits long.
+.Sh EXAMPLES
+.Bl -tag -width Ds
+.It Generate a random hostid and store it
+.Bd -literal
+# zgenhostid
+.Ed
+.It Record the libc-generated hostid in Em /etc/hostid
+.Bd -literal
+# zgenhostid $(hostid)
+.Ed
+.It Record a custom hostid (0xdeadbeef) in Em etc/hostid
+.Bd -literal
+# zgenhostid deadbeef
+.Ed
+.El
+.Sh SEE ALSO
+.Xr spl-module-parameters 5 ,
+.Xr genhostid 1 ,
+.Xr hostid 1
index 02853342c2df7a0f1b831aa6cb98154c12f6ed87..5814b4125b780d2e00c24ec203645795f19b1384 100644 (file)
@@ -732,7 +732,7 @@ in the
 man page.  In order to enable this property each host must set a unique hostid.
 See
 .Xr genhostid 1
-and
+.Xr zgenhostid 8
 .Xr spl-module-paramters 5
 for additional details.  The default value is
 .Sy off .
index 57b1bd3158ade874f82e77c2958535b3bb8a24df..32749028c10f31d44e961a80592c170bc10bf844 100644 (file)
@@ -141,6 +141,7 @@ export ZFS_FILES='zdb
     arcstat.py
     dbufstat.py
     zed
+    zgenhostid
     zstreamdump'
 
 export ZFSTEST_FILES='chg_usr_exec
index a81779b0c7fb89ef1117b21fb1513119bb30a732..ffe26dfde8200079e20a64702427f6b4db369b90 100644 (file)
@@ -79,12 +79,7 @@ function mmp_set_hostid
 {
        typeset hostid=$1
 
-       a=${hostid:6:2}
-       b=${hostid:4:2}
-       c=${hostid:2:2}
-       d=${hostid:0:2}
-
-       printf "\\x$a\\x$b\\x$c\\x$d" >$HOSTID_FILE
+       zgenhostid $1
 
        if [ $(hostid) != "$hostid" ]; then
                return 1
@@ -107,10 +102,12 @@ function mmp_pool_create # pool dir
        log_must mkdir -p $dir
        log_must truncate -s $MINVDEVSIZE $dir/vdev1 $dir/vdev2
 
+       log_must mmp_clear_hostid
        log_must mmp_set_hostid $HOSTID1
        log_must zpool create -f $pool mirror $dir/vdev1 $dir/vdev2
        log_must zpool set multihost=on $pool
        log_must zpool export $pool
+       log_must mmp_clear_hostid
        log_must mmp_set_hostid $HOSTID2
 
        log_note "Starting ztest in the background as hostid $HOSTID1"
@@ -146,6 +143,7 @@ function mmp_pool_set_hostid # pool hostid
        typeset pool=$1
        typeset hostid=$2
 
+       log_must mmp_clear_hostid
        log_must mmp_set_hostid $hostid
        log_must zpool export $pool
        log_must zpool import $pool
index 92eb9ce2d229cb07930afb73df7bfac81bdd2490..e2e30c7eabc97359817d92bbc9b96d939f822c97 100755 (executable)
@@ -86,6 +86,7 @@ log_must mmp_set_hostid $HOSTID1
 MMP_IMPORTED_MSG="The pool can be imported"
 log_must check_pool_import $MMP_POOL "-d $MMP_DIR" "action" $MMP_IMPORTED_MSG
 
+log_must mmp_clear_hostid
 log_must mmp_set_hostid $HOSTID2
 MMP_IMPORTED_MSG="The pool was last accessed by another system."
 log_must check_pool_import $MMP_POOL "-d $MMP_DIR" "status" $MMP_IMPORTED_MSG
index d65ca5b3d7646e1b3097c48f01c1e2a4f399c22a..6d34f7e77da408b970c89f99502995ccbd00ea6c 100755 (executable)
@@ -62,6 +62,7 @@ done
 for opt in "" "-f"; do
        log_must mmp_pool_set_hostid $TESTPOOL $HOSTID1
        log_must zpool export $TESTPOOL
+       log_must mmp_clear_hostid
        log_must mmp_set_hostid $HOSTID2
        log_must import_no_activity_check $TESTPOOL $opt
 done
@@ -87,6 +88,7 @@ done
 for opt in "" "-f"; do
        log_must mmp_pool_set_hostid $TESTPOOL $HOSTID1
        log_must zpool export $TESTPOOL
+       log_must mmp_clear_hostid
        log_must mmp_set_hostid $HOSTID2
        log_must import_no_activity_check $TESTPOOL $opt
 done
index c944b6b2898bd51318173123d928a72b221a6388..71f3af5c50575f704a3c154f9b48180d4fd85877 100755 (executable)
@@ -60,6 +60,7 @@ done
 
 # 3. Verify multihost=off and hostids differ (no activity check)
 log_must zpool export -F $TESTPOOL
+log_must mmp_clear_hostid
 log_must mmp_set_hostid $HOSTID2
 log_mustnot import_no_activity_check $TESTPOOL ""
 log_must import_no_activity_check $TESTPOOL "-f"
@@ -81,6 +82,7 @@ done
 
 # 6. Verify multihost=on and hostids differ (activity check)
 log_must zpool export -F $TESTPOOL
+log_must mmp_clear_hostid
 log_must mmp_set_hostid $HOSTID2
 log_mustnot import_activity_check $TESTPOOL ""
 log_must import_activity_check $TESTPOOL "-f"