summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorAndrew Bogott <abogott@wikimedia.org>2011-12-11 04:15:26 -0600
committerAndrew Bogott <abogott@wikimedia.org>2011-12-27 15:40:44 -0600
commit73c6d161855cf6e0b7f7cb6081891ca475efebb4 (patch)
tree77fff1c6e8882e4abb69ce8c0f6809e2130578e2 /nova/api
parente92bfac838e7419c75e51a25fa2f433bf7ebee3e (diff)
Add an API for associating floating IPs with DNS entries.
For blueprint public-and-private-dns Change-Id: Ia6c3f046db4dd4978aa5ef950fd472d3455fe301
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/v2/contrib/floating_ip_dns.py220
1 files changed, 220 insertions, 0 deletions
diff --git a/nova/api/openstack/v2/contrib/floating_ip_dns.py b/nova/api/openstack/v2/contrib/floating_ip_dns.py
new file mode 100644
index 000000000..cc33241b3
--- /dev/null
+++ b/nova/api/openstack/v2/contrib/floating_ip_dns.py
@@ -0,0 +1,220 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Andrew Bogott for the Wikimedia Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License
+
+import urllib
+
+import webob
+
+from nova.api.openstack import wsgi
+from nova.api.openstack import xmlutil
+from nova.api.openstack.v2 import extensions
+from nova import exception
+from nova import log as logging
+from nova import network
+
+
+LOG = logging.getLogger('nova.api.openstack.v2.contrib.floating_ip_dns')
+
+
+def _translate_dns_entry_view(dns_entry):
+ result = {}
+ result['ip'] = dns_entry.get('ip')
+ result['id'] = dns_entry.get('id')
+ result['type'] = dns_entry.get('type')
+ result['zone'] = dns_entry.get('zone')
+ result['name'] = dns_entry.get('name')
+ return {'dns_entry': result}
+
+
+def _translate_dns_entries_view(dns_entries):
+ return {'dns_entries': [_translate_dns_entry_view(entry)['dns_entry']
+ for entry in dns_entries]}
+
+
+def _translate_zone_entries_view(zonelist):
+ return {'zones': [{'zone': zone} for zone in zonelist]}
+
+
+def _unquote_zone(zone):
+ """Unquoting function for receiving a zone name in a URL.
+
+ Zone names tend to have .'s in them. Urllib doesn't quote dots,
+ but Routes tends to choke on them, so we need an extra level of
+ by-hand quoting here.
+ """
+ return urllib.unquote(zone).replace('%2E', '.')
+
+
+def _create_dns_entry(ip, name, zone):
+ return {'ip': ip, 'name': name, 'zone': zone}
+
+
+class FloatingIPDNSController(object):
+ """DNS Entry controller for OpenStack API"""
+
+ def __init__(self):
+ self.network_api = network.API()
+ super(FloatingIPDNSController, self).__init__()
+
+ def show(self, req, id):
+ """Return a list of dns entries. If ip is specified, query for
+ names. if name is specified, query for ips.
+ Quoted domain (aka 'zone') specified as id."""
+ context = req.environ['nova.context']
+ params = req.str_GET
+ floating_ip = params['ip'] if 'ip' in params else ""
+ name = params['name'] if 'name' in params else ""
+ zone = _unquote_zone(id)
+
+ if floating_ip:
+ entries = self.network_api.get_dns_entries_by_address(context,
+ floating_ip,
+ zone)
+ entrylist = [_create_dns_entry(floating_ip, entry, zone)
+ for entry in entries]
+ elif name:
+ entries = self.network_api.get_dns_entries_by_name(context,
+ name, zone)
+ entrylist = [_create_dns_entry(entry, name, zone)
+ for entry in entries]
+ else:
+ entrylist = []
+
+ return _translate_dns_entries_view(entrylist)
+
+ def index(self, req):
+ """Return a list of available DNS zones."""
+
+ context = req.environ['nova.context']
+ zones = self.network_api.get_dns_zones(context)
+
+ return _translate_zone_entries_view(zones)
+
+ def create(self, req, body):
+ """Add dns entry for name and address"""
+ context = req.environ['nova.context']
+
+ try:
+ entry = body['dns_entry']
+ address = entry['ip']
+ name = entry['name']
+ dns_type = entry['dns_type']
+ zone = entry['zone']
+ except (TypeError, KeyError):
+ raise webob.exc.HTTPUnprocessableEntity()
+
+ try:
+ self.network_api.add_dns_entry(context, address, name,
+ dns_type, zone)
+ except exception.FloatingIpDNSExists:
+ return webob.Response(status_int=409)
+
+ return _translate_dns_entry_view({'ip': address,
+ 'name': name,
+ 'type': dns_type,
+ 'zone': zone})
+
+ def delete(self, req, id):
+ """Delete the entry identified by req and id. """
+ context = req.environ['nova.context']
+ params = req.str_GET
+ name = params['name'] if 'name' in params else ""
+ zone = _unquote_zone(id)
+
+ try:
+ self.network_api.delete_dns_entry(context, name, zone)
+ except exception.NotFound:
+ return webob.Response(status_int=404)
+
+ return webob.Response(status_int=200)
+
+
+def make_dns_entry(elem):
+ elem.set('id')
+ elem.set('ip')
+ elem.set('type')
+ elem.set('zone')
+ elem.set('name')
+
+
+def make_zone_entry(elem):
+ elem.set('zone')
+
+
+class FloatingIPDNSTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('dns_entry',
+ selector='dns_entry')
+ make_dns_entry(root)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class FloatingIPDNSsTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('dns_entries')
+ elem = xmlutil.SubTemplateElement(root, 'dns_entry',
+ selector='dns_entries')
+ make_dns_entry(elem)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class ZonesTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('zones')
+ elem = xmlutil.SubTemplateElement(root, 'zone',
+ selector='zones')
+ make_zone_entry(elem)
+ return xmlutil.MasterTemplate(root, 1)
+
+
+class FloatingIPDNSSerializer(xmlutil.XMLTemplateSerializer):
+ def index(self):
+ return ZonesTemplate()
+
+ def show(self):
+ return FloatingIPDNSsTemplate()
+
+ def default(self):
+ return FloatingIPDNSTemplate()
+
+
+class Floating_ip_dns(extensions.ExtensionDescriptor):
+ """Floating IP DNS support"""
+
+ name = "Floating_ip_dns"
+ alias = "os-floating-ip-dns"
+ namespace = "http://docs.openstack.org/ext/floating_ip_dns/api/v1.1"
+ updated = "2011-12-23:00:00+00:00"
+
+ def __init__(self, ext_mgr):
+ self.network_api = network.API()
+ super(Floating_ip_dns, self).__init__(ext_mgr)
+
+ def get_resources(self):
+ resources = []
+
+ body_serializers = {
+ 'application/xml': FloatingIPDNSSerializer(),
+ }
+
+ serializer = wsgi.ResponseSerializer(body_serializers)
+
+ res = extensions.ResourceExtension('os-floating-ip-dns',
+ FloatingIPDNSController(),
+ serializer=serializer)
+ resources.append(res)
+
+ return resources