|
| 1 | +#!/usr/bin/env bash |
| 2 | +#/ Usage: ghe-restore-repositories-dgit-ng <host> |
| 3 | +#/ Restore repositories fron an rsync snapshot of all Git repository data to a GitHub cluster. |
| 4 | +#/ |
| 5 | +#/ Note: This script typically isn't called directly. It's invoked by the |
| 6 | +#/ ghe-restore command when restoring into a cluster. |
| 7 | +set -e |
| 8 | + |
| 9 | +# Bring in the backup configuration |
| 10 | +. $( dirname "${BASH_SOURCE[0]}" )/ghe-backup-config |
| 11 | + |
| 12 | +# Show usage and bail with no arguments |
| 13 | +[ -z "$*" ] && print_usage |
| 14 | + |
| 15 | +bm_start "$(basename $0)" |
| 16 | + |
| 17 | +# Grab host arg |
| 18 | +GHE_HOSTNAME="$1" |
| 19 | + |
| 20 | +# The snapshot to restore should be set by the ghe-restore command but this lets |
| 21 | +# us run this script directly. |
| 22 | +: ${GHE_RESTORE_SNAPSHOT:=current} |
| 23 | + |
| 24 | +network_paths=$(cd $GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT/ && find repositories -mindepth 6 -maxdepth 7 -name \*.git -exec dirname {} \; | uniq | grep nw | cut -d / -f2-) |
| 25 | + |
| 26 | +if [ -z "$network_paths" ]; then |
| 27 | + echo "Warning: Repositories backup missing. Skipping ..." |
| 28 | + exit 0 |
| 29 | +fi |
| 30 | + |
| 31 | +# Perform a host-check and establish GHE_REMOTE_XXX variables. |
| 32 | +ghe_remote_version_required "$GHE_HOSTNAME" |
| 33 | + |
| 34 | +# Generate SSH config for forwarding |
| 35 | +# Split host:port into parts |
| 36 | +port=$(ssh_port_part "$GHE_HOSTNAME") |
| 37 | +host=$(ssh_host_part "$GHE_HOSTNAME") |
| 38 | + |
| 39 | +# Add user / -l option |
| 40 | +user="${host%@*}" |
| 41 | +[ "$user" = "$host" ] && user="admin" |
| 42 | + |
| 43 | +tempdir=$(mktemp -d) |
| 44 | +ssh_config_file=$tempdir/ssh_config |
| 45 | +opts="$GHE_EXTRA_SSH_OPTS -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o PasswordAuthentication=no" |
| 46 | +tmp_list=$tempdir/tmp_list |
| 47 | +to_restore=$tempdir/to_restore |
| 48 | + |
| 49 | +hostnames=$(ghe-ssh "$GHE_HOSTNAME" ghe-config --get-regexp cluster.*.hostname | cut -d ' ' -f 2) |
| 50 | +for hostname in $hostnames; do |
| 51 | + echo " |
| 52 | +Host $hostname |
| 53 | + ServerAliveInterval 60 |
| 54 | + ProxyCommand ssh -q $GHE_EXTRA_SSH_OPTS -p $port $user@$host nc.openbsd %h %p |
| 55 | + StrictHostKeyChecking=no" >> $ssh_config_file |
| 56 | +done |
| 57 | + |
| 58 | +cleanup() { |
| 59 | + for hostname in $hostnames; do |
| 60 | + ghe-gc-enable -F $ssh_config_file $hostname:$port |
| 61 | + done |
| 62 | + rm -rf $tempdir |
| 63 | +} |
| 64 | +trap cleanup EXIT |
| 65 | + |
| 66 | +# Disable remote GC operations |
| 67 | +for hostname in $hostnames; do |
| 68 | + ghe-gc-disable -F $ssh_config_file $hostname:$port |
| 69 | +done |
| 70 | + |
| 71 | +# Build a list of network paths to send to the server to calculate |
| 72 | +# the restore routes, something like: |
| 73 | +# |
| 74 | +# a/nw/a8/3f/02/100000855 |
| 75 | +# a/nw/a8/bc/8d/100000880 |
| 76 | +# a/nw/a5/06/81/100000659 |
| 77 | +# a/nw/a5/84/6f/100000708 |
| 78 | +# a/nw/a5/e0/01/146 |
| 79 | +# ... |
| 80 | +# |
| 81 | +# One network path per line. |
| 82 | +OLDIFS=$IFS; IFS=$'\n' |
| 83 | +for path in $network_paths; do |
| 84 | + # Get the network ID |
| 85 | + # The nework id from a repository is the last component of the path |
| 86 | + # i.e. /data/repositories/a/nw/a5/bf/c9/37 network ID would be 37 |
| 87 | + ghe_verbose "Adding network_path $path to the list of networks to send" |
| 88 | + echo $path |
| 89 | +done > $tmp_list |
| 90 | +IFS=$OLDIFS |
| 91 | + |
| 92 | +# The server returns a list of routes: |
| 93 | +# |
| 94 | +# a/nw/a8/3f/02/100000855 dgit-node1 dgit-node2 dgit-node3 |
| 95 | +# a/nw/a8/bc/8d/100000880 dgit-node1 dgit-node2 dgit-node4 |
| 96 | +# a/nw/a5/06/81/100000659 dgit-node3 dgit-node2 dgit-node4 |
| 97 | +# ... |
| 98 | +# |
| 99 | +# One route per line. |
| 100 | +cat $tmp_list | ghe-ssh "$GHE_HOSTNAME" github-env ./bin/dgit-cluster-restore-routes \ |
| 101 | + | while read route; do |
| 102 | + ghe_verbose "Received route $route" |
| 103 | + servers=$(echo $route | cut -d ' ' -f2-) |
| 104 | + for server in $servers; do |
| 105 | + network_path=$(echo $route | cut -d ' ' -f1) |
| 106 | + ghe_verbose "Adding $network_path to $tempdir/$server.rsync" |
| 107 | + echo "$network_path" >> $tempdir/$server.rsync |
| 108 | + done |
| 109 | + |
| 110 | + network_id=$(echo $network_path | awk -F/ '{print $(NF)}') |
| 111 | + ghe_verbose "Route: $network_id /data/repositories/$network_path $servers" |
| 112 | + echo "$network_id /data/repositories/$network_path $servers" >> $to_restore |
| 113 | +done |
| 114 | + |
| 115 | +# rsync all the repositories |
| 116 | +for file_list in $tempdir/*.rsync; do |
| 117 | + server=$(basename $file_list .rsync) |
| 118 | + ghe_verbose "* Transferring repositories to $server" |
| 119 | + ghe-rsync -avrHR --delete \ |
| 120 | + -e "ssh -q $opts -p $port -F $ssh_config_file -l $user" \ |
| 121 | + --rsync-path="sudo -u git rsync" \ |
| 122 | + --files-from=$file_list \ |
| 123 | + "$GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT/repositories/./" \ |
| 124 | + "$server:$GHE_REMOTE_DATA_USER_DIR/repositories/" 1>&3 |
| 125 | +done |
| 126 | + |
| 127 | +# Tell dgit about the repositories restored |
| 128 | +cat $to_restore | ghe-ssh "$GHE_HOSTNAME" github-env ./bin/dgit-cluster-restore-finalize >&3 |
| 129 | + |
| 130 | +if [ -d $GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT/repositories/info ]; then |
| 131 | + ghe_verbose "* Transferring repository info data" |
| 132 | + for route in `ghe-ssh "$GHE_HOSTNAME" ghe-cluster-each -r git -p`; do |
| 133 | + if ! ghe-rsync -av --delete \ |
| 134 | + -e "ssh -q $opts -p $port -F $ssh_config_file -l $user" \ |
| 135 | + --rsync-path="sudo -u git rsync" \ |
| 136 | + "$GHE_DATA_DIR/$GHE_RESTORE_SNAPSHOT/repositories/info/" \ |
| 137 | + "$route:$GHE_REMOTE_DATA_USER_DIR/repositories/info" 1>&3; then |
| 138 | + echo "Error restoring /data/repositories/info to $route" |
| 139 | + fi |
| 140 | + done |
| 141 | +else |
| 142 | + ghe_verbose "* Removing repository info data" |
| 143 | + ghe-ssh "$GHE_HOSTNAME" ghe-cluster-each -r git -- rm -f /data/repositories/info/* |
| 144 | +fi |
| 145 | + |
| 146 | +bm_end "$(basename $0)" |
0 commit comments