Merge pull request #411 from JRGTH/master

New features and improvements re-revised/re-tested for upcoming release
This commit is contained in:
Christer Edwards
2021-07-11 19:12:12 -06:00
committed by GitHub
7 changed files with 426 additions and 116 deletions

View File

@@ -135,10 +135,10 @@ version|-v|--version)
help|-h|--help) help|-h|--help)
usage usage
;; ;;
bootstrap|create|destroy|import|list|rdr|restart|start|update|upgrade|verify) bootstrap|create|destroy|export|import|list|rdr|restart|start|update|upgrade|verify)
# Nothing "extra" to do for these commands. -- cwells # Nothing "extra" to do for these commands. -- cwells
;; ;;
clone|config|cmd|console|convert|cp|edit|export|htop|limits|mount|pkg|rename|service|stop|sysrc|template|top|umount|zfs) clone|config|cmd|console|convert|cp|edit|htop|limits|mount|pkg|rename|service|stop|sysrc|template|top|umount|zfs)
# Parse the target and ensure it exists. -- cwells # Parse the target and ensure it exists. -- cwells
if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells if [ $# -eq 0 ]; then # No target was given, so show the command's help. -- cwells
PARAMS='help' PARAMS='help'

View File

@@ -44,6 +44,8 @@ bastille_zfs_options="-o compress=lz4 -o atime=off" ## default
## Export/Import options ## Export/Import options
bastille_compress_xz_options="-0 -v" ## default "-0 -v" bastille_compress_xz_options="-0 -v" ## default "-0 -v"
bastille_decompress_xz_options="-c -d -v" ## default "-c -d -v" bastille_decompress_xz_options="-c -d -v" ## default "-c -d -v"
bastille_compress_gz_options="-1 -v" ## default "-1 -v"
bastille_decompress_gz_options="-k -d -c -v" ## default "-k -d -c -v"
## Networking ## Networking
bastille_network_loopback="bastille0" ## default: "bastille0" bastille_network_loopback="bastille0" ## default: "bastille0"

View File

@@ -57,6 +57,7 @@ convert_symlinks() {
done done
# Copy new files to destination jail # Copy new files to destination jail
info "Copying required base files to container..."
for _link in ${SYMLINKS}; do for _link in ${SYMLINKS}; do
if [ ! -d "${_link}" ]; then if [ ! -d "${_link}" ]; then
if [ -d "${bastille_releasesdir}/${RELEASE}/${_link}" ]; then if [ -d "${bastille_releasesdir}/${RELEASE}/${_link}" ]; then
@@ -100,13 +101,15 @@ revert_convert() {
start_convert() { start_convert() {
# Attempt container conversion and handle some errors # Attempt container conversion and handle some errors
DATE=$(date)
if [ -d "${bastille_jailsdir}/${TARGET}" ]; then if [ -d "${bastille_jailsdir}/${TARGET}" ]; then
info "Converting '${TARGET}' into a thickjail. This may take a while..." info "Converting '${TARGET}' into a thickjail. This may take a while..."
# Set some variables # Set some variables
RELEASE=$(grep -owE '([1-9]{2,2})\.[0-9](-RELEASE|-RELEASE-i386|-RC[1-2])|([0-9]{1,2}-stable-build-[0-9]{1,3})|(current-build)-([0-9]{1,3})|(current-BUILD-LATEST)|([0-9]{1,2}-stable-BUILD-LATEST)|(current-BUILD-LATEST)' "${bastille_jailsdir}/${TARGET}/fstab") RELEASE=$(grep -w "${bastille_releasesdir}/.* ${bastille_jailsdir}/${TARGET}/root/.bastille" ${bastille_jailsdir}/${TARGET}/fstab | sed "s|${bastille_releasesdir}/||;s| .*||")
FSTABMOD=$(grep -w "${bastille_releasesdir}/${RELEASE} ${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab") FSTABMOD=$(grep -w "${bastille_releasesdir}/${RELEASE} ${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab")
SYMLINKS="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/ports usr/sbin usr/share usr/src" SYMLINKS="bin boot lib libexec rescue sbin usr/bin usr/include usr/lib usr/lib32 usr/libdata usr/libexec usr/ports usr/sbin usr/share usr/src"
HASPORTS=$(grep -w ${bastille_releasesdir}/${RELEASE}/usr/ports ${bastille_jailsdir}/${TARGET}/fstab)
if [ -n "${RELEASE}" ]; then if [ -n "${RELEASE}" ]; then
cd "${bastille_jailsdir}/${TARGET}/root" cd "${bastille_jailsdir}/${TARGET}/root"
@@ -115,7 +118,12 @@ start_convert() {
convert_symlinks convert_symlinks
# Comment the line containing .bastille and rename mountpoint # Comment the line containing .bastille and rename mountpoint
sed -i '' -E "s|${FSTABMOD}|# Converted from thin to thick container on $(date)|g" "${bastille_jailsdir}/${TARGET}/fstab" sed -i '' -E "s|${FSTABMOD}|# Converted from thin to thick container on ${DATE}|g" "${bastille_jailsdir}/${TARGET}/fstab"
if [ -n "${HASPORTS}" ]; then
sed -i '' -E "s|${HASPORTS}|# Ports copied from base to container on ${DATE}|g" "${bastille_jailsdir}/${TARGET}/fstab"
info "Copying ports to container..."
cp -a "${bastille_releasesdir}/${RELEASE}/usr/ports" "${bastille_jailsdir}/${TARGET}/root/usr"
fi
mv "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/root/.bastille.old" mv "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/root/.bastille.old"
info "Conversion of '${TARGET}' completed successfully!" info "Conversion of '${TARGET}' completed successfully!"

View File

@@ -508,36 +508,40 @@ EMPTY_JAIL=""
THICK_JAIL="" THICK_JAIL=""
VNET_JAIL="" VNET_JAIL=""
## handle combined options then shift # Handle and parse options
if [ "${1}" = "-T" -o "${1}" = "--thick" -o "${1}" = "thick" ] && \ while [ $# -gt 0 ]; do
[ "${2}" = "-V" -o "${2}" = "--vnet" -o "${2}" = "vnet" ]; then
THICK_JAIL="1"
VNET_JAIL="1"
shift 2
else
## handle single options
case "${1}" in case "${1}" in
-E|--empty|empty) -E|--empty|empty)
shift
EMPTY_JAIL="1" EMPTY_JAIL="1"
shift
;; ;;
-L|--linux|linux) -L|--linux|linux)
shift shift
LINUX_JAIL="1" LINUX_JAIL="1"
;; ;;
-T|--thick|thick) -T|--thick|thick)
shift
THICK_JAIL="1" THICK_JAIL="1"
shift
;; ;;
-V|--vnet|vnet) -V|--vnet|vnet)
shift
VNET_JAIL="1" VNET_JAIL="1"
shift
;; ;;
-*) -*|--*)
error_notify "Unknown Option." error_notify "Unknown Option."
usage usage
;; ;;
*)
break
;;
esac esac
done
## validate for combined options
if [ -n "${EMPTY_JAIL}" ]; then
if [ -n "${THICK_JAIL}" ] || [ -n "${VNET_JAIL}" ]; then
error_exit "Error: Empty jail option can't be used with other options."
fi
fi fi
NAME="$1" NAME="$1"

View File

@@ -32,7 +32,25 @@
. /usr/local/etc/bastille/bastille.conf . /usr/local/etc/bastille/bastille.conf
usage() { usage() {
error_exit "Usage: bastille export TARGET [safe|tarball] | PATH" # Build an independent usage for the export command
# Valid compress/options for ZFS systems are raw, .gz, .tgz, .txz and .xz
# Valid compress/options for non ZFS configured systems are .tgz and .txz
# If no compression option specified, user must redirect standard output
echo -e "${COLOR_RED}Usage: bastille export | option(s) | TARGET | PATH${COLOR_RESET}"
cat << EOF
Options:
--gz -- Export a ZFS jail using GZIP(.gz) compressed image.
-r | --raw -- Export a ZFS jail to an uncompressed RAW image.
-s | --safe -- Safely stop and start a ZFS jail before the exporting process.
--tgz -- Export a jail using simple .tgz compressed archive instead.
--txz -- Export a jail using simple .txz compressed archive instead.
-v | --verbose -- Be more verbose during the ZFS send operation.
--xz -- Export a ZFS jail using XZ(.xz) compressed image.
EOF
exit 1
} }
# Handle special-case commands first # Handle special-case commands first
@@ -47,90 +65,258 @@ if [ "${TARGET}" = "ALL" ]; then
error_exit "Batch export is unsupported." error_exit "Batch export is unsupported."
fi fi
if [ $# -gt 2 ] || [ $# -lt 0 ]; then if [ $# -gt 5 ] || [ $# -lt 1 ]; then
usage usage
fi fi
OPTION="${1}" zfs_enable_check() {
EXPATH="${2}" # Temporarily disable ZFS so we can create a standard backup archive
SAFE_EXPORT= if [ "${bastille_zfs_enable}" = "YES" ]; then
bastille_zfs_enable="NO"
fi
}
# Handle some options TARGET="${1}"
if [ -n "${OPTION}" ]; then GZIP_EXPORT=
if [ "${OPTION}" = "-t" -o "${OPTION}" = "--txz" -o ${OPTION} = "tarball" ]; then SAFE_EXPORT=
if [ "${bastille_zfs_enable}" = "YES" ]; then USER_EXPORT=
# Temporarily disable ZFS so we can create a standard backup archive RAW_EXPORT=
bastille_zfs_enable="NO" DIR_EXPORT=
fi TXZ_EXPORT=
elif [ "${OPTION}" = "-s" -o "${OPTION}" = "--safe" -o ${OPTION} = "safe" ]; then TGZ_EXPORT=
SAFE_EXPORT="1" OPT_ZSEND="-R"
elif echo "${OPTION}" | grep -q "\/"; then COMP_OPTION="0"
if [ -d "${OPTION}" ]; then
EXPATH="${OPTION}" opt_count() {
else COMP_OPTION=$(expr ${COMP_OPTION} + 1)
error_exit "Error: Path not found." }
fi
else # Handle and parse option args
error_notify "Invalid option!" while [ $# -gt 0 ]; do
usage case "${1}" in
--gz)
GZIP_EXPORT="1"
TARGET="${2}"
opt_count
shift
;;
--xz)
XZ_EXPORT="1"
TARGET="${2}"
opt_count
shift
;;
--tgz)
TGZ_EXPORT="1"
TARGET="${2}"
opt_count
zfs_enable_check
shift
;;
--txz)
TXZ_EXPORT="1"
TARGET="${2}"
opt_count
zfs_enable_check
shift
;;
-s|--safe)
SAFE_EXPORT="1"
TARGET="${2}"
shift
;;
-r|--raw)
RAW_EXPORT="1"
TARGET="${2}"
opt_count
shift
;;
-v|--verbose)
OPT_ZSEND="-Rv"
TARGET="${2}"
shift
;;
-*|--*)
error_notify "Unknown Option."
usage
;;
*)
if echo "${1}" | grep -q "\/"; then
DIR_EXPORT="${1}"
else
if [ $# -gt 2 ] || [ $# -lt 1 ]; then
usage
fi
fi
shift
;;
esac
done
# Validate for combined options
if [ "${COMP_OPTION}" -gt "1" ]; then
error_exit "Error: Only one compression format can be used during export."
fi
if [ -n "${TXZ_EXPORT}" -o -n "${TGZ_EXPORT}" ] && [ -n "${SAFE_EXPORT}" ]; then
error_exit "Error: Simple archive modes with safe ZFS export can't be used together."
fi
if [ -z "${bastille_zfs_enable}" ]; then
if [ -n "${GZIP_EXPORT}" -o -n "${RAW_EXPORT}" -o -n "${SAFE_EXPORT}" -o "${OPT_ZSEND}" = "-Rv" ]; then
error_exit "Options --gz, --raw, --safe, --verbose are valid for ZFS configured systems only."
fi
fi
if [ -n "${SAFE_EXPORT}" ]; then
# Check if container is running, otherwise just ignore
if [ -z "$(jls name | awk "/^${TARGET}$/")" ]; then
SAFE_EXPORT=
fi fi
fi fi
# Export directory check # Export directory check
if [ -n "${EXPATH}" ]; then if [ -n "${DIR_EXPORT}" ]; then
if [ -d "${EXPATH}" ]; then if [ -d "${DIR_EXPORT}" ]; then
# Set the user defined export directory # Set the user defined export directory
bastille_backupsdir="${EXPATH}" bastille_backupsdir="${DIR_EXPORT}"
else else
error_exit "Error: Path not found." error_exit "Error: Path not found."
fi fi
fi fi
create_zfs_snap(){ # Fallback to default if missing config parameters
if [ -z "${bastille_compress_xz_options}" ]; then
bastille_compress_xz_options="-0 -v"
fi
if [ -z "${bastille_compress_gz_options}" ]; then
bastille_compress_gz_options="-1 -v"
fi
create_zfs_snap() {
# Take a recursive temporary snapshot # Take a recursive temporary snapshot
info "Creating temporary ZFS snapshot for export..." if [ -z "${USER_EXPORT}" ]; then
info "Creating temporary ZFS snapshot for export..."
fi
zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" zfs snapshot -r "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}"
} }
jail_export() clean_zfs_snap() {
{ # Cleanup the recursive temporary snapshot
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}/root@bastille_export_${DATE}"
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}"
}
export_check() {
# Inform the user about the exporting method
if [ -z "${USER_EXPORT}" ]; then
if [ -n "$(jls name | awk "/^${TARGET}$/")" ]; then
if [ -n "${SAFE_EXPORT}" ]; then
EXPORT_AS="Safely exporting"
else
EXPORT_AS="Hot exporting"
fi
else
EXPORT_AS="Exporting"
fi
if [ "${FILE_EXT}" = ".xz" -o "${FILE_EXT}" = ".gz" -o "${FILE_EXT}" = "" ]; then
EXPORT_TYPE="image"
else
EXPORT_TYPE="archive"
fi
if [ -n "${RAW_EXPORT}" ]; then
EXPORT_INFO="to a raw ${EXPORT_TYPE}"
else
EXPORT_INFO="to a compressed ${FILE_EXT} ${EXPORT_TYPE}"
fi
info "${EXPORT_AS} '${TARGET}' ${EXPORT_INFO}..."
fi
# Safely stop and snapshot the jail
if [ -n "${SAFE_EXPORT}" ]; then
bastille stop ${TARGET}
create_zfs_snap
bastille start ${TARGET}
else
create_zfs_snap
fi
if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ -z "${USER_EXPORT}" ]; then
info "Sending ZFS data stream..."
fi
fi
}
jail_export() {
# Attempt to export the container # Attempt to export the container
DATE=$(date +%F-%H%M%S) DATE=$(date +%F-%H%M%S)
if [ "${bastille_zfs_enable}" = "YES" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ -n "${bastille_zfs_zpool}" ]; then if [ -n "${bastille_zfs_zpool}" ]; then
FILE_EXT="xz" if [ -n "${RAW_EXPORT}" ]; then
FILE_EXT=""
export_check
if [ -n "${SAFE_EXPORT}" ]; then # Export the raw container recursively and cleanup temporary snapshots
info "Safely exporting '${TARGET}' to a compressed .${FILE_EXT} archive." zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" \
bastille stop ${TARGET} > "${bastille_backupsdir}/${TARGET}_${DATE}"
create_zfs_snap clean_zfs_snap
bastille start ${TARGET} elif [ -n "${GZIP_EXPORT}" ]; then
FILE_EXT=".gz"
export_check
# Export the raw container recursively and cleanup temporary snapshots
zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" | \
gzip ${bastille_compress_gz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}"
clean_zfs_snap
elif [ -n "${XZ_EXPORT}" ]; then
FILE_EXT=".xz"
export_check
# Export the container recursively and cleanup temporary snapshots
zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" | \
xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}"
clean_zfs_snap
else else
info "Hot exporting '${TARGET}' to a compressed .${FILE_EXT} archive." FILE_EXT=""
create_zfs_snap USER_EXPORT="1"
fi export_check
info "Sending ZFS data stream..." # Quietly export the container recursively, user must redirect standard output
# Export the container recursively and cleanup temporary snapshots zfs send ${OPT_ZSEND} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}"
zfs send -R "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}" | \ clean_zfs_snap
xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}" fi
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}/root@bastille_export_${DATE}"
zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}@bastille_export_${DATE}"
fi fi
else else
# Create standard backup archive if [ -n "${TGZ_EXPORT}" ]; then
FILE_EXT="txz" FILE_EXT=".tgz"
info "Exporting '${TARGET}' to a compressed .${FILE_EXT} archive..."
cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}" # Create standard tgz backup archive
info "Exporting '${TARGET}' to a compressed ${FILE_EXT} archive..."
cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | gzip ${bastille_compress_gz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}"
elif [ -n "${TXZ_EXPORT}" ]; then
FILE_EXT=".txz"
# Create standard txz backup archive
info "Exporting '${TARGET}' to a compressed ${FILE_EXT} archive..."
cd "${bastille_jailsdir}" && tar -cf - "${TARGET}" | xz ${bastille_compress_xz_options} > "${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}"
else
error_exit "Error: export option required"
fi
fi fi
if [ "$?" -ne 0 ]; then if [ "$?" -ne 0 ]; then
error_exit "Failed to export '${TARGET}' container." error_exit "Failed to export '${TARGET}' container."
else else
# Generate container checksum file if [ -z "${USER_EXPORT}" ]; then
cd "${bastille_backupsdir}" # Generate container checksum file
sha256 -q "${TARGET}_${DATE}.${FILE_EXT}" > "${TARGET}_${DATE}.sha256" cd "${bastille_backupsdir}"
info "Exported '${bastille_backupsdir}/${TARGET}_${DATE}.${FILE_EXT}' successfully." sha256 -q "${TARGET}_${DATE}${FILE_EXT}" > "${TARGET}_${DATE}.sha256"
info "Exported '${bastille_backupsdir}/${TARGET}_${DATE}${FILE_EXT}' successfully."
fi
exit 0 exit 0
fi fi
} }
@@ -140,12 +326,17 @@ if [ ! -d "${bastille_backupsdir}" ]; then
error_exit "Backups directory/dataset does not exist. See 'bastille bootstrap'." error_exit "Backups directory/dataset does not exist. See 'bastille bootstrap'."
fi fi
# Check if is a ZFS system if [ -n "${TARGET}" ]; then
if [ "${bastille_zfs_enable}" != "YES" ]; then if [ ! -d "${bastille_jailsdir}/${TARGET}" ]; then
# Check if container is running and ask for stop in UFS systems error_exit "[${TARGET}]: Not found."
if [ -n "$(jls name | awk "/^${TARGET}$/")" ]; then
error_exit "${TARGET} is running. See 'bastille stop'."
fi fi
fi
jail_export # Check if is a ZFS system
if [ "${bastille_zfs_enable}" != "YES" ]; then
# Check if container is running and ask for stop in non ZFS systems
if [ -n "$(jls name | awk "/^${TARGET}$/")" ]; then
error_exit "${TARGET} is running. See 'bastille stop'."
fi
fi
jail_export
fi

View File

@@ -32,7 +32,18 @@
. /usr/local/etc/bastille/bastille.conf . /usr/local/etc/bastille/bastille.conf
usage() { usage() {
error_exit "Usage: bastille import file [force]" # Build an independent usage for the import command
# If no file/extension specified, will import from standard input
echo -e "${COLOR_RED}Usage: bastille import [option(s)] FILE${COLOR_RESET}"
cat << EOF
Options:
-f | --force -- Force an archive import regardless if the checksum file does not match or missing.
-v | --verbose -- Be more verbose during the ZFS receive operation.
EOF
exit 1
} }
# Handle special-case commands first # Handle special-case commands first
@@ -42,39 +53,70 @@ help|-h|--help)
;; ;;
esac esac
if [ $# -gt 2 ] || [ $# -lt 1 ]; then if [ $# -gt 3 ] || [ $# -lt 1 ]; then
usage usage
fi fi
TARGET="${1}" TARGET="${1}"
OPTION="${2}" OPT_FORCE=
shift USER_IMPORT=
OPT_ZRECV="-u"
# Handle and parse option args
while [ $# -gt 0 ]; do
case "${1}" in
-f|--force)
OPT_FORCE="1"
TARGET="${2}"
shift
;;
-v|--verbose)
OPT_ZRECV="-u -v"
TARGET="${2}"
shift
;;
-*|--*)
error_notify "Unknown Option."
usage
;;
*)
if [ $# -gt 1 ] || [ $# -lt 1 ]; then
usage
fi
shift
;;
esac
done
# Fallback to default if missing config parameters
if [ -z "${bastille_decompress_xz_options}" ]; then
bastille_decompress_xz_options="-c -d -v"
fi
if [ -z "${bastille_decompress_gz_options}" ]; then
bastille_decompress_gz_options="-k -d -c -v"
fi
validate_archive() { validate_archive() {
# Compare checksums on the target archive # Compare checksums on the target archive
# Skip validation for unsupported archives # Skip validation for unsupported archive
if [ "${FILE_EXT}" != ".tar.gz" ] && [ "${FILE_EXT}" != ".tar" ]; then if [ -f "${bastille_backupsdir}/${TARGET}" ]; then
if [ -f "${bastille_backupsdir}/${TARGET}" ]; then if [ -f "${bastille_backupsdir}/${FILE_TRIM}.sha256" ]; then
if [ -f "${bastille_backupsdir}/${FILE_TRIM}.sha256" ]; then info "Validating file: ${TARGET}..."
info "Validating file: ${TARGET}..." SHA256_DIST=$(cat "${bastille_backupsdir}/${FILE_TRIM}.sha256")
SHA256_DIST=$(cat "${bastille_backupsdir}/${FILE_TRIM}.sha256") SHA256_FILE=$(sha256 -q "${bastille_backupsdir}/${TARGET}")
SHA256_FILE=$(sha256 -q "${bastille_backupsdir}/${TARGET}") if [ "${SHA256_FILE}" != "${SHA256_DIST}" ]; then
if [ "${SHA256_FILE}" != "${SHA256_DIST}" ]; then error_exit "Failed validation for ${TARGET}."
error_exit "Failed validation for ${TARGET}."
else
info "File validation successful!"
fi
else else
# Check if user opt to force import info "File validation successful!"
if [ "${OPTION}" = "-f" -o "${OPTION}" = "force" ]; then fi
warn "Warning: Skipping archive validation!" else
else # Check if user opt to force import
error_exit "Checksum file not found. See 'bastille import TARGET -f'." if [ -n "${OPT_FORCE}" ]; then
fi warn "Warning: Skipping archive validation!"
else
error_exit "Checksum file not found. See 'bastille import [option(s)] FILE'."
fi fi
fi fi
else
warn "Warning: Skipping archive validation!"
fi fi
} }
@@ -313,23 +355,34 @@ remove_zfs_datasets() {
jail_import() { jail_import() {
# Attempt to import container from file # Attempt to import container from file
FILE_TRIM=$(echo "${TARGET}" | sed 's/\.xz//g;s/\.txz//g;s/\.zip//g;s/\.tar\.gz//g;s/\.tar//g') FILE_TRIM=$(echo "${TARGET}" | sed 's/\.xz//g;s/\.gz//g;s/\.tgz//g;s/\.txz//g;s/\.zip//g;s/\.tar\.gz//g;s/\.tar//g')
FILE_EXT=$(echo "${TARGET}" | sed "s/${FILE_TRIM}//g") FILE_EXT=$(echo "${TARGET}" | sed "s/${FILE_TRIM}//g")
validate_archive
if [ -d "${bastille_jailsdir}" ]; then if [ -d "${bastille_jailsdir}" ]; then
if [ "${bastille_zfs_enable}" = "YES" ]; then if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ -n "${bastille_zfs_zpool}" ]; then if [ -n "${bastille_zfs_zpool}" ]; then
if [ "${FILE_EXT}" = ".xz" ]; then if [ "${FILE_EXT}" = ".xz" ]; then
validate_archive
# Import from compressed xz on ZFS systems # Import from compressed xz on ZFS systems
info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} archive." info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} image."
info "Receiving ZFS data stream..." info "Receiving ZFS data stream..."
xz ${bastille_decompress_xz_options} "${bastille_backupsdir}/${TARGET}" | \ xz ${bastille_decompress_xz_options} "${bastille_backupsdir}/${TARGET}" | \
zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}"
# Update ZFS mountpoint property if required
update_zfsmount
elif [ "${FILE_EXT}" = ".gz" ]; then
validate_archive
# Import from compressed xz on ZFS systems
info "Importing '${TARGET_TRIM}' from compressed ${FILE_EXT} image."
info "Receiving ZFS data stream..."
gzip ${bastille_decompress_gz_options} "${bastille_backupsdir}/${TARGET}" | \
zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}"
# Update ZFS mountpoint property if required # Update ZFS mountpoint property if required
update_zfsmount update_zfsmount
elif [ "${FILE_EXT}" = ".txz" ]; then elif [ "${FILE_EXT}" = ".txz" ]; then
validate_archive
# Prepare the ZFS environment and restore from existing .txz file # Prepare the ZFS environment and restore from existing .txz file
create_zfs_datasets create_zfs_datasets
@@ -340,7 +393,20 @@ jail_import() {
if [ "$?" -ne 0 ]; then if [ "$?" -ne 0 ]; then
remove_zfs_datasets remove_zfs_datasets
fi fi
elif [ "${FILE_EXT}" = ".tgz" ]; then
validate_archive
# Prepare the ZFS environment and restore from existing .tgz file
create_zfs_datasets
# Extract required files to the new datasets
info "Extracting files from '${TARGET}' archive..."
tar --exclude='root' -xf "${bastille_backupsdir}/${TARGET}" --strip-components 1 -C "${bastille_jailsdir}/${TARGET_TRIM}"
tar -xf "${bastille_backupsdir}/${TARGET}" --strip-components 2 -C "${bastille_jailsdir}/${TARGET_TRIM}/root" "${TARGET_TRIM}/root"
if [ "$?" -ne 0 ]; then
remove_zfs_datasets
fi
elif [ "${FILE_EXT}" = ".zip" ]; then elif [ "${FILE_EXT}" = ".zip" ]; then
validate_archive
# Attempt to import a foreign/iocage container # Attempt to import a foreign/iocage container
info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive." info "Importing '${TARGET_TRIM}' from foreign compressed ${FILE_EXT} archive."
# Sane bastille ZFS options # Sane bastille ZFS options
@@ -353,9 +419,9 @@ jail_import() {
rm -f "${FILE_TRIM}" "${FILE_TRIM}_root" rm -f "${FILE_TRIM}" "${FILE_TRIM}_root"
fi fi
info "Receiving ZFS data stream..." info "Receiving ZFS data stream..."
zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${FILE_TRIM}" zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${FILE_TRIM}"
zfs set ${ZFS_OPTIONS} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" zfs set ${ZFS_OPTIONS} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}"
zfs receive -u "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" < "${FILE_TRIM}_root" zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}/root" < "${FILE_TRIM}_root"
# Update ZFS mountpoint property if required # Update ZFS mountpoint property if required
update_zfsmount update_zfsmount
@@ -403,6 +469,27 @@ jail_import() {
else else
update_config update_config
fi fi
elif [ -z "${FILE_EXT}" ]; then
if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$'; then
validate_archive
# Based on the file name, looks like we are importing a raw bastille image
# Import from uncompressed image file
info "Importing '${TARGET_TRIM}' from uncompressed image archive."
info "Receiving ZFS data stream..."
zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET_TRIM}" < "${bastille_backupsdir}/${TARGET}"
# Update ZFS mountpoint property if required
update_zfsmount
else
# Based on the file name, looks like we are importing from previous redirected bastille image
# Quietly import from previous redirected bastille image
if ! zfs receive ${OPT_ZRECV} "${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${TARGET}"; then
exit 1
else
# Update ZFS mountpoint property if required
update_zfsmount
fi
fi
else else
error_exit "Unknown archive format." error_exit "Unknown archive format."
fi fi
@@ -412,6 +499,9 @@ jail_import() {
if [ "${FILE_EXT}" = ".txz" ]; then if [ "${FILE_EXT}" = ".txz" ]; then
info "Extracting files from '${TARGET}' archive..." info "Extracting files from '${TARGET}' archive..."
tar -Jxf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}" tar -Jxf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}"
elif [ "${FILE_EXT}" = ".tgz" ]; then
info "Extracting files from '${TARGET}' archive..."
tar -xf "${bastille_backupsdir}/${TARGET}" -C "${bastille_jailsdir}"
elif [ "${FILE_EXT}" = ".tar.gz" ]; then elif [ "${FILE_EXT}" = ".tar.gz" ]; then
# Attempt to import/configure foreign/ezjail container # Attempt to import/configure foreign/ezjail container
info "Extracting files from '${TARGET}' archive..." info "Extracting files from '${TARGET}' archive..."
@@ -442,7 +532,9 @@ jail_import() {
# This is required on foreign imports only # This is required on foreign imports only
update_jailconf update_jailconf
update_fstab update_fstab
info "Container '${TARGET_TRIM}' imported successfully." if [ -z "${USER_IMPORT}" ]; then
info "Container '${TARGET_TRIM}' imported successfully."
fi
exit 0 exit 0
fi fi
else else
@@ -465,22 +557,32 @@ fi
# Check if archive exist then trim archive name # Check if archive exist then trim archive name
if [ -f "${bastille_backupsdir}/${TARGET}" ]; then if [ -f "${bastille_backupsdir}/${TARGET}" ]; then
# Filter unsupported/unknown archives # Filter unsupported/unknown archives
if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.xz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.txz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}.zip$\|-[0-9]\{12\}.[0-9]\{2\}.tar.gz$\|@[0-9]\{12\}.[0-9]\{2\}.tar$'; then if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.xz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.gz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.tgz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.txz$\|_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}.zip$\|-[0-9]\{12\}.[0-9]\{2\}.tar.gz$\|@[0-9]\{12\}.[0-9]\{2\}.tar$'; then
if ls "${bastille_backupsdir}" | awk "/^${TARGET}$/" >/dev/null; then if ls "${bastille_backupsdir}" | awk "/^${TARGET}$/" >/dev/null; then
TARGET_TRIM=$(echo "${TARGET}" | sed "s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.xz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.txz//;s/_[0-9]*-[0-9]*-[0-9]*.zip//;s/-[0-9]\{12\}.[0-9]\{2\}.tar.gz//;s/@[0-9]\{12\}.[0-9]\{2\}.tar//") TARGET_TRIM=$(echo "${TARGET}" | sed "s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.xz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.gz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.tgz//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*.txz//;s/_[0-9]*-[0-9]*-[0-9]*.zip//;s/-[0-9]\{12\}.[0-9]\{2\}.tar.gz//;s/@[0-9]\{12\}.[0-9]\{2\}.tar//;s/_[0-9]*-[0-9]*-[0-9]*-[0-9]*//")
fi fi
else else
error_exit "Unrecognized archive name." error_exit "Unrecognized archive name."
fi fi
else else
error_exit "Archive '${TARGET}' not found." if echo "${TARGET}" | grep -q '_[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}-[0-9]\{6\}.*$'; then
error_exit "Archive '${TARGET}' not found."
else
# Assume user will import from standard input
TARGET_TRIM=${TARGET}
USER_IMPORT="1"
fi
fi fi
# Check if a running jail matches name or already exist # Check if a running jail matches name or already exist
if [ -n "$(jls name | awk "/^${TARGET_TRIM}$/")" ]; then if [ -n "$(jls name | awk "/^${TARGET_TRIM}$/")" ]; then
error_exit "A running jail matches name." error_exit "A running jail matches name."
elif [ -d "${bastille_jailsdir}/${TARGET_TRIM}" ]; then elif [ -n "${TARGET_TRIM}" ]; then
error_exit "Container: ${TARGET_TRIM} already exists." if [ -d "${bastille_jailsdir}/${TARGET_TRIM}" ]; then
error_exit "Container: ${TARGET_TRIM} already exists."
fi
fi fi
jail_import if [ -n "${TARGET}" ]; then
jail_import
fi

View File

@@ -55,9 +55,12 @@ for _jail in ${JAILS}; do
pfctl -q -t jails -T delete "$(jls -j ${_jail} ip4.addr)" pfctl -q -t jails -T delete "$(jls -j ${_jail} ip4.addr)"
fi fi
fi fi
if [ "$(bastille rdr ${_jail} list)" ]; then # Check if pfctl is present
bastille rdr ${_jail} clear if which -s pfctl; then
if [ "$(bastille rdr ${_jail} list)" ]; then
bastille rdr ${_jail} clear
fi
fi fi
## remove rctl limits ## remove rctl limits