January 6, 2020

Classes SoftLayer_Dns_Domain
Tags dns

DNS management

How to manage DNS zones and records on SoftLayer's DNS system.

This article will cover how to use the API to manage DNS zones and records. For a higher level documentation on how that all works, check out DNS Management


All the functions defined in this article will be part of this dnsManager class. Which only sets up the SoftLayer Client, and configures the debugger, which allows you to see the exact API calls being made.

import SoftLayer
from pprint import pprint as pp

class dnsManager():

    def __init__(self):
        self.client = SoftLayer.Client()
        debugger = SoftLayer.DebugTransport(self.client.transport)
        self.client.transport = debugger

    def debug(self):
        for call in self.client.transport.get_last_calls():

if __name__ == "__main__":
    main = dnsManager()

Creating a zone

A Zone here can either be a top level domain (domain.com) or a sub-domain (company.domain.com). The NS records for the zone will need to point so ns1.softlayer.com and ns2.softlayer.com.

To create a zone, we use SoftLayer_Dns_Domain::createObject() and pass in a structure of type SoftLayer_Dns_Domain. You can pass in a list of resourceRecords during domain creating for them to be added as well. You can not however change the SOA record at creation, but can do so by editing the SOA record after it has been created.


    def createZone(self):
        """Creates a DNS zone"""

        zoneTemplate = {
            'name': 'mydomain.com',
            'resourceRecords': [
                {'data': '', 'host': '@', 'type': 'a' },
                {'data': '', 'host': 'zed', 'type': 'a' },
                {'data': 'zed', 'host': '@', 'type': 'MX' }

        result = self.client.call('SoftLayer_Dns_Domain', 'createObject', zoneTemplate)


curl -u $SL_USER:$SL_APIKEY -X POST -d \
'{"parameters": [{"name": "mydomain.com", "resourceRecords": [{"type": "a", "host": "@", "data": ""}, {"type": "a", "host": "zed", "data": ""}, {"type": "MX", "host": "@", "data": "zed"}]}]}' \

Creating Records

A record will be any entry under the zone you just created, so you will need to know the ID of the zone, and use that for the domainId in the record template.

Much like creating a zone, creating a record is done with a createObject call, but this time in the SoftLayer_Dns_Domain_ResourceRecord::createObject method. Use the SoftLayer_Dns_Domain_ResourceRecord datatype to define exactly how you want the record itself to look. The example below only uses a few of the fields.


    def addRecord(self, zone_id, record):
        """Adds record to zone_id"""
        recordTemplate = {
            'domainId': zone_id,  # id of the zone this record will belong to.
            'data': record['data'],
            'host': record['host'],
            'type': record['type']
        result = self.client.call('SoftLayer_Dns_Domain_ResourceRecord', 'createObject', recordTemplate)

if __name__ == "__main__":
    main = dnsManager()
    my_zone_id = 2986181
    record = {'data': '', 'host': 'testa', 'type': 'a'}
    main.addRecord(my_zone_id, record)


curl -u $SL_USER:$SL_APIKEY -X POST  -d \
'{"parameters": [{"type": "a", "host": "testa", "domainId": 2986181, "data": ""}]}' \

The SoftLayer_Dns_Domain service has methods like SoftLayer_Dns_Domain::createARecord which can make creating records easier, but this approach is a little more flexible. They are both capable of creating the same records though, so feel free to use either approach.


There are two main ways of getting information about the domain and its records. If you know the Id of the zone, simply use SoftLayer_Dns_Domain::getObject(), otherwise use SoftLayer_Dns_Domain::getByDomainName as shown here.


    def getZone(self, domain_name=None, zone_id=None):
        if (domain_name is None) and (zone_id is None):
            raise Exception("domain_name or zone_id is required")
        mask = "mask[resourceRecords]"
        if zone_id:
            domain = self.client.call('SoftLayer_Dns_Domain', 'getObject', id=zone_id, mask=mask)
            domain = self.client.call('SoftLayer_Dns_Domain', 'getByDomainName', domain_name, mask=mask)

if __name__ == "__main__":
    main = dnsManager()


curl -u $SL_USER:$SL_APIKEY \

curl -u $SL_USER:$SL_APIKEY -X POST  -d \
'{"parameters": ["mydomain.com"]}' \

You can also get the BIND format zone file with getZoneFileContents if you need it.

curl -u $SL_USER:$SL_APIKEY \

$ORIGIN mydomain.com.
$TTL 86400
@ IN SOA ns1.softlayer.com. root.mydomain.com. (
                       2020010601        ; Serial
                       7200              ; Refresh
                       600               ; Retry
                       1728000           ; Expire
                       3600)             ; Minimum

@                      86400    IN NS    ns1.softlayer.com.
@                      86400    IN NS    ns2.softlayer.com.
@                      86400    IN A
testa                  86400    IN A

Editing records.

Editing an existing record uses SoftLayer_Dns_Domain_ResourceRecord::editObject(). You will need to know the Id of the Record (not the zone) for this.


    def editRecord(self, record_id, new_data):
        """Edits a record with new_data

        Will return True on success, and exception otherwise.
        new_data should be a structure that has fields that match the local properties of
        Only properties sent in will be updated.
        new_data = {'data':'', 'ttl':600}

        return self.client.call('SoftLayer_Dns_Domain_ResourceRecord', 'editObject', new_data, id=record_id)

if __name__ == "__main__":
    main = example()
    my_record_id = 118152560
    my_new_record = {'data': ''}
    main.editRecord(my_record_id, my_new_record)


curl -u $SL_USER:$SL_APIKEY -X -d  \
'{"parameters": [{"data": ""}]}' \

Editing SOA

The SOA for every zone will get set to something like this:

curl -u $SL_USER:$SL_APIKEY \
    "domainId": 2986181,
    "responsiblePerson": "root.mydomain.com.",
    "data": "ns1.softlayer.com.",
    "refresh": 7200,
    "mxPriority": null,
    "host": "@",
    "minimum": 3600,
    "retry": 600,
    "expire": 1728000,
    "ttl": 86400,
    "type": "soa",
    "id": 118151300

Which is usually fine, but if you need to change it, you can do the following. You will need to use the editRecords method mentioned above.


    def getSoa(self, zone_id):
        return self.client.call('SoftLayer_Dns_Domain', 'getSoaResourceRecord', id=zone_id)

if __name__ == "__main__":
    main = example()
    my_zone_id = 2986181

    soa = main.getSoa(my_zone_id)
    new_soa = {
        'data' : 'ns1.mydomain.com.',  # ending '.' is important.
        'type' : 'soa',
        'responsiblePerson' : 'root.mydomain.com.'  # ending '.' is important.
    main.editRecord(soa.get('id'), new_soa)

Delete Records and Zones

Deleting a zone or record can be done with deleteObject.


    def deleteZone(self, zone_id):
        self.client.call('SoftLayer_Dns_Domain', 'deleteObject', id=zone_id)
    def deleteRecord(self, record_id):
        self.client.call('SoftLayer_Dns_Domain_ResourceRecord', 'deleteObject', id=record_id)

if __name__ == "__main__":
    main = example()
    my_zone_id = 2986181
    my_record_id = 118152560


You can either user a GET request and specify the deleteObject method, like below.

curl -u $SL_USER:$SL_APIKEY -X GET \
curl -u $SL_USER:$SL_APIKEY -X GET \

Or use a DELETE request, and omit the method, like below.



Both will return True on success, and an exception otherwise.

Reverse Records

Reverse PTR records are a special type of DNS zone, as they can't be retrieved from a SoftLayer_Dns_Domain record exactly. Reverse PTR records link a Server or Virtual Guest with an IP. Generally setting this is very important for hosts that send out email (so spam filters can do some checking on the validity of your host).

dig -x
; <<>> DiG 9.10.6 <<>> -x


;; ANSWER SECTION: 86371 IN PTR 64.05.30a9.ip4.static.sl-reverse.com.

Each server and virtual guest will have a reverse PTR record associated with its primary IP address. You can get those with SoftLayer_Hardware_Server::getReverseDomainRecords() and SoftLayer_Virtual_Guest::getReverseDomainRecords()


records = self.client.call('SoftLayer_Virtual_Guest', 'getReverseDomainRecords', id=record_id)
records = self.client.call('SoftLayer_Hardware_Server', 'getReverseDomainRecords', id=record_id)

Once you have the Id of the record, you can use SoftLayer_Dns_Domain_ResourceRecord::editObject to make changes to it.


In this example 1111111 is the id of the virtual guest, and 222222 is the resulting id from getReverseDomainRecords.

curl -u $SL_USER:$SL_APIKEY \
'https://api.softlayer.com/rest/v3.1/SoftLayer_Virtual_Guest/1111111/getReverseDomainRecords.json' | python -m json.tool

        "id": 88847,
        "name": "184.193.173.in-addr.arpa",
        "networkAddress": "",
        "resourceRecords": [
                "data": "pg-test-01.mydomain.com.",
                "domainId": 88847,
                "expire": null,
                "host": "164",
                "id": 222222,
                "isGatewayAddress": false,
                "minimum": null,
                "mxPriority": null,
                "refresh": null,
                "retry": null,
                "ttl": 7200,
                "type": "ptr"
        "serial": 2020010600,
        "updateDate": "2020-01-06T17:03:27-06:00"

curl -u $SL_USER:$SL_APIKEY -X POST  -d \
'{"parameters": [{"data": "pg-test-01.mydomain.com"}]}' \

The SLCLI has dns-sync commands for both virtual and hardware servers.


We would love to hear it
Open an issue