Nuts AND Bolts Admin Story Lead image: © Kateryna Pruchkovska,
© Kateryna Pruchkovska,

An IT nomad's daily diary


This month, we show you how to map and install a large system landscape with Cobbler and Spacewalk – without a lot of effort. By Thorsten Scherf

I've just completed my first meeting with customers, and they look happy enough but not totally convinced. Maybe they're wondering whether I have bitten off more than I can chew. After all, I'm talking about several hundred machines. How am I going to install and configure all of these machines and install the software in such a short span of time?

Thanks to the Cobbler XMLRPC API [1], however, creating all of those system profiles in the Cobbler database shouldn't be that much of a problem. Through intensive talks with the customer, I can determine what kind of systems they have and how to configure them. And, all this easily can be handled with a matching structure and a sophisticated Kickstart profile on the Spacewalk server [2]. An article on this topic was published not so long ago in Admin magazine [3].

In other words, the many Cobbler system records are really the biggest problem. Just to jog your memory: Using system records, Cobbler can create an individual PXE configuration file for each system. With the snippets that I will be using later in the Kickstart profile, it is possible to customize a system at a very early stage. This setup applies to the operating system to be installed, the network configuration, and – thanks to arbitrary variables that I can define as kernel arguments in Cobbler – to any conceivable configuration setting.

A bit of foo script lets me use these variables for the installation and modify the system to reflect my needs. After creating a record for a system, I really only need to fire up the machines to trigger a fully automated PXE-based installation. The real task here is adding these entries to the Cobbler database. A typical example looks something like Listing 1.

Listing 1: System Settings

01 # cobbler system add --name=foo --profile=ksprofile-devel-rhel6 \
02 --mac- address=00:40:26:CA:10:DD \
03     --kopts="stage=test app=www" --ksmeta="stage=test app=www"
04 # cobbler system edit --name=foo --interface=eth0 --mac=00:40:26:CA:10:DD \
05     --ip= --subnet= --gateway= \
06     --static=1 --netboot-enabled=Y

All of this is no big deal if I'm just setting up a couple of machines; the required commands are quickly executed. But what if the customer wants me to install 1,000 machines? 1,000 manual entries? Not a pleasant thought. How about a shell script? Sounds convincing, but there's an even better way.

Besides the ability to create these records manually, Cobbler gives administrators the option of using a Python or XMLRPC API to automate the process. Which of these interfaces you choose is a matter of personal taste. Because of my negative experiences with the Python API, I decided to go for XMLRPC. XMLRPC, which stands for Extensible Markup Language Remote Procedure Call, is basically a standardized approach to letting computer programs send, receive, and exchange data over a network. The method calls determine the data to transmit. The HTTP protocol takes the data to the requesting client in the form of XML: Just about any modern language offers an XML interface. I decided to use Python here to keep things simple.

Listing 2 shows how to get started. Besides the mandatory import of the xmlrpclib, the call creates an object in line 2 and opens a connection to the Cobbler server. Line 3 creates the required login token. Thanks to the token, all of my Spacewalk users are automatically granted access to the Cobbler server. You need to modify /etc/cobbler/settings to allow this to happen. Set the redhat_management_permissive statement to 1 for this. Line 4 outputs all of the existing system records.

Listing 2: Basics

01 from xmlrpclib import *
02 conn = Server("")
03 token = conn.login(user, password)
04 print server.get_systems()

Listing 3 shows a more complex example in which I am assuming that the systems all have the required information, such as the IP address, MAC address, gateway, and so on in a CSV file. The Python script grabs the CSV file, drops the individual system properties into a dictionary, assigns the correct values to the individual dictionary keys, and finally hands the results over to Cobbler. The results are identical to manually calling Cobbler, as shown previously.

Listing 3: System Information

01  import os
02  import sys
03  from xmlrpclib import *
05  conn = Server("")
06  token = conn.login(user, password)
08  cblr_systems = '/root/cobbler.csv'
10  if os.access(cblr_systems, os.F_OK):
11     print "Reading system configuration file %s" % cblr_systems
12     print
13  else:
14     print "The system configuration file %s does not exist, aborting." % cblr_systems
15     print
16  sys.exit(1)
18  column_header = [ "name","os","eth0-mac","stage","app","gateway","eth0-ip","eth0-mask","eth1-mac","eth1-ip","eth1-mask" ]
19  system_dict = {}
21  f = open(cblr_systems, "r")
22  for line in f:
23     if line.startswith("#"):
24         continue
25     system_prop = line.split(",")
26     print "--> Checking if system %s already exists:" % system_prop[0]
27     for i,header in enumerate(column_header):
28         system_dict[header] = system_prop[i]
30     system_name=system_dict["name"]
31     dnsname = system_dict["name"] + ""
32     ksprofile = "ksprofile-devel-" + system_dict["os"]
34     try:
35         sys_id = conn.get_system_handle(system_name, token)
36     except Fault, reason:
37         if reason.faultCode == 1:
38             print "+ System doesn't exist, will create it now"
39             pass
40     else:
41         print "* System already exists - skipping "
42         print
43         continue
45     sys_id = conn.new_system(token)
46     conn.modify_system(sys_id, 'name', system_dict["name"], token)
47     conn.modify_system(sys_id, 'hostname', dnsname, token)
48     conn.modify_system(sys_id, 'gateway', system_dict["gateway"], token)
49     conn.modify_system(sys_id, 'profile', ksprofile, token)
50     conn.modify_system(sys_id, 'netboot_enabled', True, token)
51     conn.modify_system(sys_id, 'kopts', { "stage" : system_dict["stage"], "app" : system_dict["app"] }, token)
52     conn.modify_system(sys_id, 'kopts_post', { "stage" : system_dict["stage"], "app" : system_dict["app"] }, token)
53     conn.modify_system(sys_id, 'modify_interface', {
54        "macaddress-eth0"   : system_dict["eth0-mac"],
55        "ipaddress-eth0"    : system_dict["eth0-ip"],
56        "static-eth0"       : True,
57        "staticroutes-eth0" : system_dict["eth0-routes"] }, token)
58     conn.modify_system(sys_id, 'modify_interface', {
59        "macaddress-eth1"   : system_dict["eth1-mac"],
60        "ipaddress-eth1"    : system_dict["eth1-ip"],
61        "static-eth1"       : True,
62        "staticroutes-eth1" : system_dict["eth1-routes"] }, token)
63     conn.save_system(sys_id, token)
64     print "+ System created"
65     print
66 f.close()

Using the XMLRPC API, it is easy to map the whole system landscape in Cobbler. Cobbler automatically generates the system configuration files required for the PXE server. After a couple of tests and manual modifications to the Kickstart files that Cobbler references in the system records, all of the systems are installed at the drop of a hat. And, the best thing is that Cobbler is free software and available under the GPL.

After all that talk about cobbler [4], I'm starting to feel hungry. I think I'll head into town and see if I can find a restaurant that sells it.