Index: /trunk/Changelog
===================================================================
--- /trunk/Changelog	(revision 122)
+++ /trunk/Changelog	(revision 123)
@@ -45,4 +45,25 @@
  - We do need the check for a C-compiler so remove it from the configure.in
    and made a new configure
+   Author: Bas van der Vlies
+
+ - Added -R,--rack and -N,--node option, eg:
+     pxeconfig --basename gb- --rack r1-r2 --node n1-n2 -f default.memtest
+
+     will produce links to file defaul.memtest for these hosts:
+       - gb-r1n1
+       - gb-r1n2
+       - gb-r2n1
+       - gb-r2n2
+
+  If leading zeros are used, then rack and/or node names will be padded with
+  zeros, eg:
+     pxeconfig --basename gb- --rack r01-r02 --node n01-n02 -f default.memtest
+
+     will produce links to file defaul.memtest for these hosts:
+       - gb-r01n01
+       - gb-r01n02
+       - gb-r02n01
+       - gb-r02n02
+
    Author: Bas van der Vlies
 
Index: /trunk/pxeconfig.in
===================================================================
--- /trunk/pxeconfig.in	(revision 122)
+++ /trunk/pxeconfig.in	(revision 123)
@@ -32,13 +32,23 @@
 Usage: pxeconfig 
 
- [optional] -f|--file <filename> <hostname(s)>
- [optional] -i|--interactive
- [optional] -n|--net <C-net> -s|--start <number> -e|--end <number> -f|--file <filename>
- [optional] -b|--basename <string> s|--start <number> -e|--end <number> -f|--file <filename>
- -V|--version
-
-options:
+ -V,--version
+ [-r,--remove] -i,--interactive
+ [-r,--remove] -f,--file <filename> <hostname(s)>
+ [-r,--remove] -n,--net <C-net> -s,--start <number> -e,--end <number> -f,--file <filename>
+
+there are serveal ways to create a range of hostnames. they all start with:
+ * -b,--base-name <string>
+
+The different formats are:
+  1  [opt] -H,--host-range <number>-<number> -f,--file <filename>
+  2  [opt] -s,--start <number> -e,--end <number> -f,--file <filename>
+  3  [opt] -R,--rack <string>-<string>  -N,--node <string>-<string> -f,--file <filename>
+
+opt:
  -r,--remove 
- -w,--equal-width
+ -w,--equal-width 
+
+If leading zeros are used for <number>, then host names will be padded 
+with zeros. --equal-width option will be enabled.
 
 With this program you can configure which PXE configuration file a node
@@ -71,4 +81,5 @@
 import socket
 import ConfigParser
+import re
 
 # DEBUG
@@ -86,13 +97,24 @@
 END='end'
 REMOVE='remove'
+RACK='rack'
+NODE='node'
 INTERACTIVE='interactive'
 EQUALWIDTH='equalwidth'
 VERSION='2.0.0'
 
-SHORTOPT_LIST='b:e:f:hin:s:rwvH:V'
+SHORTOPT_LIST='b:e:f:hin:s:rwvN:H:R:V'
 LONGOPT_LIST=[ 'basename=', 'debug', 'end=', 'equal-width', 
     'file=', 'help', 'host-range=', 'interactive', 'net=', 
-    'start=', 'remove', 'verbose', 'version', 'equal-width'
+    'node=', 'start=', 'rack=', 'remove', 'verbose', 
+    'version', 'equal-width'
 	]
+
+# regex definition
+#
+# A regulare expression to parse string for rack/node
+id_re = re.compile(r"""
+	(?P<basename>[a-zA-Z-_]*)
+	(?P<number>[0-9]+) 
+     """, re.VERBOSE)
 
 def verbose(str):
@@ -196,5 +218,5 @@
     haddr = '%s%02X' %(naddr, i)
 
-    if dict[REMOVE]:
+    if dict[REMOVE] == True:
        if DEBUG:
           print 'removing %s/%s' %(PXE_CONF_DIR, haddr)
@@ -228,5 +250,5 @@
 
 	if DEBUG:
-		print r
+		print 'C-network in hex: ', r
 
 	return r
@@ -330,6 +352,9 @@
 
 	if binfo.has_key(BASENAME):
-		set_padding(binfo)
-		create_links =  base_2_net
+		if binfo[RACK] and binfo[NODE]:
+			create_links = rack_2_net
+		else:
+			set_padding(binfo)
+			create_links =  base_2_net
 
 	elif binfo.has_key(NETWORK):
@@ -378,5 +403,5 @@
 
 
-def parse_host_range(binfo, arg):
+def parse_number_range(binfo, arg):
 	"""
 	Parse if arg is of format <digit-digit>, if it starts 
@@ -394,4 +419,43 @@
 	binfo[END] = l[1]
 
+def parse_string_range(binfo, arg, id):
+	"""
+	Parse if arg is of format <(alpha)(digit)>-(alpha)(digit)>
+	if digit starts with a zero (0) then set EQUALWIDTH
+	"""
+	str = 'parse_string_range: %s %s' %(arg, id)
+	verbose(str)
+
+	l = arg.split('-')
+	if len(l) < 2:
+		error =  '%s : range syntax not valid,eg <string>-<string>)' %(arg)
+		raise PxeConfig, error
+	
+	binfo[id] = dict()
+	binfo[id][EQUALWIDTH] = [False, 0]
+
+	i = 0
+	for item in l: 
+		result = id_re.match(item)
+
+		if result:
+			basename = result.group('basename')
+			number = result.group('number')
+
+			if DEBUG:
+				print 'basename = %s, number = %s' %(basename, number)
+	
+			if i == 0:
+				binfo[id][BASENAME] = basename
+				binfo[id][START] = number
+				i += 1
+			else:
+				binfo[id][END] = number
+
+		else:
+			error = '%s : string syntax is not valid, eg: <alpa>*<digit>+' %(item) 
+			raise PxeConfig, error
+
+        set_padding(binfo[id])	
 	
 def parse_args(argv, binfo):
@@ -419,4 +483,8 @@
 		sys.exit(1)
 
+	# init vars
+	#
+	hostrange = node = rack = None
+
 	# Check given options
 	#
@@ -459,9 +527,22 @@
 
 		elif opt in ['-H', '--host-range']:
-		 	parse_host_range(binfo, value)
+			hostrange = value
+
+		elif opt in ['-N', '--node']:
+			node = value
+
+		elif opt in ['-R', '--rack']:
+			rack = value
 			
 		elif opt in ['-V', '--version']:
 			print VERSION
 			sys.exit(0) 
+
+	if node and rack:
+		 	parse_string_range(binfo, node, NODE)
+		 	parse_string_range(binfo, rack, RACK)
+	elif hostrange:
+		 	parse_number_range(binfo, hostrange)
+		
 
 	check_args(binfo, args)
@@ -509,5 +590,35 @@
 
 	host_2_net(hostnames,binfo)
-		
+
+def rack_2_net(binfo):
+	"""
+	"""
+	basename = binfo[BASENAME]
+	start = binfo[RACK][START]
+	end = binfo[RACK][END]
+
+
+	if start > end:
+		error = '%d >= %d : start value is greater then end value' %(start, end)
+		raise PxeConfig, error
+
+	for i in xrange(start, end + 1):
+		if binfo[RACK][EQUALWIDTH][0] == True:
+			new_base = '%s%s%0*d' %(basename,  binfo[RACK][BASENAME], binfo[RACK][EQUALWIDTH][1], i)
+		else:
+			new_base = '%s%s%d' %(basename, binfo[RACK][BASENAME], i)
+
+		# Make copy and file in the appropiate values for creating/removing links
+		#
+		new_bootinfo = binfo[NODE].copy()
+		new_bootinfo[BASENAME] = '%s%s' %(new_base, binfo[NODE][BASENAME])
+		new_bootinfo[FILENAME] = binfo[FILENAME]
+		new_bootinfo[REMOVE] = binfo[REMOVE]
+
+		if DEBUG:
+			print 'rack ', new_bootinfo
+
+		base_2_net(new_bootinfo)
+
 def main():
 	# A dictionary holding the boot info
@@ -517,7 +628,9 @@
 	
 	bootinfo = {}
+	bootinfo[NODE] = None
+	bootinfo[RACK] = None
 	bootinfo[REMOVE] = False 
 	bootinfo[EQUALWIDTH] = [ False, 0 ]
-	
+
 	configfile = '@pxeconfig_conf@'
 	settings = ReadConfig(configfile) 
