Disconnected operation.
[bootmanager.git] / source / steps / ReadNodeConfiguration.py
index e4abbb5..d19439e 100644 (file)
@@ -1,44 +1,11 @@
+#!/usr/bin/python2
+
 # Copyright (c) 2003 Intel Corporation
 # All rights reserved.
-
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-
-#     * Neither the name of the Intel Corporation nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF
-# YOUR JURISDICTION. It is licensee's responsibility to comply with any
-# export regulations applicable in licensee's jurisdiction. Under
-# CURRENT (May 2000) U.S. export regulations this software is eligible
-# for export from the U.S. and can be downloaded by or otherwise
-# exported or reexported worldwide EXCEPT to U.S. embargoed destinations
-# which include Cuba, Iraq, Libya, North Korea, Iran, Syria, Sudan,
-# Afghanistan and any other country to which the U.S. has embargoed
-# goods and services.
-
+#
+# Copyright (c) 2004-2006 The Trustees of Princeton University
+# All rights reserved.
+# expected /proc/partitions format
 
 import sys, os, traceback
 import string
@@ -49,7 +16,6 @@ import utils
 from Exceptions import *
 import BootServerRequest
 import BootAPI
-import StartDebug
 import notify_messages
 import UpdateBootStateWithPLC
 
@@ -67,8 +33,8 @@ def Run( vars, log ):
     these files can exist in several different locations with
     several different names. Below is the search order:
 
-    filename      floppy   flash    cd
-    plnode.txt      1        2      4 (/usr/boot), 5 (/usr)
+    filename      floppy   flash    ramdisk    cd
+    plnode.txt      1        2      4 (/)      5 (/usr/boot), 6 (/usr)
     planet.cnf      3
 
     The locations will be searched in the above order, plnode.txt
@@ -150,6 +116,8 @@ def Run( vars, log ):
     vars['WAS_NODE_ID_IN_CONF']= 0
     vars['WAS_NODE_KEY_IN_CONF']= 0
 
+    vars['DISCONNECTED_OPERATION']= ''
+
     # for any devices that need to be mounted to get the configuration
     # file, mount them here.
     mount_point= "/tmp/conffilemount"
@@ -161,17 +129,22 @@ def Run( vars, log ):
     
     # 1. check the regular floppy device
     log.write( "Checking standard floppy disk for plnode.txt file.\n" )
-    
+
+    log.write( "Mounting /dev/fd0 on %s\n" % mount_point )
     utils.sysexec_noerr( "mount -o ro -t ext2,msdos /dev/fd0 %s " \
                          % mount_point, log )
 
     conf_file_path= "%s/%s" % (mount_point,NEW_CONF_FILE_NAME)
+    
+    log.write( "Checking for existence of %s\n" % conf_file_path )
     if os.access( conf_file_path, os.R_OK ):
         try:
             conf_file= file(conf_file_path,"r")
             conf_file_contents= conf_file.read()
             conf_file.close()
+            log.write( "Read in contents of file %s\n" % conf_file_path )
         except IOError, e:
+            log.write( "Unable to read file %s\n" % conf_file_path )
             pass
 
         utils.sysexec_noerr( "umount %s" % mount_point, log )
@@ -186,12 +159,16 @@ def Run( vars, log ):
     # order, but do it now to save mounting/unmounting the disk twice.
     # try to parse it later...
     conf_file_path= "%s/%s" % (mount_point,OLD_CONF_FILE_NAME)
+
+    log.write( "Checking for existence of %s (used later)\n" % conf_file_path )
     if os.access( conf_file_path, os.R_OK ):
         try:
             old_conf_file= file(conf_file_path,"r")
             old_conf_file_contents= old_conf_file.read()
             old_conf_file.close()
+            log.write( "Read in contents of file %s\n" % conf_file_path )
         except IOError, e:
+            log.write( "Unable to read file %s\n" % conf_file_path )
             pass
         
     utils.sysexec_noerr( "umount %s" % mount_point, log )
@@ -208,6 +185,7 @@ def Run( vars, log ):
 
         for device in devices:
             if device[:2] != "sd":
+                log.write( "Skipping non-scsi device %s\n" % device )
                 continue
 
             # test removable
@@ -220,12 +198,16 @@ def Run( vars, log ):
                 continue
 
             if not removable:
+                log.write( "Skipping non-removable device %s\n" % device )
                 continue
 
             log.write( "Checking removable device %s\n" % device )
 
             partitions= file("/proc/partitions", "r")
             for line in partitions:
+                found_file= 0
+                parsed_file= 0
+                
                 if not re.search("%s[0-9]*$" % device, line):
                     continue
 
@@ -236,34 +218,49 @@ def Run( vars, log ):
                     # ok, try to mount it and see if we have a conf file.
                     full_device= "/dev/%s" % parts[3]
                 except IndexError, e:
+                    log.write( "Incorrect /proc/partitions line:\n%s\n" % line )
                     continue
 
+                log.write( "Mounting %s on %s\n" % (full_device,mount_point) )
                 try:
                     utils.sysexec( "mount -o ro -t ext2,msdos %s %s" \
                                    % (full_device,mount_point), log )
                 except BootManagerException, e:
+                    log.write( "Unable to mount, trying next partition\n" )
                     continue
 
                 conf_file_path= "%s/%s" % (mount_point,NEW_CONF_FILE_NAME)
+
+                log.write( "Checking for existence of %s\n" % conf_file_path )
                 if os.access( conf_file_path, os.R_OK ):
                     try:
                         conf_file= file(conf_file_path,"r")
                         conf_file_contents= conf_file.read()
                         conf_file.close()
+                        found_file= 1
+                        log.write( "Read in contents of file %s\n" % \
+                                   conf_file_path )
+
+                        if __parse_configuration_file( vars, log, \
+                                                       conf_file_contents):
+                            parsed_file= 1
                     except IOError, e:
-                        pass
+                        log.write( "Unable to read file %s\n" % conf_file_path )
 
                 utils.sysexec_noerr( "umount %s" % mount_point, log )
-                if __parse_configuration_file( vars, log, conf_file_contents):
-                    return 1
-                else:
-                    raise BootManagerException("Found configuration file plnode.txt " \
-                                               "on floppy, but was unable to parse it.")
+                if found_file:
+                    if parsed_file:
+                        return 1
+                    else:
+                        raise BootManagerException( \
+                            "Found configuration file plnode.txt " \
+                            "on floppy, but was unable to parse it.")
 
 
             
     # 3. check standard floppy disk for old file name planet.cnf
-    log.write( "Checking standard floppy disk for planet.cnf file.\n" )
+    log.write( "Checking standard floppy disk for planet.cnf file " \
+               "(from earlier.\n" )
 
     if old_conf_file_contents:
         if __parse_configuration_file( vars, log, old_conf_file_contents):
@@ -273,17 +270,44 @@ def Run( vars, log ):
                                         "on floppy, but was unable to parse it." )
 
 
-    # 4. check for plnode.txt in /usr/boot (mounted already)
+    # 4. check for plnode.txt in / (ramdisk)
+    log.write( "Checking / (ramdisk) for plnode.txt file.\n" )
+    
+    conf_file_path= "/%s" % NEW_CONF_FILE_NAME
+
+    log.write( "Checking for existence of %s\n" % conf_file_path )
+    if os.access(conf_file_path,os.R_OK):
+        try:
+            conf_file= file(conf_file_path,"r")
+            conf_file_contents= conf_file.read()
+            conf_file.close()
+            log.write( "Read in contents of file %s\n" % conf_file_path )
+        except IOError, e:
+            log.write( "Unable to read file %s\n" % conf_file_path )
+            pass
+    
+        if __parse_configuration_file( vars, log, conf_file_contents):            
+            return 1
+        else:
+            raise BootManagerException( "Found configuration file plnode.txt " \
+                                        "in /, but was unable to parse it.")
+
+    
+    # 5. check for plnode.txt in /usr/boot (mounted already)
     log.write( "Checking /usr/boot (cd) for plnode.txt file.\n" )
     
     conf_file_path= "/usr/boot/%s" % NEW_CONF_FILE_NAME
+
+    log.write( "Checking for existence of %s\n" % conf_file_path )
     if os.access(conf_file_path,os.R_OK):
         try:
             conf_file= file(conf_file_path,"r")
             conf_file_contents= conf_file.read()
             conf_file.close()
+            log.write( "Read in contents of file %s\n" % conf_file_path )
         except IOError, e:
-            pass    
+            log.write( "Unable to read file %s\n" % conf_file_path )
+            pass
     
         if __parse_configuration_file( vars, log, conf_file_contents):            
             return 1
@@ -293,16 +317,20 @@ def Run( vars, log ):
 
 
 
-    # 5. check for plnode.txt in /usr (mounted already)
+    # 6. check for plnode.txt in /usr (mounted already)
     log.write( "Checking /usr (cd) for plnode.txt file.\n" )
     
     conf_file_path= "/usr/%s" % NEW_CONF_FILE_NAME
+
+    log.write( "Checking for existence of %s\n" % conf_file_path )
     if os.access(conf_file_path,os.R_OK):
         try:
             conf_file= file(conf_file_path,"r")
             conf_file_contents= conf_file.read()
             conf_file.close()
+            log.write( "Read in contents of file %s\n" % conf_file_path )
         except IOError, e:
+            log.write( "Unable to read file %s\n" % conf_file_path )
             pass    
     
         if __parse_configuration_file( vars, log, conf_file_contents):            
@@ -330,6 +358,7 @@ def __parse_configuration_file( vars, log, file_contents ):
     NETWORK_SETTINGS= vars["NETWORK_SETTINGS"]
     
     if file_contents is None:
+        log.write( "__parse_configuration_file called with no file contents\n" )
         return 0
     
     try:
@@ -412,7 +441,10 @@ def __parse_configuration_file( vars, log, file_contents ):
 
             if name == "NET_DEVICE":
                 NETWORK_SETTINGS['mac']= string.upper(value)
-                
+
+            if name == "DISCONNECTED_OPERATION":
+                vars['DISCONNECTED_OPERATION']= value.strip()
+
 
     except IndexError, e:
         log.write( "Unable to parse configuration file\n" )
@@ -595,11 +627,9 @@ def __parse_configuration_file( vars, log, file_contents ):
         
     vars["NETWORK_SETTINGS"]= NETWORK_SETTINGS
 
-    if not hostname_resolve_ok:
+    if not hostname_resolve_ok and not vars['DISCONNECTED_OPERATION']:
         log.write( "Hostname does not resolve correctly, will not continue.\n" )
 
-        StartDebug.Run( vars, log )
-
         if can_make_api_call:
             log.write( "Notifying contacts of problem.\n" )