0 0

Ask Rick: Setting DNS Primary at Scale

Rick Ehrhart is Tintri’s Developer Evangelist, Engineering. In his column, Rick solves IT problems with one simple solution: Tintri storage. Got a question? Let us know.

Our IT department wanted to modify the primary DNS of all of our VMstores, because our network switch vendor now has HA capability. We have 200+ VMstores, so the IT department asked if there was a way to do it with APIs. I replied with a Python program.

In this blog, I will focus on the key aspects of the code. The complete code, set _dns _primary.py, is located on Tintri GitHub. The script reads a file that contains VMstore names that was provided by the IT department. However, what is important is how to modify the each VMstore.

First things first, I created a new version, 1.1, of the API function library, tintri _1 _1.py. This new library uses exceptions and is available on Tintri GitHub.


import tintri_1_1 as tintri

We need to obtain the primary and secondary DNS IP addresses. The reason for this is because the primary and secondary DNS addresses are modified together. I only want to change the primary DNS IP address, but I need the secondary IP address since I don't want to change it. Here is the function:


APPLIANCE_URL = "/v310/appliance/default"

# Return the DNS primary and secondary IP addresses.
def get_dns_info(server_name, session_id):
    url = APPLIANCE_URL + "/dns"

    # Make the get call
    r = tintri.api_get(server_name, url, session_id)
    print_debug("The JSON response of the get invoke to the server " +
                server_name + " is: " + r.text)

    # if HTTP Response is not 200 then raise an error
    if r.status_code != 200:
        message = "The HTTP response for the get invoke to the server is not 200."
        tintri.api_logout(server_name, session_id)
        raise tintri.TintriApiException(message, r.status_code, url, str(Request), r.text)

    appliance_dns = r.json()
    return appliance_dns

Since the appliance API requires a UUID, "default" is used when invoking the API on the VMstore. You could use the "/v310/appliance/default", but "/v310/appliance/default/dns" is faster, because less information is retrieved.

Now onto the key function, process_vmstore.


# Process each VMstore:
# 1. login
# 2. get the current DNS info
# 3. modify the DNS info
# 4. logout
#
# All API calls can raise exceptions and the function
# calling process_vmstore() is expected to handle it.

def process_vmstore(vmstore_name, user_name, password, new_dns_primary):

    server_name = vmstore_name

    # Get the server type
    r = tintri.api_get(server_name, '/info')
    json_info = r.json()
    if json_info['productName'] != "Tintri VMstore":
        this_error = "Server needs to be a VMstore"
        return this_error

Above we check to make sure the server is a VMstore. This was covered in more detail in my previous blog post.


    session_id = tintri.api_login(server_name, user_name, password)

    dns_info = get_dns_info(server_name, session_id)
    print_dns_info(dns_info, server_name + " current: ")

    new_dns_secondary = dns_info['dnsSecondary']

The section above logs into the VMstore with the user name and password input parameters and obtains the current primary and secondary DNS IP address information.


    # Create the ApplianceDns DTO.
    newDnsInfo = \
        {'typeId': 'com.tintri.api.rest.v310.dto.domain.beans.hardware.ApplianceDns',
         'dnsPrimary': new_dns_primary,
         'dnsSecondary': new_dns_secondary
        }

    # Create the Appliance object wit the new ApplianceDns DTO.
    newAppliance = \
        {'typeId': 'com.tintri.api.rest.v310.dto.domain.Appliance',
         'dnsConfig': newDnsInfo
        }

    # Create the Request object with the Appliance DTO.
    Request = \
        {'typeId': 'com.tintri.api.rest.v310.dto.Request',
         'objectsWithNewValues': newAppliance,
         'propertiesToBeUpdated': ['dnsConfig']
        }

To modify the VMstore configuration, the PUT /v310/appliance/default API is used. This API takes the Request DTO as input. The Request DTO contains the objects with new values and the properties to be updated. In this case the object with the new values is Appliance and the property to be modified is dnsConfig. The Appliance DTO represented in the code above by the newAppliance variable which contains the ApplianceDns DTO, newDnsInfo. Finally newDnsInfo contains dnsPrimary and dnsSecondary. Both values need to be present since you are modifying the dnsConfig field in Appliance.

Now onto the final bits of code.


    url = APPLIANCE_URL
    r = tintri.api_put(server_name, url, Request, session_id)
    print_debug("The JSON response of the get invoke to the server " +
                server_name + " is: " + r.text)

    # if HTTP Response is not 204 then raise exception
    if r.status_code != 204:
        tintri.api_logout(server_name, session_id)
        message = "The HTTP response for put call to the server is not 204."
        raise tintri.TintriApiException(message, r.status_code, url, str(Request), r.text)

    dns_info = get_dns_info(server_name, session_id)
    print_dns_info(dns_info, server_name + " now: ")

    # All pau, log out
    tintri.api_logout(server_name, session_id)

This last section of code invokes the PUT API with exception handling, displays the new DNS values, and logs off because the function is pau.

Aloha,

   - Rick -

Rick Ehrhart / May 21, 2015

Rick Ehrhart is Tintri’s Developer Evangelist with a strong software development background focusing on APIs. Rick has assisted many companies with API integrations including VMware, NetApp, HP, ...more

Temporary_css