Creating a DNS Service on the Cloud

By Alex Amies,Pan Xia Zou

Date: Jan 28, 2013

Return to the article


IBM Senior Software Engineer Alexander Amies and IBM Software Engineer Pan Xia Zou discuss how to configure and use a DNS server for management of virtual machines on the cloud. This is described in the context of a cloud-based virtual local area network and scripting to automate network configuration of virtual machines. One of the architects of the IBM SmartCloud Enterprise platform, Alex is a co-author of Developing and Hosting Applications on the Cloud.

The domain name system (DNS) is a fundamental building block of the World Wide Web, and DNS can be a powerful tool in public and private cloud computing. You can use DNS to solve many practical problems associated with the dynamic nature of cloud server provisioning. In particular, DNS can make virtual machine images, migration, and workloads portable.

This article presents an overview of the reasons and challenges for hostname management of virtual machines on the cloud. We describe client setup on Windows and Linux systems, and server setup and maintenance with the BIND DNS server on Linux. Finally, we outline how to automate and externalize DNS and network configuration of Linux virtual machines with image-customization scripts.

The procedures in this article were tested with IBM SmartCloud Enterprise (SCE). The principles we discuss apply to other Infrastructure as a Service (IaaS) clouds as well. However, no warranty is given that the tools and techniques described here will work. The opinions presented are those of the authors and not IBM.

Introduction

Introduction

The DNS system was introduced in the 1980s to provide a human-friendly system of connecting to and managing servers and interacting with network servers. The World Wide Web is a prime example of one place where DNS is crucial, and it would be hard to imagine the Web without hostnames in URLs. In cloud systems, servers are dynamically provisioned and change frequently. However, since the management of the DNS system falls between cloud provider and cloud consumer, it's a thorny and often overlooked area. That's the motivation for writing this article, which explains the concepts and steps for common requirements on the Web.

Why use DNS instead of using IP addresses? DNS names are easier to remember and more meaningful than IP addresses. Consider using them in bookmarks, configuration files, email to other people, and so on. You'll easily be able to remember the purpose of the virtual machine with a meaningful hostname, but have difficulty using an IP address. When giving addresses to other people, you'll be free to switch the hostname to another machine, but you'll have difficulty switching IP addresses.

One assumption often made about cloud systems is that it's simple to capture images of virtual machine instances and reinstantiate those images later. Unfortunately, hostname is a critical parameter in many configuration files, and it usually becomes "frozen" in the images. For example, hostnames are embedded in X.509 (SSL) certificates and application-server configuration files. In some cases, this fact prevents system services from operating. If you have no control over the hostname assigned to your server, it might require considerable configuration effort to set things right. With the techniques described in this article, however, you'll be able to assign the hostname of your choice to a virtual machine, completely avoiding the problem.

Overview of DNS and Networking

Overview of DNS and Networking

Hostnames are traditionally assigned by end users, who inform an administrator of the virtual machine's desired IP address and primary hostname (such as vhost1234). The administrator creates a record in the DNS system so the fully qualified domain name can be used (such as vhost.sceexample.com). In addition, an alias is created (such as fred-db2-singapore.sceexample.com).

The article makes special reference to virtual local area networks (VLANs). Having a VLAN is just like having your own private data center on the cloud. After you provision a virtual machine to a VLAN, it won't be visible to the Internet. Making the changes to the virtual machine instances in this document will enable networking and DNS within your VLAN. However, for most cloud providers, DNS typically won't be configured when provisioning virtual machines on a VLAN, because it's difficult for a cloud provider to manage hostnames for private IP addresses. On the public Internet, IP addresses are unique, but private IP addresses only need to be unique within the private network to which they belong. A more precise definition is beyond the scope of this article, but you can roughly understand that the private network domain is visible to you, including your corporate network, as well as any VPN connections that you might have to different VLANs on the cloud. So it makes more sense to use your own DNS server when working with virtual machines on a VLAN. Figure 1 shows a simple DNS topology with VLANs on the cloud.

Figure 1 Simple DNS topology with VLANs.

The same arguments for the DNS server also apply to the network gateway. In a VLAN you'll also be responsible for managing your own network gateway, which will typically be a virtual machine with IP addresses on both the Internet and the VLAN. That virtual machine might be configured to route all traffic originating in the VLAN to the Internet, allowing only restricted traffic into the VLAN.

The Firewall image in IBM SmartCloud Enterprise is a good choice for the gateway because it includes preconfigured firewall software and is security-hardened in a way that's appropriate for an Internet-facing server. In the examples in this article, the network gateway hosts the DNS servers. Figure 2 shows the network topology for the example in this article.

Figure 2 Network topology for the examples in this article.

Although in Figure 1 we showed the user communicating directly with a Linux virtual machine in a VLAN, this is actually a simplification. As Figure 2 shows, the network topology forces all traffic to and from the Linux virtual machine on the VLAN to be routed through the firewall, which has one IP address on the Internet (shown as the public IP) and one on the VLAN (shown as the private IP). Outbound traffic to the Internet with a connection originating on the Linux virtual machine (VM) in the VLAN must use the private IP address of the firewall as a gateway.

In IBM SmartCloud Enterprise, all IP addresses are statically assigned. With the dynamic nature of the self-service user interface (that is, the web portal), which can allocate IP addresses rapidly and automatically, you get the convenience of a DHCP system without concern for the IP address changing. Not all clouds operate this way. Some clouds use DHCP to assign IP addresses to virtual machines. In that kind of network environment, some steps described in this article would need to be modified.

Client Setup

Client Setup

In these steps, we'll configure Linux and Windows machines to act as DNS clients. We start with client setup because it's the most common task. Provisioning virtual machines to a VLAN offers several challenges, including configuring the network gateway and the DNS servers you want to use. It's difficult for the cloud provider to know the gateway and DNS settings for your VLAN, so that you typically need to do this part yourself. First we'll explain the steps for configuring network and hostname settings for a Linux virtual machine on a VLAN. The client in this example was provisioned from the base Red Hat Enterprise Linux (RHEL) version 6.2 virtual machine image in the SCE image library.

If your goal is to configure a DNS server, these steps are also good to try out manually if your goal is to automate them. You may want to revisit this section after performing the steps in the later section "DNS Server Setup."

Prerequisites

The steps in this section assume the following:

If you're the administrative contact and you haven't set up your own DNS server yet, you can begin with the cloud provider's public DNS server. You can determine whether this will work by provisioning a virtual machine to the Internet and checking the DNS system that it's configured to use.

Conventions

Several conventions are used in the following sections related to commands:

The text after the command is the output from the command. We include it only when there's something particular to note in the output. In cases where the command is vi, the text following the command is the contents of a file for editing.

Step 1: Configure the Gateway

In this step, you'll configure your Linux virtual machine to point at the proper network gateway. Set the gateway to the private IP of the gateway server for the VLAN and restart the network service. As root, edit the files shown in Listing 1.

Listing 1—Configuring the gateway on the RHEL 6 virtual machine on a VLAN.

# vi /etc/sysconfig/network-scripts/route-eth0
. . .
default table route_eth0 via <gateway> dev eth0
# vi /etc/sysconfig/network-scripts/ifcfg-eth0
. . .
GATEWAY=<gateway>
# /sbin/service network restart

Replace the <gateway> values in Listing 1 with the values for your own environment.

Test that you can reach a public server, such as a Yahoo! server, by using curl:

$ curl 106.10.170.118

You should see the HTML page returned from curl.

Step 2: Configure DNS Resolution

Client network settings are configured in the resolv.conf file in Linux. Edit the /etc/resolv.conf file as shown in Listing 2; add a line using the IP address of your own DNS server, and substituting the names of your own domain and DNS server IP.

Listing 2—Configuring a DNS client.

# vi /etc/resolv.conf
domain sceexample.com nameserver <dns_server_ip>

Test the settings by using the nslookup or dig command on the VM with the BIND server using a well-known website, such as Yahoo! (http://www.yahoo.com). Basic use of the nslookup command is as follows:

$ nslookup http://www.yahoo.com
Name:    ds-sg-fp3.wg1.b.yahoo.com
Address: 106.10.170.118
. . .

The result of this nslookup command shows that the IP address 106.10.170.118 of the Yahoo! server was found.

Step 3: Add Compatible Entries for the Local Server

The hostname settings for the virtual machine itself are contained in the /etc/hosts file. Edit the /etc/hosts file to add a line as shown :

# vi /etc/hosts
. . .
10.128.105.47  vm-10-128-105-47 vm-10-128-105-47.scexample.com
10.128.105.47 myserver myserver.scexample.com

Substitute the hostname of your own virtual machine and your own domain name.

Using nslookup as shown below, test that you can look up the address of your own server, including the newly configured domain and some other servers that are on the same VLAN:

#  nslookup vm-10-128-105-47
. . .
Name:    vm-10-128-105-47.sceexample.com
Address: 10.128.105.47
# nslookup vm-10-128-105-48
. . .
Name:    vm-10-128-105-48.sceexample.com
Address: 10.128.105.48

This completes the configuration of the Linux machine as a DNS client.

Configuring a Windows Client

It can be convenient to set up your Windows client workstation to use the same DNS server as your cloud-based virtual machines. The configuration for Windows Server is similar. You can configure these settings to use the nameserver with the dialog in Figure 3.

Figure 3 Windows DNS configuration.

DNS Server Setup

DNS Server Setup

BIND is an open source DNS server software package. It's the most popular DNS server on the Internet and can be installed easily on Linux systems via the package management system. After that, some configuration is necessary to enable the server to listen for incoming requests and to act as an authoritative server for your domain. Several executable files are packaged with BIND; the main file that concerns us is the named DNS service. We'll also briefly describe the dig command for doing DNS lookup and the rndc management utility.

Prerequisites

To follow the instructions in this section, you'll need the following things:

Step 1: Provision the Server and Install BIND

In this step, we provision a virtual machine for the DNS server. We also install and start the BIND named service.

Provision an instance of the IBM Firewall image with two IP addresses. The VPN server or firewall for the VPN is a good choice. It should be a hardened image like the IBM firewall in the image catalog. You can use either the SCE web user interface or API to create the virtual machine instance.

Reserve an IP address on the VLAN with the command in Listing 3. Execute the command on your local workstation.

Listing 3—Allocating an IP address with the SCE command-line tool.

> ic-allocate-address.cmd -u <user_id> -g <password_file>
 -w <passphrase> -x <vlan_id> -L 141 -O 20027868
Executing action: AllocateAddress  ...
The request has been submitted successfully.
ID: 344533
InstanceId:
State: NEW
Executing AllocateAddress  finished

In the command in Listing 3, substitute your own username for <user_id>, password file for <password_file>, and password phrase for <passphrase>.

The -x parameter lists the VLAN ID (<vlan_id>); this is specific to your customer account. Use ic-describe-vlans to find it.

The -L parameter is the data center ID; 141 is the ID for the Singapore data center. If you don't want to use Singapore, use the ic-describe-locations command to find the ID for another data center.

The -O parameter is the offering ID; 20027868 is the ID for an IP address on a private VLAN in Singapore. Use the ic-describe-address-offerings command to find an alternative offering ID if you don't want to use the Singapore data center.

This command will give an address ID in the response output, as shown in Listing 3. The IP address will take a short period of time to be allocated. Use the ic-describe-addresses command to check the status of the request, and wait for the state to be FREE, indicating that the address is available to be associated with a virtual machine instance.

The command in Listing 4 shows how to create the virtual machine with the SCE command line.

Listing 4—Creating a DNS server with the SCE command-line tool.

> ic-create-instance.cmd -u <user_id> -g <password_file> -w
 <passphrase> -k 20036705 -n DNS_Server -t "COP32.1/2048/60"
 -L 141 -m "{secondary.ip.0:<address_id>}"
. . .
ID: 325599
. . .
Status: NEW

The -k parameter is the specific image ID for the IBM Firewall image in the Singapore data center. Search the image catalog or use the ic-describe-images command to find an alternative image.

The -n parameter is the name that you give the server. You can use any name you want here, but enclose it in double quotes (" ") if the name includes spaces or special characters.

The -t parameter is the server size—in this case, a single-CPU, 32-bit machine with 2048MB of memory and 60GB of disk space. If you want a different size, use the ic-describe-image command to find the supported server sizes.

The -L parameter is the data center, as described for Listing 3. The -m is the ID for the secondary address (<address_id>), which was obtained in the output of the ic-allocate-address command in Listing 3. The Internet-facing primary address will be assigned automatically.

The instance will take a short time to be provisioned. The instance ID is shown in the output of the ic-create-instance command, in this case 325599. Note this ID and use it in the ic-describe-instance command to check the status of the request, waiting for it to become ACTIVE:

> ic-describe-instance.cmd -u <user_id> -g <password_file> -w <passphrase> -l 325599
. . .
IP: 170.225.160.40
. . .
Status: ACTIVE
. . .

At this point you can use your default SSH key to connect to the instance via the primary IP address, which is also the Internet-facing address. That IP address is also shown in the output from the ic-describe-instance command we just discussed.

The secondary IP address faces the VLAN. Initially, the network interface associated with the secondary IP is not active. The network interface for the secondary IP is typically eth1; you can check the status with the ifconfig -a command. SSH to the server and execute the ifup command shown in Listing 5 to activate the secondary network address.

Listing 5—Activating the network interface for the secondary IP address

$ sudo /sbin/ifconfig -a
eth1      Link encap:Ethernet  HWaddr DE:AD:BE:6A:71:45
          BROADCAST MULTICAST  MTU:1500  Metric:1
. . .
$ sudo /sbin/ifup eth1
$ sudo /sbin/ifconfig -a
eth1      Link encap:Ethernet  HWaddr DE:AD:BE:6A:71:45
          inet addr:10.128.105.40  Bcast:10.128.105.255  Mask:255.255.255.0
          inet6 addr: fe80::dcad:beff:fe6a:7145/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
. . .

Notice that the status of the network interface changes to UP in the output of the ifconfig command and the Internet address is displayed.

Follow the instructions in the Firewall image guide, located in the SCE image catalog, to enable routing from the Internet to virtual machines in the VLAN. If you didn't use the Firewall image, configure iptables to route between the Internet and the VLAN.

SSH to the server and install BIND from the yum repository with the following commands:

$ sudo yum install bind

Set the service to be on by default, and start it with these commands:

$ sudo chkconfig named on
$ sudo service named start

After the BIND server has started, verify installation against your local interface to make sure that the firewall is open on each end.

You can check that BIND is running properly by using the dig command:

$ dig @127.0.0.1 http://www.yahoo.com
. . .
;; ANSWER SECTION:
http://www.yahoo.com.          300     IN      CNAME   fd-fp3.wg1.b.yahoo.com.
fd-fp3.wg1.b.yahoo.com. 300     IN      CNAME   ds-fp3.wg1.b.yahoo.com.
ds-fp3.wg1.b.yahoo.com. 60      IN      CNAME   ds-sg-fp3-lfb.wg1.b.yahoo.com.
ds-sg-fp3-lfb.wg1.b.yahoo.com. 300 IN   CNAME   ds-sg-fp3.wg1.b.yahoo.com.
ds-sg-fp3.wg1.b.yahoo.com. 60   IN      A       106.10.170.118
. . .

The dig command is packaged with BIND and also installed by default on the Firewall image in the SCE image catalog. It's a Linux DNS client utility similar to nslookup, but it provides more useful information in the command output. The @ parameter specifies the DNS server to use. If it's not provided, the DNS server in resolv.conf will be used.

The output of the command shows a CNAME record that defines the domain name http://www.yahoo.com as an alias, and several other aliases are defined, which finally point at the address (A) record linking to the IP address 106.10.170.118. We'll look at how to define the CNAME and A records for our own domain shortly.

On RHEL systems, BIND is configured by default to respond only to requests from the local system. We need to perform additional configuration to enable it to respond to external requests.

Step 2: Configure the DNS Server to Accept External Requests

In this step we configure BIND to accept requests from any incoming client. Open the main configuration file /etc/named.conf and edit the lines related to the listener and query restrictions, as shown in Listing 6.

Listing 6—Configuring BIND to accept outside requests for DNS queries.

# vi /etc/named.conf
listen-on port 53 { any; };
. . .
allow-query     { any; };

After saving the changes to named.conf, restart the named server:

# service named restart

At this point the BIND server is listening for outside requests, but the firewall is blocking those requests from being delivered.

Step 3: Configure the Firewall

In this step we configure the firewall and check the DNS service. Open port 53 in the firewall for both UDP and TCP with the commands in Listing 7.

Listing 7—Configuring iptablesto accept outside requests connections on port 53.

# vi /etc/sysconfig/iptables
# Add lines allowing any port if accessed from the local machine.
. . .
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT
. . .
# /sbin/service iptables restart

After restarting the firewall, verify installation against all network interfaces to make sure that the firewall is open on each one:

$ dig @<private_ip> http://www.yahoo.com
$ dig @<public_ip> http://www.yahoo.com

The <private_ip> and <public_ip> parameters are the IP addresses of the two network interfaces with which you provisioned the server in the earlier section "Step 1: Provision the Server and Install BIND." If you only want to accept requests from within your VLAN, you should add a further restriction to the firewall rules above, based on source address range.

Step 4: Set Up the Zone for the New Domain in the DNS System

In this step, we configure BIND to be the primary domain server for our new domain. A zone entry is used to specify a DNS domain. We'll make our server the primary name server for the domain sceexample.com. You should substitute your own domain for all occurrences of sceexample.com in the listings here. We'll add a zone statement for this purpose and include a zone file that will contain the individual resource records for the domain. Edit the main configuration file /etc/named.conf to add the section in Listing 8.

Listing 8—Zone entry in named configuration file.

zone "sceexample.com" {
        type master;
        file "sceexample.com";
};

Now we've defined the zone, but we don't have any DNS records for that zone.

Step 5: Add DNS Records

In this step we add DNS records for the zone. Create the zone file /var/named/sceexample.com for the domain, and add text as shown in Listing 9. It includes Time to Live ($TTL), root name ($ORIGIN), start of Authority (SOA) entries, and some Address (A) resource records. Use your own hostname <client> and IP address <linux_client_ip>. We also name this as a web server with a www prefix to the hostname, as an example of an alias.

Listing 9—DNS zone file.

$TTL 1h
$ORIGIN sceexample.com.
@ 1D   IN     SOA   ns hostmaster (
                        2006100201 ; se = serial number
                        1h         ; ref = refresh
                        15m        ; ret = update retry
                        3w         ; ex = expiry
                        3h         ; min = minimum
                        )
           IN    NS      ns.sceexample.com.
ns         IN    A       <nameserver_ip> <client>   IN    A       <linux_client_ip>
www        IN    CNAME   <client>
:wq!

Substitute your own hostname for <client> and IP addresses for <nameserver_ip> and <linux_client_ip>. This should be another virtual machine instance on your VLAN. If you don't have one, leave out the two lines with <client>. The value for <client> is the primary hostname, such as vhost0915.sceexample.com. This is specified in an Address (A) record. The alias www is just an example, appropriate for a web server. It's what's known as a CNAME or alias record that defines an additional name by which you can refer to the machine . After saving the file, restart the server:

# /sbin/service named restart

Now that we've created the zone and entries for it, we can test it.

Step 6: Test Looking Up a Domain Name

In this step we use dig to test the definition of the domain in the BIND configuration files. Use the dig command on the machine with the BIND server:

# dig @127.0.0.1 http://www.sceexample.com
. . .
;; ANSWER SECTION:
http://www.sceexample.com. 3600 IN      CNAME   vm-10-128-105-48.sceexample.com.
vm-10-128-105-48.sceexample.com. 3600 IN A  10.128.105.48
. . .

The result of the command shows the alias (CNAME record) for the xx server referring to the primary hostname and the Address (A) record pointing to the IP address (<linux_client_ip> in Listing 9).

If you don't want to register your domain with a public domain registration provider or don't need a secondary server, then you can skip Steps 7–8 in the next two sections and jump directly to the later section "Managing the BIND Server." However, public domain registration providers require a minimum of two DNS servers when registering a self-managed domain. See how to define a secondary server in the next section.

Step 7: Set Up a Secondary Server

In this step we set up a secondary DNS server on another virtual machine instance, similar to the primary. Change the secondary BIND server file to be the same as the primary except for the lines in Listing 10.

Listing 10—Testing the domain definition with dig.

# vi /etc/named.conf
. . .
zone "sceexample.com" {
        type slave;
        file "sceexample.com";
        masters { <primary_ip>; };
};

This code defines the BIND server to be a slave for the domain. All the resource records will be copied from the primary server. Restart the server with the following command:

$ sudo /sbin/service named start

At this point we have a working DNS system, but it's not known to anyone other than us. We can perform a special client setup to refer to it, or we can make it publicly discoverable on the World Wide Web with the step in the next section.

Step 8: Register the Domain

This section explains how to register the DNS system that we have set up to be authoritative for our domain. You can do it by registering the domain with a public DNS registration service, such as GoDaddy.com. You'll need to set the nameservers for the domain to be the DNS servers that you set up earlier. You must configure at least two DNS servers if you're setting these as the DNS servers using a public service.

If you're using GoDaddy.com, first add the two DNS servers as hosts using their hostnames, such as vhostxxx. The domain will be appended. (It will take some time to process.) Then set the DNS servers for the domain.

Managing the BIND Server

Managing the BIND Server

The way that we've set up the DNS servers makes them visible on the Internet, so security is a prime concern. You should check the BIND server regularly and keep it up to date with the latest software available in the yum repository. This process is explained in the following sections.

Maintaining BIND

This section explains the basics of checking the status of the named service and updating BIND. To check the status, use the following command:

$ sudo /sbin/service named status
rndc: connect failed: 127.0.0.1#953: connection refused
named is stopped

The output of the command shows that the named server is stopped.

To check the BIND version installed, use the yum command:

$ sudo yum info bind
Installed Packages
Name        : bind
Version     : 9.8.2
Release     : 0.10.rc1.el6_3.5
Repo        : installed
. . .

To upgrade BIND, use the yum upgrade command:

$ sudo yum upgrade bind

Using the rndc Command-Line Tool

The rndc utility is a management client that communicates over a TCP connection to manage the BIND server. You can use rndc to add DNS entries without restarting the named server. It's authenticated with a cryptographic key; the default key is stored in /etc/rndc.key. The default port is 953. The configuration settings are stored at /etc/rndc.conf.

Make sure that the firewall is open on port 953. Using the command line on the BIND server, use rndc as shown in Listing 11 to check status, reload configuration files, or reload a zone.

Listing 11—Managing BIND with the rndc command.

$ sudo rndc status
. . .
$ sudo rndc reload
server reload successful
$ sudo rndc reload sceexample.com
zone reload up-to-date

Maintaining the Firewall

This section explains the basics of firewall settings for DNS beyond what we discussed in the earlier section "Step 3: Configure the Firewall." Running BIND on the Internet can be a potential security risk if the software isn't kept up to date with security patches and proper settings. To reduce security risks, you can limit traffic to within your VLAN, by using a CIDR IP address range in the iptables rules, as shown in Listing 12.

Listing 12—Restricting access to the DNS system with the firewall.

# vi /etc/sysconfig/iptables
-A INPUT -p udp -m udp -s 10.128.120.0/24 --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp -s 10.128.120.0/24 --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp -s 127.0.0.1 --dport 953 -j ACCEPT

The -s (source) flag takes a CIDR range 10.128.120.0/24, indicating that only the packets originating in the 10.128.120.x VLAN will be accepted. (Substitute your own VLAN address range in place of the one given here.) The management port is configured to allow only connections from the local machine. Restart the firewall with the iptables restart command.

Automation of Client Configuration

Automation of Client Configuration

IBM SmartCloud Enterprise and some other cloud providers give a framework for injecting data and scripts into virtual machines at provisioning time. We'll use the SCE framework here for automation of the DNS and other network configurations, explaining the features as we use them. If your cloud doesn't support dynamic injection of scripts and data during provisioning, another way to automate the configuration is to create a virtual machine instance, copying the automation files manually, and then save it as a base image.

Externalization of the virtual machine network customization from the image binary is a critical step. It allows you adapt to a changed network environment without creating a new image binary, and it enables you to inject different network configurations into an image binary that already exists. The image binary is opaque to us unless we provision an instance of it, so externalizing critical settings is an important advantage.

However you customize the image, a Python script will be used to make file changes and a configuration file will be created to store the network settings. We'll use Python to automate the steps that we've described above in the client configuration. Python is part of the Linux Standard Base and is an excellent choice for image-customization scripts. The version of Python shipped in RHEL 6.2 and most Linux systems is Python 2.6.6. There are some differences between this version and Python 3, but the scripts shown here are mostly compatible with Python 3 (with the exception of the ConfigParser class). Listing 13 shows the Python configuration script.

Listing 13—Python script for automated network and DNS client configuration. Python keywords are in bold.

import ConfigParser
import re
import shutil

def update_file(filename, patterns, replacements):
    ''' Update file with lines matching given patterns '''
    backup = filename + '.bak'
    shutil.copyfile(filename, backup)
    f = open(backup, 'r')
    text = ""
    for line in f:
        if (len(line.strip()) == 0) or (line[0] == '#'):
            text += line
        else:
            matched = False
            for i in range(len(patterns)):
                if re.match(patterns[i], line):
                    text += replacements[i] + '\n'
                    matched = True
            if not matched:
                text += line
    f.close()
    f = open(filename, 'w')
    f.write(text)
    f.close()

def configure():
    ''' Make configuration changes '''
    print("Make configuration changes")
    config = ConfigParser.ConfigParser()
    config.read('/etc/cloud/dns.conf')
    replacement = 'GATEWAY={0}'.format(config.get('Network','gateway'))
    update_file('/etc/sysconfig/network-scripts/ifcfg-eth0', ['GATEWAY'], [replacement])
    replacement = 'default table route_eth0 via {0} dev eth0'.format(config.get('Network','gateway'))
    update_file('/etc/sysconfig/network-scripts/route-eth0', ['default'], [replacement])
    patterns = ['domain', 'nameserver']
    replacements = ['domain {0}'.format(config.get('Network','domain')),
                    'nameserver {0}'.format(config.get('Network','nameserver'))]
    update_file('/etc/resolv.conf', patterns, replacements)

if __name__ == '__main__':
    configure()

The entry point to this program from the command line is the if __name__ statement, which calls the configure() function. You can copy this script into any editor and save it. I developed it on my Windows workstation with the Eclipse PyDev plug-in and then tested it on a Linux machine that was already running before inserting it into the virtual machine instance-provisioning process.

The Python script will read the network settings in dns.conf and inject the values stored there into the virtual machine files for setting the gateway and DNS server. The dns.conf file is shown in Listing 14.

Listing 14—Configuration file dns.conf.

# Network configuration file
[Network]
gateway: <gateway_ip>
domain: sceexample.com
nameserver: <dns_server_ip>

Replace the values of <gateway_ip>, sceexample.com, and <dns_server_ip> with appropriate values for your own environment.

To add this script and configuration file to a virtual machine image, we make a clone of an image in the public image catalog and add the scripts as image metadata. This step is essential because we need ownership of the image to change the metadata. In the SCE web portal, navigate to the Control Panel > Images tab and click the Add Image button, as shown in Figure 4.

Figure 4 Cloning an image in IBM SmartCloud Enterprise.

The next screen allows you to choose an image to clone. In this example, we'll use Red Hat Enterprise Linux 6 (64-bit) in the Singapore data center. After adding the image clone, the image will appear under My Assets in the My Dashboard of the cloud Asset Catalog, as shown in Figure 5.

Figure 5 The cloned image appears under My Assets.

Clicking the name of the image in My Assets will lead you to the metadata for the image, as shown in Figure 6. Make a note of the image ID, which we'll use later when creating an instance of the image with the command-line tool.

Figure 6 Cloned image metadata.

Navigate to the activation_scripts folder (see Figure 7) and download the files it contains. Place these files in a directory called activation_scripts on your local workstation, adding dns_client_config.py and dns.conf to it.

Figure 7 Image metadata contents.

Edit the cloud-startup script to call our Python script dns_client_config.py, as shown in Listing 15.

Listing 15—Modification of the startup script cloud-startup3.txt.

    start)
    . . .
        if [ -e /etc/cloud/dns_client_config.py ] ; then
            echo " [cloud-startup] Performing network configuration ..."
            /usr/bin/python /etc/cloud/dns_client_config.py
        fi
        ;;
    stop)

Edit scripts.txt to define the location where dns_client_config.py and dns.conf will be copied during instance-provisioning time, as shown in Listing 16.

Listing 16—Modification of scripts.txt.

cloud-startup3.txt=/etc/init.d/cloud-startup3.sh
activate.txt=/etc/cloud/activate.sh
dns.conf=/etc/cloud/dns.conf
dns_client_config.py=/etc/cloud/dns_client_config.py

After making the changes to scripts.txt, zip the activation_scripts directory. Click the pencil icon in the upper-right corner of the Asset Catalog tab (marked in Figure 7) to edit the asset metadata. Upload activation_scripts to the image catalog and save to update the image asset. The Contents should look like those in Figure 8.

Figure 8 Updated image metadata.

To test our automation script, we provision an instance with the SCE command-line tool and check the network settings. Execute the ic-create-instance command:

>ic-create-instance.cmd -u <user_id> -g <password_file> -w <passphrase>
 -k 20069951 -n "RHEL Clone Instance" -t "COP64.2/4096/60" -L 141 -x <vlan_id>
. . .
ID: 326329
Name: RHEL Clone Instance
. . .

In the command above, the -k parameter is the image ID of the image that you've customized, -n is the cloud display name of the virtual machine, -t is the server size, -L is the data center (Singapore), and -x is the VLAN ID. After the instance has become active, log in with SSH and check the resolv.conf and other network configuration files to make sure that your script injected the settings as expected. Use the nslookup command to exercise the DNS server as shown below:

$ dig http://www.yahoo.com
. . .
;; ANSWER SECTION:
http://www.yahoo.com.          300     IN      CNAME   fd-fp3.wg1.b.yahoo.com.
fd-fp3.wg1.b.yahoo.com. 300     IN      CNAME   ds-fp3.wg1.b.yahoo.com.
ds-fp3.wg1.b.yahoo.com. 60      IN      CNAME   ds-any-fp3-lfb.wa1.b.yahoo.com.
ds-any-fp3-lfb.wa1.b.yahoo.com. 300 IN  CNAME   ds-any-fp3-real.wa1.b.yahoo.com.
ds-any-fp3-real.wa1.b.yahoo.com. 60 IN  A       72.30.38.140

If the dig command can find the IP address of the Yahoo! server, you've successfully automated the network configuration of a Linux client on a private VLAN.

Next Steps

Next Steps

Consider the steps below when applying the principles in this article to your own system.

Resources

Resources

Copyright and Trademarks

Copyright and Trademarks

©IBM Corporation 2012.

IBM, the IBM logo, ibm.com, Cognos, DB2, Informix, Lotus, Rational, SmartCloud, System x, Tivoli and WebSphere are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. If these and other IBM trademarked terms are marked on their first occurrence in this information with the appropriate symbol (® or ™), these symbols indicate U.S. registered or common law trademarks owned by IBM at the time this information was published. Such trademarks may also be registered or common law trademarks in other countries. A current list of IBM trademarks is available on the web at "Copyright and trademark information" at http://www.ibm.com/legal/copytrade.shtml.

Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both.

Microsoft and Windows are trademarks of Microsoft Corporation in the United States, other countries, or both.

Other company, product, and service names may be trademarks or service marks of others.

References in this publication to IBM products or services do not imply that IBM intends to make them available in all countries in which IBM operates.