Beispiel #1
0
 def test_try_thread_lock_context_mgr_no_exception(self):
     stack_lock_object.StackLock.create = mock.Mock(return_value=None)
     stack_lock_object.StackLock.release = mock.Mock(return_value=None)
     slock = stack_lock.StackLock(self.context, self.stack_id,
                                  self.engine_id)
     with slock.try_thread_lock():
         self.assertEqual(1, stack_lock_object.StackLock.create.call_count)
     assert not stack_lock_object.StackLock.release.called
Beispiel #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):
            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()

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

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

            # 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, self.engine_id)

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

        # 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
Beispiel #3
0
    def test_failed_acquire_existing_lock_current_engine(self):
        mock_create = self.patchobject(stack_lock_object.StackLock,
                                       'create',
                                       return_value=self.engine_id)

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)

        self.assertRaises(exception.ActionInProgress, slock.acquire)
        mock_create.assert_called_once_with(self.stack.id, self.engine_id)
Beispiel #4
0
    def test_successful_acquire_new_lock(self):
        mock_create = self.patchobject(stack_lock_object.StackLock,
                                       'create',
                                       return_value=None)

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        slock.acquire()

        mock_create.assert_called_once_with(self.stack.id, self.engine_id)
Beispiel #5
0
    def test_successful_acquire_new_lock(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id, self.engine_id).AndReturn(None)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        slock.acquire()
        self.m.VerifyAll()
Beispiel #6
0
    def test_failed_acquire_existing_lock_current_engine(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id, self.engine_id).\
            AndReturn(self.engine_id)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.assertRaises(rpc_common.ClientException, slock.acquire)
        self.m.VerifyAll()
Beispiel #7
0
 def test_try_thread_lock_context_mgr_existing_lock(self):
     db_api.stack_lock_create = mock.Mock(return_value=1234)
     db_api.stack_lock_release = mock.Mock(return_value=None)
     slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
     try:
         with slock.try_thread_lock(self.stack.id):
             db_api.stack_lock_create.assert_called_once()
             raise Exception
     except:
         assert not db_api.stack_lock_release.called
Beispiel #8
0
 def test_try_thread_lock_context_mgr_exception(self):
     db_api.stack_lock_create = mock.Mock(return_value=None)
     db_api.stack_lock_release = mock.Mock(return_value=None)
     slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
     try:
         with slock.try_thread_lock(self.stack.id):
             self.assertEqual(1, db_api.stack_lock_create.call_count)
             raise Exception
     except:
         self.assertEqual(1, db_api.stack_lock_release.call_count)
Beispiel #9
0
 def test_engine_alive_timeout(self):
     slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
     mget_client = self.patchobject(stack_lock.rpc_messaging,
                                    'get_rpc_client')
     mclient = mget_client.return_value
     mclient_ctx = mclient.prepare.return_value
     mclient_ctx.call.side_effect = messaging.MessagingTimeout('too slow')
     ret = slock.engine_alive(self.context, self.engine_id)
     self.assertIs(False, ret)
     mclient.prepare.assert_called_once_with(timeout=2)
     mclient_ctx.call.assert_called_once_with(self.context, 'listening')
    def test_try_thread_lock_context_mgr_existing_lock(self):
        db_api.stack_lock_create = mock.Mock(return_value=1234)
        db_api.stack_lock_release = mock.Mock(return_value=None)
        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)

        def check_thread_lock():
            with slock.try_thread_lock(self.stack.id):
                self.assertEqual(1, db_api.stack_lock_create.call_count)
                raise self.TestThreadLockException
        self.assertRaises(self.TestThreadLockException, check_thread_lock)
        assert not db_api.stack_lock_release.called
    def test_thread_lock_context_mgr_exception_acquire_fail(self):
        db_api.stack_lock_create = mock.Mock(return_value=self.engine_id)
        db_api.stack_lock_release = mock.Mock()
        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)

        def check_thread_lock():
            with slock.thread_lock(self.stack.id):
                self.assertEqual(1, db_api.stack_lock_create.call_count)
                raise exception.ActionInProgress
        self.assertRaises(exception.ActionInProgress, check_thread_lock)
        assert not db_api.stack_lock_release.called
Beispiel #12
0
    def test_failed_acquire_existing_lock_engine_alive(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id,
                                 self.engine_id).AndReturn("fake-engine-id")

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.patchobject(slock, 'engine_alive', return_value=True)
        self.assertRaises(exception.ActionInProgress, slock.acquire)
        self.m.VerifyAll()
Beispiel #13
0
 def test_engine_alive_ok(self):
     slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
     mget_client = self.patchobject(stack_lock.rpc_messaging,
                                    'get_rpc_client')
     mclient = mget_client.return_value
     mclient_ctx = mclient.prepare.return_value
     mclient_ctx.call.return_value = True
     ret = slock.engine_alive(self.context, self.engine_id)
     self.assertTrue(ret)
     mclient.prepare.assert_called_once_with(timeout=2)
     mclient_ctx.call.assert_called_once_with(self.context, 'listening')
Beispiel #14
0
    def test_try_thread_lock_context_mgr_existing_lock(self):
        stack_lock_object.StackLock.create = mock.Mock(return_value=1234)
        stack_lock_object.StackLock.release = mock.Mock(return_value=None)
        slock = stack_lock.StackLock(self.context, self.stack_id,
                                     self.engine_id)

        def check_thread_lock():
            with slock.try_thread_lock():
                self.assertEqual(1,
                                 stack_lock_object.StackLock.create.call_count)
                raise self.TestThreadLockException
        self.assertRaises(self.TestThreadLockException, check_thread_lock)
        self.assertFalse(stack_lock_object.StackLock.release.called)
Beispiel #15
0
    def test_thread_lock_context_mgr_exception_acquire_success(self):
        stack_lock_object.StackLock.create = mock.Mock(return_value=None)
        stack_lock_object.StackLock.release = mock.Mock(return_value=None)
        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)

        def check_thread_lock():
            with slock.thread_lock(self.stack.id):
                self.assertEqual(1,
                                 stack_lock_object.StackLock.create.call_count)
                raise self.TestThreadLockException

        self.assertRaises(self.TestThreadLockException, check_thread_lock)
        self.assertEqual(1, stack_lock_object.StackLock.release.call_count)
Beispiel #16
0
    def test_thread_lock_context_mgr_exception_acquire_fail(self):
        stack_lock_object.StackLock.create = mock.Mock(
            return_value=self.engine_id)
        stack_lock_object.StackLock.release = mock.Mock()
        slock = stack_lock.StackLock(self.context, self.stack_id,
                                     self.engine_id)

        def check_thread_lock():
            with slock.thread_lock():
                self.assertEqual(1,
                                 stack_lock_object.StackLock.create.call_count)
                raise exception.ActionInProgress
        self.assertRaises(exception.ActionInProgress, check_thread_lock)
        self.assertFalse(stack_lock_object.StackLock.release.called)
Beispiel #17
0
    def test_failed_acquire_existing_lock_engine_alive(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id,
                                 self.engine_id).AndReturn("fake-engine-id")

        self.m.StubOutWithMock(messaging.rpc.client._CallContext, "call")
        messaging.rpc.client._CallContext.call(self.context,
                                               "listening").AndReturn(True)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.assertRaises(exception.ActionInProgress, slock.acquire)
        self.m.VerifyAll()
Beispiel #18
0
    def test_successful_acquire_existing_lock_engine_dead(self):
        mock_create = self.patchobject(stack_lock_object.StackLock,
                                       'create',
                                       return_value='fake-engine-id')
        mock_steal = self.patchobject(stack_lock_object.StackLock,
                                      'steal',
                                      return_value=None)

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.patchobject(slock, 'engine_alive', return_value=False)
        slock.acquire()

        mock_create.assert_called_once_with(self.stack.id, self.engine_id)
        mock_steal.assert_called_once_with(self.stack.id, 'fake-engine-id',
                                           self.engine_id)
Beispiel #19
0
    def test_failed_acquire_existing_lock_engine_dead(self):
        mock_create = self.patchobject(stack_lock_object.StackLock,
                                       'create',
                                       return_value='fake-engine-id')
        mock_steal = self.patchobject(stack_lock_object.StackLock,
                                      'steal',
                                      return_value='fake-engine-id2')

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.patchobject(slock, 'engine_alive', return_value=False)
        self.assertRaises(exception.ActionInProgress, slock.acquire)

        mock_create.assert_called_once_with(self.stack.id, self.engine_id)
        mock_steal.assert_called_once_with(self.stack.id, 'fake-engine-id',
                                           self.engine_id)
Beispiel #20
0
    def test_successful_acquire_existing_lock_engine_dead(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id,
                                 self.engine_id).AndReturn("fake-engine-id")

        self.m.StubOutWithMock(db_api, "stack_lock_steal")
        db_api.stack_lock_steal(self.stack.id, "fake-engine-id",
                                self.engine_id).AndReturn(None)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.patchobject(slock, 'engine_alive', return_value=False)
        slock.acquire()
        self.m.VerifyAll()
Beispiel #21
0
    def test_failed_acquire_existing_lock_engine_alive(self):
        mock_create = self.patchobject(stack_lock_object.StackLock,
                                       'create',
                                       return_value='fake-engine-id')

        slock = stack_lock.StackLock(self.context, self.stack_id,
                                     self.engine_id)
        self.patchobject(service_utils, 'engine_alive', return_value=True)
        self.assertRaises(exception.ActionInProgress, slock.acquire)
        self.mock_get_by_id.assert_called_once_with(self.context,
                                                    self.stack_id,
                                                    tenant_safe=False,
                                                    show_deleted=True)

        mock_create.assert_called_once_with(self.stack_id, self.engine_id)
Beispiel #22
0
    def test_successful_acquire_with_retry(self):
        mock_create = self.patchobject(stack_lock_object.StackLock,
                                       'create',
                                       return_value='fake-engine-id')
        mock_steal = self.patchobject(stack_lock_object.StackLock,
                                      'steal',
                                      side_effect=[True, None])

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.patchobject(slock, 'engine_alive', return_value=False)
        slock.acquire()

        mock_create.assert_has_calls(
            [mock.call(self.stack.id, self.engine_id)] * 2)
        mock_steal.assert_has_calls(
            [mock.call(self.stack.id, 'fake-engine-id', self.engine_id)] * 2)
Beispiel #23
0
    def test_failed_acquire_existing_lock_engine_alive(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id, self.engine_id).\
            AndReturn("fake-engine-id")

        topic = self.stack.id
        self.m.StubOutWithMock(proxy.RpcProxy, "call")
        rpc = proxy.RpcProxy(topic, "1.0")
        rpc.call(self.context, rpc.make_msg("listening"), timeout=2,
                 topic="fake-engine-id").AndReturn(True)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.assertRaises(exception.ActionInProgress, slock.acquire)
        self.m.VerifyAll()
Beispiel #24
0
    def test_failed_acquire_one_retry_only(self):
        mock_create = self.patchobject(stack_lock_object.StackLock,
                                       'create',
                                       return_value='fake-engine-id')
        mock_steal = self.patchobject(stack_lock_object.StackLock,
                                      'steal',
                                      return_value=True)

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.patchobject(slock, 'engine_alive', return_value=False)
        self.assertRaises(exception.ActionInProgress, slock.acquire)

        mock_create.assert_has_calls(
            [mock.call(self.stack.id, self.engine_id)] * 2)
        mock_steal.assert_has_calls(
            [mock.call(self.stack.id, 'fake-engine-id', self.engine_id)] * 2)
Beispiel #25
0
 def abandon_stack(self, cnxt, stack_identity):
     """
     The abandon_stack method abandons a given stack.
     :param cnxt: RPC context.
     :param stack_identity: Name of the stack you want to abandon.
     """
     st = self._get_stack(cnxt, stack_identity)
     LOG.info(_('abandoning stack %s') % st.name)
     stack = parser.Stack.load(cnxt, stack=st)
     lock = stack_lock.StackLock(cnxt, stack, self.engine_id)
     with lock.thread_lock(stack.id):
         # Get stack details before deleting it.
         stack_info = stack.prepare_abandon()
         self.thread_group_mgr.start_with_acquired_lock(
             stack, lock, stack.delete)
         return stack_info
Beispiel #26
0
    def start_with_lock(self, cnxt, stack, engine_id, func, *args, **kwargs):
        """
        Try to acquire a stack lock and, if successful, run the given
        method in a sub-thread.  Release the lock when the thread
        finishes.

        :param cnxt: RPC context
        :param stack: Stack to be operated on
        :type stack: heat.engine.parser.Stack
        :param engine_id: The UUID of the engine acquiring the lock
        :param func: Callable to be invoked in sub-thread
        :type func: function or instancemethod
        :param args: Args to be passed to func
        :param kwargs: Keyword-args to be passed to func.
        """
        lock = stack_lock.StackLock(cnxt, stack, engine_id)
        with lock.thread_lock(stack.id):
            self.start_with_acquired_lock(stack, lock, func, *args, **kwargs)
Beispiel #27
0
    def test_successful_acquire_existing_lock_engine_dead(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id,
                                 self.engine_id).AndReturn("fake-engine-id")

        self.m.StubOutWithMock(messaging.rpc.client._CallContext, "call")
        messaging.rpc.client._CallContext.call(
            self.context, "listening").AndRaise(messaging.MessagingTimeout)

        self.m.StubOutWithMock(db_api, "stack_lock_steal")
        db_api.stack_lock_steal(self.stack.id, "fake-engine-id",
                                self.engine_id).AndReturn(None)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        slock.acquire()
        self.m.VerifyAll()
Beispiel #28
0
    def test_successful_acquire_existing_lock_engine_dead(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id, self.engine_id).\
            AndReturn("fake-engine-id")

        topic = self.stack.id
        self.m.StubOutWithMock(proxy.RpcProxy, "call")
        rpc = proxy.RpcProxy(topic, "1.0")
        rpc.call(self.context, rpc.make_msg("listening"), timeout=2,
                 topic="fake-engine-id").AndRaise(rpc_common.Timeout)

        self.m.StubOutWithMock(db_api, "stack_lock_steal")
        db_api.stack_lock_steal(self.stack.id, "fake-engine-id",
                                self.engine_id).AndReturn(None)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        slock.acquire()
        self.m.VerifyAll()
Beispiel #29
0
    def test_failed_acquire_one_retry_only(self):
        self.m.StubOutWithMock(db_api, "stack_lock_create")
        db_api.stack_lock_create(self.stack.id, self.engine_id).\
            AndReturn("fake-engine-id")

        topic = self.stack.id
        self.m.StubOutWithMock(proxy.RpcProxy, "call")
        rpc = proxy.RpcProxy(topic, "1.0")
        rpc.call(self.context,
                 rpc.make_msg("listening"),
                 timeout=2,
                 topic="fake-engine-id").AndRaise(rpc_common.Timeout)

        self.m.StubOutWithMock(db_api, "stack_lock_steal")
        db_api.stack_lock_steal(self.stack.id, "fake-engine-id",
                                self.engine_id).\
            AndReturn(True)

        db_api.stack_lock_create(self.stack.id, self.engine_id).\
            AndReturn("fake-engine-id")

        topic = self.stack.id
        rpc = proxy.RpcProxy(topic, "1.0")
        rpc.call(self.context,
                 rpc.make_msg("listening"),
                 timeout=2,
                 topic="fake-engine-id").AndRaise(rpc_common.Timeout)

        db_api.stack_lock_steal(self.stack.id, "fake-engine-id",
                                self.engine_id).\
            AndReturn(True)

        self.m.ReplayAll()

        slock = stack_lock.StackLock(self.context, self.stack, self.engine_id)
        self.assertRaises(rpc_common.ClientException, slock.acquire)
        self.m.VerifyAll()