Background and Motivation

At that time, my motivation for migrating away from Zerigo was mostly fueled by a very unreliable service which was a consequence of DDoS attacks and less than ideal service architecture.

I have a paid Zerigo plan, so back then, I only migrated the most important domains to a different provider. Not long after I have done this, Zerigo announced that they have partnered with Akamai and that going forward, they will outsource running of the DNS infrastructure to Akami and as such, the service should be way more stable and reliable.

I thought great, I won’t need to migrate rest of the domains away, but an unplesant surprise came earlier this month, when Zerigo announced pricing changes (see 1, 2, 3 & 4).

Previously, I have paid 19$ years per year, but with a new plan which matches my current one, I would need to pay 25$ per month. That’s with an existing customer loyalty discount. New customers will need to pay 38$ per month (what a great deal, instead of paying 24 times more, now I need to pay just 15 times more!). Yes, you have read this correctly, that’s more than one order of magniture per year more than I used to pay before.

I honestly don’t mind paying for a great software and services and I wouldn’t mind paying a little more if the service improved, but that kind or price increase is simply too much. That is especially true, because all of the ~15 domains that I still have at Zerigo are used to host non-profit and community websites and paying 25$ per month is simply too much.

Why Rackspace Cloud DNS?

Disclamer: I used to work at Rackspace, but I don’t work there anymore and I’m not affiliated with them in any way.

Before I dive further, lets have a look at why you might want to use Rackspace Cloud DNS.

The main reason for me to migrate to Rackspace is that they have a decent API, they are supported in Libcloud and best of all, the service is totally free for the existing cloud servers customers. On top of that, the service is supposed to use Anycast.

All of that made it a good fit for hosting my non-profit domains there.

I also need to add that I haven’t used the service a lot before, so I can’t really talk much about the service relablitity at this point. Only time and monitoring will tell how reliable the service really is.

Migrating from Zerigo DNS to Rackspace Cloud DNS using Libcloud

Instead of using Libcloud’s export to BIND zone file functionality, this script works by talking directly to both of the provider APIs.

The reason for that is that this approach is more robust and makes performing partial migrations and synchronizations easier. On top of that it also works with other providers which don’t support importing a BIND zone file.

It’s also important to note that the script relies on some Libcloud fixes which are currently only available in trunk. As such, you should use pip to install latest version from Git inside a virtual environment:

After you have done this, you can use the script bellow to migrate all of your zones from Zerigo to Rackspace:

importhashlibfromlibcloud.dns.typesimportProvider,RecordTypefromlibcloud.dns.providersimportget_driverZERIGO_USERNAME=''ZERIGO_API_KEY=''RACKSPACE_USERNAME=''RACKSPACE_API_KEY=''CONTACT_EMAIL=''# Rackspace requires a valid email for every domainZONE_TTL=30*60# Default zone TTL (in seconds) which should be usedMIN_TTL=300# Minim TTL supported by the target providerIGNORED_RECORD_TYPES=[RecordType.NS,RecordType.PTR]source_cls=get_driver(Provider.ZERIGO)(ZERIGO_USERNAME,ZERIGO_API_KEY)destination_cls=get_driver(Provider.RACKSPACE)(RACKSPACE_USERNAME,RACKSPACE_API_KEY)defget_record_hash(record):""" Return a hash for the provided record. This is used to determine if the record already exists. """record_hash=hashlib.md5('%s-%s-%s'%(record.name,record.type,record.data)).hexdigest()returnrecord_hashsource_zones=source_cls.list_zones()destination_zones=destination_cls.list_zones()destination_domains=[zone.domainforzoneindestination_zones]# 1. Create zonesforzoneinsource_zones:ifzone.domainindestination_domains:print('Zone "%s" already exists, skipping...'%(zone.domain))continueextra={'email':CONTACT_EMAIL}print('Creating zone: %s'%(zone.domain))destination_cls.create_zone(domain=zone.domain,ttl=ZONE_TTL,extra=extra)destination_zones=destination_cls.list_zones()supported_record_type=destination_cls.list_record_types()# 2. Create recordsforsource_zoneinsource_zones:destination_zone=[zoneforzoneindestination_zonesifzone.domain==source_zone.domain][0]source_records=source_zone.list_records()destination_records=destination_zone.list_records()forsource_recordinsource_records:# Rackspace doesn't have a special SPF record typeifsource_record.type==RecordType.SPF:source_record.type=RecordType.TXTrecord_hash=get_record_hash(source_record)destination_record_hashes=[get_record_hash(record)forrecordindestination_records]ifsource_record.name:fqdn='%s.%s'%(source_record.name,source_zone.domain)else:fqdn=source_zone.domainifrecord_hashindestination_record_hashes:print('Record "%s" already exists, skipping...'%(fqdn))continueifsource_record.typeinIGNORED_RECORD_TYPES:print(('Encountered ignored record type (type=%s,name=%s) ''skipping...')%(source_record.type,fqdn))continueiftypenotinsupported_record_type:print(('Encountered unsupported record type (type=%s,name=%s)'', skipping...')%(source_record.type,fqdn))continueextra={}ttl=source_record.extra.get('ttl',None)priority=source_record.extra.get('priority',None)ifttl:ifttl<MIN_TTL:ttl=MIN_TTLextra['ttl']=ttlifpriority:extra['priority']=priorityname=source_record.nametype=source_record.typedata=source_record.dataprint('Creating a record: %s'%(fqdn))destination_zone.create_record(name=name,type=type,data=data,extra=extra)

Before proceeeding it’s worth knowing that there are some differences between the providers and some limitations you should be aware of:

Zerigo supports more record types. If you use more advanced record types which are not supported by Rackspace, then Rackspace might not be a good fit for you.

Rackspace only allows you to create PTR records for resources (cloud servers & load balancers) which are hosted in their data centers.

Rackspace doesn’t support SPF record type. This is not a big deal since this record type has been deprecated anyway and TXT can be used instead. This script transparently handled remapping of SPF to TXT for you.

Minimum supported TTL by Zerigo is 180 seconds and the minimum supported TTL by Rackspace is 300 seconds. If during the migration the script encounteres a TTL smaller than 300 seconds, it simply uses the smallest possible TTL which is 300 seconds.

To use it, simply plug in your API credentials and run it:

python migrate_dns_providers.py

Zerigo control panel.

If the script for some reason fails half-way through (bad connectivity, API issues, etc.), it’s safe to run it again since all the operations are idempotent.

Rackspace Cloud DNS control panel after the migration.

After you have run the script, you should check if everything looks OK and if it does, you can go ahead and change the DNS records for your domains to point to the Rackspace Cloud DNS servers (dns1.stabletransit.com & dns2.stabletransit.com).