Last active
September 8, 2018 17:18
-
-
Save pydevops/da4558bda308d274c4c3e5371f98f460 to your computer and use it in GitHub Desktop.
GCS based locking function
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
set -u | |
# constants | |
PROJECT=$(gcloud info --format='value(config.project)') | |
LOCKS_BUCKET=$PROJECT-db2-locks | |
# how long do we wait for lock or condition | |
SLEEP=5 | |
# Check if a lock file exists | |
# Globals: | |
# None | |
# Arguments: | |
# LOCK_FILE_URL | |
# Returns: | |
# 0 | |
function no_lock_yet() { | |
local LOCK_FILE_URL="$1" | |
# blocking till the lock is released by some other process | |
until ! gsutil ls $LOCK_FILE_URL >/dev/null 2>&1; do | |
sleep "${SLEEP}" | |
done | |
# no lock any more | |
echo 0 | |
} | |
function lock() { | |
local LOCK_FILE_PREFIX="$1" | |
local LOCK_FILE="$2" | |
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE | |
# ONLY lock if there is no lock file exists | |
# mkdir -p the prefix and geneate the lock file, then rsync over to GCS | |
if ! gsutil ls "$LOCK_FILE_URL" >/dev/null 2>&1;then | |
local TEMP_DIR=$(mktemp -d) | |
local LOCK_DIR=${TEMP_DIR}/${LOCK_FILE_PREFIX} | |
mkdir -p $LOCK_DIR && touch $LOCK_DIR/$LOCK_FILE | |
(cd $TEMP_DIR && gsutil rsync -r . gs://$LOCKS_BUCKET) | |
else | |
echo "lock $LOCK_FILE_PREFIX/$LOCK_FILE exists already" | |
fi | |
} | |
# Acquire a lock | |
# Globals: | |
# LOCKS_BUCKET | |
# Arguments: | |
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE) | |
# Returns: | |
# 0 | |
# blocking till we can lock | |
function db2_acquire_lock() { | |
local ENV=$1 | |
local DB_INSTANCE_NAME=$2 | |
local DB_NAME=$3 | |
local LOCK_FILE=$4 | |
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME} | |
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE | |
free_to_lock=$(no_lock_yet $LOCK_FILE_URL) | |
# echo "free_to_lock is $free_to_lock" | |
if [[ $free_to_lock -eq 0 ]];then | |
echo "$LOCK_FILE_URL is free to lock" | |
lock $LOCK_FILE_PREFIX $LOCK_FILE | |
fi | |
} | |
# Release a lock | |
# Globals: | |
# LOCKS_BUCKET | |
# Arguments: | |
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE) | |
# Returns: | |
# 0 | |
function db2_release_lock() { | |
local ENV=$1 | |
local DB_INSTANCE_NAME=$2 | |
local DB_NAME=$3 | |
local LOCK_FILE=$4 | |
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME} | |
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE | |
# release the lock if there is a one | |
if gsutil ls "$LOCK_FILE_URL" >/dev/null 2>&1;then | |
echo "unlock $LOCK_FILE_URL" | |
gsutil rm "$LOCK_FILE_URL" | |
# error check here | |
fi | |
} | |
# wait for a lock to be acquired | |
# Globals: | |
# LOCKS_BUCKET | |
# Arguments: | |
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE) | |
# Returns: | |
# 0 | |
function wait_for() { | |
local ENV=$1 | |
local DB_INSTANCE_NAME=$2 | |
local DB_NAME=$3 | |
local LOCK_FILE=$4 | |
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME} | |
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE | |
# blocking till the lock is acquired by some other process | |
until gsutil ls $LOCK_FILE_URL >/dev/null 2>&1; do | |
echo "wait_for $LOCK_FILE_URL" | |
sleep "${SLEEP}" | |
done | |
} | |
# notify that a lock is acquired | |
# Globals: | |
# LOCKS_BUCKET | |
# Arguments: | |
# (ENV,DB_INSTANCE_NAME,DB_NAME,LOCK_FILE) | |
# Returns: | |
# 0 | |
function notify() { | |
local ENV=$1 | |
local DB_INSTANCE_NAME=$2 | |
local DB_NAME=$3 | |
local LOCK_FILE=$4 | |
local LOCK_FILE_PREFIX=${ENV}/${DB_INSTANCE_NAME}/${DB_NAME} | |
local LOCK_FILE_URL=gs://$LOCKS_BUCKET/$LOCK_FILE_PREFIX/$LOCK_FILE | |
lock $LOCK_FILE_PREFIX $LOCK_FILE | |
} | |
# test functions below | |
# function test_lock() { | |
# local LOCK_FILE_PREFIX=dev/primary-dbi-1/db-1 | |
# lock $LOCK_FILE_PREFIX lock-1 | |
# lock $LOCK_FILE_PREFIX lock-2 | |
# } | |
# create the bucket for testing | |
if ! gsutil ls "gs://${LOCKS_BUCKET}";then | |
gsutil mb -c regional -l us-central1 gs://${LOCKS_BUCKET} | |
fi | |
# test the func used by the main backup script | |
#db2_acquire_lock dev primary-dbi-1 db-1 lock-backup | |
# gsutil ls -r gs://${LOCKS_BUCKET} | |
# test_release_lock | |
#db2_release_lock dev primary-dbi-1 db-1 lock-backup | |
# gsutil ls -r gs://${LOCKS_BUCKET} | |
# test_wait_for | |
#wait_for dev primary-dbi-1 db-1 lock-primary-ready | |
# gsutil ls -r gs://${LOCKS_BUCKET} | |
# test_notify | |
#notify dev primary-dbi-1 db-1 lock-primary-ready | |
# gsutil ls -r gs://${LOCKS_BUCKET} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment