Add an API for associating floating IPs with DNS entries.
For blueprint public-and-private-dns Change-Id: Ia6c3f046db4dd4978aa5ef950fd472d3455fe301
This commit is contained in:
160
doc/source/api_ext/ext_floating_ip_dns.rst
Normal file
160
doc/source/api_ext/ext_floating_ip_dns.rst
Normal 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
|
||||||
|
|
@@ -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.")
|
||||||
|
|
||||||
|
@@ -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',
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user