'Perform a GCE operation, blocking until the operation completes.
This will call `function` with the passed in keyword arguments plus
additional keyword arguments for project and zone which come from the
private member variables with the same name. It is expected that
`function` returns an object that has an `execute()` method that
returns a GCE operation resource dict.
This function will then poll the operation until it reaches
state \'DONE\' or times out, and then returns the final
operation resource dict. The value for the timeout was chosen
by testing the running time of our GCE operations. Sometimes
certain operations can take over 30s but they rarely, if ever,
take over a minute.
Timeouts should not be caught here but should propogate up the
stack and the node will eventually retry the operation via the
convergence loop.
:param function: Callable that takes keyword arguments project and
zone, and returns an executable that results in a GCE operation
resource dict as described above.
:param int timeout_sec: The maximum amount of time to wait in seconds
for the operation to complete.
:param sleep: A callable that has the same signature and function as
``time.sleep``. Only intended to be used in tests.
:param kwargs: Additional keyword arguments to pass to function.
:returns dict: A dict representing the concluded GCE operation
resource.'

def _do_blocking_operation(self, function, timeout_sec=VOLUME_DEFAULT_TIMEOUT, sleep=None, **kwargs):

    if (sleep is None):
        sleep = time.sleep
    def lock_dropped_sleep(*args, **kwargs):
        '\n                                                A    custom    sleep    function    that    drops    the    lock    while    the    actual\n                                                sleeping    is    going    on.\n                                                '
        self._lock.release()
        try:
            return sleep(*args, **kwargs)
        finally:
            self._lock.acquire()
    args = dict(project=self._project, zone=self._zone)
    args.update(kwargs)
    with self._lock:
        operation = function(**args).execute()
        return wait_for_operation(self._compute, operation, ([1] * timeout_sec), lock_dropped_sleep)
