1 # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
2 # vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
4 defined_backends=(local, chroot)
7 function init_backends () {
8 for backend in "${defined_backends[@]}"; do
9 . "$libdirectory/backends/$backend"
10 if "backend_${backend}_init"; then
11 append available_backends "$backend"
12 debug "Backend '$backend' is available on this system"
14 debug "Backend '$backend' is not available on this system"
19 function init_source_hosts () {
20 # Use our first argument as the name of a configuration parameter to
21 # load the hosts from, or use the "hosts" parameter if nothing was
22 # passed. If the parameter is empty, use "localhost".
23 getconf_words "hosts" "local:"
24 # Allow the default backend variable to be overridden in this
25 # handler's configuration, but fall back to the global default
26 # backend. We use printconf instead of getconf to prevent the global
27 # $default_backend from getting clobbered.
28 local_default_backend=`printconf "default_backend" $default_backend`
30 # Check to see if the default backend is valid (don't check
31 # availability yet, though)
32 if [ -n "$local_default_backend" ] && ! backend_defined "$local_default_backend"; then
33 fatal "Default backend '$local_default_backend' does not exist"
37 for hostspec in "${hosts[@]}"; do
40 local backend=`backend_for_hostspec "$hostspec"`
41 if [ -z "$backend" ]; then
42 if [ -z "$local_default_backend" ]; then
43 fatal "No default backend set and no explicit backend in hostspec '$hostspec'"
45 backend=$local_default_backend
49 # Check if the backend is valid and available
50 if ! backend_defined "$backend"; then
51 fatal "Backend '$backend' does not exist"
52 elif ! backend_available "$backend"; then
53 fatal "Backend '$backend' is not available on this system"
56 # Check if the host is available
58 local host=`host_for_hostspec "$hostspec"`
59 if ! "backend_${backend}_host_available" "$host" reason; then
60 fatal "Host '$hostspec' is not available: $reason"
63 # Everything is ok, we can run on this host!
67 # Run the function pointed to by $1 for each of the source hosts defined
68 # in the configuration. Sets up the current backend and source host
69 # variables, so source_run & friends can be used. Also sets up the $root
70 # variable to point to the current source host's root filesystem (with
72 # This function should only be used after calling init_source_hosts.
73 function run_for_source_hosts () {
74 # $hosts will have been filled by init_source_hosts
75 for hostspec in "${hosts[@]}"; do
76 current_backend=`backend_for_hostspec "$hostspec"`
77 current_host=`host_for_hostspec "$hostspec"`
78 # Set the current source's root.
79 root=`"backend_${current_backend}_host_root" "$current_host"`
81 info "Running on $current_backend:$current_host"
83 # Run the actual backup handler
88 # Run the given command on the current source host.
89 # The command should be $1, with $2, $3, etc. being its arguments.
91 "backend_${current_backend}_run" "$@"
94 function backend_available () {
95 in_array "$1" "${available_backends[@]}"
98 function backend_defined () {
99 in_array "$1" "${defined_backends[@]}"
102 function backend_for_hostspec () {
103 echo "$1" | sed 's/^\(\([^:]*\):\)\?\(.*\)$/\2/'
106 function host_for_hostspec () {
107 echo "$1" | sed 's/^\(\([^:]*\):\)\?\(.*\)$/\3/'
111 # Replaces escape sequences in $1 with the proper values for the current
113 # The result is put on stdout. If $2 is empty, values for the host are
114 # replaced. The following values are replaced:
117 # %h The short hostname (as returned by hostname -s)
118 # %H The full hostname (as returned by hostname --fqdn)
119 # %n The vserver name, or empty for the host
120 # %N The vserver name, or "host" for the host
121 # %v The vserver root directory, or empty for the host
123 # Note that the given vserver must be running!
125 function interpolate() {
129 # Allow backends to supply extra vars
130 vars=`"backend_${current_backend}_interpolate_vars"`
131 vars="h H s S r $vars"
133 # Do indirect lookup of the value to replace
134 val=`interpolate_value "$var"`
135 # Escape slashes, backslashes and ampersands, since those have
136 # special meaning for sed (note that we need to double the \
137 # twice, since it has special meaning to bash in the val=
138 # assignment, but also to sed.
139 val=`echo "$val" | sed 's#[/&\\\\]#\\\\&#g'`
140 # Add replacement pattern. The first part checks that there is
141 # an odd number of percent signs before the variable, so
142 # double % is properly left alone.
143 expr="${expr}s/\(\(^\|[^%]\)\(%%\)*\)%$var/\1$val/g;"
145 # Finally replace literal % signs
146 expr="${expr}s/%%/%/g"
148 # Do the actual interpolation
149 echo $path | sed "$expr"
152 function interpolate_value () {
154 h) `source_run hostname -s`;;
155 H) `source_run hostname --fqdn`;;
156 s) echo "$current_host";;
157 S) echo "$current_backend:$current_host";;
159 # Not one of the defaults, ask the backend
160 *) "backend_${current_backend}_interpolate_value" "$current_host" "$1"