Chapter 7. Version Management System

Imagine you are the administrator of three computer labs. Some of the machines have had their versions of Java and Python updated, but you're not sure how many, or which ones. You could go to each computer individually and check.

But you're not going to do that.

By building a Python script to connect to your machines and check version levels, you can automatically build a list of the version of installed applications on each computer.

The version management system in this chapter shows how you can use Telnet to retrieve version information for a list of applications (in this program, the applications checked will be Java, Python, and Perl). The program will then write the results of the check to a CSV log file.

The application will perform the following functions:

  • Allow the user to identify an IP address and a list of applications to check for (entered via command-line arguments)

  • Log in, using Telnet, to the machine and check the version numbers of each application

  • Write the results of the query to a CSV log file

Using the Program

Before the program is run, any remote computers to be connected to from the application must be set up.

Note

The computers connected to in this application were Linux machines, but the application could easily be adapted to also connect to Windows machines.

Setting Up Remote Computers

Remote computers need to have the following features enabled:

  1. Java, Python, and Perl should be installed.

  2. A Telnet server should be installed and running (the application assumes it is running on its default port).

  3. A common account (with a common password) should be set for each machine.

Running the Program — Command-Line Syntax

You can get to the program by navigating to the directory corresponding to this chapter. Once again, the files are available for download from the website (www.wrox.com). To run the application, simply go to a command prompt, and from the directory on your system where the Chapter 7 program files are located, type the following:

python version_checker.py <ip address> <applications>

The command-line options are as follows:

  • <ip address> — Enter the IP address to connect to.

  • <applications> — Enter the applications, enclosed in quotes. The applications can be selected from the following:

    • Java

    • Python

    • Perl

Command-Line Examples

If the following is typed at the command line, the script will connect to IP address 192.168.1.108 and check the versions of Java, Python, and Perl:

python version_checker.py 192.168.1.108 "java python perl"

The result will look something like this:

I:Applied_PythonChapter_7>python version_checker.py 192.168.1.108 "java python
 perl"
HOST -  192.168.1.108
Java version =  1.6.0_0
Python version =  2.5.1
Perl version =  5.8.8

If the following is typed at the command line, the script will connect to IP address 192.168.1.108 and check the versions of Java and Perl:

python version_checker.py 192.168.1.108 "java perl"

The result will look something like this:

I:Applied_PythonChapter_7>python version_checker.py 192.168.1.108 "java perl"
HOST -  192.168.1.108
Java version =  1.6.0_0
Perl version =  5.8.8

If the following is typed at the command line, the script will connect to IP address 192.168.1.108 and check the versions of Perl and Python:

python version_checker.py 192.168.1.108 "perl python"

Notice that the order of the applications listed does not matter. The result will look something like this:

I:Applied_PythonChapter_7>python version_checker.py 192.168.1.108 "perl python"
HOST -  192.168.1.108

Python version =  2.5.1
Perl version =  5.8.8

If the following is typed at the command line, the script will connect to IP address 192.168.1.108 and check the version of Perl:

python version_checker.py 192.168.1.108 "perl"

The result will look something like this:

I:Applied_PythonChapter_7>python version_checker.py 192.168.1.108 " perl"
HOST -  192.168.1.108
Perl version =  5.8.8

If you don't enter all the options, a message like the following one will be displayed:

I:Applied_PythonChapter_7>python version_checker.py 192.168.1.108
 Insufficient arguments:  suggested use -
    python version_checker.py <ip address> "<applications to check>"

    NOTES:
    1.  Replace <ip address> with the ip address you want to check.
    2.  Replace <applications to check> with any combination of the following
       applications (in quotes):
            java
            python
            perl

    EXAMPLE:

    python version_checker.py 1.1.1.1 "python java"

    This command will check the versions of Python and Java on computer with
ip address 1.1.1.1.

Viewing the CSV Log File

After you have run a few reports, you can view the CSV log of the version checks. If you open the CSV file in a spreadsheet program, it will look something like what is shown in Figure 7-1.

FIGURE 7-1

Figure 7.1. FIGURE 7-1

Running Against Several Different Machines in Batch Mode

To run the script against several different machines in batch mode, you could simply create a shell script (or batch file, if on Windows) that runs the script against several different machines, as in the following example:

python version_checker.py 192.168.1.108 "java python perl"
python version_checker.py 192.168.1.109 "java perl"
python version_checker.py 192.168.1.110 "java python perl"
python version_checker.py 192.168.1.111 "python perl"
python version_checker.py 192.168.1.112 "python"
python version_checker.py 192.168.1.113 "perl python"
python version_checker.py 192.168.1.114 "java"
python version_checker.py 192.168.1.115 "perl"
python version_checker.py 192.168.1.116 "java python perl"
python version_checker.py 192.168.1.117 "java perl"
python version_checker.py 192.168.1.118 "python perl"
python version_checker.py 192.168.1.119 "perl"
python version_checker.py 192.168.1.120 "java python perl"
python version_checker.py 192.168.1.121 "java perl"
python version_checker.py 192.168.1.122 "python"
python version_checker.py 192.168.1.123 "java python perl"

Design

This is the first application that doesn't have any kind of a "driveable" user interface — it uses the command line to pass options to the script. This enables a script to be more easily implemented in another script or batch file, which is why it was handled this way in this case.

Modules

There are three modules in this application:

  • version_checker.py is the main program. It receives the command-line option, prints error messages, and calls functions in other modules to do the checking and output to the CSV file.

  • check_versions.py logs in to the remote machine and returns the version of the particular application being checked.

  • csv_report.py takes a version check result and writes it to the CSV log file.

version_checker.py

version_checker.py is the main program. It calls the functions to run checks and output the results to a CSV. It also displays output to the screen. Table 7-1 shows the version_checker module functions.

Table 7.1. Table 7-1

Function

Return Type

Description

check_arguments()

none

Checks arguments entered at the command line. If there are insufficient arguments, then it generates an error message and exits.

get_versions ()

none

Launches functions to log in to the remote computer to display and log results.

check_versions.py

check_versions.py is called by version_checker.py and checks versions of the respective applications being checked. Table 7-2 shows the check_versions module functions.

Table 7.2. Table 7-2

Function

Return Type

Description

check_java(host, user, password)

string

Takes hostname, username, and password as arguments, connects to the host, checks the version of Java, and returns that version to the caller

check_python(host, user, password)

string

Takes hostname, username, and password as arguments, connects to the host, checks the version of Python, and returns that version to the caller

check_perl(host, user, password)

string

Takes hostname, username, and password as arguments, connects to the host, checks the version of Perl, and returns that version to the caller

csv_report.py

csv_report.py takes the results of a version check and outputs the results to the CSV report log. Table 7-3 shows the csv_report module function.

Table 7.3. Table 7-3

Function

Return Type

Description

write_csv_log(host, application, version)

none

Takes host, application, and version information as parameters and outputs an entry to the CSV log file

Code and Code Explanation

Essentially, this application takes parameters at the command line, logs in (through Telnet) to a remote computer, checks the version of an identified application, and reports the result to the screen and to a CSV log file.

In the interests of page space, I've omitted the code headers, but make sure you use them. Your coworkers will thank you.

version_checker.py

The version_checker module is the program users actually run on the command line. It contains code that's run at the module level, and two functions:

import sys
import check_versions, csv_report

HOST = sys.argv[1]
USER = "jars"
PASSWORD = "jars"

def check_arguments():
    if (len(sys.argv)) < 3:
        print """ Insufficient arguments:  suggested use -
        python version_checker.py <ip address> "<applications to check>"

        NOTES:
        1.  Replace <ip address> with the ip address you want to check.
        2.  Replace <applications to check> with any combination of the following
applications (in quotes):
                java
                python
                perl

        EXAMPLE:

        python version_checker.py 1.1.1.1 "python java"

        This command will check the versions of Python and Java on computer with ip
address 1.1.1.1."""
        sys.exit()


def get_versions():
    print "HOST - ", HOST
    if "java" in sys.argv[2]:
        java_version = check_versions.check_java(HOST, USER, PASSWORD)
        csv_report.write_csv_log(HOST, "Java", java_version)
        print "Java version = ", java_version
    if "python" in sys.argv[2]:
        python_version = check_versions.check_python(HOST, USER, PASSWORD)
        csv_report.write_csv_log(HOST, "Python", python_version)
        print "Python version = ", python_version
    if "perl" in sys.argv[2]:
        perl_version = check_versions.check_perl(HOST, USER, PASSWORD)
        csv_report.write_csv_log(HOST, "Perl", perl_version)
        print "Perl version = ", perl_version

check_arguments()
get_versions()

Main Program

The main program starts off by importing the modules it needs:

import sys
import check_versions, csv_report

Then variables are initialized for the host, user, and password:

HOST = sys.argv[1]
USER = "jars"
PASSWORD = "jars"

Note two things about the preceding code:

  • The variable HOST is assigned the first command-line parameter. This is how Python enables a program to take command-line arguments and use them in a Python script.

  • The user and password are assigned here. If you want the password to be something different, change it here.

Down at the bottom of the module (after the function definitions), the program runs the functions to check both the arguments and the versions:

check_arguments()
get_versions()

check_arguments()

check_arguments() checks the command-line arguments entered at the command line to ensure that the correct number of arguments appears. If not, it generates an error and exits:

def check_arguments():
        if len(sys.argv) < 3:
            print """ Insufficient arguments:  suggested use -
            python version_checker.py <ip address> "<applications to check>"

            NOTES:
            1.  Replace <ip address> with the ip address you want to check.
            2.  Replace <applications to check> with any combination of the
    following applications (in quotes):
                    java
                    python
                    perl

            EXAMPLE:
python version_checker.py 1.1.1.1 "python java"

        This command will check the versions of Python and Java on computer with
ip address 1.1.1.1."""
        sys.exit()

The function initially determines whether two arguments appear (the first argument is the Python script name, so there should be three elements in sys.argv):

if len(sys.argv) < 3:

If there are fewer than two command-line arguments, it prints an error/help message:

print """ Insufficient arguments:  suggested use -
        python version_checker.py <ip address> "<applications to check>"

        NOTES:
        1.  Replace <ip address> with the ip address you want to check.
        2.  Replace <applications to check> with any combination of the following
applications (in quotes):
                java
                python
                perl

        EXAMPLE:

        python version_checker.py 1.1.1.1 "python java"

        This command will check the versions of Python and Java on computer with ip
address 1.1.1.1."""

The last line of the if loop (and the function) is a command to exit:

sys.exit(1)

Note

Notice that you exit with a 1. Non-zero exit codes are for situations in which something has gone wrong, so if you exit the program in an error condition, it makes sense to pass a 1.

get_versions()

The get_versions() function launches the various functions to check the application version, based on what the user entered on the command line:

def get_versions():
    print "HOST - ", HOST
    if sys.argv[2].find("java") != −1:
        java_version = check_versions.check_java(HOST, USER, PASSWORD)
        csv_report.write_csv_log(HOST, "Java", java_version)
        print "Java version = ", java_version
    if sys.argv[2].find("python") != −1:
        python_version = check_versions.check_python(HOST, USER, PASSWORD)
        csv_report.write_csv_log(HOST, "Python", python_version)
        print "Python version = ", python_version
    if sys.argv[2].find("perl") != −1:
        perl_version = check_versions.check_perl(HOST, USER, PASSWORD)
        csv_report.write_csv_log(HOST, "Perl", perl_version)
        print "Perl version = ", perl_version

The first thing the function does is print a header with the IP address of the entered host:

print "HOST - ", HOST

Then the function implements an if block to determine whether "java" was entered on the command line. If it was, then the check_java() function is called and the result is assigned to the variable java_version:

java_version = check_versions.check_java(HOST, USER, PASSWORD)

Then the write_csv_log() function is called to write the result to the CSV log file:

csv_report.write_csv_log(HOST, "Java", java_version)

The if block ends by printing the result to the screen:

print "Java version = ", java_version

Then the function implements an if block to determine whether "python" was entered on the command line. If it was, then the check_python() function is called and the result is assigned to the variable python_version:

python_version = check_versions.check_python(HOST, USER, PASSWORD)

Then the write_csv_log() function is called to write the result to the CSV log file:

csv_report.write_csv_log(HOST, "Python", python_version)

The if block ends by printing the result to the screen:

print "Python version = ", python_version

Then the function implements an if block to determine whether perl was entered on the command line. If it was, then the check_perl() function is called and the result is assigned to the variable perl_version:

perl_version = check_versions.check_perl(HOST, USER, PASSWORD)

Then the write_csv_log() function is called to write the result to the CSV log file:

csv_report.write_csv_log(HOST, "Perl", perl_version)

The if block ends by printing the result to the screen:

print "Perl version = ", perl_version

check_versions.py

The check_versions.py module is responsible for logging into the remote computer, checking the version of the application, and returning the result to the calling program:

import sys
import telnetlib




def check_java(host, user, password):
    java_version = ""
    tn = telnetlib.Telnet(host)
    tn.read_until("login: ")
    tn.write(user + "
")

    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

    tn.write("java -version
")
    tn.write("exit
")
    result = tn.read_all()
    result_list = result.split("
")

    for line in result_list:
if line.startswith("java version"):
            java_version = line[14:21]

    return java_version


def check_python(host, user, password):
    python_version = ""
    tn = telnetlib.Telnet(host)

    tn.read_until("login: ")
    tn.write(user + "
")
    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

    tn.write("python -V
")
    tn.write("exit
")
    result = tn.read_all()
    result_list = result.split("
")

    for line in result_list:
        if line.startswith("Python "):
            python_version = line[7:]

    return python_version



def check_perl(host, user, password):
    perl_version = ""
    tn = telnetlib.Telnet(host)
    tn.read_until("login: ")
    tn.write(user + "
")
    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

    tn.write("perl -version
")
    tn.write("exit
")

    result = tn.read_all()
    result_list = result.split("
")
    for line in result_list:
        if line.startswith("This is perl"):
            perl_version = line[15:20]
    return perl_version

check_java()

The check_java() function logs into the identified server and runs the java –version command, which returns the version of Java. It captures the result of that command and returns it to the calling program:

def check_java(host, user, password):
    java_version = ""
    tn = telnetlib.Telnet(host)
    tn.read_until("login: ")
    tn.write(user + "
")

    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

    tn.write("java -version
")
    tn.write("exit
")
    result = tn.read_all()
    result_list = result.split("
")

    for line in result_list:
        if line.startswith("java version"):
            java_version = line[14:21]

    return java_version

After initializing variables, the function opens a Telnet connection to the host:

tn = telnetlib.Telnet(host)

The function then logs in, providing username and password:

tn.read_until("login: ")
    tn.write(user + "
")

    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

Then the Java version is captured and the screen output assigned to a variable:

tn.write("java -version
")
    tn.write("exit
")
    result = tn.read_all()

The Java version is then parsed out of the output of the Telnet session:

result_list = result.split("
")
    for line in result_list:
        if line.startswith("java version"):
            java_version = line[14:21]

Finally, the Java version is returned to the calling program:

return java_version

check_python()

The check_python() function logs into the identified server and runs the python −V command, which returns the version of Python. It captures the result of that command and returns it to the calling program:

def check_python(host, user, password):
    python_version = ""
    tn = telnetlib.Telnet(host)

    tn.read_until("login: ")
    tn.write(user + "
")
    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

    tn.write("python -V
")
    tn.write("exit
")
    result = tn.read_all()
    result_list = result.split("
")

    for line in result_list:
        if line.startswith("Python "):
            python_version = line[7:]

    return python_version

After initializing variables, the function opens a Telnet connection to the host:

tn = telnetlib.Telnet(host)

The function then logs in, providing username and password:

tn.read_until("login: ")
    tn.write(user + "
")

    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

Then the Python version is captured and the screen output assigned to a variable:

tn.write("python -V
")
    tn.write("exit
")
    result = tn.read_all()

The Python version is then parsed out of the output of the Telnet session:

result_list = result.split("
")
    for line in result_list:
        if line.startswith("Python "):
            python_version = line[7:]

Finally, the Python version is returned to the calling program:

return python_version

check_perl()

The check_perl() function logs into the identified server and runs the perl–version command, which queries the version of Perl. It captures the result of that query and returns it to the calling program:

def check_perl(host, user, password):
    perl_version = ""
    tn = telnetlib.Telnet(host)
    tn.read_until("login: ")
    tn.write(user + "
")
    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

    tn.write("perl -version
")
    tn.write("exit
")

    result = tn.read_all()
    result_list = result.split("
")
for line in result_list:
       if line.startswith("This is perl"):
           perl_version = line[15:20]
    return perl_version

After initializing variables, the function opens a Telnet connection to the host:

tn = telnetlib.Telnet(host)

The function then logs in, providing username and password:

tn.read_until("login: ")
    tn.write(user + "
")

    if password:
        tn.read_until("Password: ")
        tn.write(password + "
")

Then the Java version is captured and the screen output assigned to a variable:

tn.write("perl -version
")
    tn.write("exit
")
    result = tn.read_all()

The Java version is then parsed out of the output of the Telnet session:

tn.write("java -version
")
    tn.write("exit
")
    result = tn.read_all()
    result_list = result.split("
")
for line in result_list:
        if line.startswith("This is perl"):
            perl_version = line[15:20]

Finally, the Perl version is returned to the calling program:

return perl_version

csv_report.py

The csv_report.py module captures version check information and writes it to the CSV log file.

write_csv_log()

The write_csv_log() function writes the version check information to the CSV log file. The log file, versionchecklog.csv, is in the program directory. It can be viewed, sorted, and queried with a spreadsheet program.

Here is the function:

def write_csv_log(host, application, version):
    today = datetime.datetime.now().strftime("%m/%d/%Y")
    row = [today, host, application, version]
    try:
        writer = csv.writer(open("versionchecklog.csv", "a"))
        writer.writerow(row)
    except:
        print "Error writing to file!"
        sys.exit(1)

The first line of the function formats the current date and assigns it to a variable:

today = datetime.datetime.now().strftime("%m/%d/%Y")

Then it assigns to a list the date, the IP address, the application, and the version:

row = [today, host, application, version]

Finally, the function uses a try/except block to open the CSV file and write the row to the CSV file:

try:
        writer = csv.writer(open("versionchecklog.csv", "a"))
        writer.writerow(row)
    except:
        print "Error writing to file!"
        sys.exit(1)

Testing

This program takes a multitude of parameters, so that is where testing should be focused. Here are some testing ideas:

  • Enter all possible combinations of applications, including changing case and changing the order of applications.

  • Set up a batch file to run a series of IP addresses, to ensure that the system does not time out.

  • Log in to multiple operating systems, to ensure that there are no issues with that.

Modifying the Program

There are several ways this project could be enhanced, including the following:

  • Modify the program to accept application names in any format (i.e., uppercase or lowercase).

  • Modify the program to accept hostnames in addition to IP addresses.

Security Considerations

This program did not take into account two security considerations that would need to be addressed in a real-world scenario:

  • The program uses a single login and password for every hostname. You could allow command-line arguments to enable users to pass a username and password when the script is run.

  • Telnet, a protocol that was invented in 1969, is fairly insecure. For increased security, use SSH. (There are open-source Python SSH modules available on the web — just do a Google search and you'll have more tools than you know what to do with.)

Summary

In this chapter, you learned how to use Python as a telnet client, and to capture and process telnet output.

One of the most important domains for an interpreted language like Python is in the area of system administration. Whether it is moving files, checking the status of processes, or (in the case of this project) checking version levels on a list of computers on a network, Python is ideally suited to the task. Being a cross-platform language, it enables you to access Windows, Linux/Unix, and even Macintosh computers if necessary.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.127.37