Changeset 139


Ignore:
Timestamp:
04/15/09 14:36:04 (12 years ago)
Author:
bas
Message:

pxeconfig.in:

  • is now only a simple main script
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/pxeconfig.in

    r137 r139  
    1 #!@PYTHON@
     1##!@PYTHON@
    22#
    33# set ts=4, sw=4
     
    55# Author: Bas van der Vlies <basv@sara.nl>
    66# Date  : 16 February 2002
    7 #
    8 # Tester: Walter de Jong <walter@sara.nl>
    97#
    108# SVN info
     
    2927# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
    3028#
    31 """
    32 Usage: pxeconfig [-f,--filename <name>] <hosts>
     29import sys
     30import pxeconfig
    3331
    34 Specifying hostnames:
    35    To specify a range use the [] to indicate a range,
    36    a couple of examples herebelow.
    37 
    38    The first five nodes of rack 16
    39           - gb-r16n[1-5]
    40 
    41    The first five nodes and node 12 and 18 of rack 16 to 20
    42       - gb-r[16-20]n[1-5,12,18]
    43 
    44    The first five nodes de in rack 16 with padding enabled
    45           - gb-r[16]n[01-5]
    46 
    47 The ranges ([]) are not only limited to numbers, letters can also be used.
    48 
    49 With this program you can configure which PXE configuration file a node
    50 will use when it boots.
    51 
    52 See following link for usage and examples:
    53  - https://subtrac.sara.nl/oss/pxeconfig/wiki/PxeUsage
    54 """
    55 
    56 import string
    57 import sys
    58 import os
    59 import glob
    60 import getopt
    61 import socket
    62 import ConfigParser
    63 import re
    64 
    65 # import from the sara_python_modules
    66 from sara import AdvancedParser
    67 
    68 # Constants
    69 #
    70 PXE_CONF_DIR = '/tftpboot/pxelinux.cfg'
    71 NETWORK      = 'network'
    72 START        = 'start'
    73 END          = 'end'
    74 VERSION      = '3.0.0'
    75 
    76 class PxeConfig(Exception):
    77         def __init__(self, msg=''):
    78                 self.msg = msg
    79                 Exception.__init__(self, msg)
    80 
    81         def __repr__(self):
    82                 return self.msg
    83 
    84 def ReadConfig(file):
    85         """
    86         Parse the config file
    87         """
    88         if not os.path.isfile(file):
    89                 error = 'File %s does not exist' %file
    90                 raise PxeConfig, error
    91 
    92         config = ConfigParser.RawConfigParser()
    93         try:
    94                 config.read(file)
    95         except ConfigParser.MissingSectionHeaderError,detail:
    96                 raise PxeConfig, detail
    97 
    98         # Not yet uses
    99         #
    100         #projects = {}
    101         #for section in config.sections():
    102         #       projects[section] = {}
    103         #       for option in  config.options(section):
    104         #       projects[section][option] = config.get(section, option)
    105 
    106         stanza = config.defaults()
    107         return stanza
    108 
    109 def select_pxe_configfile():
    110         """
    111         Let user choose which pxeconfig file to use.
    112         """
    113        
    114         os.chdir(PXE_CONF_DIR)
    115        
    116         # Try to determine to which file the default symlink points, and
    117         # if it exists, remove it from the list.
    118         #
    119         try:
    120                 default_file = os.readlink('default')
    121         except OSError:
    122                 default_file = None
    123         pass
    124 
    125         files = glob.glob('default.*')
    126         if not files:
    127                 error =  'There are no pxe config files starting with: default.'
    128                 raise PxeConfig, error
    129 
    130         if default_file:
    131                 files.remove(default_file)
    132 
    133         # sort the files
    134         #
    135         files.sort()
    136  
    137         print 'Which pxe config file must we use: ?'
    138         i = 1   
    139         for file in files:
    140                 print "%d : %s" %(i,file)
    141                 i = i + 1
    142 
    143         while 1:
    144                 index = raw_input('Select a number: ')
    145                 try:
    146                         index = int(index)
    147                 except ValueError:
    148                         index = len(files) + 1
    149 
    150                 # Is the user smart enough to select
    151                 # the right value??
    152                 #
    153                 if 0 < index <= len(files):
    154                         break
    155 
    156         return files[index-1]
    157 
    158 def manage_links(haddr, options):
    159         """
    160         Create the links in the PXE_CONF_DIR,
    161         list : A list containing: network hex address, pxe config file,
    162            start number, end number
    163         """
    164         if options.VERBOSE:
    165                 print 'manage_links(%s)' %(haddr)
    166        
    167         os.chdir(PXE_CONF_DIR)
    168         pxe_filename = options.filename
    169        
    170         if options.REMOVE:
    171                 if options.DEBUG or options.DRY_RUN or options.VERBOSE:
    172                         print 'removing %s/%s' %(PXE_CONF_DIR, haddr)
    173 
    174                 if os.path.exists(haddr) and not options.DRY_RUN:
    175                         os.unlink(haddr)
    176 
    177         else:
    178                 if options.DEBUG or options.DRY_RUN or options.VERBOSE:
    179                         print 'linking %s to %s' %(haddr, pxe_filename)
    180 
    181                 if not options.DRY_RUN:
    182                         if os.path.exists(haddr):
    183                                 os.unlink(haddr)
    184                         os.symlink(pxe_filename, haddr)
    185 
    186 def net_2_hex(net, options):
    187         """
    188         This function checks if the give network is a Class C-network and will
    189         convert the network address to a hex address if true.
    190         """
    191         if options.DEBUG:
    192                 str = 'net_2_hex : %s' %(net)
    193                 print str
    194        
    195         d = string.split(net, '.')
    196         if len(d) != 3:
    197                 error = '%s is not a valid  C-class network address' %(net)
    198                 raise PxeConfig, error
    199 
    200         # Check if we have valid network values
    201         r = ''
    202         for i in d:
    203                 r = '%s%02X' %(r, int(i))
    204 
    205         if options.DEBUG:
    206                 print 'C-network converted to hex: ', r
    207 
    208         return r
    209 
    210 def hosts_2_hex(hosts, options):
    211         """
    212         Convert hostname(s) to a net address that can be handled by manage_links function
    213         """
    214         if options.DEBUG:
    215                 str = 'host_2_hex: %s' %hosts
    216                 print str
    217 
    218         for host in hosts:
    219                 try:
    220                         addr = socket.gethostbyname(host)
    221                 except socket.error,detail:
    222                         error =  '%s not an valid hostname: %s' %(host,detail)
    223                         raise PxeConfig, error
    224 
    225                 net = string.splitfields(addr, '.')
    226                 cnet = string.joinfields(net[0:3], '.')
    227 
    228                 haddr = '%s%02X' %(net_2_hex(cnet, options), int(net[3]))
    229 
    230                 manage_links(haddr, options)
    231                
    232 
    233 def add_options(p):
    234         """
    235         add the default options
    236         """
    237         p.set_defaults(
    238                 DEBUG   = False,
    239                 VERBOSE = False,
    240                 DRY_RUN = False,
    241                 REMOVE  = False,
    242                 VERSION  = False,
    243         )
    244 
    245         p.add_option('-d', '--debug',
    246                 action = 'store_true',
    247                 dest   = 'DEBUG',
    248                 help   = 'Toggle debug mode (default : False)'
    249         )
    250 
    251         p.add_option('-f', '--filename',
    252                 action = 'store',
    253                 dest   = 'filename',
    254                 help   = 'Specifies which PXE filename must be use'
    255         )
    256 
    257         p.add_option('-n', '--dry-run',
    258                 action = 'store_true',
    259                 dest   = 'DRY_RUN',
    260                 help   = 'Do not execute any command'
    261         )
    262 
    263         p.add_option('-r', '--remove',
    264                 action = 'store_true',
    265                 dest   = 'REMOVE',
    266                 help   = 'Removes the PXE filename for a host(s)'
    267         )
    268 
    269         p.add_option('-v', '--verbose',
    270                 action = 'store_true',
    271                 dest   = 'VERBOSE',
    272                 help   = 'Make the program more verbose (default: False)'
    273         )
    274 
    275         p.add_option('-V', '--version',
    276                 action = 'store_true',
    277                 dest   = 'VERSION',
    278                 help   = 'Print the program version number and exit'
    279         )
    280 
    281 def parser(argv, settings):
    282         """
    283         Make use of sara advance parser module. It can handle regex in hostnames
    284         """
    285         parser = AdvancedParser.AdvancedParser(usage=__doc__)
    286         add_options(parser)
    287 
    288         options, args = parser.parse_args()
    289 
    290         if not args:
    291                 print __doc__
    292                 sys.exit(0)
    293        
    294         if options.VERSION:
    295                 print VERSION
    296                 sys.exit(0)
    297 
    298         # debug can be specified by the command line or options file
    299         #
    300         if not options.DEBUG:
    301                 try:
    302                         if settings['debug']:
    303                                 options.DEBUG = int(settings['debug'])
    304                 except KeyError:
    305                         pass
    306 
    307         if options.filename:
    308                 if not os.path.isfile(os.path.join(PXE_CONF_DIR, options.filename)):
    309                                 error =  '%s: Filename does not exists' %(options.filename)
    310                                 raise PxeConfig, error
    311         else:
    312                 options.filename = select_pxe_configfile()
    313 
    314         if options.DEBUG:
    315                 print args, options
    316 
    317         hosts_2_hex(args, options)
    318 
    319 
    320 def main():
    321         # A dictionary holding the boot info
    322         #
    323         global PXE_CONF_DIR
    324        
    325         configfile = '@pxeconfig_conf@'
    326         settings = ReadConfig(configfile)
    327        
    328         try:
    329                 PXE_CONF_DIR = settings['pxe_config_dir']
    330 
    331         except KeyError:
    332                 pass
    333 
    334         PXE_CONF_DIR = os.path.realpath(PXE_CONF_DIR)
    335         if not os.path.isdir(PXE_CONF_DIR):
    336                 error =  'pxeconfig directory: %s does not exists' %(PXE_CONF_DIR)
    337                 raise PxeConfig, error
    338 
    339         parser(sys.argv, settings)
    340 
    341        
    34232if __name__ == '__main__':
    34333        try:
    344                 main()
    345         except PxeConfig, detail:
     34                pxeconfig.main()
     35        except pxeconfig.PxeConfig, detail:
    34636                print detail
    34737                sys.exit(1)
Note: See TracChangeset for help on using the changeset viewer.