This chapter describes how to write OpenVault applications using the Perl language.
You can write OpenVault applications in Perl (an interpretive programming language by Larry Wall) without access to an OpenVault application developer's kit. This is because Perl offers a socket library that can interface to the MLM server.
The Perl interpreter is available precompiled in an IRIX subsystem from several locations, including fw_LWperl5.sw.perl on the Freeware distribution. It can also be compiled from scratch with modest effort.
Commercial OpenVault applications are best written in C, for two reasons:
You can distribute them in binary form to help keep source code proprietary.
Compiled applications can take advantage of security features built into the CAPI/AAPI libraries. See Chapter 4, “Programming the C Interface”, for an introduction to OpenVault programming in C.
When new sessions are established, OpenVault employs public key session verification to authenticate the connecting client. At setup time, the OpenVault system administrator configures a password for each application, library, and drive. Specifying a password of “none” disables security checking.
A Perl application must be configured with a password of “none” and the MLM server grants it access only to libraries and drives configured with the “none” password. This implies that a Perl application cannot share libraries or drives with any applications that use the OpenVault security facilities.
There are two different areas to learn about before writing OpenVault Perl scripts:
Perl code that connects with and talks to the OpenVault server
CAPI/AAPI language to request OpenVault actions
The code that connects with and talks to the OpenVault server is basically the same in every script. Depending on your knowledge of Perl, the learning curve may be steep, but needs to be learned only once. Code shown in this chapter can be used almost verbatim for new scripts; so true understanding might not be necessary.
Learning to write CAPI/AAPI language requires a less steep learning curve, but is an ongoing process. CAPI/AAPI commands could be entirely different for different scripts. The most difficult part is writing code to deal with the results of CAPI/AAPI commands. Some form of parsing may be required, or scripts must assume fixed results. For information about AAPI and CAPI commands, see “AAPI Command Descriptions” in Chapter 2.
The scripts provided in this chapter are intended only for use as examples. They are not guaranteed to be free of bugs. Some have limitations, or make possibly false assumptions about OpenVault configuration.
Procedure 3-1 describes the steps involved in creating an OpenVault Perl script:
Procedure 3-1. OpenVault Perl Script
Open connection to the OpenVault server.
Send initial startup (hello) commands.
Repeat the following steps as necessary:
Send CAPI/AAPI command.
Receive command acknowledgment.
When command succeeds, receive command results.
Do something with results.
Close connection to the OpenVault server.
![]() | Note: The code for the first two and final steps is the same for each script. |
There are a few things to know about OpenVault Perl scripts to make writing them easier.
CAPI/AAPI commands and responses are composed of a single line, ending with a semicolon, a carriage return (\r), and a line feed (\n).
Failing to end a command with a semicolon results in an error being returned from the OpenVault server. Not ending a command with “\r\n” results in the script seeming to hang, as the OpenVault server waits for the end of a command line.
Use the -Z option of OpenVault commands to see the structure of CAPI/AAPI commands and responses.
Try running OpenVault commands that are similar to what your script is attempting to do. This may provide you with a general idea of the commands to write, and may also give you an idea of what the results look like. Examples in this chapter use OpenVault commands, with the -Z option, as a basis for CAPI/AAPI commands. This allows for easy comparison of CAPI/AAPI commands and responses between the OpenVault command and the Perl script.
If you find it difficult to understand the perl code that establishes a connection to the OpenVault server, just use the code verbatim, changing variables as necessary, and trust that it works.
This section contains two sample Perl scripts for your use: demo_stat.pl and demo_show.pl
Example 3-1, contains the simplest and smallest possible OpenVault Perl script, equivalent to the ov_stat command with the -u option, which checks to see if the OpenVault server is up or not.
The ov_stat command checks to see if the OpenVault server is up or not by connecting and saying hello to the OpenVault server. Once a response comes back, it is known that the server is up; so the script sends a goodbye command and exits (there is no time-out mechanism).
To show content of the conversation, run the ov_stat command with the -u and -Z options:
vega# ov_stat -uZ WRITTEN: vega WRITTEN: SYSTEM WRITTEN: onlyInstance WRITTEN: AAPI WRITTEN: 0 READ: ok WRITTEN: hello language [`AAPI']versions[`1.0'] instance[`onlyInstance'] client[`SYSTEM']; READ: welcome version[`1.0']; The OV server `vega' is UP. WRITTEN: goodbye task[`0']; READ: response whichtask[`0'] accepted ; READ: response whichtask[`0'] success ; |
Lines starting with WRITTEN: are commands sent to the server. Lines starting with READ: are responses coming back from the server.
The Perl script in Example 3-1 sends the exact same commands:
Example 3-1. demo_stat.pl Script
#! /usr/bin/perl -w # demo_stat.pl # # This script will attempt to connect to the OpenVault server and # get a response. If for some reason we can't connect to the # server, we know OpenVault is down. require 5.002; use Socket; use FileHandle; # This assumes that the OV core is on the same host as # this script is running. $ov_server = `hostname `; chop $ov_server; $ov_port = “44444”; # Setup connection to OpenVault server process. # See “Programming Perl” 2nd ED. P. 498 for discussion # on network programming with Perl. $iaddr = inet_aton($ov_server) or die “no host: $ov_server”; $paddr = sockaddr_in($ov_port, $iaddr); $proto = getprotobyname(“tcp”); socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die “socket: $!”; connect(SOCK, $paddr) or die “connect: $!”; SOCK -> autoflush(); # Now that a connection is made to the OpenVault server # process, we treat it just like another other file. # Send initial data to server print SOCK “$ov_server\r\nSYSTEM\r\nonlyInstance\r\nAAPI\r\n0\r\n”; # Get response and ignore it # Response should only be `ok' $line = <SOCK>; # Send HELLO greeting print SOCK “hello client[`SYSTEM']instance[`onlyInstance']”; print SOCK “language[`AAPI']versions[`1.0'];\r\n”; $line = <SOCK>; if (substr($line,0,7) eq “welcome”) { # Welcome is good and what we want } elsif (substr($line,0,9) eq “unwelcome”) { # Server has rejected us die “Server Not Allowing Request\n”; } else { #Got an undefined answer from server #We should not get here die “Undefined Error\n”; } # Since we have communicated with the server, # we know that OpenVault is running. print “OpenVault server $ov_server is UP\n\n”; # Send goodbye command print SOCK “goodbye task[`0'];\r\n”; # Get command `accepted' from server. $line = <SOCK>; # Get command `success' from server. $line = <SOCK>; close(SOCK) or die “close: $!”; exit; |
Example 3-2, contains a Perl script that sends an OpenVault command and receives a reply. This script queries the server for a list of drives, and is similar to the ov_drive command.
To see the CAPI/AAPI commands involved, run the ov_drive command with -l .* and -Z options, as follows:
vega# ov_drive -lZ ".*" WRITTEN: vega WRITTEN: SYSTEM WRITTEN: onlyInstance WRITTEN: AAPI WRITTEN: 0 READ: ok WRITTEN: hello language[`AAPI'] versions[ `1.0' ] instance[`onlyInstance'] client[`SYSTEM']; READ: welcome version[`1.0']; WRITTEN: show match[ regEx(`.*' DRIVE.'DriveName')] report[DRIVE.'DriveName' DRIVE.'DriveGroupName' DRIVE.'DriveDisabled'] reportmode[value] task[`0']; READ: response whichtask[`0'] accepted ; READ: response whichtask[`0'] success text[`tape1' `drives' `false' ] text[`tape2' `drives' `false' ]; Drives: Drive Drive Group Disabled tape1 drives false tape2 drives false WRITTEN: goodbye task[`1']; READ: response whichtask[`1'] accepted ; READ: response whichtask[`1'] success ; |
The Perl script in Example 3-2 issues a similar set of CAPI/AAPI commands, but is a bit simpler. Instead of requesting the DriveName, DriveGroupName, and DriveDisabled, this script only requests the DriveName:
#! /usr/bin/perl -w require 5.002; use Socket; use FileHandle; $ov_server = `hostname `; chop $ov_server; $ov_port = “44444”; # Setup connection to OpenVault server process. # See “Programming Perl” 2nd ED. P. 498 for discussion # on network programming with Perl. $iaddr = inet_aton($ov_server) or die “no host: $ov_server”; $paddr = sockaddr_in($ov_port, $iaddr); $proto = getprotobyname(“tcp”); socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die “socket: $!”; connect(SOCK, $paddr) or die “connect: $!”; SOCK -> autoflush(); # Now that a connection is made to the OpenVault server # process, we treat it just like another other file. #Send initial data to server print SOCK “$ov_server\r\nSYSTEM\r\nOnlyInstance\r\nAAPI\r\n0\r\n”; #Get response and ignore it # Response should only be `ok' $line = <SOCK>; # Send HELLO greeting print SOCK “hello client[`SYSTEM']instance[`onlyInstance']”; print SOCK “language[`AAPI']versions[`1.0'];\r\n”; $line = <SOCK>; if (substr($line,0,7) eq “welcome”) { # Welcome is good and what we want } elsif ( substr($line,0,9) eq “unwelcome”) { # Server has rejected us die “Server Not Allowing Request\n”; } else { #Got an undefined answer from server #We should not get here die “Undefined Error\n”; } # Send show command print SOCK “show match[ regEx (`.*' DRIVE.'DriveName')]”; print SOCK “report[DRIVE.'DriveName'] task[`0'];\r\n”; # Get command `accepted' from server $line = <SOCK>; # Get command `success' from server with results of command # along with results $line = <SOCK>; #Now we need to do something with the data #A non-trivial script would parse out the results #and display it in a more human readable form. print $line; print SOCK “goodbye task[`1'];\r\n”; # Get command `accepted' from server $line = <SOCK>; # Get command `success' from server $line = <SOCK>; close(SOCK) or die “close: $!”; exit; |