Esempio n. 1
0
    def delete_stack(self, cnxt, stack_identity):
        """
        The delete_stack method deletes a given stack.

        :param cnxt: RPC context.
        :param stack_identity: Name of the stack you want to delete.
        """
        def remote_stop(lock_engine_id):
            rpc = proxy.RpcProxy(lock_engine_id, "1.0")
            msg = rpc.make_msg("stop_stack", stack_identity=stack_identity)
            timeout = cfg.CONF.engine_life_check_timeout
            try:
                rpc.call(cnxt, msg, topic=lock_engine_id, timeout=timeout)
            except rpc_common.Timeout:
                return False

        st = self._get_stack(cnxt, stack_identity)
        logger.info(_('Deleting stack %s') % st.name)
        stack = parser.Stack.load(cnxt, stack=st)

        lock = stack_lock.StackLock(cnxt, stack, self.engine_id)
        acquire_result = lock.try_acquire()

        # Successfully acquired lock
        if acquire_result is None:
            self.thread_group_mgr.start_with_acquired_lock(stack, lock,
                                                           stack.delete)
            return

        # Current engine has the lock
        elif acquire_result == self.engine_id:
            self.thread_group_mgr.stop(stack.id)

        # Another active engine has the lock
        elif stack_lock.StackLock.engine_alive(cnxt, acquire_result):
            stop_result = remote_stop(acquire_result)
            if stop_result is None:
                logger.debug(_("Successfully stopped remote task on engine %s")
                             % acquire_result)
            else:
                raise exception.StopActionFailed(stack_name=stack.name,
                                                 engine_id=acquire_result)

        # If the lock isn't released here, then the call to
        # start_with_lock below will raise an ActionInProgress
        # exception.  Ideally, we wouldn't be calling another
        # release() here, since it should be called as soon as the
        # ThreadGroup is stopped.  But apparently there's a race
        # between release() the next call to lock.acquire().
        db_api.stack_lock_release(stack.id, acquire_result)

        # There may be additional resources that we don't know about
        # if an update was in-progress when the stack was stopped, so
        # reload the stack from the database.
        st = self._get_stack(cnxt, stack_identity)
        stack = parser.Stack.load(cnxt, stack=st)

        self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id,
                                              stack.delete)
        return None
Esempio n. 2
0
    def delete_stack(self, cnxt, stack_identity):
        """
        The delete_stack method deletes a given stack.

        :param cnxt: RPC context.
        :param stack_identity: Name of the stack you want to delete.
        """
        def remote_stop(lock_engine_id):
            timeout = cfg.CONF.engine_life_check_timeout
            self.cctxt = self._client.prepare(version='1.0',
                                              timeout=timeout,
                                              topic=lock_engine_id)
            try:
                self.cctxt.call(cnxt,
                                'stop_stack',
                                stack_identity=stack_identity)
            except messaging.MessagingTimeout:
                return False

        st = self._get_stack(cnxt, stack_identity)
        LOG.info(_('Deleting stack %s') % st.name)
        stack = parser.Stack.load(cnxt, stack=st)

        lock = stack_lock.StackLock(cnxt, stack, self.engine_id)
        with lock.try_thread_lock(stack.id) as acquire_result:

            # Successfully acquired lock
            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

        # Current engine has the lock
        if acquire_result == self.engine_id:
            # give threads which are almost complete an opportunity to
            # finish naturally before force stopping them
            eventlet.sleep(0.2)
            self.thread_group_mgr.stop(stack.id)

        # Another active engine has the lock
        elif stack_lock.StackLock.engine_alive(cnxt, acquire_result):
            stop_result = remote_stop(acquire_result)
            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)

        # There may be additional resources that we don't know about
        # if an update was in-progress when the stack was stopped, so
        # reload the stack from the database.
        st = self._get_stack(cnxt, stack_identity)
        stack = parser.Stack.load(cnxt, stack=st)

        self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id,
                                              stack.delete)
        return None