def test_with(self): class SpecialException(RuntimeError): pass m = DynamoDbMutex(random_name(), holder=random_name()) try: with m: assert m.is_locked() time.sleep(3) raise SpecialException except SpecialException: print("In exception handler") assert not m.is_locked()
def configure_vpx(vpx_info, services): try: NS_URL = vpx_info['ns_url'] NS_LOGIN = os.environ['NS_LOGIN'] NS_PASSWORD = os.environ.get('NS_PASSWORD') if NS_PASSWORD is None or NS_PASSWORD == 'SAME_AS_INSTANCE_ID': NS_PASSWORD = vpx_info['instance_id'] instance_id = vpx_info['instance_id'] state_bucket = os.environ['S3_TFSTATE_BUCKET'] config_bucket = os.environ['S3_TFCONFIG_BUCKET'] except KeyError as ke: logger.warn("Bailing since we can't get the required variable: " + ke.args[0]) return vip_config = '' vip = vpx_info.get('vip') if vip is not None: vip_config = "-var '" + 'vip_config={{vip="{}"}}'.format(vip) + "'" logger.info(vpx_info) configure_snip(vpx_info) fetch_tfstate(state_bucket, instance_id) fetch_tfconfig(config_bucket) command = "{} NS_URL={} NS_LOGIN={} NS_PASSWORD={} {}/terraform apply -state={} -backup=- -no-color -var-file={}/terraform.tfvars -var 'backend_services=[{}]' {} {}".format(tf_log, NS_URL, NS_LOGIN, NS_PASSWORD, bindir, get_tfstate_path(instance_id), tfconfig_local_dir, services, vip_config, tfconfig_local_dir) logger.info("****Executing on NetScaler: " + instance_id + " command: " + command) try: m = DynamoDbMutex(name=instance_id, holder=random_name(), timeoutms=40 * 1000) if m.lock(): tf_output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True) logger.info("****Executed terraform apply on NetScaler:" + instance_id + ", output follows***") logger.info(tf_output) upload_tfstate(state_bucket, instance_id) m.release() else: logger.warn("Failed to acquire mutex (no-op)") except subprocess.CalledProcessError as cpe: logger.warn("****ERROR executing terraform apply cmd on NetScaler: " + instance_id + ", error follows***") logger.warn(cpe.output) m.release() except: logger.warn("Caught exception: " + str(sys.exc_info()[:2])) logger.warn("Caught exception, releasing lock") m.release()
def test_create_delete_us_east_1(self): m = DynamoDbMutex(random_name(), holder=random_name(), region_name='us-east-1') assert (m.lock()) m.release() DynamoDbMutex.delete_table(region_name='us-east-1')
def test_with_fail(self): name = random_name() m1 = DynamoDbMutex(name, holder=random_name()) m1.lock() m2 = DynamoDbMutex(name, holder=random_name()) exceptionHappened = False try: with m2: time.sleep(3) except AcquireLockFailedError: print("In exception handler") assert (m2.is_locked() == False) exceptionHappened = True assert (exceptionHappened)
def main(args): setup_logging() import inspect, argparse spec = inspect.getargspec(DynamoDbMutex.__init__) defaults = dict(zip(reversed(spec.args), reversed(spec.defaults))) parser = argparse.ArgumentParser( description='Mutexes for AWS using conditional PUTs in DynamoDB.') # required positionals parser.add_argument('mutex', metavar='MUTEX', help='The name of the mutex.') parser.add_argument('action', metavar='ACTION', choices=['lock', 'release'], help='The action to take on the mutex.') # optional flags assert defaults['region_name'] is None parser.add_argument( '--region', '-r', metavar='NAME', help= 'The name of the AWS region to host the mutexes in. The default depends on your Boto3 ' 'configuration: http://boto3.readthedocs.io/en/latest/guide/configuration.html' ) parser.add_argument( '--holder', '-H', metavar='NAME', help= 'A name identifying the lock holder. The default is dynamically generated UUID.' ) parser.add_argument( '--expiration', '-e', metavar='SECONDS', type=float, default=defaults['expiration'], help= 'The number of seconds after which a lock is released automatically.') parser.add_argument( '--blocking', '-b', action='store_' + ('false' if defaults['blocking'] else 'true'), help='Do not exit until the mutex is locked or a timeout occurs.') parser.add_argument( '--timeout', '-t', metavar='SECONDS', type=float, default=defaults['timeout'], help= 'The maximum amount of time to block on attempting to lock a mutex.') options = parser.parse_args(args=args) mutex = DynamoDbMutex(options.mutex, region_name=options.region, holder=options.holder, expiration=options.expiration, timeout=options.timeout, blocking=options.blocking) if options.action == 'lock': return mutex.lock() elif options.action == 'release': mutex.release() return True else: assert False
def test_release_expired(self): name = random_name() caller = "caller1" m1 = DynamoDbMutex(name, holder=caller, expiration=2) m1.lock() time.sleep(3) caller = "caller2" m2 = DynamoDbMutex(name, holder=caller, expiration=2) assert (m2.lock()) m1.release() assert (m2.is_locked()) m2.release()
def test_mutual_exclusion(self): m = DynamoDbMutex(random_name(), holder=random_name()) m.lock() assert (m.lock() == False) m.release()
def test_timeout(self): m = DynamoDbMutex(random_name(), holder="myself", expiration=3) m.lock() time.sleep(5) assert (m.lock()) m.release()
def test_create(self): m = DynamoDbMutex(random_name(), holder="myself", expiration=3) assert (m.lock()) m.release()