Add zgenhostid utility script
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
This commit is contained in:
parent
ffb195c256
commit
b9373170e3
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
dist_bin_SCRIPTS = zgenhostid
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -4,6 +4,7 @@ dist_man_MANS = \
|
|||
vdev_id.8 \
|
||||
zdb.8 \
|
||||
zfs.8 \
|
||||
zgenhostid.8
|
||||
zinject.8 \
|
||||
zpool.8 \
|
||||
zstreamdump.8
|
||||
|
|
|
@ -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
|
|
@ -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 .
|
||||
|
|
|
@ -141,6 +141,7 @@ export ZFS_FILES='zdb
|
|||
arcstat.py
|
||||
dbufstat.py
|
||||
zed
|
||||
zgenhostid
|
||||
zstreamdump'
|
||||
|
||||
export ZFSTEST_FILES='chg_usr_exec
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue