From bf574929266e1f6b367f4943007a3d496a394a03 Mon Sep 17 00:00:00 2001 From: Tetsuro Nakamura Date: Sun, 17 Mar 2019 04:56:02 +0000 Subject: [PATCH] Do not execute event of transitional lease If the continuous execution of an event is called just after the lease creation is called, it can fail with the invalid lease status transition error from CREATING to STARTING. This patch adds a check before the event execution whether the lease status of the event is not transitional but stable and pend the execution to the next time if it is transitional. Change-Id: I033dd814d384131de8e7494d22cd42f1ea67112b Closes-Bug: #1820476 --- blazar/manager/service.py | 4 ++++ blazar/status.py | 10 ++++++++++ blazar/tests/manager/test_service.py | 30 +++++++++++++++++++++++++--- blazar/tests/test_status.py | 15 ++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/blazar/manager/service.py b/blazar/manager/service.py index 31894516..10d63ce0 100644 --- a/blazar/manager/service.py +++ b/blazar/manager/service.py @@ -155,6 +155,10 @@ class ManagerService(service_utils.RPCServer): LOG.info("Trying to execute events: %s", events) for event in events: + if not status.LeaseStatus.is_stable(event['lease_id']): + LOG.info("Skip event %s because the status of the lease %s " + "is still transitional", event, event['lease_id']) + continue db_api.event_update(event['id'], {'status': status.event.IN_PROGRESS}) try: diff --git a/blazar/status.py b/blazar/status.py index e8d549ee..ef3920b2 100644 --- a/blazar/status.py +++ b/blazar/status.py @@ -168,6 +168,16 @@ class LeaseStatus(BaseStatus): return True + @classmethod + def is_stable(cls, lease_id): + """Check if the lease status is stable + + :param lease_id: Lease ID + :return: True if the status is in (PENDING, ACTIVE, TERMINATED, ERROR) + """ + lease = db_api.lease_get(lease_id) + return (lease['status'] in cls.STABLE) + @classmethod def lease_status(cls, transition, result_in): """Decorator for managing a lease status. diff --git a/blazar/tests/manager/test_service.py b/blazar/tests/manager/test_service.py index 55c2a942..1d1dc23c 100644 --- a/blazar/tests/manager/test_service.py +++ b/blazar/tests/manager/test_service.py @@ -145,6 +145,7 @@ class ServiceTestCase(tests.TestCase): 'resource_id': '111', 'resource_type': 'virtual:instance', 'status': 'FAKE PROGRESS'}], + 'status': status.LeaseStatus.PENDING, 'start_date': datetime.datetime(2013, 12, 20, 13, 00), 'end_date': datetime.datetime(2013, 12, 20, 15, 00), 'trust_id': 'exxee111qwwwwe'} @@ -231,8 +232,12 @@ class ServiceTestCase(tests.TestCase): def test_event_success(self): events = self.patch(self.db_api, 'event_get_all_sorted_by_filters') event_update = self.patch(self.db_api, 'event_update') - events.return_value = [{'id': '111-222-333', 'time': self.good_date}, - {'id': '444-555-666', 'time': self.good_date}] + events.return_value = [{'id': '111-222-333', + 'lease_id': 'lease_id1', + 'time': self.good_date}, + {'id': '444-555-666', + 'lease_id': 'lease_id2', + 'time': self.good_date}] self.patch(eventlet, 'spawn_n') self.manager._event() @@ -245,7 +250,9 @@ class ServiceTestCase(tests.TestCase): events = self.patch(self.db_api, 'event_get_all_sorted_by_filters') event_update = self.patch(self.db_api, 'event_update') self.patch(eventlet, 'spawn_n').side_effect = Exception - events.return_value = [{'id': '111-222-333', 'time': self.good_date}] + events.return_value = [{'id': '111-222-333', + 'lease_id': self.lease_id, + 'time': self.good_date}] self.manager._event() @@ -253,6 +260,23 @@ class ServiceTestCase(tests.TestCase): mock.call('111-222-333', {'status': status.event.IN_PROGRESS}), mock.call('111-222-333', {'status': status.event.ERROR})]) + def test_event_pass(self): + events = self.patch(self.db_api, 'event_get_all_sorted_by_filters') + events.return_value = [{'id': '111-222-333', + 'lease_id': self.lease_id, + 'time': self.good_date}] + + self.lease_get = self.patch(self.db_api, 'lease_get') + lease = self.lease.copy() + lease.update({'status': status.LeaseStatus.CREATING}) + self.lease_get.return_value = lease + + event_update = self.patch(self.db_api, 'event_update') + + self.manager._event() + + event_update.assert_not_called() + def test_exec_event_success(self): event = {'id': '111-222-333', 'event_type': 'start_lease', diff --git a/blazar/tests/test_status.py b/blazar/tests/test_status.py index 22be8a30..e2cdd955 100644 --- a/blazar/tests/test_status.py +++ b/blazar/tests/test_status.py @@ -154,6 +154,21 @@ class LeaseStatusTestCase(tests.TestCase): self.assertFalse(result) + def test_is_stable(self): + lease_id = self.lease_id + lease_pending = {'id': lease_id, + 'status': status.LeaseStatus.PENDING} + lease_creating = {'id': lease_id, + 'status': status.LeaseStatus.CREATING} + + self.patch(self.db_api, 'lease_get').return_value = lease_pending + result = self.status.LeaseStatus.is_stable(lease_id) + self.assertTrue(result) + + self.patch(self.db_api, 'lease_get').return_value = lease_creating + result = self.status.LeaseStatus.is_stable(lease_id) + self.assertFalse(result) + def test_lease_status(self): lease = { 'status': status.LeaseStatus.PENDING