'Delete a given stack.
:param cnxt: RPC context.
:param stack_identity: Name of the stack you want to delete.'

@context.request_context
def delete_stack(self, cnxt, stack_identity):

    st = self._get_stack(cnxt, stack_identity)
    if ((st.status == parser.Stack.COMPLETE) and (st.action == parser.Stack.DELETE)):
        raise exception.EntityNotFound(entity='Stack', name=st.name)
    LOG.info('Deleting    stack    %s', st.name)
    stack = parser.Stack.load(cnxt, stack=st)
    self.resource_enforcer.enforce_stack(stack)
    if (stack.convergence and cfg.CONF.convergence_engine):
        def convergence_delete():
            stack.thread_group_mgr = self.thread_group_mgr
            self.worker_service.stop_all_workers(stack)
            stack.delete_all_snapshots()
            template = templatem.Template.create_empty_template(from_template=stack.t)
            stack.converge_stack(template=template, action=stack.DELETE)
        self.thread_group_mgr.start(stack.id, convergence_delete)
        return
    lock = stack_lock.StackLock(cnxt, stack.id, self.engine_id)
    with lock.try_thread_lock() as acquire_result:
        if (acquire_result is None):
            self.thread_group_mgr.stop_timers(stack.id)
            self.thread_group_mgr.start_with_acquired_lock(stack, lock, stack.delete)
            return
    if (acquire_result == self.engine_id):
        self.thread_group_mgr.send(stack.id, rpc_api.THREAD_CANCEL)
    elif service_utils.engine_alive(cnxt, acquire_result):
        cancel_result = self._remote_call(cnxt, acquire_result, cfg.CONF.engine_life_check_timeout, self.listener.SEND, stack_identity=stack_identity, message=rpc_api.THREAD_CANCEL)
        if (cancel_result is None):
            LOG.debug(('Successfully    sent    %(msg)s    message    to    remote    task    on    engine    %(eng)s' % {'eng': acquire_result, 'msg': rpc_api.THREAD_CANCEL}))
        else:
            raise exception.EventSendFailed(stack_name=stack.name, engine_id=acquire_result)
    def reload():
        st = self._get_stack(cnxt, stack_identity)
        stack = parser.Stack.load(cnxt, stack=st)
        self.resource_enforcer.enforce_stack(stack)
        return stack
    def wait_then_delete(stack):
        watch = timeutils.StopWatch((cfg.CONF.error_wait_time + 10))
        watch.start()
        while (not watch.expired()):
            LOG.debug('Waiting    for    stack    cancel    to    complete:    %s', stack.name)
            with lock.try_thread_lock() as acquire_result:
                if (acquire_result is None):
                    stack = reload()
                    self.thread_group_mgr.start_with_acquired_lock(stack, lock, stack.delete)
                    return
            eventlet.sleep(1.0)
        if (acquire_result == self.engine_id):
            self.thread_group_mgr.stop(stack.id)
        elif service_utils.engine_alive(cnxt, acquire_result):
            stop_result = self._remote_call(cnxt, acquire_result, STOP_STACK_TIMEOUT, self.listener.STOP_STACK, stack_identity=stack_identity)
            if (stop_result is None):
                LOG.debug('Successfully    stopped    remote    task    on    engine    %s', acquire_result)
            else:
                raise exception.StopActionFailed(stack_name=stack.name, engine_id=acquire_result)
        stack = reload()
        self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id, stack.delete)
    self.thread_group_mgr.start(stack.id, wait_then_delete, stack)
