source: trunk/pxeconfig/pxeconfig @ 19

Last change on this file since 19 was 19, checked in by sscpbas, 20 years ago

pxeconfig:

Added command line options so that we can use the program interactivly
and via command line

changed the info structure of a lot of functions. So the functions can
report different error messages for interactive usage and command line
usage.

File size: 6.4 KB
Line 
1#!/usr/bin/env python
2#
3# Author: Bas van der Vlies <basv@sara.nl>
4# Date  : 16 February 2002
5#
6# Tester: Walter de Jong <walter@sara.nl>
7#
8# CVS info
9#  $Date: 2002/09/27 14:47:36 $
10#  $Revision: 1.10 $
11#
12# Copyright (C) 2002
13#
14# This file is part of the pxeconfig utils
15#
16# This program is free software; you can redistribute it and/or modify it
17# under the terms of the GNU General Public License as published by the
18# Free Software Foundation; either version 2, or (at your option) any
19# later version.
20#
21# This program is distributed in the hope that it will be useful,
22# but WITHOUT ANY WARRANTY; without even the implied warranty of
23# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24# GNU General Public License for more details.
25#
26# You should have received a copy of the GNU General Public License
27# along with this program; if not, write to the Free Software
28# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
29#
30"""
31Usage: pxeconfig
32 [-d|--directory <pxe_config_dir>]
33 [-n|--net <C-net> -s|--start <number> -e|--end <number> -f|--file <filename>]
34
35With this program you can configure which PXE configuration file a node
36will use when it boots. The program can be started interactivly or via
37command line options.
38
39When this program is started interactive it will ask the following questions:
40  1) Network address (Class C-network address only)
41  2) Starting number
42  3) Ending number
43  4) Which PXE config file to use
44
45For example, if the answers are:
46  1) 10.168.44
47  2) 2
48  3) 4
49  4) default.node_install
50
51Then the result is that is create symbolic links in /tftpboot/pxelinux.cfg:
52  0AA82C02 ----> default.node_install
53  0AA82C03 ----> default.node_install
54  0AA82C04 ----> default.node_install
55"""
56
57import string
58import sys
59import os
60import glob
61import getopt
62
63# DEBUG
64#
65DEBUG=0
66
67# Constants
68#
69PXE_CONF_DIR='/tftpboot/pxelinux.cfg'
70NETWORK='network'
71FILENAME='filename'
72START='start'
73END='end'
74
75SHORTOPT_LIST='d:n:s:e:f:'
76LONGOPT_LIST=['directory=', 'net=', 'start=', 'end=', 'file=']
77
78def select_pxe_configfile():
79  """
80  Let user choose which pxeconfig file to use.
81  """
82
83  os.chdir(PXE_CONF_DIR)
84
85  # Try to determine to which file the default symlink points, and
86  # if it exists, remove it from the list.
87  #
88  try:
89    default_file = os.readlink('default')
90  except OSError:
91    default_file = None
92    pass
93
94  files = glob.glob('default.*')
95  if not files:
96    print 'There are no pxe config files starting with: default.'
97    sys.exit(1)
98
99  if default_file:
100    files.remove(default_file)
101 
102
103  print 'Which pxe config file must we use: ?' 
104  i = 1   
105  for file in files:
106    print "%d : %s" %(i,file)
107    i = i +1
108
109  while 1:
110    index = raw_input('Select a number: ')
111    try:
112      index = int(index)
113    except ValueError:
114      index = len(files) + 1
115
116    # Is the user smart enough to select
117    # the right value??
118    #
119    if 0 < index <= len(files): break
120
121  return files[index-1]
122
123def create_links(dict):
124  """
125  Create the links in the PXE_CONF_DIR,
126    list : A list containing: network hex address, pxe config file,
127           start number, end number
128  """
129  os.chdir(PXE_CONF_DIR)
130  naddr = dict[NETWORK]
131  pxe_filename = dict[FILENAME]
132  for i in range(dict[START], dict[END]+1):
133    haddr = '%s%02X' %(naddr, i)
134    if DEBUG:
135      print 'linking %s to %s' %(haddr, pxe_filename)
136
137    if os.path.exists(haddr):
138       os.unlink(haddr)
139
140    os.symlink(pxe_filename, haddr)
141
142
143def check_network(net, prefix=''):
144  """
145  This function checks if the give network is a Class C-network and will
146  convert the network address to a hex address if true.
147  """
148  d = string.split(net, '.')
149
150  if len(d) != 3:
151    if prefix:
152      net = prefix + ' : ' + net
153     
154    print '%s is not a valid  C-class network address!!!' %net
155    sys.exit(1)
156
157
158  # Display right message for interactive/commandline
159  if prefix:
160    prefix = prefix + ' ' + net
161  else:
162    prefix = net
163
164  # Check if we have valid network values
165  r = ''
166  for i in d:
167    i = check_number(i, prefix)
168    r = '%s%02X' %(r,i)
169
170  if DEBUG:
171    print r
172
173  return r
174
175def check_number(number, prefix=''):
176  """
177  This functions checks if the input is between 0 < number < 255:
178     number : is a string
179     prefix ; a string that must be displayed if an error occurs
180  """
181  try:
182    n = int(number)
183  except ValueError, detail:
184    print prefix,detail
185    sys.exit(1)
186
187  if 0 <= n <= 255:
188    return n
189  else:
190
191    if prefix:
192      number = prefix +' : ' + number
193
194    print '%s is not a valid number, must be between 0 and 255' %number
195    sys.exit(1)
196
197def interactive(binfo):
198
199  print __doc__
200
201  network = raw_input('Give network address (xxx.xxx.xxx): ') 
202  naddr = check_network(network)
203
204  start = raw_input('Starting number: ') 
205  start = check_number(start)
206
207  end = raw_input('Ending number: ') 
208  end = check_number(end)
209
210  pxe_filename = select_pxe_configfile()
211
212  binfo[NETWORK] = naddr
213  binfo[START] = int(start)
214  binfo[END] = int(end)
215  binfo[FILENAME] = pxe_filename
216
217  if DEBUG:
218    print network, binfo
219
220def check_cmd_line(binfo):
221  if len(binfo.keys()) != 4:
222    print 'Not enough arguments to create the links'
223    print __doc__
224    sys.exit(1)
225
226  # check_filename
227  #
228  if not os.path.isfile(os.path.join(PXE_CONF_DIR, binfo[FILENAME])):
229    print '%s: Filename does not exists' %binfo[FILENAME]
230    sys.exit(1)
231
232def check_args(argv, binfo):
233  """
234  command line option:
235    -d|--directory <dir>
236      Where <dir> is the directory where the pxe config files reside.
237  """
238  global PXE_CONF_DIR
239
240  try:
241    opts, args = getopt.getopt(argv[1:], SHORTOPT_LIST, LONGOPT_LIST)
242  except getopt.error, detail:
243    print check_args.__doc__
244    print detail
245    sys.exit(1)
246
247  # Check given options
248  #
249  for opt,value in opts:
250    if opt in ['-d', '--directory']:
251      if os.path.isdir(value):
252        PXE_CONF_DIR = value
253      else:
254        print 'Directory %s does not exists\n' %value
255        sys.exit(1)
256
257    elif opt in ['-n', '--net']:
258      network = value
259      binfo[NETWORK] = check_network(value, opt)
260
261    elif opt in ['-s', '--start']:
262      binfo[START] = check_number(value, opt)
263
264    elif opt in ['-e', '--end']:
265      binfo[END] = check_number(value, opt)
266
267    elif opt in ['-f', '--file']:
268      binfo[FILENAME] = value
269
270
271def main():
272  # A dictionary holding the boot info
273  #
274  bootinfo = {}
275  check_args(sys.argv, bootinfo)
276
277  if bootinfo:   
278    check_cmd_line(bootinfo)
279  else:
280    interactive(bootinfo)
281
282  create_links(bootinfo)
283
284if __name__ == '__main__':
285  main()
Note: See TracBrowser for help on using the repository browser.