summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Olof Gunnar Andersson <eandersson@blizzard.com>2022-02-22 20:37:35 -0800
committerErik Olof Gunnar Andersson <eandersson@blizzard.com>2022-03-02 17:57:48 -0800
commit93ebb1af53d216982210cff21a1bde87489ed0f1 (patch)
treec636ad8b3976123730424d0d32caf58485449183
parent8ce022a7b98521a1016e63350abff97aba9b9f77 (diff)
downloaddesignate-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.py60
-rw-r--r--designate/common/constants.py16
-rw-r--r--designate/objects/floating_ip.py9
-rw-r--r--designate/tests/test_api/test_v2/test_floatingips.py82
-rw-r--r--designate/tests/test_central/test_service.py22
-rw-r--r--releasenotes/notes/new-ptr-status-69958252a2f294c9.yaml5
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