Skip to content

Instantly share code, notes, and snippets.

@wido
Created November 26, 2013 19:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wido/7664859 to your computer and use it in GitHub Desktop.
Save wido/7664859 to your computer and use it in GitHub Desktop.
PowerDNS backend for Ceph's RGW It responds with a CNAME to the correct bucket location
#!/usr/bin/python
from flask import abort, Flask, request, Response
import json
import subprocess
listen_port = 6780
listen_addr = "0.0.0.0"
debug_mode = True
# The DNS zone this backend serves for
dns_zone = "o.myobject.store"
dns_soa_ttl = 3600
dns_default_ttl = 60
# Map region names to hostnames
region_map = {}
region_map.update({'eu': 'o.myobject.eu'})
# The Flask App
app = Flask(__name__)
# PowerDNS expects a 200 what ever happends and always wants
# 'result' to 'true' if the query fails
def abort_early():
return json.dumps({'result': 'true'}) + "\n"
# Call radosgw-admin to get bucket metadata information
def get_radosgw_metadata(key):
try:
info = subprocess.check_output(["radosgw-admin", "metadata", "get", key])
except subprocess.CalledProcessError as e:
return None
return json.loads(info)
# Returns a string of the region where the bucket is in
def get_bucket_region(bucket):
meta = get_radosgw_metadata("bucket:%s" % bucket)
bucket_id = meta['data']['bucket']['bucket_id']
meta_instance = get_radosgw_metadata("bucket.instance:%s:%s" % (bucket, bucket_id))
region = meta_instance['data']['bucket_info']['region']
return region
# Returns the correct host for the bucket based on the region
def get_bucket_host(bucket):
region = get_bucket_region(bucket)
return bucket + "." + region_map[region]
@app.route('/')
def index():
abort(404)
@app.route("/dns/lookup/<qname>/<qtype>")
def bucket_location(qname, qtype):
if len(qname) == 0:
return abort_early()
split = qname.split(".", 1)
if len(split) != 2:
return abort_early()
bucket = split[0]
zone = split[1]
# If the received qname doesn't match our zone abort
if zone != dns_zone:
return abort_early()
# We do not serve MX records
if qtype == "MX":
return abort_early()
# The basic result we always return
response = {'result': 'true'}
result = {}
# A hardcoded SOA response
if qtype == "SOA":
result.update({'qtype': qtype})
result.update({'qname': qname})
result.update({'content':'dns1.icann.org. hostmaster.icann.org. 2012080849 7200 3600 1209600 3600'})
result.update({'ttl': dns_soa_ttl})
else:
region_hostname = get_bucket_host(bucket)
result.update({'qtype': 'CNAME'})
result.update({'qname': qname})
result.update({'content': region_hostname})
result.update({'ttl': dns_default_ttl})
if len(result) > 0:
res = []
res.append(result)
response['result'] = res
return json.dumps(response) + "\n"
if __name__ == '__main__':
app.debug = debug_mode
app.run(host=listen_addr, port=listen_port)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment