#!/bin/bash # iff executed under VERBOSE=yes provide more information verbose() { if [[ "$VERBOSE" == "yes" ]] ; then echo "$*" fi } usage() { echo -e "Usage: $0 [OPTION]..." 1>&2 echo -e "\t-f: Force update, even if running on active node" 1>&2 } FORCE_ACTIVE_NODE=false while getopts "fh" opt; do case "${opt}" in f) FORCE_ACTIVE_NODE=true ;; h) usage; exit 0; ;; *) usage; exit 1; ;; esac done shift $((OPTIND-1)) nodename=$(/usr/sbin/ngcp-nodename 2>/dev/null || echo "unknown") if [ "${nodename}" = "unknown" ] ; then echo "Error: nodename could not be identified." >&2 exit 1 fi /etc/init.d/mysql start || true . /etc/mysql/sipwise.cnf if [ -z "${SIPWISE_DB_PASSWORD}" ] ; then echo 'Error: SIPWISE_DB_PASSWORD is unset (using /etc/mysql/sipwise.cnf).' >&2 exit 1 fi # check connection with sipwise user if ! mysql -usipwise -p${SIPWISE_DB_PASSWORD} -e 'SELECT 1;' 1>/dev/null 2>/dev/null ; then echo 'Error: cant connect to local MySQL with sipwise user' >&2 exit 1 fi # support automated installation if [ -n "$AUTOMATED_INSTALL_MODE" ] ; then echo "Running in automated installation mode, ignoring check for empty db_schema." else if [ "$(mysql -usipwise -p${SIPWISE_DB_PASSWORD} -e 'use ngcp; select * from db_schema;' 2>/dev/null)" = "" ] ; then echo "=================================================================" echo "Warning: the db_schema table of the ngcp database is empty." echo "Are you sure you want to proceed with applying db-schema changes?" echo "This will DROP and then re-initialize your existing database." printf "Please type 'agree' to really continue: " unset AGREE read AGREE if [ "$AGREE" != "agree" ]; then echo "Exiting as requested." >&2 exit 1 fi fi fi if ! mysql -usipwise -p${SIPWISE_DB_PASSWORD} -e 'use ngcp;' 2>/dev/null ; then mysql -usipwise -p${SIPWISE_DB_PASSWORD} < /usr/share/ngcp-db-schema/db_scripts/init/0005_create_ngcp.up fi if ! mysql -usipwise -p${SIPWISE_DB_PASSWORD} -e 'use ngcp;' 2>/dev/null ; then echo 'Error: ngcp database does not exist.' >&2 exit 1 fi if ! mysql -usipwise -p${SIPWISE_DB_PASSWORD} ngcp -e 'describe db_schema' >/dev/null; then echo 'Error: db_schema table does not exit.' >&2 exit 1 fi running_on_active_node() { if [ "$nodename" = "spce" ] ; then return 1 else if /usr/sbin/ngcp-check_active -q ; then if $FORCE_ACTIVE_NODE; then verbose "Force update on active node as requested." else verbose "This seems to be the active node, nothing to do." fi return 0 else verbose "This seems to be the inactive node, applying revisions." return 1 fi fi } if running_on_active_node ; then ACTIVE_NODE=true else ACTIVE_NODE=false fi apply_revision() { [ -n "$1" ] || return 1 rev="$1" revname="$(basename $rev)" printf "Applying revision script %s: " "$rev" if mysql -usipwise -p${SIPWISE_DB_PASSWORD} < "$rev" ; then echo done else echo "failed. :(" >&2 echo "Please resolve the problem and run ngcp-update-db-schema again." >&2 exit 1 fi if mysql -usipwise -p${SIPWISE_DB_PASSWORD} ngcp -e "insert into db_schema values (0, '${revname}', \""${nodename}"\", CURRENT_TIMESTAMP);" ; then verbose "Marked revision $rev as applied." else echo "Error while executing DB commands using revision $rev for node $nodename" >&2 exit 1 fi } # execute the rev script iff there's no entry for *any* host yet apply_revs() { [ -n "$1" ] || return 1 revs="$1" # generate list of rev scripts that are node specific, used inside # missing_revision's ngcp-check-rev-applied ... --node $nodename for rev in $revs ; do revision_file="$(find /usr/share/ngcp-db-schema/ -name "$rev")" case "$revision_file" in *_not_replicated.up) node_revs="$node_revs $rev" ;; esac done for missing_revision in \ $( { ngcp-check-rev-applied --schema db_schema --revision $revs | awk '/^No match for revision/ {print $5}' ; ngcp-check-rev-applied --schema db_schema --revision $node_revs --node "$nodename" | awk '/^No match for revision/ {print $5}' ; } | sort -z -n -u ) ; do revision_file="$(find /usr/share/ngcp-db-schema/ -name "$missing_revision")" # execute the rev script iff there's no entry for the *current* host yet case "$revision_file" in *_not_replicated.up) if ngcp-check-rev-applied --schema db_schema --revision $missing_revision --node "$nodename" | grep -q 'already executed' ; then continue fi ;; esac if [ -r "$revision_file" ] ; then apply_revision "$revision_file" else echo "Warning: missing revision $missing_revision identified but could not find according db-schema file." fi done } revision_wrapper() { [ -n "$1" ] || return 1 local revlist for rev in $* ; do if ! [ -r "$rev" ] ; then echo "Error: $rev can not be read." >&2 exit 1 fi cd $(dirname $rev) || exit 1 # would fail if a script references a file (like language_strings.txt) in its CWD revname="$(basename $rev)" case "$revname" in # the scripts that should be executed on *all* hosts, no matter whether # they are active or inactive, since the script's content doesn't get replicated # NOTE: the actual logic is inside the apply_revs to avoid *_not_replicated.up # scripts being executed independent from the other ones *_not_replicated.up) revlist="$revlist $(basename $rev)" ;; *) if $ACTIVE_NODE ; then if $FORCE_ACTIVE_NODE; then revlist="$revlist $(basename $rev)" else verbose "Replication script ${revname} noted, nothing to do on active node" fi else revlist="$revlist $(basename $rev)" fi ;; esac done apply_revs "$revlist" } # make sure we get sorted 10XXX after 9XXX cd /usr/share/ngcp-db-schema/db_scripts/base/ revision_wrapper $(printf '%s\0' *.up | sort -z -n | while IFS= read -r -d "" file; do \ echo /usr/share/ngcp-db-schema/db_scripts/base/$file; done) cd /usr/share/ngcp-db-schema/db_scripts/diff/ revision_wrapper $(printf '%s\0' *.up | sort -z -n | while IFS= read -r -d "" file; do \ echo /usr/share/ngcp-db-schema/db_scripts/diff/$file; done) echo "Synchronizing passwords with MySQL" ngcp-sync-constants >/dev/null ## END OF FILE #################################################################