How to Use a Perl Script to Reboot a NetWare Server Using a UPS
Articles and Tips: article
Directory Engineer
Phoenix Home Life
Michael_Lee@phl.com
01 Jan 2001
This AppNote describes a method devised to reboot a NetWare server using an Uninterruptible Power Supply (UPS) from American Power Conversion.
Introduction
There are many times when a NetWare server may need to be rebooted. For example:
When a service pack has been applied to a NetWare server and changes were made to one or more of the startup scripts or drivers
When an abend has occurred
To free up more memory
To reset a piece of hardware, such as a SCSI controller
Many NetWare administrators have used an NCF file such as the one shown below to reboot a NetWare server:
REMOVE DOS
DOWN
EXIT
You can use RCONSOLE to execute this NCF file to reboot a server remotely. This works well in most situations, but not all. For example, there are times when NetWare servers hang when coming down due to log files being full, other abends, and so on. Furthermore, executing an NCF like this does a warm boot of the server, not a cold boot, and a cold boot may be needed to reset a piece of hardware. To do that, the power would have to be cut to the server. You also have to be connected to the server to initiate an NCF-style reboot.
Another problem is keeping users logged off during regular work hours in order to reboot a server. This forces system administrators to be either the first one in the office or the last one to leave the office in order to reboot a server. Like anyone else, I like to be able to leave work at a reasonable time and have dinner with my family. This AppNote describes what I did to resolve the problem of having to stay late just to reboot servers.
Scheduled Reboot Scenario
My company (Phoenix Home Life) has approximately 80 field offices, most of which do not have a system administrator or even someone who is familiar with NetWare onsite. These field offices are connected to the home office by 64 Kbps frame relay links, allowing these servers to be administered from the home office. When we rolled out NetWare 4.11 into these offices last year, each office received an APC UPS and an external tape drive in addition to the NetWare server. At the offices, the servers and their external tape drives are plugged into the APC UPS to protect them from power failure.
Before shipping the equipment to each office, APC's new Web/SNMP Management Cards were installed into each UPS. These management cards have a single 10Base-T network connector so the devices can be networked. They also allow the UPS to be managed via a browser, telnet, or even Novell Directory Services (NDS). Prior to shipping, the TCP/IP settings were configured, and their IP addresses and DNS names were added to our DNS servers.
Once these preparations were made, we could use a browser to receive information from these management cards regarding the UPS's power and battery, as shown in Figure 1 (note that IP addresses and DNS names have been removed from the graphic).
The Web/SNMP Management Cards send information about the UPS's power and battery.
When connecting to a Web/SNMP Management Card, an ID and Password prompt appears, forcing you to authenticate to the card before being able to view information or change the card's configuration.
A serial cable comes with each UPS to connect the UPS to the server, allowing the UPS to communicate with an NLM loaded on the server. If the UPS detects a power outage, the UPS communicates over the serial cable to the NLM running on the server, initiating a graceful shutdown after a few minutes.
The Web/SNMP Management Card has a selectable action called "Reboot UPS Gracefully," as seen in Figure 2. Selecting this option will initiate a graceful shutdown of the server. The UPS will communicate to the NLM running on the server causing the server to bring itself down gracefully. The UPS will then cut off power to the server and after several seconds will restore power back to the server, allowing the server to boot back up.
The "Reboot UPS Gracefully" option causes the UPS to shut off power to the server and then restore it, resulting in a cold boot.
Unfortunately, this "Reboot UPS Gracefully" option does not allow you to initiate the graceful shutdown at a time in the future; the graceful reboot initiates immediately.
My Remote Cold Boot Process
What I wanted to be able to do was, during regular business hours, initiate a graceful UPS reboot that would occur at some time in the future, even outside of regular business hours. As this capability was not available in the APC Web/SNMP Management Cards, I decided to write my own process. My goals were:
To be able to reboot the server at any time desired
To make the routine flexible so the same program or script will run on any of the servers without modification
To make the routine easy to use
I decided to write the routines in Perl, a programming language with which I am familiar. I find Perl to be powerful and flexible, and it runs on NetWare servers. My design criteria included the following:
After using the RCONSOLE program to check a NetWare server and deciding that the server needs to be rebooted, one can type in a command such as "PERL REBOOT 1:30" and the "REBOOT" Perl script will be executed. Since PERL.NLM is automatically loaded when our servers are booted, we do not have to load PERL before this script is executed. The time ("1:30" in this example) becomes an argument to the reboot script, telling the script what time to initiate the reboot process. The Perl script process then "sleeps" until the reboot time arrives.
When the desired reboot time arrives, the Perl script checks the AUTOEXEC.NCF file to determine the server's name. This is done because the UPS's DNS name is similar to the server's name: 'if-' is removed from beginning and '-ups' is appended to the end. This allows the same Perl script to run on any server without modification.
At this time a upsReboot.pl Perl module is called. It is passed the UPS's DNS name, along with the ID and Password of the Web/SNMP Management Card. A telnet socket connection to the server's UPS is made and the commands to execute a graceful reboot are sent to the UPS.
The same capabilities of the browser-based session are available in the telnet-based session, although not graphical in nature (see Figure 3).
The reboot process can be initiated via telnet.
This process satisfies all of my criteria mentioned earlier:
By entering time in 24-hour military format, you can select any time of day to initiate the reboot process. For instance, you can have the server reboot after everybody has left for the day but before a backup is made by entering "PERL REBOOT 20" at the server prompt. The Perl script will wait until 8:00 p.m. (2000 hours in military time) before starting the reboot process. If a time is not entered, the graceful reboot process will start immediately. (If you are running CRON.NLM on your NetWare servers, you can put the PERL REBOOT command into the crontab file to initiate an automatic server reboot weekly or monthly.)
Because the Perl script parses the AUTOEXEC.NCF file to retrieve the server's name to determine the DNS name of the server's UPS, the Perl script does not hard-code the UPS's DNS name. This allows the same Perl script to run without modification on any server.
The Perl script is easily initiated by running RCONSOLE to get to the server's NetWare prompt and typing the command 'PERL REBOOT time', replacing time with the actual time you want the graceful reboot process to run. The system administrator will most likely already be using RCONSOLE to troubleshoot problems the server may be experiencing.
Logic Pieces
The REBOOT Perl script is not very long. The logic is as follows:
The script retrieves the time argument, checking for any inaccuracies and giving an immediate error message if the time entered is not valid.
The NetWare server's local time is checked every 30 seconds until the server's time becomes the same as the desired reboot time.
The UPS's name is determined from the server's name found within the AUTOEXEC.NCF file.
The gracefulReboot routine is called within the "ups" package. This package logic is stored within the upsBoot.pl Perl module. This package stores any routines written to deal with an APC UPS.
The actual Perl script is given below. The explanatory notes correspond to the numbered lines in the sample script.
(1) - Load the upsboot.pl Perl module.
(2) - Check to see if an argument is passed to reboot.
(3) - Set the reboot time to the argument passed.
(4) - Set the reboot time to now if there are no arguments passed.
(5) - Check to see if a reboot time was passed to the script.
(6) - Extract the reboot hour and minute from the argument passed.
(7, 8) - Remove any extraneous characters from the reboot hour and minute.
(9, 10) - Set the reboot hour or minute to 0 if a value was not passed.
(11) - Check for a valid reboot time.
(12) - Give an error message and exit the program if an invalid time was entered.
(13) - Get the server's current time, returning hour and minute values.
(14) - Display a message to wait until the reboot time.
require ('upsboot.pl'); ' (1)' if (@ARGV) { # (2)# ($rebootTime) = @ARGV; # (3)# } else { $rebootTime = 0; # (4)# } if ($rebootTime) { # (5)# ($rebootHour, $rebootMinute) = split /:/, $rebootTime; # (6)# $rebootHour =~ s/\D*(\d*)\D*/$1/; # (7)# $rebootMinute =~ s/\D*(\d*)\D*/$1/; # (8)# $rebootHour = 0 if ! $rebootHour; ! (9)! $rebootMinute = 0 if ! $rebootMinute; ! (10)! if ((($rebootHour < 0) || ($rebootHour < 23)) || < (11)< (($rebootMinute < 0) || ($rebootMinute < 59))) {< print "\n^GInvalid time entered"";" print "Please enter time in format HH:MM using 24 hour\n";" print "clock" Ex. 23:59 for 11:59 PM, 00:00 for midnight, or\n";" die ("do not enter a time to reboot now."); " (12)" } ($blah, $nowMinute, $nowHour, @blahA) = localtime (); # (13)# print "Waiting until $rebootHour:$rebootMinute...\n"; " (14)" until (($rebootHour == $nowHour) && ($rebootMinute == $nowMinute)) { #;&& ($rebootMinute == $nowMinute)) { #; (15) sleep (30); # (16)# ($blah, $nowMinute, $nowHour, @blahA) = localtime (); # (17)# } } open AUTO, "sys:/system/autoexec.ncf"; " (18)" while (<AUTO<) { < (19)< $officeName = $1 if /^file server name .*?-(.{1,8})/i; # (20)# } close AUTO; # (21)# $upsName = lc ($officeName) . "-ups"; " (22)" print "Sending graceful reboot request to $upsName."; " (23)" if (! ups::gracefulReboot ($upsName, !id!, !password!)) { ! (24)! for ($i = 0; $i < 30; $i++) { < (25)< print "trying another $i\n";" sleep (20); $i = 30 if (ups::gracefulReboot ($upsName, id', 'password'));' } { require ('upsboot.pl'); ' (1)' if (@ARGV) { # (2)# ($rebootTime) = @ARGV; # (3)# } else { $rebootTime = 0; # (4)# } if ($rebootTime) { # (5)# ($rebootHour, $rebootMinute) = split /:/, $rebootTime; # (6)# $rebootHour =~ s/\D*(\d*)\D*/$1/; # (7)# $rebootMinute =~ s/\D*(\d*)\D*/$1/; # (8)# $rebootHour = 0 if ! $rebootHour; ! (9)! $rebootMinute = 0 if ! $rebootMinute; ! (10)! if ((($rebootHour < 0) || ($rebootHour < 23)) || < (11)< (($rebootMinute < 0) || ($rebootMinute < 59))) {< print "\n^GInvalid time entered"";" print "Please enter time in format HH:MM using 24 hour\n";" print "clock" Ex. 23:59 for 11:59 PM, 00:00 for midnight, or\n";" die ("do not enter a time to reboot now."); " (12)" } ($blah, $nowMinute, $nowHour, @blahA) = localtime (); # (13)# print "Waiting until $rebootHour:$rebootMinute...\n"; " (14)" until (($rebootHour == $nowHour) && ($rebootMinute == $nowMinute)) { #;&& ($rebootMinute == $nowMinute)) { #; (15) sleep (30); # (16)# ($blah, $nowMinute, $nowHour, @blahA) = localtime (); # (17)# } } open AUTO, "sys:/system/autoexec.ncf"; " (18)" while (<AUTO<) { < (19)< $officeName = $1 if /^file server name .*?-(.{1,8})/i; # (20)# } close AUTO; # (21)# $upsName = lc ($officeName) . "-ups"; " (22)" print "Sending graceful reboot request to $upsName."; " (23)" if (! ups::gracefulReboot ($upsName, !id!, !password!)) { ! (24)! for ($i = 0; $i < 30; $i++) { < (25)< print "trying another $i\n";" sleep (20); $i = 30 if (ups::gracefulReboot ($upsName, id', 'password'));' } {
(15) - Check to see if the reboot time is the same as the current time.
(16) - Wait 30 seconds.
(17) - Get the server's current time, returning hour and minute values.
(18) - Open the server's AUTOEXEC.NCF file.
(19) - Read in the entire AUTOEXEC.NCF file.
(20) - When the file server name line is found within the AUTOEXEC.NCF file, retrieve the office's name.
(21) - Close the server's AUTOEXEC.NCF file.
(22) - Determine the UPS's DNS name.
(23) - Display a message that the graceful reboot request is being made.
(24) - Execute the graceful reboot process within the UPS package, passing the UPS's DNS name and its ID and Password.
(25) - If the UPS could not be communicated with for some reason, retry a maximum of 30 times.
The upsBoot Perl APC UPS library is longer and more complex than the reboot Perl script. The logic of the library goes like this:
The UPS class is defined.
The IP address of the UPS is returned from the DNS request. This DNS request is created from the DNS name passed from the reboot Perl script.
A socket connection is made to the UPS.
The ID and Password are used to log into the UPS.
The commands are passed to the UPS to initiate the graceful shutdown of the NetWare server and the UPS.
Conclusion
Quite often there are ways to make a NetWare administrator's job a little easier. The process described in this AppNote allows an administrator, during regular business hours, to schedule a graceful cold reboot of a NetWare server to occur at any time, even in the middle of the night. The administrator does not need to be connected to the server at the time of rebooting, thus allowing the administrator to go home on time, spend a relaxing evening with the family, and get a good night's sleep.
For more information on APC Web/SNMP Management Cards, visit http://www.apc.com.
* Originally published in Novell AppNotes
Disclaimer
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.