Add an API for associating floating IPs with DNS entries.

For blueprint public-and-private-dns

Change-Id: Ia6c3f046db4dd4978aa5ef950fd472d3455fe301
This commit is contained in:
Andrew Bogott
2011-12-11 04:15:26 -06:00
parent 9838689680
commit eaa75aaae7
4 changed files with 241 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
About The Floating IP DNS Extension
================================
The Floating IP DNS extension provides an interface for managing DNS records associated with IP addresses
allocated by the Floating Ips extension. Requests are dispatched to a DNS driver selected at startup.
To obtain current information the extensions available to you, issue an EXTENSION query on the OpenStack system where it is installed, such as http://mycloud.com/v1.1/tenant/extension.
Floating IPs Extension Overview
-------------------------------
Name
Floating IP DNS
Namespace
http://docs.openstack.org/ext/floating_ip_dns/api/v1.1
Alias
OPS-DNS
Contact
Andrew Bogott <abogott@wikimedia.org>
Status
Alpha
Extension Version
v1.0 (2011-12-22)
Dependencies
Compute API v1.1
Floating IPs Extension, v1.0
Doc Link (PDF)
http://
Doc Link (WADL)
http://
Short Description
This extension enables associated DNS entries with floating IPs.
Sample Query Responses
----------------------
As shown below, responses to an EXTENSION query in XML or JSON provide basic information about the extension.
Extension Query Response: XML::
None
Extension Query Response: JSON::
{'extensions':
[{'updated': '2011-12-23T00:00:00+00:00',
'name': 'Floating_ip_dns',
'links': [],
'namespace': 'http://docs.openstack.org/ext/floating_ip_dns/api/v1.1',
'alias': 'os-floating-ip_dns',
'description': 'Floating IP DNS support'}]}
Document Change History
-----------------------
============= =====================================
Revision Date Summary of Changes
2011-12-23 Initial draft
============= =====================================
Summary of Changes
==================
This extension to the Compute API enables management of DNS entries for floating IP addresses.
New Action
----------
None
New Faults
----------
None
New Headers
-----------
None
New Resources
-------------
Get a list of DNS Domains (aka 'zones') published by the DNS driver:
GET /v1.1/<tenant_id>/os-floating-ip-dns/
# Sample Response:
{ 'zones' : [
{'zone' : 'example.org'}
{'zone' : 'example.net'}]}
Create a DNS entry:
POST /v1.1/<tenant_id>/os-floating-ip-dns/
# Sample body:
{ 'dns_entry' :
{ 'name': 'instance1',
'ip': '192.168.53.11',
'dns_type': 'A',
'zone': 'example.org'}}
# Sample Response (success):
{ 'dns_entry' :
{ 'ip' : '192.168.53.11',
'type' : 'A',
'zone' : 'example.org',
'name' : 'instance1' }}
Failure Response Code: 409 (indicates an entry with name & zone already exists.)
Find DNS entries for a given domain and name:
GET /v1.1/<tenant_id>/os-floating-ip-dns/<domain>?name=<name>
# Sample Response:
{ 'dns_entries' : [
{ 'ip' : '192.168.53.11',
'type' : 'A',
'zone' : <domain>,
'name' : <name> }]}
Find DNS entries for a given domain and ip:
GET /v1.1/<tenant_id>/os-floating-ip-dns/<domain>/?ip=<ip>
# Sample Response:
{ 'dns_entries' : [
{ 'ip' : <ip>,
'type' : 'A',
'zone' : <domain>,
'name' : 'example1' }
{ 'ip' : <ip>,
'type' : 'A',
'zone' : <domain>,
'name' : 'example2' }]}
Delete a DNS entry:
DELETE /v1.1/<tenant_id>/os-floating-ip-dns/<domain>?name=<name>
Normal Response Code: 200
Failure Response Code: 404 (Entry to be deleted not found)
New States
----------
None
Changes to the Cloud Servers Specification
------------------------------------------
None

View File

@@ -555,6 +555,10 @@ class FloatingIpNotFound(NotFound):
message = _("Floating ip not found for id %(id)s.") message = _("Floating ip not found for id %(id)s.")
class FloatingIpDNSExists(Invalid):
message = _("The DNS entry %(name)s already exists in zone %(zone)s.")
class FloatingIpNotFoundForAddress(FloatingIpNotFound): class FloatingIpNotFoundForAddress(FloatingIpNotFound):
message = _("Floating ip not found for address %(address)s.") message = _("Floating ip not found for address %(address)s.")

View File

@@ -370,6 +370,12 @@ DEFINE_string('instance_dns_manager',
'DNS Manager for instance IPs') 'DNS Manager for instance IPs')
DEFINE_string('instance_dns_zone', '', DEFINE_string('instance_dns_zone', '',
'DNS Zone for instance IPs') 'DNS Zone for instance IPs')
DEFINE_string('floating_ip_dns_manager',
'nova.network.dns_driver.DNSDriver',
'DNS Manager for floating IPs')
DEFINE_multistring('floating_ip_dns_zones', '',
'DNS zones for floating IPs.'
'e.g. "example.org"')
DEFINE_string('network_manager', 'nova.network.manager.VlanManager', DEFINE_string('network_manager', 'nova.network.manager.VlanManager',
'Manager for network') 'Manager for network')
DEFINE_string('volume_manager', 'nova.volume.manager.VolumeManager', DEFINE_string('volume_manager', 'nova.volume.manager.VolumeManager',

View File

@@ -19,11 +19,13 @@ import mox
from nova import context from nova import context
from nova import db from nova import db
from nova import exception from nova import exception
from nova import flags
from nova import log as logging from nova import log as logging
from nova import rpc from nova import rpc
from nova import test from nova import test
from nova import utils from nova import utils
from nova.network import manager as network_manager from nova.network import manager as network_manager
from nova.network import api as network_api
from nova.tests import fake_network from nova.tests import fake_network
@@ -1123,11 +1125,17 @@ class FloatingIPTestCase(test.TestCase):
def setUp(self): def setUp(self):
super(FloatingIPTestCase, self).setUp() super(FloatingIPTestCase, self).setUp()
self.network = TestFloatingIPManager() self.network = TestFloatingIPManager()
temp = utils.import_object('nova.network.minidns.MiniDNS')
self.network.floating_dns_manager = temp
self.network.db = db self.network.db = db
self.project_id = 'testproject' self.project_id = 'testproject'
self.context = context.RequestContext('testuser', self.project_id, self.context = context.RequestContext('testuser', self.project_id,
is_admin=False) is_admin=False)
def tearDown(self):
super(FloatingIPTestCase, self).tearDown()
self.network.floating_dns_manager.delete_dns_file()
def test_double_deallocation(self): def test_double_deallocation(self):
instance_ref = db.api.instance_create(self.context, instance_ref = db.api.instance_create(self.context,
{"project_id": self.project_id}) {"project_id": self.project_id})
@@ -1138,3 +1146,66 @@ class FloatingIPTestCase(test.TestCase):
instance_id=instance_ref['id']) instance_id=instance_ref['id'])
self.network.deallocate_for_instance(self.context, self.network.deallocate_for_instance(self.context,
instance_id=instance_ref['id']) instance_id=instance_ref['id'])
def test_floating_dns_zones(self):
zone1 = "example.org"
zone2 = "example.com"
flags.FLAGS.floating_ip_dns_zones = [zone1, zone2]
zones = self.network.get_dns_zones(self.context)
self.assertEqual(len(zones), 2)
self.assertEqual(zones[0], zone1)
self.assertEqual(zones[1], zone2)
def test_floating_dns_create_conflict(self):
zone = "example.org"
address1 = "10.10.10.11"
name1 = "foo"
name2 = "bar"
self.network.add_dns_entry(self.context, address1, name1, "A", zone)
self.assertRaises(exception.FloatingIpDNSExists,
self.network.add_dns_entry, self.context,
address1, name1, "A", zone)
def test_floating_create_and_get(self):
zone = "example.org"
address1 = "10.10.10.11"
name1 = "foo"
name2 = "bar"
entries = self.network.get_dns_entries_by_address(self.context,
address1, zone)
self.assertFalse(entries)
self.network.add_dns_entry(self.context, address1, name1, "A", zone)
self.network.add_dns_entry(self.context, address1, name2, "A", zone)
entries = self.network.get_dns_entries_by_address(self.context,
address1, zone)
self.assertEquals(len(entries), 2)
self.assertEquals(entries[0], name1)
self.assertEquals(entries[1], name2)
entries = self.network.get_dns_entries_by_name(self.context,
name1, zone)
self.assertEquals(len(entries), 1)
self.assertEquals(entries[0], address1)
def test_floating_dns_delete(self):
zone = "example.org"
address1 = "10.10.10.11"
name1 = "foo"
name2 = "bar"
self.network.add_dns_entry(self.context, address1, name1, "A", zone)
self.network.add_dns_entry(self.context, address1, name2, "A", zone)
self.network.delete_dns_entry(self.context, name1, zone)
entries = self.network.get_dns_entries_by_address(self.context,
address1, zone)
self.assertEquals(len(entries), 1)
self.assertEquals(entries[0], name2)
self.assertRaises(exception.NotFound,
self.network.delete_dns_entry, self.context,
name1, zone)