mirror of
				https://github.com/xcat2/xNBA.git
				synced 2025-10-31 03:12:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			201 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/perl -w
 | |
| #
 | |
| # $Id$
 | |
| # Maintains set of NBIs based on currently-installed kernels
 | |
| # Network card module sets are taken from /etc/mknbi-set.conf
 | |
| 
 | |
| use strict;
 | |
| use vars qw($verbosity);
 | |
| 
 | |
| use constant EB_PCI_DEVICE => 1;
 | |
| 
 | |
| # Utility function: calculate output id given a kernel file name and
 | |
| # space-separated list of modules
 | |
| sub calc_output_id ($$) {
 | |
|   my $kernel = shift;
 | |
|   my $moduleset = shift;
 | |
|   my $kernel_ver = "";
 | |
|   ( $kernel_ver ) = ( $kernel =~ /vmlinuz-(.*)$/ );
 | |
|   ( my $output_id = "$moduleset".( $kernel_ver ? ".$kernel_ver" : "" ) ) =~ tr/,/./;
 | |
|   return ( $kernel_ver, $output_id );
 | |
| }
 | |
| 
 | |
| # Utility function: read modules.pcimap-style file
 | |
| # Add modules to modulesets hash, write out dhcpd.conf fragment
 | |
| sub read_config_file ($$$$) {
 | |
|   my $configfile = shift;
 | |
|   my $modulesets = shift;
 | |
|   my $dhcpfh = shift;
 | |
|   my $alwaysuse = shift;
 | |
| 
 | |
|   print "Scanning through $configfile for network modules...\n" if $verbosity >= 1;
 | |
|   open CF, $configfile or die "Could not open $configfile: $!\n";
 | |
|   chomp ( my $tempmodule = `mktemp /tmp/mknbi-set.XXXXXX` );
 | |
|   chomp ( my $cwd = `pwd` ); chdir '/'; # Modprobe searches the current directory...
 | |
|   print $dhcpfh "    \# Generated from $configfile\n";
 | |
|   while (<CF>) {
 | |
|     chomp;
 | |
|     next if /^[\#;]/ or /^\s*$/;
 | |
|     ( my $module, undef, my $vendor, my $device ) = /^(\S+)(\s+(\S+)\s+(\S+))?/ ;
 | |
|     $modulesets->{$module} = 1 if $alwaysuse;
 | |
|     if ( ! exists $modulesets->{$module} ) {
 | |
|       # Check to see if module is a network module
 | |
|       # Only do this the first time we encounter a module
 | |
|       my @modulepaths = `/sbin/modprobe -l $module.o*` ;
 | |
|       chomp ( my $modulepath = $modulepaths[0] );
 | |
|       if ( $modulepath ) {
 | |
| 	if ( $modulepath =~ /.o.gz$/ ) {
 | |
| 	  system ( "zcat $modulepath > $tempmodule" );
 | |
| 	} else {
 | |
| 	  system ( "cp $modulepath $tempmodule" );
 | |
| 	}
 | |
| 	$modulesets->{$module} = 0;
 | |
| 	foreach ( `nm $tempmodule` ) {
 | |
| 	  chomp;
 | |
| 	  $modulesets->{$module} = 1 if /(ether|wlan)/ ;
 | |
| 	}
 | |
| 	unlink $tempmodule;
 | |
|       } else {
 | |
| 	print STDERR "Cannot locate module $module specified in $configfile\n";
 | |
|       }
 | |
|     }
 | |
|     if ( $modulesets->{$module} ) {
 | |
|       if ( $vendor ) {
 | |
| 	print "$module ($vendor,$device) listed in $configfile\n" if $verbosity >= 2;
 | |
| 	printf $dhcpfh ( "    if option etherboot.nic-dev-id = %02x:%02x:%02x:%02x:%02x { option etherboot.kmod \"%s\"; }\n",
 | |
| 			 EB_PCI_DEVICE,
 | |
| 			 ( hex($vendor) >> 8 ) & 0xff, hex($vendor) & 0xff,
 | |
| 			 ( hex($device) >> 8 ) & 0xff, hex($device) & 0xff,
 | |
| 			 $module );
 | |
|       } else {
 | |
| 	print "$module (without PCI IDs) listed in $configfile\n" if $verbosity >= 2;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   close CF;
 | |
|   print $dhcpfh "\n";
 | |
|   chdir $cwd;
 | |
| }
 | |
| 
 | |
| my $conffile = '/etc/mknbi-set.conf';
 | |
| my $mkinitrd_net = 'mkinitrd-net';
 | |
| my $mknbi = 'mknbi-linux';
 | |
| my $output_dir = '/var/lib/tftpboot';
 | |
| my $dhcpfile = '/etc/dhcpd.conf.etherboot-pcimap.include';
 | |
| my $use_local;
 | |
| our $verbosity = 1;
 | |
| my $modulesets = {};
 | |
| my $kernel = '';
 | |
| my @kernels = ();
 | |
| 
 | |
| my $usage="Usage: $0 [-l|--local] [-q] [-v] [-r|--refresh module[,module...]] [--help]";
 | |
| 
 | |
| # Parse command-line options
 | |
| while ( $_ = shift ) {
 | |
|   if ( /-l|--local/ ) {
 | |
|     $conffile = 'mknbi-set.conf';
 | |
|     $mkinitrd_net = './mkinitrd-net';
 | |
|     $mknbi = './mknbi-linux --format=nbi --target=linux';
 | |
|     $output_dir = 'tftpboot';
 | |
|     $dhcpfile = 'tftpboot/dhcpd.conf.etherboot-pcimap.include';
 | |
|     $use_local = 1;
 | |
|   } elsif ( /-r|--refresh/ ) {
 | |
|     my $moduleset = shift;
 | |
|     $modulesets->{$moduleset} = 1;
 | |
|   } elsif ( /-k|--kernel/ ) {
 | |
|     $kernel = shift;
 | |
|   } elsif ( /-v|--verbose/ ) {
 | |
|     $verbosity++;
 | |
|   } elsif ( /-q|--quiet/ ) {
 | |
|     $verbosity--;
 | |
|   } elsif ( /--help/ ) {
 | |
|     die "$usage\n".
 | |
| 	"  -k, --kernel   Build NBIs for a particular kernel\n".
 | |
|         "  -l, --local    Run locally from CVS (for developers only)\n".
 | |
| 	"  -r, --refresh  Refresh NBI for a particular module\n".
 | |
| 	"  -v, --verbose  Be more verbose\n".
 | |
| 	"  -q, --quiet    Be less verbose\n";
 | |
|   } else {
 | |
|     die "$usage\n";
 | |
|   }
 | |
| }
 | |
| 
 | |
| # Get set of current kernels
 | |
| if ($kernel) {
 | |
|   @kernels = ( $kernel );
 | |
| } else {
 | |
|   @kernels = glob('/boot/vmlinuz*');
 | |
| }
 | |
| die "Could not find any kernels in /boot\n" unless @kernels;
 | |
| 
 | |
| # If modules have been specified via --refresh, do not scan for modules or rewrite the
 | |
| # dhcpd.conf fragment file
 | |
| unless ( %$modulesets ) {
 | |
|   # Write dhcpd.conf fragment file
 | |
|   open my $dhcpfh, ">$dhcpfile" or die "Could not open $dhcpfile for writing: $!\n";
 | |
|   print $dhcpfh "# Etherboot PCI ID -> Linux kernel module mapping file\n";
 | |
|   print $dhcpfh "# Generated by mknbi-set on ".(scalar localtime)."\n";
 | |
|   print $dhcpfh "#\n";
 | |
|   print $dhcpfh "if substring ( option vendor-class-identifier, 0, 9 ) = \"Etherboot\" {\n";
 | |
|   print $dhcpfh "  if exists etherboot.nic-dev-id {\n";
 | |
|   print $dhcpfh "    \# Legacy nic-dev-id mechanism: there are some DLink DFE538 cards in circulation that\n";
 | |
|   print $dhcpfh "    \# predated the change to the new nic-dev-id binary structure\n";
 | |
|   print $dhcpfh "    if option etherboot.nic-dev-id = \"PCI:1186:1300\" { option etherboot.kmod \"8139too\"; }\n";
 | |
|   print $dhcpfh "\n";
 | |
| 
 | |
|   # Get set of network modules to build NBIs for
 | |
|   # Read explicitly-specified module sets from $conffile
 | |
|   read_config_file($conffile, $modulesets, $dhcpfh, 1);
 | |
|   # Obtain list of all network modules from pcimap file
 | |
|   my $pcimap;
 | |
|   foreach ( `/sbin/modprobe -c` ) {
 | |
|     $pcimap = $1 if /^pcimap.*?=(.*)$/;
 | |
|   }
 | |
|   if ( $pcimap ) {
 | |
|     read_config_file($pcimap, $modulesets, $dhcpfh, 0);
 | |
|   } else {
 | |
|     print STDERR "Could not identify pcimap file\n";
 | |
|   }
 | |
|   # Finish off dhcpd.conf fragment file
 | |
|   print $dhcpfh "  }\n}\n";
 | |
|   close $dhcpfh;
 | |
| }
 | |
| 
 | |
| # Build initrd and nbi for each kernel-moduleset combination
 | |
| foreach my $moduleset ( sort keys %$modulesets ) {
 | |
|   next unless $modulesets->{$moduleset}; # Ignore if value is 0
 | |
|   print "Building NBIs for module set $moduleset\n" if $verbosity >= 1;
 | |
|   foreach my $kernel ( @kernels ) {
 | |
|     ( my $kernel_ver, my $output_id ) = calc_output_id ( $kernel, $moduleset );
 | |
|     if ( -l $kernel ) {
 | |
|       # Symbolic link; create matching symlink
 | |
|       my $real_kernel = readlink ( $kernel );
 | |
|       ( my $real_kernel_ver, my $real_output_id ) = calc_output_id ( $real_kernel, $moduleset );
 | |
|       print "Symlinking $output_id to $real_output_id\n" if $verbosity >= 2;
 | |
|       my $initrd_file = "$output_dir/initrd-$output_id.img";
 | |
|       unlink ( $initrd_file ) if -l $initrd_file;
 | |
|       system ( "ln -s initrd-$real_output_id.img $initrd_file" ) == 0 or print STDERR "Could not symlink $initrd_file to initrd-$real_output_id.img: $!\n";
 | |
|       my $nbi_file = "$output_dir/boot-$output_id.nbi";
 | |
|       unlink ( $nbi_file ) if -l $nbi_file;
 | |
|       system ( "ln -s boot-$real_output_id.nbi $nbi_file" ) == 0 or print STDERR "Could not symlink $nbi_file to boot-$real_output_id.nbi: $!\n";
 | |
|     } else {
 | |
|       # Real file: create initrd and nbi
 | |
|       print "Creating initrd and nbi for $output_id\n" if $verbosity >= 2;
 | |
|       ( my $moduleset_spaces = $moduleset ) =~ tr/,/ /;
 | |
|       my $initrd_cmd = "$mkinitrd_net --nolink ".
 | |
| 	  ( $use_local ? "--local " : "" ).
 | |
| 	      ( $kernel_ver ? "--kernel $kernel_ver " : "" ).
 | |
| 		  ( $verbosity >= 2 ? "" : "-q " ).
 | |
| 		      $moduleset_spaces;
 | |
|       print "$initrd_cmd\n" if $verbosity >= 3;
 | |
|       if ( system ( $initrd_cmd ) == 0 ) {
 | |
| 	my $mknbi_cmd = "$mknbi $kernel $output_dir/initrd-$output_id.img > $output_dir/boot-$output_id.nbi";
 | |
| 	print "$mknbi_cmd\n" if $verbosity >= 3;
 | |
| 	system ( $mknbi_cmd ) == 0 or print STDERR "mknbi failed: $!\n";
 | |
|       } else {
 | |
| 	print STDERR "$initrd_cmd failed: $!\n";
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 |