Backup and Restore implementation changes

This commit is contained in:
Jose
2019-11-21 01:28:33 -04:00
parent ffe34ddc12
commit 5f7e712b9e
5 changed files with 161 additions and 13 deletions

View File

@@ -3,6 +3,7 @@
====================== ======================
Version Description Version Description
1.0.11......Backup and Restore implementation changes.
1.0.10......Cosmetic changes and version number adjust. 1.0.10......Cosmetic changes and version number adjust.
1.0.09......Allow for distfiles download override. 1.0.09......Allow for distfiles download override.
1.0.08......Add option for thickjail creation if supported. 1.0.08......Add option for thickjail creation if supported.

View File

@@ -51,6 +51,10 @@ SCRIPTNAME=$(basename $0)
CONFIG="/cf/conf/config.xml" CONFIG="/cf/conf/config.xml"
PRDNAME="Bastille" PRDNAME="Bastille"
APPNAME="bastille" APPNAME="bastille"
DEF_ZFS_SENDPARAMS=""
DEF_ZFS_RECVPARAM=""
DEF_ZFS_COMPRESS="xz -0 -v --threads=0"
DEF_ZFS_DECOMPRESS="xz -c -d -v --threads=0"
EXTLOGFILE="${CWDIR}/log/bastille_ext.log" EXTLOGFILE="${CWDIR}/log/bastille_ext.log"
FULLAPPNAME="${APPNAME}-dist" FULLAPPNAME="${APPNAME}-dist"
WWWPATH="/usr/local/www" WWWPATH="/usr/local/www"
@@ -71,6 +75,12 @@ BATSILLE_URL="https://github.com/BastilleBSD/${APPNAME}/archive/${BRANCH}.zip" #
BASTILE_VERSION="https://raw.githubusercontent.com/BastilleBSD/${APPNAME}/${BRANCH}/usr/local/bin/${APPNAME}" BASTILE_VERSION="https://raw.githubusercontent.com/BastilleBSD/${APPNAME}/${BRANCH}/usr/local/bin/${APPNAME}"
GITURL="https://github.com/JRGTH/xigmanas-${APPNAME}-extension/archive/${BRANCH}.zip" GITURL="https://github.com/JRGTH/xigmanas-${APPNAME}-extension/archive/${BRANCH}.zip"
VERFILE="https://raw.githubusercontent.com/JRGTH/xigmanas-${APPNAME}-extension/${BRANCH}/version" VERFILE="https://raw.githubusercontent.com/JRGTH/xigmanas-${APPNAME}-extension/${BRANCH}/version"
ARG="$2"
# Required
if [ -f "${BASTILLECONF}" ]; then
. /${BASTILLECONF}
fi
error_notify() error_notify()
{ {
@@ -88,6 +98,8 @@ runtime_config()
sysrc -f ${INSTALLPATH}/${BASTILLECONF} bastille_prefix="${CWDIR}" >/dev/null 2>&1 sysrc -f ${INSTALLPATH}/${BASTILLECONF} bastille_prefix="${CWDIR}" >/dev/null 2>&1
fi fi
fi fi
# Check for directories.
if [ ! -d ${CWDIR}/backups ]; then if [ ! -d ${CWDIR}/backups ]; then
mkdir -p ${CWDIR}/backups mkdir -p ${CWDIR}/backups
fi fi
@@ -100,6 +112,20 @@ runtime_config()
if [ ! -d ${CWDIR}/locale-bastille ]; then if [ ! -d ${CWDIR}/locale-bastille ]; then
mkdir -p ${CWDIR}/locale-bastille mkdir -p ${CWDIR}/locale-bastille
fi fi
# Set rquired zfs send/recv parameters is missing.
if ! grep -qw "ZFS_SENDPARAMS=" ${CWDIR}${EXTCONF} >/dev/null 2>&1; then
sysrc -f ${CWDIR}${EXTCONF} ZFS_SENDPARAMS="${DEF_ZFS_SENDPARAMS}" >/dev/null 2>&1
fi
if ! grep -qw "ZFS_RECVPARAM=" ${CWDIR}${EXTCONF} >/dev/null 2>&1; then
sysrc -f ${CWDIR}${EXTCONF} ZFS_RECVPARAM="${DEF_ZFS_RECVPARAM}" >/dev/null 2>&1
fi
if ! grep -qw "DEFAULT_COMPRESS=" ${CWDIR}${EXTCONF} >/dev/null 2>&1; then
sysrc -f ${CWDIR}${EXTCONF} ZFS_COMPRESS="${DEF_ZFS_COMPRESS}" >/dev/null 2>&1
fi
if ! grep -qw "DEFAULT_DECOMPRESS=" ${CWDIR}${EXTCONF} >/dev/null 2>&1; then
sysrc -f ${CWDIR}${EXTCONF} ZFS_DECOMPRESS="${DEF_ZFS_DECOMPRESS}" >/dev/null 2>&1
fi
} }
bastille_initial_download() bastille_initial_download()
@@ -307,7 +333,9 @@ sys_symlinkdir()
fi fi
else else
if [ -f "${BASTILLECONF_EXT}" ]; then if [ -f "${BASTILLECONF_EXT}" ]; then
cp ${BASTILLECONF_EXT} ${INSTALLPATH}/${USRLOCAL}/etc/${APPNAME}/${APPNAME}.conf if [ ! -f "${INSTALLPATH}/${USRLOCAL}/etc/${APPNAME}/${APPNAME}.conf" ]; then
cp ${BASTILLECONF_EXT} ${INSTALLPATH}/${USRLOCAL}/etc/${APPNAME}/${APPNAME}.conf
fi
fi fi
fi fi
@@ -455,6 +483,87 @@ gui_disable()
fi fi
} }
jail_backup()
{
# Backup container on request.
ZFS_COMPRESS=$(sysrc -f ${CWDIR}${EXTCONF} -qn ZFS_COMPRESS)
ZFS_SENDPARAMS=$(sysrc -f ${CWDIR}${EXTCONF} -qn ZFS_SENDPARAMS)
JAIL_NAME="${ARG}"
DATE=$(date +%Y-%m-%d-%H%M%S)
EXCLUDE="--exclude=.bastille --exclude=.template"
if [ -n "${JAIL_NAME}" ]; then
if [ -d "${CWDIR}/jails/${JAIL_NAME}" ]; then
if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ ! -z "${bastille_zfs_zpool}" ]; then
# Take a temp snapshot of the jail.
SNAP_NAME="bastille-$(date +%Y-%m-%d-%H%M%S)"
zfs snapshot -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL_NAME}@${SNAP_NAME}
# Backup the jail then cleanup temp zfs snapshots.
zfs send ${ZFS_SENDPARAMS} -R ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL_NAME}@${SNAP_NAME} | ${ZFS_COMPRESS} > ${CWDIR}/backups/${JAIL_NAME}-${DATE}.zfs
zfs destroy -r ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${JAIL_NAME}@${SNAP_NAME}
fi
else
# Create backup file with tar.
cd ${CWDIR}/jails && tar ${EXCLUDE} -zcf ${JAIL_NAME}-${DATE}.tar ${JAIL_NAME} && mv ${JAIL_NAME}-${DATE}.tar ${CWDIR}/backups
fi
if [ $? -ne 0 ]; then
echo "Failed to backup '${JAIL_NAME}' container."
exit 1
else
exit 0
fi
else
echo "Container '${JAIL_NAME}' does not exist."
exit 1
fi
else
exit 0
fi
}
jail_restore()
{
# Restore container on request.
ZFS_DECOMPRESS=$(sysrc -f ${CWDIR}${EXTCONF} -qn ZFS_DECOMPRESS)
ZFS_RECVPARAM=$(sysrc -f ${CWDIR}${EXTCONF} -qn ZFS_RECVPARAM)
BACKUP_FILE="${ARG}"
NAME_TRIM=$(echo ${BACKUP_FILE} | awk '{print $1}' | grep -o '[^/]*$' | cut -d '-' -f1)
if [ -f "${CWDIR}/backups/${BACKUP_FILE}" ]; then
if [ -d "${CWDIR}/jails" ]; then
if [ ! -d "${CWDIR}/jails/${NAME_TRIM}" ]; then
if [ "${bastille_zfs_enable}" = "YES" ]; then
if [ ! -z "${bastille_zfs_zpool}" ]; then
# Restore from zfs file and mount jail/root dataset.
${ZFS_DECOMPRESS} ${CWDIR}/backups/${BACKUP_FILE} | zfs receive ${ZFS_RECVPARAM} ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME_TRIM}
zfs mount ${bastille_zfs_zpool}/${bastille_zfs_prefix}/jails/${NAME_TRIM}/root
fi
else
# Restore from tar file.
tar -xf ${CWDIR}/backups/${BACKUP_FILE} -C ${CWDIR}/jails
fi
if [ $? -ne 0 ]; then
echo "Failed to restore '${NAME_TRIM}' container."
exit 1
else
mkdir -p ${CWDIR}/jails/${NAME_TRIM}/root/.bastille
mkdir -p ${CWDIR}/jails/${NAME_TRIM}/root/.template
exit 0
fi
else
echo "Container '${NAME_TRIM}' directory/dataset already exist."
exit 1
fi
else
echo "Jails directory/dataset does not exist."
exit 1
fi
else
echo "Archive '${BACKUP_FILE}' does not exist."
exit 1
fi
}
pkg_upgrade() pkg_upgrade()
{ {
# Re-fetch bastille package and extract. # Re-fetch bastille package and extract.
@@ -695,9 +804,9 @@ bastille_init()
# Run-time configuration. # Run-time configuration.
runtime_config runtime_config
while getopts ":ospruxRvgth" option; do while getopts ":ospruxUvgtBRh" option; do
case ${option} in case ${option} in
[h]) echo "Usage: ${SCRIPTNAME} -[option]"; [h]) echo "Usage: ${SCRIPTNAME} -[option] | [container]";
echo "Options:" echo "Options:"
echo " -s Start All ${PRDNAME} Containers." echo " -s Start All ${PRDNAME} Containers."
echo " -p Stop All ${PRDNAME} Containers." echo " -p Stop All ${PRDNAME} Containers."
@@ -706,8 +815,10 @@ while getopts ":ospruxRvgth" option; do
echo " -v Display product versions." echo " -v Display product versions."
echo " -g Enables the addon GUI." echo " -g Enables the addon GUI."
echo " -t Disable the addon GUI." echo " -t Disable the addon GUI."
echo " -B Backup a ${PRDNAME} container."
echo " -R Restore a ${PRDNAME} container."
echo " -x Reset ${PRDNAME}/Extension config." echo " -x Reset ${PRDNAME}/Extension config."
echo " -R Remove ${PRDNAME} (Extension files only)." echo " -U Uninstall ${PRDNAME} (Extension files only)."
echo " -h Display this help message."; exit 0;; echo " -h Display this help message."; exit 0;;
[o]) OBI_INSTALL="ON";; # To prevent nested PHP-CGI call for installation with OBI. [o]) OBI_INSTALL="ON";; # To prevent nested PHP-CGI call for installation with OBI.
[s]) bastille_start;; [s]) bastille_start;;
@@ -715,10 +826,12 @@ while getopts ":ospruxRvgth" option; do
[r]) bastille_restart;; [r]) bastille_restart;;
[u]) pkg_upgrade;; [u]) pkg_upgrade;;
[x]) reset_install;; [x]) reset_install;;
[R]) remove_addon;; [U]) remove_addon;;
[v]) get_versions;; [v]) get_versions;;
[g]) gui_enable; exit 0 ;; # For enable the addon gui. [g]) gui_enable; exit 0 ;; # For enable the addon gui.
[t]) gui_disable; exit 0 ;; # For disable the addon gui. [t]) gui_disable; exit 0 ;; # For disable the addon gui.
[B]) jail_backup;;
[R]) jail_restore;;
[?]) echo "Invalid option, -h for usage."; exit 1;; [?]) echo "Invalid option, -h for usage."; exit 1;;
esac esac
done done

View File

@@ -40,6 +40,7 @@ require_once 'system.inc';
// internal PHP functions rather than external shell commands. // internal PHP functions rather than external shell commands.
//$rootfolder = dirname($config['rc']['postinit']['cmd'][$i]); //$rootfolder = dirname($config['rc']['postinit']['cmd'][$i]);
$application = "Bastille Manager";
$restore_name = "restore"; $restore_name = "restore";
$confdir = "/var/etc/bastille_conf"; $confdir = "/var/etc/bastille_conf";
$cwdir = exec("/usr/bin/grep 'INSTALL_DIR=' {$confdir}/conf/bastille_config | /usr/bin/cut -d'\"' -f2"); $cwdir = exec("/usr/bin/grep 'INSTALL_DIR=' {$confdir}/conf/bastille_config | /usr/bin/cut -d'\"' -f2");

View File

@@ -41,7 +41,6 @@ require("auth.inc");
require("guiconfig.inc"); require("guiconfig.inc");
require_once("bastille_manager-lib.inc"); require_once("bastille_manager-lib.inc");
$application = "Bastille";
$pgtitle = array(gtext("Extensions"), "Bastille", "Maintenance"); $pgtitle = array(gtext("Extensions"), "Bastille", "Maintenance");
// For legacy product versions. // For legacy product versions.
@@ -87,7 +86,7 @@ if ($_POST) {
if (is_dir($confdir)) mwexec("rm -Rf {$confdir}", true); if (is_dir($confdir)) mwexec("rm -Rf {$confdir}", true);
mwexec("rm /usr/local/www/bastille_manager_gui.php && rm -R /usr/local/www/ext/bastille", true); mwexec("rm /usr/local/www/bastille_manager_gui.php && rm -R /usr/local/www/ext/bastille", true);
mwexec("{$rootfolder}/usr/local/sbin/bastille-init -t", true); mwexec("{$rootfolder}/usr/local/sbin/bastille-init -t", true);
$uninstall_cmd = "echo 'y' | /usr/local/sbin/bastille-init -R"; $uninstall_cmd = "echo 'y' | /usr/local/sbin/bastille-init -U";
mwexec($uninstall_cmd, true); mwexec($uninstall_cmd, true);
if (is_link("/usr/local/share/{$prdname}")) mwexec("rm /usr/local/share/{$prdname}", true); if (is_link("/usr/local/share/{$prdname}")) mwexec("rm /usr/local/share/{$prdname}", true);
if (is_link("/var/cache/pkg")) mwexec("rm /var/cache/pkg", true); if (is_link("/var/cache/pkg")) mwexec("rm /var/cache/pkg", true);
@@ -137,18 +136,50 @@ if ($_POST) {
unset($retval);mwexec($cmd,$retval); unset($retval);mwexec($cmd,$retval);
if ($retval == 0) { if ($retval == 0) {
$savemsg .= gtext("Extension settings saved successfully."); $savemsg .= gtext("Extension settings saved successfully.");
exec("echo '{$date}: {$application} Extension settings saved successfully' >> {$logfile}"); exec("echo '{$date}: {$application}: Extension settings saved successfully' >> {$logfile}");
} }
else { else {
$input_errors[] = gtext("Failed to save extension settings."); $input_errors[] = gtext("Failed to save extension settings.");
exec("echo '{$date}: {$application} Failed to save extension settings' >> {$logfile}"); exec("echo '{$date}: {$application}: Failed to save extension settings' >> {$logfile}");
} }
} }
else { else {
$input_errors[] = gtext("Failed to save extension settings."); $input_errors[] = gtext("Failed to save extension settings.");
exec("echo '{$date}: {$application} Failed to save extension settings' >> {$logfile}"); exec("echo '{$date}: {$application}: Failed to save extension settings' >> {$logfile}");
} }
} }
if (isset($_POST['restore']) && $_POST['restore']) {
// Ensure to have NO whitespace & trailing slash.
$backup_file = rtrim(trim($_POST['backup_path']),'/');
$filename_trim = exec("echo {$backup_file} | awk '{print $1}' | grep -o '[^/]*$'");
$jailname_trim = exec("echo {$backup_file} | awk '{print $1}' | grep -o '[^/]*$' | cut -d '-' -f1");
if ("{$backup_file}" == "") {
$input_errors[] = gtext("Error: backup file undefined.");
}
if (is_dir("{$jail_dir}/{$jailname_trim}")):
$input_errors[] = gtext("Container directory/dataset already exist.");
else:
if (is_file($backup_file)) {
$cmd = ("/usr/local/sbin/bastille-init -R '{$filename_trim}'");
unset($retval);mwexec($cmd,$retval);
if ($retval == 0) {
$savemsg .= gtext("Container restored successfully.");
exec("echo '{$date}: {$application}: Container restored successfully from {$filename_trim}' >> {$logfile}");
}
else {
$input_errors[] = gtext("Failed to restore container.");
exec("echo '{$date}: {$application}: Failed to restore container from {$filename_trim}' >> {$logfile}");
}
}
else {
$input_errors[] = gtext("Failed to restore container, file not found.");
exec("echo '{$date}: {$application}: Failed to restore container, file {$filename_trim} not found' >> {$logfile}");
}
endif;
}
} }
function get_version_bastille() { function get_version_bastille() {
@@ -240,11 +271,12 @@ $(document).ready(function(){
<td class="vncellt"><?=gtext("Extension version");?></td> <td class="vncellt"><?=gtext("Extension version");?></td>
<td class="vtable"><span name="getinfo_ext" id="getinfo_ext"><?=get_version_ext()?></span></td> <td class="vtable"><span name="getinfo_ext" id="getinfo_ext"><?=get_version_ext()?></span></td>
</tr> </tr>
<?php html_filechooser("backup_path", gtext("Backup directory"), $backup_path, gtext("Directory to store containers .tar backup archives."), $backup_path, true, 60);?> <?php html_filechooser("backup_path", gtext("Backup directory"), $backup_path, gtext("Directory to store containers .tar backup archives, use as file chooser for restoring from file."), $backup_path, true, 60);?>
</table> </table>
<div id="submit"> <div id="submit">
<input id="save" name="save" type="submit" class="formbtn" title="<?=gtext("Save settings");?>" value="<?=gtext("Save");?>"/> <input id="save" name="save" type="submit" class="formbtn" title="<?=gtext("Save settings");?>" value="<?=gtext("Save");?>"/>
<input name="upgrade" type="submit" class="formbtn" title="<?=gtext("Upgrade Extension and Bastille Packages");?>" value="<?=gtext("Upgrade");?>" /> <input name="upgrade" type="submit" class="formbtn" title="<?=gtext("Upgrade Extension and Bastille Packages");?>" value="<?=gtext("Upgrade");?>" />
<input name="restore" type="submit" class="formbtn" title="<?=gtext("Restore a container");?>" value="<?=gtext("Restore");?>" />
</div> </div>
<div id="remarks"> <div id="remarks">
<?php html_remark("note", gtext("Info"), sprintf(gtext("For general information visit the following link(s):")));?> <?php html_remark("note", gtext("Info"), sprintf(gtext("For general information visit the following link(s):")));?>

View File

@@ -114,15 +114,16 @@ if($_POST):
$container['jailname'] = $_POST['jailname']; $container['jailname'] = $_POST['jailname'];
$confirm_name = $pconfig['confirmname']; $confirm_name = $pconfig['confirmname'];
$item = $container['jailname']; $item = $container['jailname'];
$date = (strftime('%Y-%m-%d-%H%M%S')); $cmd = ("/usr/local/sbin/bastille-init -B '{$item}'");
$cmd = ("cd {$rootfolder}/jails && /usr/bin/tar -cf {$item}-{$date}.tar --exclude=.bastille --exclude=.template {$item} && /bin/mv {$item}-{$date}.tar {$backup_path}");
unset($output,$retval);mwexec2($cmd,$output,$retval); unset($output,$retval);mwexec2($cmd,$output,$retval);
if($retval == 0): if($retval == 0):
$savemsg .= gtext("Container backup process completed successfully."); $savemsg .= gtext("Container backup process completed successfully.");
exec("echo '{$date}: {$application}: Container backup process completed successfully for {$item}' >> {$logfile}");
//header('Location: bastille_manager_gui.php'); //header('Location: bastille_manager_gui.php');
//exit; //exit;
else: else:
$errormsg .= gtext("Failed to backup container."); $errormsg .= gtext("Failed to backup container.");
exec("echo '{$date}: {$application}: Failed to backup container {$item}' >> {$logfile}");
endif; endif;
endif; endif;
break; break;