Ninth Commit - working on backups

This commit is contained in:
Andrew Hurley 2023-03-04 15:27:45 +08:00
parent 72cf21db20
commit dda4dd3f22
1 changed files with 151 additions and 83 deletions

236
podmanctl
View File

@ -8,14 +8,15 @@ set -e
# sub ----------------------------------------------------- usage # sub ----------------------------------------------------- usage
usage () { usage () {
printf "Usage:\n" printf "Usage:\n"
printf " podmanctl [<options>] <project> [<project>...]\n" printf " podmanctl [<options>] <server> [<server>...]\n"
printf " - command is assumed to be 'create'\n" printf " - command is assumed to be 'create'\n"
printf " podmanctl [${COMMANDS}] [<options>] <project> [<project>...]\n" printf " podmanctl [${COMMANDS}] [<options>] <server> [<server>...]\n"
printf " Options:\n" printf " Options:\n"
printf " For run|create:\n" printf " For run|create:\n"
printf " -e <additional_environment_vars>\n" printf " -e <additional_environment_vars>\n"
printf " For backup:\n" printf " For backup:\n"
printf " -d (keep containers down)\n" printf " -d (keep containers down)\n"
printf " -w (store backups under weekday subdirectory)\n"
} }
# --------------------------------------------------------- command # --------------------------------------------------------- command
@ -38,7 +39,8 @@ fi
ARGS_ENV="" ARGS_ENV=""
PULL="" PULL=""
DOWN="false" DOWN="false"
while getopts ':pe:' OPT; do WEEKDAY=""
while getopts ':pe:dw' OPT; do
case $OPT in case $OPT in
e) e)
if [[ "${COMMAND}" =~ ^(create|run)$ ]]; then if [[ "${COMMAND}" =~ ^(create|run)$ ]]; then
@ -64,6 +66,14 @@ while getopts ':pe:' OPT; do
exit 1 exit 1
fi fi
;; ;;
w)
if [[ "${COMMAND}" =~ ^(backup)$ ]]; then
WEEKDAY="$(date +%^a)/"
else
printf "option 'w' does not apply to command '${COMMAND}'\n"
exit 1
fi
;;
\?) \?)
usage usage
@ -100,7 +110,7 @@ start-pod () {
|grep -Fq "podman-${PODNAME}.service"; then |grep -Fq "podman-${PODNAME}.service"; then
systemctl start podman-${PODNAME}.service || return 1 systemctl start podman-${PODNAME}.service || return 1
else else
printf ":: ${COMMAND} ${PROJECT} - service not found!\n"; return 2 printf ":: ${COMMAND} ${SERVER} - service not found!\n"; return 2
fi fi
} }
@ -110,7 +120,7 @@ restart-pod () {
|grep -Fq "podman-${PODNAME}.service"; then |grep -Fq "podman-${PODNAME}.service"; then
systemctl restart podman-${PODNAME}.service || return 1 systemctl restart podman-${PODNAME}.service || return 1
else else
printf ":: ${COMMAND} ${PROJECT} - service not found!\n"; return 2 printf ":: ${COMMAND} ${SERVER} - service not found!\n"; return 2
fi fi
} }
@ -121,7 +131,7 @@ remove-services () {
fi fi
find "${SYSTEMD}" \ find "${SYSTEMD}" \
-maxdepth 1 \ -maxdepth 1 \
-name "podman-${PROJECT}-*.service" \ -name "podman-${SERVER}-*.service" \
-exec rm {} + -exec rm {} +
systemctl daemon-reload systemctl daemon-reload
} }
@ -149,96 +159,151 @@ clean-pod () {
# sub ----------------------------------------------------- backup volumes # sub ----------------------------------------------------- backup volumes
backup-volumes () { backup-volumes () {
VOLUMES="$(podman volume ls --filter="name=${PROJECT}-" -q |grep -v ".backup")" VOLUMES="$(podman volume ls --format='{{.Name}}' |grep -v ".backup" |grep "${SERVER}")"
if [[ -z $VOLUMES ]]; then if [[ -z $VOLUMES ]]; then
printf ":: ${COMMAND} ${PROJECT} - no volumes found to backup\n" printf ":: ${COMMAND} ${SERVER} - no volumes found to backup.\n"
return return
fi fi
for VOL in $VOLUMES; do for VOLUME in $VOLUMES; do
SOURCE="${VOL}" SOURCE="${VOLUME}"
TARGET="${VOL}.backup" TARGET="${VOLUME}.backup"
TARGET_VOLUME="$(docker volume ls -q --filter name="^${TARGET}$")" TARGET_VOLUME="$(docker volume ls -q --filter name="^${TARGET}$")"
if [[ -z $TARGET_VOLUME ]]; then if [[ -z $TARGET_VOLUME ]]; then
if docker volume create "${TARGET}"; then if docker volume create "${TARGET}"; then
printf ":: ${COMMAND} ${PROJECT} - target volume '${TARGET}' created.\n" printf ":: ${COMMAND} ${SERVER} - target volume '${TARGET}' created\n"
else else
printf ":: ${COMMAND} ${PROJECT} - target volume ${TARGET} could not be created.\n" printf ":: ${COMMAND} ${SERVER} - target volume ${TARGET} could not be created\n"
return 1 return 1
fi fi
fi fi
printf ":: ${COMMAND} ${PROJECT} - backup of source: ${SOURCE} to target ${TARGET} commencing\n" printf ":: ${COMMAND} ${SERVER} - rsync ${SOURCE} to ${TARGET} commencing\n"
if "${RUNTIME}" run --rm \ if "${RUNTIME}" run \
--rm \
--env "SOURCE_DIR=/source" \ --env "SOURCE_DIR=/source" \
--env "TARGET_DIR=/target" \ --env "TARGET_DIR=/target" \
--volume "${SOURCE}:/source:ro" \ --volume "${SOURCE}:/source:ro" \
--volume "${TARGET}:/target" \ --volume "${TARGET}:/target" \
cor.cherished.me/system/helper-rsync; then cor.cherished.me/system/helper-rsync \
printf ":: ${COMMAND} ${PROJECT} - backup successful.\n" > /dev/null; then
printf ":: ${COMMAND} ${SERVER} - backup of ${VOLUME} successful\n"
else else
printf ":: ${COMMAND} ${PROJECT} - backup error.\n"; return 2 printf ":: ${COMMAND} ${SERVER} - error in backup of ${VOLUME}\n"; return 2
fi fi
done done
} }
# sub ----------------------------------------------------- save images # sub ----------------------------------------------------- save images
save-images () { save-images () {
IMAGES="$(podman image ls --filter="reference=\$${PROJECT}-*" --format="{{.Repository}}" |grep -v "docker.io")" IMAGES="$(podman image ls --format="{{.Repository}}" |grep -v "docker.io" |grep "${SERVER}")"
if [[ -z $IMAGES ]]; then
printf ":: ${COMMAND} ${SERVER} - no images found\n"
return
fi
printf ":: ${COMMAND} ${SERVER} - SAVING IMAGES\n"
for IMAGE in $IMAGES; do for IMAGE in $IMAGES; do
podman image save --compress --format docker-dir --output "${BACKDIR}"/"$(basename $IMAGE)" $IMAGE OUT="${BACKDIR}/${WEEKDAY}$(basename $IMAGE)"
printf ":: ${COMMAND} ${SERVER} - saving image ${IMAGE} to ${OUT}\n"
if "${RUNTIME}" image save \
--compress \
--format docker-dir \
--output "${OUT}" \
"${IMAGE}" \
> /dev/null; then
printf ":: ${COMMAND} ${SERVER} - saving ${IMAGE} successful\n"
else
printf ":: ${COMMAND} ${SERVER} - error saving ${IMAGE}\n"; return 2
fi
done done
} }
# --------------------------------------------------------- save backup volumes # --------------------------------------------------------- save backup volumes
save-backups () { save-backups () {
echo "doit" VOLUMES="$(podman volume ls --format='{{.Name}}' |grep ".backup" |grep "${SERVER}")"
if [[ -z $VOLUMES ]]; then
printf ":: ${COMMAND} ${SERVER} - no volumes found.\n"
return
fi
printf ":: ${COMMAND} ${SERVER} - EXPORT BACKUP VOLUMES.\n"
for VOLUME in $VOLUMES; do
OUT="${BACKDIR}/${WEEKDAY}${VOLUME}.tar"
printf ":: ${COMMAND} ${SERVER} - exporting volume ${VOLUME} to ${OUT}.\n" > /dev/null
if "${RUNTIME}" volume export \
--output "${OUT}" \
"${VOLUME}" > /dev/null; then
printf ":: ${COMMAND} ${SERVER} - exporting ${VOLUME} successful\n"
else
printf ":: ${COMMAND} ${SERVER} - error exporting ${VOLUME}\n"; return 2
fi
done
} }
# --------------------------------------------------------- main
# --------------------------------------------------------- starts
# --------------------------------------------------------- here
RUNTIME="podman"
CONFDIR="$(realpath ../config)"
PODMDIR="$(realpath ../podman)"
BACKDIR="$(realpath ../.store)"
CERTDIR="$(realpath ../.certs)"
REGADDR="cor.cherished.me/cherished.me"
SYSTEMD="/etc/systemd/system"
SYSTEMT="/srv"
# --------------------------------------------------------- rsync build
podman build \
-t cor.cherished.me/system/helper-rsync \
- <<EOT
FROM docker.io/weikinhuang/rsync-backup:amd64-b022c6c5bd9a553451e8c9114c7aa591ee9a7dc4-145886
EOT
# --------------------------------------------------------- project loop
for PROJECT in $*; do
if [[ ! -r ${PROJECT} ]]; then
printf "Project spec file '${PROJECT}' missing or not readable\n"
# --------------------------------------------------------- system top
SYSTEMT="$(realpath /srv)"
if [[ ! -d "${SYSTEMT}" ]]; then
printf "Error: /srv directory missing\n"
exit 1 exit 1
fi fi
# --------------------------------------------------------- project vars # --------------------------------------------------------- system runtime
NETWORK="${PROJECT}-net" RUNTIME="podman"
ENVFILE="${CONFDIR}/${PROJECT}-env.conf" RUNTDIR="${SYSTEMT}/${RUNTIME}"
PODNAME="${PROJECT}-pod" mkdir -p "${RUNTDIR}"
chmod 755 "${RUNTDIR}"
# project check # --------------------------------------------------------- system dirs
if [[ ! -r $ENVFILE ]] then BMNTDIR="${SYSTEMT}/.mount"
printf "Environment file ${ENVFILE} not found or readable.\n" ENVRDIR="${SYSTEMT}/.envar"
usage BACKDIR="${SYSTEMT}/.store"
exit 2; CERTDIR="${SYSTEMT}/.certs"
fi BUILDIR="${SYSTEMT}/builds"
if [[ ! "$(stat -L -c "%A" "${CONFDIR}" |cut -c8-10 )" = "---" ]] then
printf "Error: ${CONFDIR} is world readable\n" # --------------------------------------------------------- other dirs
usage SYSTEMD="/etc/systemd/system"
exit 3; REPADDR="cor.cherished.me/cherished.me"
# --------------------------------------------------------- dir checks
for DIR in \
${BMNTDIR} ${ENVRDIR} ${BACKDIR} ${CERTDIR} ${BUILDIR}; do
mkdir -p "${DIR}"
chmod 700 "${DIR}"
done
# --------------------------------------------------------- rsync build
IMG="cor.cherished.me/system/helper-rsync"
if ! podman image exists ${IMG}; then
"${RUNTIME}" build \
-t "${IMG}" \
"${BUILDIR}/github/weikinhuang/rsync-backup"
fi fi
printf ":: ${COMMAND} ${PROJECT}\n" # --------------------------------------------------------- server loop
for SERVER in $*; do
if [[ ! -r ${SERVER} ]]; then
printf ":: Server spec file '${SERVER}' missing or not readable\n"
usage
exit 1
fi
# --------------------------------------------------------- server vars
NETWORK="${SERVER}-net"
PODNAME="${SERVER}-pod"
printf ":: ${COMMAND} ${SERVER}\n"
# --------------------------------------------------------- network # --------------------------------------------------------- network
"${RUNTIME}" network exists ${NETWORK} \ "${RUNTIME}" network exists ${NETWORK} \
@ -246,7 +311,7 @@ for PROJECT in $*; do
SUBNET="$(podman network inspect ${NETWORK} \ SUBNET="$(podman network inspect ${NETWORK} \
|grep -w "\"subnet\":" |sed 's/[\":,a-z,A-Z ]//g')" |grep -w "\"subnet\":" |sed 's/[\":,a-z,A-Z ]//g')"
SUBNET_PREFIX="${SUBNET%\.0/24}" SUBNET_PREFIX="${SUBNET%\.0/24}"
#printf "${SUBNET_PREFIX}" > "${PROJECT}-subnet" #printf "${SUBNET_PREFIX}" > "${SERVER}-subnet"
# --------------------------------------------------------- proxy network # --------------------------------------------------------- proxy network
"${RUNTIME}" network exists proxy-net \ "${RUNTIME}" network exists proxy-net \
@ -260,34 +325,33 @@ for PROJECT in $*; do
(ps) (ps)
# --------------------------------------------------------- ps # --------------------------------------------------------- ps
${RUNTIME} ps -a --watch=1 --filter "pod=${PODNAME}" --format '{{.Names}}\t\t{{.Image}}\t\t{{.ExitCode}}\t\t{{.Status}}' ${RUNTIME} ps -a --filter "pod=${PODNAME}" --format '{{.Names}}\t\t{{.Image}}\t\t{{.ExitCode}}\t\t{{.Status}}'
;; ;;
(create|run) (create|run)
# --------------------------------------------------------- create|run # --------------------------------------------------------- create|run
SPEC_CREATE="${RUNTIME} create"
SPEC_IP="--ip ${SUBNET_PREFIX}" SPEC_IP="--ip ${SUBNET_PREFIX}"
SPEC_POD="--pod ${PODNAME}" SPEC_POD="--pod ${PODNAME}"
SPEC_PULL="${PULL}"
SPEC_DNS="--dns ${SUBNET_PREFIX}.254" SPEC_DNS="--dns ${SUBNET_PREFIX}.254"
SPEC_ENV="--env-file ${ENVFILE}" SPEC_ENV="--env SUBNET=${SUBNET} ${ARGS_ENV}"
SPEC_ENV="${SPEC_ENV} --env SUBNET=${SUBNET}" SPEC_ENVFILE="--env-file ${ENVRDIR}"
SPEC_ENV="${SPEC_ENV} ${ARGS_ENV}" SPEC_NAME="--name ${SERVER}"
SPEC_NAME="--name ${PROJECT}" SPEC_INFRA_NAME="--infra-name ${SERVER}-infra"
SPEC_INFRA_NAME="--infra-name ${PROJECT}-infra" SPEC_REPO="${REPADDR}/${SERVER}"
SPEC_IMAGE="${REGADDR}/${PROJECT}" SPEC_CERTS="--volume ${CERTDIR}"
SPEC_CONFIG="--volume ${CONFDIR}" SPEC_BMOUNT="--volume ${BMNTDIR}"
SPEC_SUBNET="--subnet ${SUBNET}" SPEC_SUBNET="--subnet ${SUBNET}"
SPEC_LABELS="--label io.containers.autoupdate=registry" SPEC_LABELS="--label io.containers.autoupdate=registry"
SPEC_VOLUME="--volume ${PROJECT}" SPEC_VOLUME="--volume ${SERVER}"
SPEC_NETWORK="--network ${NETWORK}" SPEC_NETWORK="--network ${NETWORK}"
SPEC_NETWORK_PREFIX="${SPEC_NETWORK}:ip=${SUBNET_PREFIX}" SPEC_NETWORK_PREFIX="${SPEC_NETWORK}:ip=${SUBNET_PREFIX}"
SPEC_PROXY_NET="--network proxy-net" SPEC_PROXY_NET="--network proxy-net"
SPEC_PROXY_NET_PREFIX="${SPEC_PROXY_NET}:ip=${PROXY_SUBNET_PREFIX}" SPEC_PROXY_NET_PREFIX="${SPEC_PROXY_NET}:ip=${PROXY_SUBNET_PREFIX}"
SPEC_HOSTS="" SPEC_HOSTS=""
SPEC_PUBLISH="" SPEC_PUBLISH="--publish"
SPEC_ALIAS="--network-alias " SPEC_ALIAS="--network-alias "
SPEC_BUILD="${RUNTIME} build ${PULL}"
SPEC_CREATE="${RUNTIME} create ${SPEC_POD} ${SPEC_LABELS} ${SPEC_ENV}"
# --------------------------------------------------------- recreate pod # --------------------------------------------------------- recreate pod
stop-pod stop-pod
@ -297,7 +361,7 @@ for PROJECT in $*; do
--replace --replace
# --------------------------------------------------------- create containers # --------------------------------------------------------- create containers
source ${PROJECT} source ${SERVER}
# --------------------------------------------------------- install services # --------------------------------------------------------- install services
install-services install-services
@ -307,24 +371,24 @@ for PROJECT in $*; do
systemctl start podman-${PODNAME} systemctl start podman-${PODNAME}
fi fi
printf ":: ${COMMAND} ${PROJECT} - success\n" printf ":: ${COMMAND} ${SERVER} - success\n"
;; ;;
(stop) (stop)
if stop-pod; then if stop-pod; then
printf ":: ${COMMAND} ${PROJECT} - success\n" printf ":: ${COMMAND} ${SERVER} - success\n"
else else
printf ":: ${COMMAND} ${PROJECT} - failure\n" printf ":: ${COMMAND} ${SERVER} - failure\n"
fi fi
;; ;;
(start) (start)
if start-pod; then if start-pod; then
printf ":: ${COMMAND} ${PROJECT} - success\n" printf ":: ${COMMAND} ${SERVER} - success\n"
else else
printf ":: ${COMMAND} ${PROJECT} - failure\n" printf ":: ${COMMAND} ${SERVER} - failure\n"
fi fi
sleep 1 sleep 1
;; ;;
@ -332,9 +396,9 @@ for PROJECT in $*; do
(restart) (restart)
if restart-pod; then if restart-pod; then
printf ":: ${COMMAND} ${PROJECT} - success\n" printf ":: ${COMMAND} ${SERVER} - success\n"
else else
printf ":: ${COMMAND} ${PROJECT} - failure\n" printf ":: ${COMMAND} ${SERVER} - failure\n"
fi fi
sleep 1 sleep 1
;; ;;
@ -342,9 +406,9 @@ for PROJECT in $*; do
(clean) (clean)
if clean-pod; then if clean-pod; then
printf ":: ${COMMAND} ${PROJECT} - success\n" printf ":: ${COMMAND} ${SERVER} - success\n"
else else
printf ":: ${COMMAND} ${PROJECT} - failure\n" printf ":: ${COMMAND} ${SERVER} - failure\n"
fi fi
;; ;;
@ -355,15 +419,16 @@ for PROJECT in $*; do
if [[ $DOWN == "false" ]]; then if [[ $DOWN == "false" ]]; then
start-pod start-pod
fi fi
printf ":: ${COMMAND} ${PROJECT} - success\n" save-backups
printf ":: ${COMMAND} ${SERVER} - success\n"
else else
printf ":: ${COMMAND} ${PROJECT} - failure\n" printf ":: ${COMMAND} ${SERVER} - failure\n"
fi fi
;; ;;
(restore) (restore)
printf ":: ${COMMAND} ${PROJECT} - not implemented\n"; continue printf ":: ${COMMAND} ${SERVER} - not implemented\n"; continue
;; ;;
(?) (?)
@ -373,3 +438,6 @@ for PROJECT in $*; do
esac esac
done done
# if [[ ! "$(stat -L -c "%A" "${DIR}" |cut -c5-10 )" = "------" ]] then