diff options
author | Erik Olof Gunnar Andersson <eandersson@blizzard.com> | 2022-02-22 20:37:35 -0800 |
---|---|---|
committer | Erik Olof Gunnar Andersson <eandersson@blizzard.com> | 2022-03-02 17:57:48 -0800 |
commit | 93ebb1af53d216982210cff21a1bde87489ed0f1 (patch) | |
tree | c636ad8b3976123730424d0d32caf58485449183 | |
parent | 8ce022a7b98521a1016e63350abff97aba9b9f77 (diff) | |
download | designate-93ebb1af53d216982210cff21a1bde87489ed0f1.tar.gz |
Add inactive value to floating ip status
This patch adds a new status value for floating ips called
inactive that is used to indicate if there is not a dns record
assosciated with a floating ip.
Partial-Bug: #1932026
Change-Id: Ieca3cb06b99ba4556f4e6e770f82ec594d1ab1b6
-rw-r--r-- | designate/central/service.py | 60 | ||||
-rw-r--r-- | designate/common/constants.py | 16 | ||||
-rw-r--r-- | designate/objects/floating_ip.py | 9 | ||||
-rw-r--r-- | designate/tests/test_api/test_v2/test_floatingips.py | 82 | ||||
-rw-r--r-- | designate/tests/test_central/test_service.py | 22 | ||||
-rw-r--r-- | releasenotes/notes/new-ptr-status-69958252a2f294c9.yaml | 5 |
6 files changed, 164 insertions, 30 deletions
diff --git a/designate/central/service.py b/designate/central/service.py index dadd3706..eda8a955 100644 --- a/designate/central/service.py +++ b/designate/central/service.py @@ -1993,31 +1993,55 @@ class Service(service.RPCService): 'ptrdname': None, 'ttl': None, 'description': None, - 'action': None, - 'status': 'ACTIVE' + 'action': constants.NONE, + 'status': constants.INACTIVE }) + # TTL population requires a present record in order to find the - # RS or Zone. - if record and record.action != 'DELETE': - if not recordset: + # Recordset or Zone. + if not record: + LOG.debug('No record information found for %s', fip['id']) + return fip_ptr + + if not recordset: + try: recordset = self.storage.get_recordset( - elevated_context, record.recordset_id) + elevated_context, record.recordset_id + ) + except exceptions.RecordSetNotFound: + LOG.debug('No recordset found for %s', fip['id']) + return fip_ptr - fip_ptr['action'] = recordset.action - fip_ptr['status'] = recordset.status + if recordset.ttl is not None: + fip_ptr['ttl'] = recordset.ttl + else: + if not zone: + try: + zone = self.get_zone( + elevated_context, record.zone_id + ) + except exceptions.ZoneNotFound: + LOG.debug('No zone found for %s', fip['id']) + return fip_ptr - if recordset.ttl is not None: - fip_ptr['ttl'] = recordset.ttl - else: - if not zone: - zone = self.get_zone(elevated_context, - record.zone_id) - fip_ptr['ttl'] = zone.ttl + fip_ptr['ttl'] = zone.ttl - fip_ptr['ptrdname'] = record.data - fip_ptr['description'] = record.description + if recordset.action in constants.FLOATING_IP_ACTIONS: + fip_ptr['action'] = recordset.action else: - LOG.debug('No record information found for %s', fip['id']) + LOG.debug( + 'Action %s not valid for floating ip action', recordset.action + ) + + if recordset.status in constants.FLOATING_IP_STATUSES: + fip_ptr['status'] = recordset.status + else: + LOG.debug( + 'Status %s not valid for floating ip status', recordset.status + ) + + fip_ptr['ptrdname'] = record.data + fip_ptr['description'] = record.description return fip_ptr diff --git a/designate/common/constants.py b/designate/common/constants.py index 99433462..1275c44c 100644 --- a/designate/common/constants.py +++ b/designate/common/constants.py @@ -15,3 +15,19 @@ # RBAC related constants RBAC_PROJECT_ID = 'project_id' RBAC_TARGET_PROJECT_ID = 'target_project_id' + +# Statuses +ACTIVE = 'ACTIVE' +ERROR = 'ERROR' +INACTIVE = 'INACTIVE' +PENDING = 'PENDING' + +# Actions +CREATE = 'CREATE' +DELETE = 'DELETE' +NONE = 'NONE' +UPDATE = 'UPDATE' + +# Floating IP constants +FLOATING_IP_ACTIONS = [CREATE, DELETE, UPDATE, NONE] +FLOATING_IP_STATUSES = [ACTIVE, ERROR, INACTIVE, PENDING] diff --git a/designate/objects/floating_ip.py b/designate/objects/floating_ip.py index 5423b1a8..87036838 100644 --- a/designate/objects/floating_ip.py +++ b/designate/objects/floating_ip.py @@ -13,6 +13,7 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +from designate.common import constants from designate.objects import base from designate.objects import fields @@ -27,10 +28,10 @@ class FloatingIP(base.DictObjectMixin, base.PersistentObjectMixin, "ttl": fields.IntegerFields(nullable=True, minimum=1, maximum=2147483647), "region": fields.StringFields(nullable=True), - "action": fields.EnumField(['CREATE', 'DELETE', - 'UPDATE', 'NONE'], nullable=True), - "status": fields.EnumField(['ACTIVE', - 'PENDING', 'ERROR'], nullable=True) + "action": fields.EnumField(constants.FLOATING_IP_ACTIONS, + nullable=True), + "status": fields.EnumField(constants.FLOATING_IP_STATUSES, + nullable=True) } STRING_KEYS = [ diff --git a/designate/tests/test_api/test_v2/test_floatingips.py b/designate/tests/test_api/test_v2/test_floatingips.py index 4667da55..0203d1a5 100644 --- a/designate/tests/test_api/test_v2/test_floatingips.py +++ b/designate/tests/test_api/test_v2/test_floatingips.py @@ -41,8 +41,8 @@ class ApiV2ReverseFloatingIPTest(ApiV2TestCase): self.assertEqual(fip['address'], fip_record['address']) self.assertIsNone(fip_record['description']) self.assertIsNone(fip_record['ptrdname']) - self.assertIsNone(fip_record['action']) - self.assertEqual('ACTIVE', fip_record['status']) + self.assertEqual('NONE', fip_record['action']) + self.assertEqual('INACTIVE', fip_record['status']) def test_get_floatingip_with_record(self): fixture = self.get_ptr_fixture() @@ -72,6 +72,61 @@ class ApiV2ReverseFloatingIPTest(ApiV2TestCase): self.assertEqual('CREATE', fip_record['action']) self.assertEqual('PENDING', fip_record['status']) + def test_get_floatingip_after_unset(self): + fixture = self.get_ptr_fixture() + context = self.get_context(project_id='a') + elevated_context = context.elevated() + elevated_context.all_tenants = True + + fip = self.network_api.fake.allocate_floatingip(context.project_id) + + # Unsetting via "None" + self.central_service.update_floatingip( + context, fip['region'], fip['id'], fixture) + + criterion = { + 'managed_resource_id': fip['id'], + 'managed_tenant_id': context.project_id + } + zone_id = self.central_service.find_record( + elevated_context, criterion=criterion).zone_id + + # Simulate the unset on the backend + zone_serial = self.central_service.get_zone( + elevated_context, zone_id).serial + self.central_service.update_status( + elevated_context, zone_id, 'SUCCESS', zone_serial, 'UPDATE') + + # Unset PTR ('ptrdname' is None aka null in JSON) + response = self.client.patch_json( + '/reverse/floatingips/%s' % ":".join([fip['region'], fip['id']]), + {'ptrdname': None}, + headers={'X-Test-Tenant-Id': context.project_id}) + self.assertIsNone(response.json) + self.assertEqual(202, response.status_int) + + # Simulate the unset on the backend + zone_serial = self.central_service.get_zone( + elevated_context, zone_id).serial + self.central_service.update_status( + elevated_context, zone_id, 'SUCCESS', zone_serial, 'UPDATE') + + response = self.client.get( + '/reverse/floatingips/%s' % ":".join([fip['region'], fip['id']]), + headers={'X-Test-Tenant-Id': context.project_id}) + + self.assertEqual(200, response.status_int) + self.assertEqual('application/json', response.content_type) + + fip_record = response.json + self.assertEqual(":".join([fip['region'], fip['id']]), + fip_record['id']) + self.assertEqual(fip['address'], fip_record['address']) + self.assertIsNone(fip_record['description']) + self.assertIsNone(fip_record['ptrdname']) + self.assertEqual('NONE', fip_record['action']) + self.assertEqual('INACTIVE', fip_record['status']) + def test_get_floatingip_not_allocated(self): url = '/reverse/floatingips/foo:04580c52-b253-4eb7-8791-fbb9de9f856f' @@ -108,8 +163,8 @@ class ApiV2ReverseFloatingIPTest(ApiV2TestCase): fip_record['id']) self.assertEqual(fip['address'], fip_record['address']) self.assertIsNone(fip_record['description']) - self.assertIsNone(fip_record['action']) - self.assertEqual('ACTIVE', fip_record['status']) + self.assertEqual('NONE', fip_record['action']) + self.assertEqual('INACTIVE', fip_record['status']) def test_list_floatingip_with_record(self): fixture = self.get_ptr_fixture() @@ -197,6 +252,19 @@ class ApiV2ReverseFloatingIPTest(ApiV2TestCase): self.central_service.update_floatingip( context, fip['region'], fip['id'], fixture) + criterion = { + 'managed_resource_id': fip['id'], + 'managed_tenant_id': context.project_id + } + zone_id = self.central_service.find_record( + elevated_context, criterion=criterion).zone_id + + # Simulate the unset on the backend + zone_serial = self.central_service.get_zone( + elevated_context, zone_id).serial + self.central_service.update_status( + elevated_context, zone_id, 'SUCCESS', zone_serial, 'UPDATE') + # Unset PTR ('ptrdname' is None aka null in JSON) response = self.client.patch_json( '/reverse/floatingips/%s' % ":".join([fip['region'], fip['id']]), @@ -205,6 +273,12 @@ class ApiV2ReverseFloatingIPTest(ApiV2TestCase): self.assertIsNone(response.json) self.assertEqual(202, response.status_int) + # Simulate the unset on the backend + zone_serial = self.central_service.get_zone( + elevated_context, zone_id).serial + self.central_service.update_status( + elevated_context, zone_id, 'SUCCESS', zone_serial, 'UPDATE') + fip = self.central_service.get_floatingip( context, fip['region'], fip['id']) self.assertIsNone(fip['ptrdname']) diff --git a/designate/tests/test_central/test_service.py b/designate/tests/test_central/test_service.py index 60d9e15b..7649856a 100644 --- a/designate/tests/test_central/test_service.py +++ b/designate/tests/test_central/test_service.py @@ -2222,6 +2222,8 @@ class CentralServiceTest(CentralTestCase): criterion = { 'managed_resource_id': fip['id'], 'managed_tenant_id': context_a.project_id} + zone_id = self.central_service.find_record( + elevated_a, criterion).zone_id self.network_api.fake.deallocate_floatingip(fip['id']) @@ -2243,9 +2245,15 @@ class CentralServiceTest(CentralTestCase): context_b, fip['region'], fip['id']) self.assertIsNone(fip_ptr['ptrdname']) + # Simulate the invalidation on the backend + zone_serial = self.central_service.get_zone( + elevated_a, zone_id).serial + self.central_service.update_status( + elevated_a, zone_id, 'SUCCESS', zone_serial, 'UPDATE') + record = self.central_service.find_record(elevated_a, criterion) - self.assertEqual('DELETE', record.action) - self.assertEqual('PENDING', record.status) + self.assertEqual('NONE', record.action) + self.assertEqual('DELETED', record.status) def test_list_floatingips_no_allocations(self): context = self.get_context(project_id='a') @@ -2331,9 +2339,15 @@ class CentralServiceTest(CentralTestCase): self.assertEqual(1, len(fips)) self.assertIsNone(fips[0]['ptrdname']) + # Simulate the invalidation on the backend + zone_serial = self.central_service.get_zone( + elevated_a, zone_id).serial + self.central_service.update_status( + elevated_a, zone_id, 'SUCCESS', zone_serial, 'UPDATE') + record = self.central_service.find_record(elevated_a, criterion) - self.assertEqual('DELETE', record.action) - self.assertEqual('PENDING', record.status) + self.assertEqual('NONE', record.action) + self.assertEqual('DELETED', record.status) def test_set_floatingip(self): context = self.get_context(project_id='a') diff --git a/releasenotes/notes/new-ptr-status-69958252a2f294c9.yaml b/releasenotes/notes/new-ptr-status-69958252a2f294c9.yaml new file mode 100644 index 00000000..20ad44e0 --- /dev/null +++ b/releasenotes/notes/new-ptr-status-69958252a2f294c9.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Added new state ``INACTIVE`` to the Floating IP status to indicate that + it is not currently associated to a DNS record.
\ No newline at end of file |