#!/usr/bin/perl -w # Drakwizard PXE # release 0.2 # Copyright (C) 2003 Mandrakesoft # # Author: Antoine Ginies # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package MDK::Wizard::Pxe; use lib qw(/usr/lib/libDrakX); use strict; use common; use services; use MDK::Wizard::Wizcommon; my $wiz = new MDK::Wizard::Wizcommon; #my $INSTALLDIR = "/var/install/pxe"; #my $IA64PATH = '/IA64PC'; my $TMPDIR = '/tmp'; my $HOSTNAME = chomp_(`hostname`); my $TFTPDIR = "/var/lib/tftpboot"; my $CLIENTPATH = '/X86PC/linux'; my $X86 = $TFTPDIR . $CLIENTPATH; my $IMGPATH = $X86 . '/images'; my $PXEHELP = $X86 . '/help.txt'; my $PXEMESSAGE = $X86 . '/messages'; my $PXEDEFAULT = $X86 . '/pxelinux.cfg/default'; my $CONF = '/etc/pxe.conf'; my $SYSLINUXPATH = '/usr/lib/syslinux/'; my $MEMDISK = $SYSLINUXPATH . '/memdisk'; my $XINETDDIR = "/etc/xinetd.d"; my $o = { name => N("PXE Wizard (devel)"), var => { IMG => '/var/install/92/images/network.img', PXENAME => '92', DESCR => 'install 9.2', IMGTOREMOVE => '', IMGTOMODIFY => '', IP => '127.0.0.1', DIR => '/var/install/', i => '', }, needed_rpm => [ 'pxe', 'tftp-server', 'xinetd' ], }; my %level = ( 1 => N("PXE - Set PXE server"), 2 => N("add - Add image in PXE"), 3 => N("remove - remove image in PXE"), 4 => N("Modify - Modify image in PXE"), ); #($o->{var}{METHOD}, $o->{var}{IP}, $o->{var}{DIR}, $o->{var}{RAM}, $o->{var}{VGA}, $o->{var}{ACPI}, $o->{var}{APIC}); # to get list menu entry my @list_menu; foreach (cat_($PXEDEFAULT)) { my ($ent) = /# TAG: (\w+)_BEGIN/; ! $ent or push @list_menu,$ent; } #set default list for entry in syslinux.cfg my @list_method = qw(nfs http); my @list_ram = qw(32000 64000 1280000); my @list_vga = qw(788 normal 785 791 text); my @list_acpi = qw(ht force off); my @list_apic = qw(apic noapic); my @list_eth = qw(eth0 eth1 eth2); # to get list menu entry my @list_menu; foreach (cat_($PXEDEFAULT)) { my ($ent) = /# TAG: (\w+)_BEGIN/; ! $ent or push @list_menu,$ent; } #begin of wizard $o->{pages} = { welcome => { name => N("PXE wizard") . "\n\n" . N("Set a PXE server.") . "\n\n" . N("This wizard will help you configuring the PXE server. This configuration will provide a pxe service, and ability to add/remove/modify boot images."), no_back => 1, pre => sub { $o->{var}{wiz_level} ||= 1; }, post => sub { if ($o->{var}{wiz_level} == 2) { return 'addimg' } elsif ($o->{var}{wiz_level} == 3) { return 'removeimg' } elsif ($o->{var}{wiz_level} == 4) { return 'modifyimg' } }, data => [ { label => N("Which operation:"), val => \$o->{var}{wiz_level}, list => [ keys %level ], format => sub { $level{$_[0]} } }, ], no_back => 1, next => 'pxeserver', }, addimg => { name => N("Add a boot Image") . "\n\n" . N("Path to image: Full path to image (need network boot image)") . "\n\n" . N("PXE Name: Name in PXE menu (one word/number, no space)"), data => [ { label => "PXE Name:", val => \$o->{var}{PXENAME} }, { label => "PXE Description:", val => \$o->{var}{DESCR} }, { label => "Full Path to image:", val => \$o->{var}{IMG} }, ], post => \&test_data, next => 'summaryadd', }, removeimg => { name => N("Remove a boot Image") . "\n\n" . N("Which one ?"), data => [ { label => N("Which one:"), val => \$o->{var}{IMGTOREMOVE}, fixed_list => \@list_menu }, ], next => 'summaryremove', }, modifyimg => { name => N("Add Option to boot image") . "\n\n" . N("on which image ?"), data => [ { label => N("Which one:"), val => \$o->{var}{IMGTOMODIFY}, fixed_list => \@list_menu }, ], post => \&read_option, next => 'gomodify', }, gomodify => { name => N("Options to add to PXE boot disk"), data => [ { label => N("Image to modify"), fixed_val => \$o->{var}{i} }, { label => N("Server IP"), val => \$o->{var}{IP} }, { label => N("Install directory"), val => \$o->{var}{DIR} }, { label => N("Installation method"), val => \$o->{var}{METHOD}, fixed_list => \@list_method }, { label => N("Network Client Interface"), val => \$o->{var}{ETH}, fixed_list => \@list_eth }, { label => N("Ramsize"), val => \$o->{var}{RAM}, fixed_list => \@list_ram }, { label => N("VGA option"), val => \$o->{var}{VGA}, fixed_list => \@list_vga }, { label => N("Acpi option"), val => \$o->{var}{ACPI}, fixed_list => \@list_acpi }, { label => N("Apic option"), val => \$o->{var}{APIC}, fixed_list => \@list_apic }, ], next => 'summarymodify', }, pxeserver => { name => N("Set PXE server") . "\n\n" . N("We will use a special dhcpd.conf"), next => 'summaryserver', }, error_img => { name => N('Please provide a Bootable image...'), next => 'addimg', }, error_name => { name => N('Please provide a correct name in PXE entry (one word)'), next => 'addimg', }, simmilar_entry => { name => N('Similar Name is already used in PXE menu entry') . "\n\n" . N("Please provide another Pxe Menu Name"), next => 'addimg', }, summaryserver => { name => N('Now will prepapre all default files to get PXE server'), data => [ { label => N("Tftp directory"), fixed_val => \$TFTPDIR }, { label => N("Image path"), fixed_val => \$IMGPATH }, { label => N("PXE \'default\' file "), fixed_val => \$PXEDEFAULT }, { label => N("PXE \'help\' file"), fixed_val => \$PXEHELP }, ], post => \&do_it_pxe, next => 'endserver', }, summarymodify => { name => N('Now will Modify boot options in image'), data => [ { label => N("Image to Modify"), fixed_val => \$o->{var}{i} }, { label => N("Server IP"), fixed_val => \$o->{var}{IP} }, { label => N("Install directory"), fixed_val => \$o->{var}{DIR} }, { label => N("Installation method"), fixed_val => \$o->{var}{METHOD} }, { label => N("Network Client Interface"), fixed_val => \$o->{var}{ETH} }, { label => N("Ramsize"), fixed_val => \$o->{var}{RAM} }, { label => N("VGA option"), fixed_val => \$o->{var}{VGA} }, { label => N("Acpi option"), fixed_val => \$o->{var}{ACPI} }, { label => N("Apic option"), fixed_val => \$o->{var}{APIC} }, ], post => \&do_it_modify, next => 'endmodify', }, summaryremove => { name => N('Now will remove your PXE boot image'), data => [ { label => N("PXE entry to remove:"), fixed_val => \$o->{var}{IMGTOREMOVE} }, ], post => \&do_it_remove, next => 'endremove', }, summaryadd => { name => N('Now will add your PXe boot image'), data => [ { label => "PXE Name:", fixed_val => \$o->{var}{PXENAME} }, { label => "PXE Description:", fixed_val => \$o->{var}{DESCR} }, { label => "Path to image:", fixed_val => \$o->{var}{IMG} }, ], post => \&do_it_add, next => 'endadd', }, endadd => { name => N('Congratulations'), data => [ { label => N('The wizard successfully add a PXE image.') } ], next => 'welcome', }, endremove => { name => N('Congratulations'), data => [ { label => N('The wizard successfully remove a PXE image.') } ], next => 'welcome', }, endmodify => { name => N('Congratulations'), data => [ { label => N('The wizard successfully modify image(s).') } ], next => 'welcome', }, endserver => { name => N('Congratulations'), data => [ { label => N('The wizard successfully configured Your PXE server.') } ], no_back => 1, end => 1, next => 0 }, }; #cp memlinux from syslinux sub memlinux_prep { if (!-f "$X86/memdisk") { cp_af($MEMDISK, $X86); } } # test img and similar entry in PXE sub test_data { $o->{var}{PXENAME} =~ /^\w+$/ or return 'error_name'; if (!-f $o->{var}{IMG}) { return 'error_img' } if (any { /^$o->{var}{PXENAME}/ } cat_($PXEHELP)) { return 'simmilar_entry' } } # enable tftp server sub enable_tftps { substInFile { s/disable.*/disable = no/ } "$XINETDDIR/tftp"; } # can change option in tftp server sub tftp_blksize { # $o should be with W or not N my ($o) = @_; if ($o =~ /W/) { substInFile { s/server_args.*/server_args = -r blksize -s $TFTPDIR/ } "$XINETDDIR/tftp"; } else { substInFile { s/server_args.*/server_args = -s $TFTPDIR/ } "$XINETDDIR/tftp"; } } sub crea_wdir { if (-e $TMPDIR) { rm_rf($TMPDIR); } mkdir_p($TMPDIR); } # add TAGGED entry in PXE menu sub add_in_default { my ($NAME) = @_; if (!any { /${NAME}_BEGIN/ } cat_($PXEDEFAULT)) { append_to_file($PXEDEFAULT ,<{var}{PXENAME}, $o->{var}{DESCR}); add_in_default($o->{var}{PXENAME}); add_img($o->{var}{IMG}, $o->{var}{PXENAME}); } # main remove image sub do_it_remove { return if $::testing; remove_in_menu($o->{var}{IMGTOREMOVE}); remove_in_help($o->{var}{IMGTOREMOVE}); remove_img($o->{var}{IMGTOREMOVE}); } # get default option for an image sub read_option { my ($IMG) = $o->{var}{IMGTOMODIFY}; my $mount = "/tmp/loop_for_images"; mkdir_p($mount); system("mount $IMGPATH/$IMG.img $mount -o loop"); my $line = cat_("$mount/syslinux.cfg"); $o->{var}{i} = "$IMGPATH/$IMG.img"; ($o->{var}{METHOD}, $o->{var}{ETH}, $o->{var}{IP}, $o->{var}{DIR}, $o->{var}{RAM}, $o->{var}{VGA}, $o->{var}{ACPI}, $o->{var}{APIC}) = $line =~ /method:(nfs|http),interface:(eth0|eth1|eth2),network:dhcp,server:(.*?),directory:(.*?) ramdisk_size=(.*?) root=\/dev\/ram3 rw vga=(.*?)acpi=(ht|force|off)\s(apic|noapic)/; system("umount $mount"); if (-e $mount) { rm_rf($mount); } } # modify default boot option of an image sub do_it_modify { my ($IMG, $METHOD, $ETH, $IP, $DIR, $RAM, $VGA, $ACPI, $APIC) = ($o->{var}{IMGTOMODIFY}, $o->{var}{METHOD}, $o->{var}{ETH}, $o->{var}{IP}, $o->{var}{DIR}, $o->{var}{RAM}, $o->{var}{VGA}, $o->{var}{ACPI}, $o->{var}{APIC}); $o->{var}{i} = "$IMGPATH/$IMG.img"; return if $::testing; #APPEND initrd=images/ken/cooker/i586/isolinux/alt0/all.rdz automatic=method:nfs,interface:eth0,network:dhcp,server:192.168.100.7,directory:/c/cooker ramdisk_size=32000 root=/dev/ram3 rw vga=788 meta_class=discovery my $mount = "/tmp/loop_for_images"; mkdir_p($mount); system("mount $o->{var}{i} $mount -o loop"); output("$mount/syslinux.cfg", <vnew('su', 'PXE server'); my $w = $in->wait_message(N("PXE server"), N("Configuring PXE server on your system...")); mkdir_p($IMGPATH); memlinux_prep(); default_pxe_menu(); default_pxe_messages(); enable_tftps(); tftp_blksize('N'); map { system("service $_ restart"); $_ } qw(xinetd pxe); undef $w; } sub new { my ($class, $conf) = @_; bless { o => $o, }, $class; } 1;