diff --git a/doc/source/api_ext/ext_floating_ip_dns.rst b/doc/source/api_ext/ext_floating_ip_dns.rst index 632949ca2..ef7229b6e 100644 --- a/doc/source/api_ext/ext_floating_ip_dns.rst +++ b/doc/source/api_ext/ext_floating_ip_dns.rst @@ -85,70 +85,90 @@ None New Resources ------------- -Get a list of DNS Domains (aka 'zones') published by the DNS driver: +Get a list of registered DNS Domains published by the DNS drivers: GET /v1.1//os-floating-ip-dns/ # Sample Response: - { 'zones' : [ - {'zone' : 'example.org'} - {'zone' : 'example.net'}]} + {'zone_entries' : [ + {'domain': 'domain1.example.org', 'scope': 'public', 'project': 'proj1'} + {'domain': 'domain2.example.net', 'scope': 'public', 'project': 'proj2'} + {'domain': 'example.net', 'scope': 'public', 'project': ''} + {'domain': 'example.internal', 'scope': 'private', 'zone': 'zone1'}]} -Create a DNS entry: +Create or modify a DNS domain: - POST /v1.1//os-floating-ip-dns/ + PUT /v1.1//os-floating-ip-dns/ + + # Sample body, public domain: + {'zone_entry' : + {'scope': 'public', + 'project' : 'project1'}} + + # Sample body, public (projectless) domain: + {'zone_entry' : + {'scope': 'public'}} + + # Sample Response, public domain (success): + {'zone_entry' : + {'zone': 'domain1.example.org', + 'scope': 'public', + 'project': 'project1'}} + + # Sample body, private domain: + {'zone_entry' : + {'scope': 'private', + 'availability_zone': 'zone1'}} + + # Sample Response, private domain (success): + {'zone_entry' : + {'zone': 'domain1.private', + 'scope': 'private', + 'availability_zone': 'zone1'}} + + Failure Response Code: 403 (Insufficient permissions.) + + +Delete a DNS domain and all associated host entries: + +DELETE /v1.1//os-floating-ip-dns/ + + Normal Response Code: 200 + Failure Response Code: 404 (Domain to be deleted not found.) + Failure Response Code: 403 (Insufficient permissions to delete.) + + +Create or modify a DNS entry: + + PUT /v1.1//os-floating-ip-dns//entries/ # Sample body: { 'dns_entry' : - { 'name': 'instance1', - 'ip': '192.168.53.11', - 'dns_type': 'A', - 'zone': 'example.org'}} + { 'ip': '192.168.53.11', + 'dns_type': 'A' }} # Sample Response (success): { 'dns_entry' : - { 'ip' : '192.168.53.11', - 'type' : 'A', - 'zone' : 'example.org', + { 'type' : 'A', 'name' : 'instance1' }} - Failure Response Code: 409 (indicates an entry with name & zone already exists.) +Find unique DNS entry for a given domain and name: -Change the ip address of an existing DNS entry: - - PUT /v1.1//os-floating-ip-dns/ - - # Sample body: - { 'dns_entry' : - { 'name': 'instance1', - 'ip': '192.168.53.99'}} - - # Sample Response (success): - { 'dns_entry' : - { 'ip' : '192.168.53.99', - 'name' : 'instance1', - 'zone' : 'example.org'}} - - Failure Response Code: 404 (Entry to be modified not found) - - -Find DNS entries for a given domain and name: - - GET /v1.1//os-floating-ip-dns/?name= + GET /v1.1//os-floating-ip-dns//entries/ # Sample Response: - { 'dns_entries' : [ + { 'dns_entry' : { 'ip' : '192.168.53.11', 'type' : 'A', 'zone' : , - 'name' : }]} + 'name' : }} Find DNS entries for a given domain and ip: - GET /v1.1//os-floating-ip-dns//?ip= + GET /v1.1//os-floating-ip-dns//entries?ip= # Sample Response: { 'dns_entries' : [ @@ -164,11 +184,12 @@ Find DNS entries for a given domain and ip: Delete a DNS entry: -DELETE /v1.1//os-floating-ip-dns/?name= +DELETE /v1.1//os-floating-ip-dns//entries/ Normal Response Code: 200 Failure Response Code: 404 (Entry to be deleted not found) + New States ---------- None @@ -176,4 +197,3 @@ None Changes to the Cloud Servers Specification ------------------------------------------ None - diff --git a/nova/tests/policy.json b/nova/tests/policy.json index a12a84ab1..6048425d8 100644 --- a/nova/tests/policy.json +++ b/nova/tests/policy.json @@ -4,7 +4,7 @@ "compute:create:attach_volume": [], "compute:get": [], - "compute:get_all" :[], + "compute:get_all": [], "compute:update": [], @@ -122,5 +122,8 @@ "network:modify_dns_entry": [], "network:delete_dns_entry": [], "network:get_dns_entries_by_address": [], - "network:get_dns_entries_by_name": [] + "network:get_dns_entries_by_name": [], + "network:create_private_dns_domain": [], + "network:create_public_dns_domain": [], + "network:delete_dns_domain": [] } diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py index 29e1a0520..1afb5cd3c 100644 --- a/nova/tests/test_db_api.py +++ b/nova/tests/test_db_api.py @@ -521,3 +521,27 @@ class AggregateDBApiTestCase(test.TestCase): self.assertRaises(exception.AggregateHostNotFound, db.aggregate_host_delete, ctxt, result.id, _get_fake_aggr_hosts()[0]) + + def test_dns_registration(self): + domain1 = 'test.domain.one' + domain2 = 'test.domain.two' + testzone = 'testzone' + ctxt = context.get_admin_context() + + db.dnsdomain_register_for_zone(ctxt, domain1, testzone) + domain_ref = db.dnsdomain_get(ctxt, domain1) + zone = domain_ref.availability_zone + scope = domain_ref.scope + self.assertEqual(scope, 'private') + self.assertEqual(zone, testzone) + + db.dnsdomain_register_for_project(ctxt, domain2, + self.project_id) + domain_ref = db.dnsdomain_get(ctxt, domain2) + project = domain_ref.project_id + scope = domain_ref.scope + self.assertEqual(project, self.project_id) + self.assertEqual(scope, 'public') + + db.dnsdomain_unregister(ctxt, domain1) + db.dnsdomain_unregister(ctxt, domain2) diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 8b230376b..7b8bd3aa3 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -277,6 +277,8 @@ class FlatNetworkTestCase(test.TestCase): db.instance_get(self.context, 1).AndReturn({'display_name': HOST, 'uuid': 'test-00001'}) + db.instance_get(mox.IgnoreArg(), + mox.IgnoreArg()).AndReturn({'availability_zone': ''}) db.fixed_ip_associate_pool(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn('192.168.0.101') @@ -343,6 +345,8 @@ class FlatNetworkTestCase(test.TestCase): db.instance_get(self.context, 1).AndReturn({'display_name': HOST, 'uuid': 'test-00001'}) + db.instance_get(mox.IgnoreArg(), + mox.IgnoreArg()).AndReturn({'availability_zone': ''}) db.fixed_ip_associate_pool(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(fixedip) @@ -750,7 +754,8 @@ class VlanNetworkTestCase(test.TestCase): db.instance_get(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn({'security_groups': - [{'id': 0}]}) + [{'id': 0}], + 'availability_zone': ''}) db.fixed_ip_associate_pool(mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg()).AndReturn('192.168.0.101') @@ -1264,16 +1269,6 @@ class FloatingIPTestCase(test.TestCase): self.network.deallocate_for_instance(self.context, 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" @@ -1327,6 +1322,49 @@ class FloatingIPTestCase(test.TestCase): self.network.delete_dns_entry, self.context, name1, zone) + def test_floating_dns_domains_public(self): + zone1 = "testzone" + domain1 = "example.org" + domain2 = "example.com" + address1 = '10.10.10.10' + entryname = 'testentry' + + context_admin = context.RequestContext('testuser', 'testproject', + is_admin=True) + + self.assertRaises(exception.AdminRequired, + self.network.create_public_dns_domain, self.context, + domain1, zone1) + self.network.create_public_dns_domain(context_admin, domain1, + 'testproject') + self.network.create_public_dns_domain(context_admin, domain2, + 'fakeproject') + + domains = self.network.get_dns_zones(self.context) + self.assertEquals(len(domains), 2) + self.assertEquals(domains[0]['domain'], domain1) + self.assertEquals(domains[1]['domain'], domain2) + self.assertEquals(domains[0]['project'], 'testproject') + self.assertEquals(domains[1]['project'], 'fakeproject') + + self.network.add_dns_entry(self.context, address1, entryname, + 'A', domain1) + entries = self.network.get_dns_entries_by_name(self.context, + entryname, domain1) + self.assertEquals(len(entries), 1) + self.assertEquals(entries[0], address1) + + self.assertRaises(exception.AdminRequired, + self.network.delete_dns_domain, self.context, + domain1) + self.network.delete_dns_domain(context_admin, domain1) + self.network.delete_dns_domain(context_admin, domain2) + + # Verify that deleting the domain deleted the associated entry + entries = self.network.get_dns_entries_by_name(self.context, + entryname, domain1) + self.assertFalse(entries) + class NetworkPolicyTestCase(test.TestCase): def setUp(self): @@ -1355,3 +1393,44 @@ class NetworkPolicyTestCase(test.TestCase): network_manager.check_policy(self.context, 'get_all') self.mox.UnsetStubs() self.mox.VerifyAll() + + +class InstanceDNSTestCase(test.TestCase): + """Tests nova.network.manager instance DNS""" + def setUp(self): + super(InstanceDNSTestCase, self).setUp() + self.network = TestFloatingIPManager() + temp = utils.import_object('nova.network.minidns.MiniDNS') + self.network.instance_dns_manager = temp + temp = utils.import_object('nova.network.dns_driver.DNSDriver') + self.network.floating_dns_manager = temp + self.network.db = db + self.project_id = 'testproject' + self.context = context.RequestContext('testuser', self.project_id, + is_admin=False) + + def tearDown(self): + super(InstanceDNSTestCase, self).tearDown() + self.network.instance_dns_manager.delete_dns_file() + + def test_dns_domains_private(self): + zone1 = 'testzone' + domain1 = 'example.org' + + context_admin = context.RequestContext('testuser', 'testproject', + is_admin=True) + + self.assertRaises(exception.AdminRequired, + self.network.create_private_dns_domain, self.context, + domain1, zone1) + + self.network.create_private_dns_domain(context_admin, domain1, zone1) + domains = self.network.get_dns_zones(self.context) + self.assertEquals(len(domains), 1) + self.assertEquals(domains[0]['domain'], domain1) + self.assertEquals(domains[0]['availability_zone'], zone1) + + self.assertRaises(exception.AdminRequired, + self.network.delete_dns_domain, self.context, + domain1) + self.network.delete_dns_domain(context_admin, domain1)