#!/usr/bin/env bash # Put it into /usr/lib/cups/backend/bbb-copy-raw # This virtual "printer" is run after BigBlueButton collects # all artefacts of the meeting to /var/bigbluebutton/recording/raw/$meeting_id # and sends all that to a special worker which processes (converts) recordings. # All recordings are sent, even those where recording was not turned on, # because it may have been not turned on erroneously and so we still have # to keep the recording artefact. The storage of recordings will rotate them. # "Printer class" in CUPS may be used to load balance processing of recordings # to multiple workers. Printer Device URI can be used to show which "printer" # (recordings processing worker) has been chosen by CUPS. # Authors: # - Mikhail Novosyolov , 2021 # Based on examples at https://community.kde.org/Printing/Developer_Tools # Docs: # - backend(7) https://www.cups.org/doc/man-backend.html ############################################################################### set -efu set -o pipefail # jobtitle=meeting ID (/var/bigbluebutton/recording/raw/$meeting_id), # we are not interested in all other variables readonly jobtitle=${3} BBB_DIR_RAW="${BBB_DIR_RAW:-/var/bigbluebutton/recording/raw}" # Exit codes from /usr/include/cups/backend.h CUPS_BACKEND_OK=0 # Job completed successfully CUPS_BACKEND_FAILED=1 # Job failed, use error-policy CUPS_BACKEND_AUTH_REQUIRED=2 # Job failed, authentication required CUPS_BACKEND_HOLD=3 # Job failed, hold job CUPS_BACKEND_STOP=4 # Job failed, stop queue CUPS_BACKEND_CANCEL=5 # Job failed, cancel job CUPS_BACKEND_RETRY=6 # Job failed, retry this job later CUPS_BACKEND_RETRY_CURRENT=7 # Job failed, retry this job immediately # We use 'set -e', script may fail somewhere, # make CUPS restart the job later if the error was unexpected _trap_exit(){ if [ $? != "$CUPS_BACKEND_OK" ] && [ $? != "$CUPS_BACKEND_FAILED" ]; then exit "$CUPS_BACKEND_RETRY" fi } trap '_trap_exit' EXIT input="" case ${#} in 0 ) # This is CUPS listing backends # device-class scheme "Unknown" "device-info" echo direct bbb-copy-raw \"Unknown\" \"Collect raw recording of BigBlueButton\" exit ;; 12 ) input=/dev/stdin ;; 13 ) # do not remove {} here! input="${13}" ;; * ) echo CRIT: unsupported number of arguements! 1>&2 exit "$CUPS_BACKEND_FAILED" ;; esac if [ "$jobtitle" = "(stdin)" ]; then echo CRIT: printing job must be titled! 1>&2 exit "$CUPS_BACKEND_FAILED" fi if [ -z "$jobtitle" ]; then echo CRIT: empty title of the printing job! 1>&2 exit "$CUPS_BACKEND_FAILED" fi # Examples of valid URIs: # - local/srv/container2/raw # it means copy from /var/bigbluebutton/recording/raw/$meeting_id to /srv/container2/raw/$meeting_id DEVICE_URI="$(echo "$DEVICE_URI" | sed -e 's,^bbb-copy-raw://,,' -e 's,^bbb-copy-raw:/,,')" case "$DEVICE_URI" in local/* ) # https://docstore.mik.ua/orelly/unix3/upt/ch10_13.htm # pack /var/bigbluebutton/recording/raw/$meeting_id into file.tar (root of $meeting_id = root of tarball) # and send to stdin of CUPS target_dir=/"$(echo "$DEVICE_URI" | sed -e 's,^local/,,')" if ! test -d "$target_dir"; then echo CRIT: directory "$target_dir" does not exist! 1>&2 exit "$CUPS_BACKEND_FAILED" fi mkdir -p "$target_dir"/"$jobtitle" dd if="$input" | tar -C "$target_dir"/"$jobtitle" xf - echo > "$target_dir"/"$jobtitle"/.cups.copied_raw chown -R bigbluebutton:bigbluebutton "$target_dir"/"$jobtitle" # TODO: rebuild recordings via CUPS instead of bbb worker in ruby #if [ "$target_dir" = /var/bigbluebutton/recording/raw ]; then # bbb-record --rebuild "$jobtitle" #fi ;; # XXX ssh probably makes no sense here, comment it for now # ssh can make sense if we use ionotify on directory where new recordings appear and run building task # but we run CUPS on every wndpoint, so ssh seems to not make any sense # ssh/* ) # ssh_port="$(echo "$DEVICE_URI" | awk -F '/' '{print $2}')" # ssh_userhost="$(echo "$DEVICE_URI" | awk -F '/' '{print $3}')" # # ssh/port/user@host/remote_path/dir1/dir2 -> remote_path/dir1/dir2 # # https://stackoverflow.com/a/49130247 # ssh_remote_path="$(echo "$DEVICE_URI" | awk -F '/' '{for(i=4; i<=NF; ++i) printf "%s/", $i;}')" # # TODO: run as sudo -u ssh ... # ssh -p "$ssh_port" "$ssh_userhost" mkdir -p "$ssh_remote_path"/"$jobtitle" # dd if="$input" | ssh -p "$ssh_port" "$ssh_userhost" tar -C "$ssh_remote_path"/"$jobtitle" xf - # ;; * ) echo CRIT: Device URI is not supported! 1>&1 exit "$CUPS_BACKEND_FAILED" ;; esac