def test_do_cleanup_not_cleaning_already_claimed(self):
        """Basic cleanup that doesn't touch already cleaning works."""
        vol = utils.create_volume(self.context, status='creating')
        worker1 = db.worker_create(self.context, status='creating',
                                   resource_type='Volume', resource_id=vol.id,
                                   service_id=self.service.id)
        worker1 = db.worker_get(self.context, id=worker1.id)
        vol2 = utils.create_volume(self.context, status='deleting')
        worker2 = db.worker_create(self.context, status='deleting',
                                   resource_type='Volume', resource_id=vol2.id,
                                   service_id=self.service.id + 1)
        worker2 = db.worker_get(self.context, id=worker2.id)

        # Simulate that the change to vol2 worker happened between
        # worker_get_all and trying to claim a work for cleanup
        worker2.service_id = self.service.id

        clean_req = objects.CleanupRequest(service_id=self.service.id)
        mngr = FakeManager(self.service.id)
        with mock.patch('cinder.db.worker_get_all') as get_all_mock:
            get_all_mock.return_value = [worker1, worker2]
            mngr.do_cleanup(self.context, clean_req)

        workers = db.worker_get_all(self.context)
        self.assertEqual(1, len(workers))
        self.assertEqual(worker2.id, workers[0].id)

        vol.refresh()
        self.assertEqual('creating_cleaned', vol.status)
        vol2.refresh()
        self.assertEqual('deleting', vol2.status)
Пример #2
0
    def test_do_cleanup_not_cleaning_already_claimed(self):
        """Basic cleanup that doesn't touch already cleaning works."""
        vol = utils.create_volume(self.context, status='creating')
        worker1 = db.worker_create(self.context,
                                   status='creating',
                                   resource_type='Volume',
                                   resource_id=vol.id,
                                   service_id=self.service.id)
        worker1 = db.worker_get(self.context, id=worker1.id)
        vol2 = utils.create_volume(self.context, status='deleting')
        worker2 = db.worker_create(self.context,
                                   status='deleting',
                                   resource_type='Volume',
                                   resource_id=vol2.id,
                                   service_id=self.service.id + 1)
        worker2 = db.worker_get(self.context, id=worker2.id)

        # Simulate that the change to vol2 worker happened between
        # worker_get_all and trying to claim a work for cleanup
        worker2.service_id = self.service.id

        clean_req = objects.CleanupRequest(service_id=self.service.id)
        mngr = FakeManager(self.service.id)
        with mock.patch('cinder.db.worker_get_all') as get_all_mock:
            get_all_mock.return_value = [worker1, worker2]
            mngr.do_cleanup(self.context, clean_req)

        workers = db.worker_get_all(self.context)
        self.assertEqual(1, len(workers))
        self.assertEqual(worker2.id, workers[0].id)

        vol.refresh()
        self.assertEqual('creating_cleaned', vol.status)
        vol2.refresh()
        self.assertEqual('deleting', vol2.status)
Пример #3
0
    def test_worker_claim_fails_this_service_claimed(self):
        """Test claim fails when worker was already claimed by this service."""
        service_id = 1
        worker = db.worker_create(self.ctxt,
                                  resource_type='Volume',
                                  resource_id=fake.VOLUME_ID,
                                  status='creating',
                                  service_id=service_id)

        # Read it back to have the updated_at value
        worker = db.worker_get(self.ctxt, id=worker.id)
        claimed_worker = db.worker_get(self.ctxt, id=worker.id)

        time.sleep(0.1)
        # Simulate that this service starts processing this entry
        res = db.worker_claim_for_cleanup(self.ctxt, service_id,
                                          claimed_worker)
        self.assertEqual(1, res)

        res = db.worker_claim_for_cleanup(self.ctxt, service_id, worker)
        self.assertEqual(0, res)
        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(claimed_worker, db_worker)
        self._assertEqualObjects(worker, db_worker, ['updated_at'])
        self.assertNotEqual(worker.updated_at, db_worker.updated_at)
    def test_worker_claim_fails_this_service_claimed(self):
        """Test claim fails when worker was already claimed by this service."""
        service_id = 1
        worker = db.worker_create(self.ctxt, resource_type='Volume',
                                  resource_id=fake.VOLUME_ID,
                                  status='creating',
                                  service_id=service_id)

        # Read it back to have the updated_at value
        worker = db.worker_get(self.ctxt, id=worker.id)
        claimed_worker = db.worker_get(self.ctxt, id=worker.id)

        time.sleep(0.1)
        # Simulate that this service starts processing this entry
        res = db.worker_claim_for_cleanup(self.ctxt,
                                          service_id,
                                          claimed_worker)
        self.assertEqual(1, res)

        res = db.worker_claim_for_cleanup(self.ctxt, service_id, worker)
        self.assertEqual(0, res)
        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(claimed_worker, db_worker)
        self._assertEqualObjects(worker, db_worker,
                                 ['updated_at', 'race_preventer'])
        self.assertNotEqual(worker.updated_at, db_worker.updated_at)
        self.assertEqual(worker.race_preventer + 1, db_worker.race_preventer)
Пример #5
0
    def test_worker_update(self):
        """Test basic worker update."""
        worker = self._create_workers(1)[0]
        worker = db.worker_get(self.ctxt, id=worker.id)
        res = db.worker_update(self.ctxt, worker.id, service_id=1)
        self.assertEqual(1, res)
        worker.service_id = 1

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ['updated_at'])
Пример #6
0
    def test_worker_update(self):
        """Test basic worker update."""
        worker = self._create_workers(1)[0]
        worker = db.worker_get(self.ctxt, id=worker.id)
        res = db.worker_update(self.ctxt, worker.id, service_id=1)
        self.assertEqual(1, res)
        worker.service_id = 1

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ['updated_at'])
Пример #7
0
    def test_worker_update_no_subsecond(self):
        """Test basic worker update."""
        db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = False
        worker = self._create_workers(1)[0]
        worker = db.worker_get(self.ctxt, id=worker.id)
        now = datetime.utcnow().replace(microsecond=123)
        with mock.patch("oslo_utils.timeutils.utcnow", return_value=now):
            res = db.worker_update(self.ctxt, worker.id, service_id=1)
        self.assertEqual(1, res)
        worker.service_id = 1

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ["updated_at"])
        self.assertEqual(0, db_worker.updated_at.microsecond)
Пример #8
0
    def test_worker_update_no_subsecond(self):
        """Test basic worker update."""
        db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = False
        worker = self._create_workers(1)[0]
        worker = db.worker_get(self.ctxt, id=worker.id)
        now = datetime.utcnow().replace(microsecond=123)
        with mock.patch('oslo_utils.timeutils.utcnow', return_value=now):
            res = db.worker_update(self.ctxt, worker.id, service_id=1)
        self.assertEqual(1, res)
        worker.service_id = 1

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ['updated_at'])
        self.assertEqual(0, db_worker.updated_at.microsecond)
Пример #9
0
 def test_worker_create_no_subsecond(self, mock_utcnow):
     """Test basic creation of a worker record."""
     db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = False
     worker = db.worker_create(self.ctxt, **self.worker_fields)
     db_worker = db.worker_get(self.ctxt, id=worker.id)
     self._assertEqualObjects(worker, db_worker)
     self.assertEqual(0, db_worker.updated_at.microsecond)
Пример #10
0
 def test_worker_create_no_subsecond(self, mock_utcnow):
     """Test basic creation of a worker record."""
     db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = False
     worker = db.worker_create(self.ctxt, **self.worker_fields)
     db_worker = db.worker_get(self.ctxt, id=worker.id)
     self._assertEqualObjects(worker, db_worker)
     self.assertEqual(0, db_worker.updated_at.microsecond)
Пример #11
0
    def test_do_cleanup_not_cleaning_already_claimed_by_us(self):
        """Basic cleanup that doesn't touch other thread's claimed works."""
        now = timeutils.utcnow()
        delta = timeutils.datetime.timedelta(seconds=1)
        original_time = now - delta
        # Creating the worker in the future, and then changing the in-memory
        # value of worker2.updated_at to an earlier time, we effectively
        # simulate that the worker entry was created in the past and that it
        # has been just updated between worker_get_all and trying
        # to claim a work for cleanup
        other_thread_claimed_time = now + delta
        vol = utils.create_volume(self.context, status='creating')
        worker1 = db.worker_create(self.context,
                                   status='creating',
                                   resource_type='Volume',
                                   resource_id=vol.id,
                                   service_id=self.service.id,
                                   updated_at=original_time)
        worker1 = db.worker_get(self.context, id=worker1.id)
        vol2 = utils.create_volume(self.context, status='deleting')
        worker2 = db.worker_create(self.context,
                                   status='deleting',
                                   resource_type='Volume',
                                   resource_id=vol2.id,
                                   service_id=self.service.id,
                                   updated_at=other_thread_claimed_time)
        worker2 = db.worker_get(self.context, id=worker2.id)
        # This with the mock below simulates worker2 was created in the past
        # and updated right between worker_get_all and worker_claim_for_cleanup
        worker2.updated_at = original_time

        clean_req = objects.CleanupRequest(service_id=self.service.id)
        mngr = FakeManager(self.service.id)
        with mock.patch('cinder.manager.timeutils.utcnow', return_value=now),\
                mock.patch('cinder.db.worker_get_all') as get_all_mock:
            get_all_mock.return_value = [worker1, worker2]
            mngr.do_cleanup(self.context, clean_req)

        workers = db.worker_get_all(self.context)
        self.assertEqual(1, len(workers))
        self.assertEqual(worker2.id, workers[0].id)

        vol.refresh()
        self.assertEqual('creating_cleaned', vol.status)
        vol2.refresh()
        self.assertEqual('deleting', vol2.status)
Пример #12
0
    def test_worker_update_update_orm(self):
        """Test worker update updating the worker orm object."""
        worker = self._create_workers(1)[0]
        res = db.worker_update(self.ctxt, worker.id, orm_worker=worker,
                               service_id=1)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ['updated_at'])
Пример #13
0
    def test_worker_claim_same_service(self):
        """Test worker claim of a DB entry that has our service_id."""
        service_id = 1
        worker = db.worker_create(
            self.ctxt, resource_type="Volume", resource_id=fake.VOLUME_ID, status="deleting", service_id=service_id
        )
        # Read from DB to get updated_at field
        worker = db.worker_get(self.ctxt, id=worker.id)
        claimed_worker = db.worker_get(self.ctxt, id=worker.id)

        res = db.worker_claim_for_cleanup(self.ctxt, service_id, claimed_worker)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)

        self._assertEqualObjects(claimed_worker, db_worker)
        self._assertEqualObjects(worker, db_worker, ["updated_at"])
        self.assertNotEqual(worker.updated_at, db_worker.updated_at)
Пример #14
0
    def test_worker_update_update_orm(self):
        """Test worker update updating the worker orm object."""
        worker = self._create_workers(1)[0]
        res = db.worker_update(self.ctxt, worker.id, orm_worker=worker, service_id=1)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        # If we are updating the ORM object we don't ignore the update_at field
        # because it will get updated in the ORM instance.
        self._assertEqualObjects(worker, db_worker)
Пример #15
0
    def test_worker_claim_fails_status_change(self):
        """Test that claim fails if the work entry has changed its status."""
        worker = db.worker_create(self.ctxt, resource_type="Volume", resource_id=fake.VOLUME_ID, status="deleting")
        worker.status = "creating"

        res = db.worker_claim_for_cleanup(self.ctxt, 1, worker)
        self.assertEqual(0, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ["status"])
        self.assertIsNone(db_worker.service_id)
Пример #16
0
    def test_worker_update_update_orm(self):
        """Test worker update updating the worker orm object."""
        worker = self._create_workers(1)[0]
        res = db.worker_update(self.ctxt,
                               worker.id,
                               orm_worker=worker,
                               service_id=1)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ['updated_at'])
Пример #17
0
    def test_worker_claim_same_service(self):
        """Test worker claim of a DB entry that has our service_id."""
        service_id = 1
        worker = db.worker_create(self.ctxt,
                                  resource_type='Volume',
                                  resource_id=fake.VOLUME_ID,
                                  status='deleting',
                                  service_id=service_id)
        # Read from DB to get updated_at field
        worker = db.worker_get(self.ctxt, id=worker.id)
        claimed_worker = db.worker_get(self.ctxt, id=worker.id)

        res = db.worker_claim_for_cleanup(self.ctxt, service_id,
                                          claimed_worker)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)

        self._assertEqualObjects(claimed_worker, db_worker)
        self._assertEqualObjects(worker, db_worker, ['updated_at'])
        self.assertNotEqual(worker.updated_at, db_worker.updated_at)
Пример #18
0
    def test_worker_claim(self):
        """Test worker claim of normal DB entry."""
        service_id = 1
        worker = db.worker_create(self.ctxt, resource_type="Volume", resource_id=fake.VOLUME_ID, status="deleting")

        res = db.worker_claim_for_cleanup(self.ctxt, service_id, worker)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)

        self._assertEqualObjects(worker, db_worker, ["updated_at"])
        self.assertEqual(service_id, db_worker.service_id)
        self.assertEqual(worker.service_id, db_worker.service_id)
Пример #19
0
    def test_worker_update_update_orm(self):
        """Test worker update updating the worker orm object."""
        worker = self._create_workers(1)[0]
        res = db.worker_update(self.ctxt,
                               worker.id,
                               orm_worker=worker,
                               service_id=1)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        # If we are updating the ORM object we don't ignore the update_at field
        # because it will get updated in the ORM instance.
        self._assertEqualObjects(worker, db_worker)
Пример #20
0
    def set_worker(self):
        worker = self.worker

        service_id = service.Service.service_id
        resource_type = self.__class__.__name__

        if worker:
            if worker.cleaning:
                return
        else:
            try:
                worker = db.worker_get(self._context,
                                       resource_type=resource_type,
                                       resource_id=self.id)
            except exception.WorkerNotFound:
                # If the call didn't come from an RPC call we still have to
                # create the entry in the DB.
                try:
                    self.worker = db.worker_create(self._context,
                                                   status=self.status,
                                                   resource_type=resource_type,
                                                   resource_id=self.id,
                                                   service_id=service_id)
                    return
                except exception.WorkerExists:
                    # If 2 cleanable operations are competing for this resource
                    # and the other one created the entry first that one won
                    raise exception.CleanableInUse(type=resource_type,
                                                   id=self.id)

        # If we have to claim this work or if the status has changed we have
        # to update DB.
        if (worker.service_id != service_id or worker.status != self.status):
            try:
                db.worker_update(self._context,
                                 worker.id,
                                 filters={
                                     'service_id': worker.service_id,
                                     'status': worker.status,
                                     'race_preventer': worker.race_preventer,
                                     'updated_at': worker.updated_at
                                 },
                                 service_id=service_id,
                                 status=self.status,
                                 orm_worker=worker)
            except exception.WorkerNotFound:
                self.worker = None
                raise exception.CleanableInUse(type=self.__class__.__name__,
                                               id=self.id)
        self.worker = worker
Пример #21
0
    def test_worker_claim_fails_status_change(self):
        """Test that claim fails if the work entry has changed its status."""
        worker = db.worker_create(self.ctxt,
                                  resource_type='Volume',
                                  resource_id=fake.VOLUME_ID,
                                  status='deleting')
        worker.status = 'creating'

        res = db.worker_claim_for_cleanup(self.ctxt, 1, worker)
        self.assertEqual(0, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self._assertEqualObjects(worker, db_worker, ['status'])
        self.assertIsNone(db_worker.service_id)
Пример #22
0
    def test_worker_claim_fails_service_change(self):
        """Test that claim fails on worker service change."""
        failed_service = 1
        working_service = 2
        this_service = 3
        worker = db.worker_create(
            self.ctxt, resource_type="Volume", resource_id=fake.VOLUME_ID, status="deleting", service_id=working_service
        )

        worker.service_id = failed_service
        res = db.worker_claim_for_cleanup(self.ctxt, this_service, worker)
        self.assertEqual(0, res)
        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self.assertEqual(working_service, db_worker.service_id)
Пример #23
0
    def _create_workers(self, num, read_back=False, **fields):
        workers = []
        base_params = self.worker_fields.copy()
        base_params.update(fields)

        for i in range(num):
            params = base_params.copy()
            params['resource_id'] = self._uuid()
            workers.append(db.worker_create(self.ctxt, **params))

        if read_back:
            for i in range(len(workers)):
                workers[i] = db.worker_get(self.ctxt, id=workers[i].id)

        return workers
Пример #24
0
    def _create_workers(self, num, read_back=False, **fields):
        workers = []
        base_params = self.worker_fields.copy()
        base_params.update(fields)

        for i in range(num):
            params = base_params.copy()
            params['resource_id'] = self._uuid()
            workers.append(db.worker_create(self.ctxt, **params))

        if read_back:
            for i in range(len(workers)):
                workers[i] = db.worker_get(self.ctxt, id=workers[i].id)

        return workers
Пример #25
0
    def set_worker(self):
        worker = self.worker

        service_id = service.Service.service_id
        resource_type = self.__class__.__name__

        if worker:
            if worker.cleaning:
                return
        else:
            try:
                worker = db.worker_get(self._context,
                                       resource_type=resource_type,
                                       resource_id=self.id)
            except exception.WorkerNotFound:
                # If the call didn't come from an RPC call we still have to
                # create the entry in the DB.
                try:
                    self.worker = db.worker_create(self._context,
                                                   status=self.status,
                                                   resource_type=resource_type,
                                                   resource_id=self.id,
                                                   service_id=service_id)
                    return
                except exception.WorkerExists:
                    # If 2 cleanable operations are competing for this resource
                    # and the other one created the entry first that one won
                    raise exception.CleanableInUse(type=resource_type,
                                                   id=self.id)

        # If we have to claim this work or if the status has changed we have
        # to update DB.
        if (worker.service_id != service_id or worker.status != self.status):
            try:
                db.worker_update(
                    self._context, worker.id,
                    filters={'service_id': worker.service_id,
                             'status': worker.status,
                             'race_preventer': worker.race_preventer,
                             'updated_at': worker.updated_at},
                    service_id=service_id,
                    status=self.status,
                    orm_worker=worker)
            except exception.WorkerNotFound:
                self.worker = None
                raise exception.CleanableInUse(type=self.__class__.__name__,
                                               id=self.id)
        self.worker = worker
Пример #26
0
    def test_worker_claim_fails_service_change(self):
        """Test that claim fails on worker service change."""
        failed_service = 1
        working_service = 2
        this_service = 3
        worker = db.worker_create(self.ctxt,
                                  resource_type='Volume',
                                  resource_id=fake.VOLUME_ID,
                                  status='deleting',
                                  service_id=working_service)

        worker.service_id = failed_service
        res = db.worker_claim_for_cleanup(self.ctxt, this_service, worker)
        self.assertEqual(0, res)
        db_worker = db.worker_get(self.ctxt, id=worker.id)
        self.assertEqual(working_service, db_worker.service_id)
Пример #27
0
    def test_worker_claim(self):
        """Test worker claim of normal DB entry."""
        service_id = 1
        worker = db.worker_create(self.ctxt,
                                  resource_type='Volume',
                                  resource_id=fake.VOLUME_ID,
                                  status='deleting')

        res = db.worker_claim_for_cleanup(self.ctxt, service_id, worker)
        self.assertEqual(1, res)

        db_worker = db.worker_get(self.ctxt, id=worker.id)

        self._assertEqualObjects(worker, db_worker, ['updated_at'])
        self.assertEqual(service_id, db_worker.service_id)
        self.assertEqual(worker.service_id, db_worker.service_id)
Пример #28
0
 def test_worker_create_and_get(self):
     """Test basic creation of a worker record."""
     worker = db.worker_create(self.ctxt, **self.worker_fields)
     db_worker = db.worker_get(self.ctxt, id=worker.id)
     self._assertEqualObjects(worker, db_worker)
Пример #29
0
 def test_worker_create_and_get(self):
     """Test basic creation of a worker record."""
     worker = db.worker_create(self.ctxt, **self.worker_fields)
     db_worker = db.worker_get(self.ctxt, id=worker.id)
     self._assertEqualObjects(worker, db_worker)