Get lock (with optional timeout)

    path
        The path in zookeeper where the lock is

    zk_hosts
        zookeeper connect string

    identifier
        Name to identify this minion, if unspecified defaults to the hostname

    max_concurrency
        Maximum number of lock holders

    timeout
        timeout to wait for the lock. A None timeout will block forever

    ephemeral_lease
        Whether the locks in zookeper should be ephemeral

    force
        Forcibly acquire the lock regardless of available slots

    Example:

    .. code-block: bash

        salt minion zk_concurrency.lock /lock/path host1:1234,host2:1234

def lock(path,
         zk_hosts=None,
         identifier=None,
         max_concurrency=1,
         timeout=None,
         ephemeral_lease=False,
         force=False,  # foricble get the lock regardless of open slots
         profile=None,
         scheme=None,
         username=None,
         password=None,
         default_acl=None,
         ):
    '''
    Get lock (with optional timeout)

    path
        The path in zookeeper where the lock is

    zk_hosts
        zookeeper connect string

    identifier
        Name to identify this minion, if unspecified defaults to the hostname

    max_concurrency
        Maximum number of lock holders

    timeout
        timeout to wait for the lock. A None timeout will block forever

    ephemeral_lease
        Whether the locks in zookeper should be ephemeral

    force
        Forcibly acquire the lock regardless of available slots

    Example:

    .. code-block: bash

        salt minion zk_concurrency.lock /lock/path host1:1234,host2:1234
    '''
    zk = _get_zk_conn(profile=profile, hosts=zk_hosts, scheme=scheme,
                      username=username, password=password, default_acl=default_acl)
    if path not in __context__['semaphore_map']:
        __context__['semaphore_map'][path] = _Semaphore(zk, path, identifier,
                                                        max_leases=max_concurrency,
                                                        ephemeral_lease=ephemeral_lease)

    # forcibly get the lock regardless of max_concurrency
    if force:
        __context__['semaphore_map'][path].assured_path = True
        __context__['semaphore_map'][path].max_leases = sys.maxint

    # block waiting for lock acquisition
    if timeout:
        logging.info('Acquiring lock %s with timeout=%s', path, timeout)
        __context__['semaphore_map'][path].acquire(timeout=timeout)
    else:
        logging.info('Acquiring lock %s with no timeout', path)
        __context__['semaphore_map'][path].acquire()

    return __context__['semaphore_map'][path].is_acquired