#!/usr/bin/perl # # Copyright (C) 2004 by Mandrakesoft aginies _ateuh_ mandrakesoft.com # # 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. # Quick configuration of PXE menu parameters # release 0.5 # use with care developement release.... # thx R1 for test and some debug use lib qw(/usr/lib/libDrakX); use standalone; use strict; use common; use MDK::Common; use ugtk2 qw(:ask :helpers :wrappers :create :dialogs); use constant FALSE => 0; use constant TRUE => 1; # ie of entry menu in PXE: #label linux # KERNEL images/vmlinuz # APPEND initrd=images/all.rdz automatic=method:http,interface:eth0,network:dhcp,server:10.0.1.33,directory:/install/ ramdisk_size=64000 root=/dev/ram3 rw vga=788 display=:0 my $conf = "/var/lib/tftpboot/X86PC/linux/pxelinux.cfg/default"; #my $conf = "/tmp/tr"; my $help = " PXE Label: the name displayed in PXE menu (a word/number) Server: IP address of server, which contains installation directory Kernel: memdisk or vmlinuz Initrd: network boot image (network.img ) or all.rdz Interface: network interface used for the installation process Network: DHCP or an IP address Directory: full path to MDK install server directory Method: installation method: choose NFS or HTTP Ramsize: ramsize parameter on boot disk Display: export display on another computer (ie: 10.0.1.33:0) VGA: if you encounter any problem with VGA, please adjust "; my $date = chomp_(`date +%d-%m-20%y`); if (!-f $conf) { err_dialog("Error !", "missing $conf\n\nPlease install pxe package.") and die; } else { cp_af($conf, "$conf-$date"); } my @listpxe; my @list_method = qw(nfs http); my @list_ram = qw(48000 32000 64000 1280000); my @list_vga = qw(788 normal 785 791 792 text); my @list_eth = qw(eth0 eth1 eth2); use constant COLUMN_LABEL => 0; use constant COLUMN_INFO => 1; use constant COLUMN_KERNEL => 2; use constant COLUMN_INITRD => 3; use constant COLUMN_AUTOMATIC => 4; use constant COLUMN_INTERFACE => 5; use constant COLUMN_NETWORK => 6; use constant COLUMN_SERVER => 7; use constant COLUMN_DIRECTORY => 8; use constant COLUMN_RAMDISK => 9; use constant COLUMN_VGA => 10; use constant COLUMN_DISPLAY => 11; use constant COLUMN_OPTION => 12; use constant NUM_COLUMNS => 13; sub get_items() { my $info; my $label; my $kernel; my $initrd; foreach (cat_($conf)) { if (any { /^label/ } cat_($conf)) { if (/^label/) { ($label) = /^label\s(.*)/ } if (/KERNEL/) { ($kernel) = /KERNEL\s(.*)/ } my ($initrd, $automatic, $interface, $network, $server, $directory, $ramdisk, $vga, $display) = m!\s*APPEND\sinitrd=(.*?rdz)\s\bautomatic=method\b:(nfs|http),interface:(eth0|eth1|eth2),network:(dhcp|10.0.1.33),server:(.*?),directory:(.*?)\s\bramdisk_size\b=(.*?)\sroot=/dev/ram3\srw\svga=(.*?)\sdisplay=(.*?)\s!; # in case of parameter not on this order (previous pxe default file) $initrd or my ($init) = m!\s*APPEND\s\binitrd\b=(.*?)\s!; $ramdisk or my ($ramdis) = m!\bramdisk_size\b=(\d+)\s!; $automatic or my ($automati) = m!\bautomatic\b=method:(nfs|http)!; $vga or my ($vg) = m!\bvga\b=(.*?)\s!; $display or my ($displa) = m!\bdisplay\b=(.*?)\s!; $interface or my ($interfac) = m!\binterface\b:(eth0|eth1|eth2)!; $network or my ($networ) = m!\bnetwork\b:(dhcp|10.0.1.33)!; $server or my ($serve) = m!\bserver\b:(.*?),!; $directory or my ($director) = m!\bdirectory\b:(.*?)\s!; my $information = "$label $automati"; my $initall; my $ramdiskall; my $autoall; my $vgaall; my $displayall; my $interfaceall; my $networkall; my $serverall; my $directoryall; if ($initrd) { $initall = $initrd } else { $initall = $init } if ($ramdisk) { $ramdiskall = $ramdisk } else { $ramdiskall = $ramdis } if ($automatic) { $autoall = $automatic } else { $autoall = $automati } if ($vga) { $vgaall = $vga } else { $vgaall = $vg } if ($display) { $displayall = $display } else { $displayall = $displa } if ($interface) { $interfaceall = $interface } else { $interfaceall = $interfac } if ($network) { $networkall = $network } else { $networkall = $networ } if ($server) { $serverall = $server } else { $serverall = $serve } if ($directory) { $directoryall = $directory } else { $directoryall = $director } my ($allopt) = m!\s*APPEND\s(.*)!; my ($autocomp) = m!\bautomatic\b=(.*?)\s!; my ($devram) = m!root=/dev/ram3\srw!; my $optionsall = join(' ', grep { ! /$devram/ and ! /initrd=$initall/ and ! /display=$displayall/ and ! /ramdisk_size=$ramdiskall/ and ! /automatic=$autocomp/ and ! /vga=$vgaall/ } split(' ', $allopt)); if ($label and $kernel and $initall) { push @listpxe, { label => $label, info => $information, kernel => $kernel, initrd => $initall, automatic => $autoall, interface => $interfaceall, network => $networkall, server => $serverall, directory => $directoryall, ramdisk => $ramdiskall, vga => $vgaall, display => $displayall, option => $optionsall, },; } } } } sub list_label_pxe() { my @labels; foreach (cat_($conf)) { my ($label) = /label\s(.*)/; $label and push @labels, $label; } @labels; } sub set_new_default { my ($default) = @_; substInFile { s/^DEFAULT.*/DEFAULT $default/; } $conf; } sub get_default_pxe { my ($defaultpxe) = cat_($conf) =~ /DEFAULT\s+(\S+)/; return $defaultpxe; } sub get_default_prompt() { my ($prompt) = cat_($conf) =~ /^PROMPT\s(\d+)/; return $prompt; } sub get_default_timeout() { my ($time) = cat_($conf) =~ /^TIMEOUT\s(\d+)/; return $time; } sub write_conf_pxe { my $default = get_default_pxe; my $prompt = get_default_prompt; my $time = get_default_timeout; output($conf, <{interface}) { append_to_file($conf, " label $a->{label} KERNEL $a->{kernel} APPEND initrd=$a->{initrd} automatic=method:$a->{automatic},interface:$a->{interface},network:$a->{network},server:$a->{server},directory:$a->{directory} ramdisk_size=$a->{ramdisk} root=/dev/ram3 rw vga=$a->{vga} display=$a->{display} "); } else { append_to_file($conf, " label $a->{label} KERNEL $a->{kernel} APPEND initrd=$a->{initrd} "); } } } sub create_model { get_items(); my $model = Gtk2::ListStore->new(("Glib::String") x13); foreach my $a (@listpxe) { my $iter = $model->append; $model->set($iter, COLUMN_LABEL, $a->{label}, COLUMN_INFO, $a->{info}, COLUMN_KERNEL, $a->{kernel}, COLUMN_INITRD, $a->{initrd}, COLUMN_AUTOMATIC, $a->{automatic}, COLUMN_INTERFACE, $a->{interface}, COLUMN_NETWORK, $a->{network}, COLUMN_SERVER, $a->{server}, COLUMN_DIRECTORY, $a->{directory}, COLUMN_RAMDISK, $a->{ramdisk}, COLUMN_VGA, $a->{vga}, COLUMN_DISPLAY, $a->{display}, COLUMN_OPTION, $a->{option}, ), } return $model; } sub add_item { my ($button, $model) = @_; my @a; push @a, { label => "cooker", info => "install cooker", kernel => "/images/cooker", initrd => "cooker.rdz", automatic => "http", interface => "eth0", network => "dhcp", server => "10.0.1.33", directory => "/install/cooker", ramdisk => "64000", vga => "788", display => ":0", option => "acpi=ht", }; my $iter = $model->append; $model->set($iter, COLUMN_LABEL, $a[-1]{label}, COLUMN_INFO, $a[-1]{info}, COLUMN_KERNEL, $a[-1]{kernel}, COLUMN_INITRD, $a[-1]{initrd}, COLUMN_AUTOMATIC, $a[-1]{automatic}, COLUMN_INTERFACE, $a[-1]{interface}, COLUMN_NETWORK, $a[-1]{network}, COLUMN_SERVER, $a[-1]{server}, COLUMN_DIRECTORY, $a[-1]{directory}, COLUMN_RAMDISK, $a[-1]{ramdisk}, COLUMN_VGA, $a[-1]{vga}, COLUMN_DISPLAY, $a[-1]{display}, COLUMN_OPTION, $a[-1]{option}, ); # write_conf_pxe; } sub remove_item { my ($widget, $treeview) = @_; my $model = $treeview->get_model; my $selection = $treeview->get_selection; my $iter = $selection->get_selected; if ($iter) { my $path = $model->get_path($iter); my $i = ($path->get_indices)[0]; ask_okcancel("Remove $listpxe[$i]{label} PXE entry ?") or return; $model->remove($iter); splice @listpxe, $i, 1; } write_conf_pxe; } sub edit_box_item { my ($widget, $treeview) = @_; my $model = $treeview->get_model; my $selection = $treeview->get_selection; my $iter = $selection->get_selected; if ($iter) { my $path = $model->get_path($iter); my $i = ($path->get_indices)[0]; my $dialog = new Gtk2::Dialog(); $dialog->set_modal(1); $dialog->set_resizable(FALSE); my $label = Gtk2::Entry->new; $label->set_text($listpxe[$i]{label}); my $info = Gtk2::Entry->new; $info->set_text($listpxe[$i]{info}); my $kernel = Gtk2::Entry->new; $kernel->set_text($listpxe[$i]{kernel}); # file selection for kernel my $file_dialogk = new Gtk2::FileSelection("File Selection"); $file_dialogk->set_modal(TRUE); $file_dialogk->signal_connect("destroy", sub { $file_dialogk->hide }); $file_dialogk->ok_button->signal_connect(clicked => sub { my $file = $file_dialogk->get_filename; $kernel->set_text($file); $file_dialogk->hide; }, $file_dialogk); $file_dialogk->cancel_button->signal_connect(clicked => sub { $file_dialogk->hide }); # button kernel my $buttonkernel = Gtk2::Button->new("Select kernel"); $buttonkernel->signal_connect(clicked => sub { $file_dialogk->show }); my $initrd = Gtk2::Entry->new; $initrd->set_text($listpxe[$i]{initrd}); # file selection for initrd my $file_dialog = new Gtk2::FileSelection("File Selection"); $file_dialog->set_modal(TRUE); $file_dialog->signal_connect("destroy", sub { $file_dialog->hide }); $file_dialog->ok_button->signal_connect(clicked => sub { my $filei = $file_dialog->get_filename; $initrd->set_text($filei); $file_dialog->hide; }, $file_dialog); $file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->hide }); my $buttoninitrd = Gtk2::Button->new("Select initrd"); $buttoninitrd->signal_connect(clicked => sub { $file_dialog->show }); # combo box to pop down automatic installation my $automatic = Gtk2::Combo->new; $automatic->set_popdown_strings(@list_method); $automatic->entry->set_text($listpxe[$i]{automatic}); # combo box to pop down list of network interface my $interface = new Gtk2::Combo(); $interface->set_popdown_strings(@list_eth); $interface->entry->set_text($listpxe[$i]{interface}); my $network = Gtk2::Entry->new; $network->set_text($listpxe[$i]{network}); my $server = Gtk2::Entry->new; $server->set_text($listpxe[$i]{server}); my $directory = Gtk2::Entry->new; $directory->set_text($listpxe[$i]{directory}); my $ramdisk = new Gtk2::Combo(); $ramdisk->set_popdown_strings(@list_ram); $ramdisk->entry->set_text($listpxe[$i]{ramdisk}); my $vga = new Gtk2::Combo(); $vga->set_popdown_strings(@list_vga); $vga->entry->set_text($listpxe[$i]{vga}); my $display = Gtk2::Entry->new; $display->set_text($listpxe[$i]{display}); my $option = Gtk2::Entry->new; $option->set_text($listpxe[$i]{option}); my %size_groups = map { $_ => Gtk2::SizeGroup->new('horizontal') } qw(label widget button); my $label_and_widgets = sub { my ($label, $widget, $button) = @_; gtkpack_(Gtk2::HBox->new(0,5), 0, gtkadd_widget($size_groups{label}, $label), 1, gtkadd_widget($size_groups{widget}, $widget), 2, gtkadd_widget($size_groups{button}, $button), ); }; gtkpack_($dialog->vbox, 0, gtkadd(Gtk2::Frame->new(("Descrition")), gtkpack_(Gtk2::VBox->new, 0, $label_and_widgets->(N("Label"), $label, ""), 0, $label_and_widgets->(N("Info"), $info, ""), ), ), 0, gtkadd(Gtk2::Frame->new(("Boot image")), gtkpack_(Gtk2::VBox->new, 0, $label_and_widgets->(N("Kernel"), $kernel, $buttonkernel), 0, $label_and_widgets->(N("Initrd"), $initrd, $buttoninitrd), ), ), 0, gtkadd(Gtk2::Frame->new(("Automatic Options")), gtkpack_(Gtk2::VBox->new, 0, $label_and_widgets->(N("Automatic"), $automatic, ""), 0, $label_and_widgets->(N("Interface"), $interface, ""), 0, $label_and_widgets->(N("Network"), $network, ""), 0, $label_and_widgets->(N("Server"), $server, ""), 0, $label_and_widgets->(N("Directory"), $directory, ""), ), ), 0, gtkadd(Gtk2::Frame->new(("Display")), gtkpack_(Gtk2::VBox->new, 0, $label_and_widgets->(N("Vga"), $vga, ""), 0, $label_and_widgets->(N("Display"), $display, ""), ), ), 0, gtkadd(Gtk2::Frame->new(("Other options")), gtkpack_(Gtk2::VBox->new, 0, $label_and_widgets->(N("Ramdisk"), $ramdisk, ""), 0, $label_and_widgets->(N("Option"), $option, ""), ), ), 0, create_okcancel({ cancel_clicked => sub { $dialog->destroy }, ok_clicked => sub { #ask_okcancel("are you sure you want to update all those values ?"); $listpxe[$i]{label} = $label->get_text; $listpxe[$i]{info} = $info->get_text; $listpxe[$i]{kernel} = $kernel->get_text; $listpxe[$i]{initrd} = $initrd->get_text; $listpxe[$i]{automatic} = $automatic->entry->get_text; $listpxe[$i]{interface} = $interface->entry->get_text; $listpxe[$i]{network} = $network->get_text; $listpxe[$i]{server} = $server->get_text; $listpxe[$i]{directory} = $directory->get_text; $listpxe[$i]{ramdisk} = $ramdisk->entry->get_text; $listpxe[$i]{vga} = $vga->entry->get_text; $listpxe[$i]{display} = $display->get_text; $listpxe[$i]{option} = $option->get_text; # update value in cells $model->set($iter, COLUMN_LABEL, $listpxe[$i]{label}, COLUMN_INFO, $listpxe[$i]{info}, COLUMN_KERNEL, $listpxe[$i]{kernel}, COLUMN_INITRD, $listpxe[$i]{initrd}, COLUMN_AUTOMATIC, $listpxe[$i]{automatic}, COLUMN_INTERFACE, $listpxe[$i]{interface}, COLUMN_NETWORK, $listpxe[$i]{network}, COLUMN_SERVER, $listpxe[$i]{server}, COLUMN_DIRECTORY, $listpxe[$i]{directory}, COLUMN_RAMDISK, $listpxe[$i]{ramdisk}, COLUMN_VGA, $listpxe[$i]{vga}, COLUMN_DISPLAY, $listpxe[$i]{display}, COLUMN_OPTION, $listpxe[$i]{option}, ); $dialog->destroy; write_conf_pxe; }, }, ), ); $dialog->show_all; } } sub cell_edited { my ($cell, $path_string, $new_text, $model) = @_; my $path = Gtk2::TreePath->new_from_string($path_string); my $column = $cell->get_data("column"); my $iter = $model->get_iter($path); if ($column == COLUMN_LABEL) { my $i = ($path->get_indices)[0]; $listpxe[$i]{label} = $new_text; $model->set($iter, $column, $listpxe[$i]{label}); } elsif ($column == COLUMN_INFO) { my $i = ($path->get_indices)[0]; $listpxe[$i]{info} = $new_text; $model->set($iter, $column, $listpxe[$i]{info}); } elsif ($column == COLUMN_KERNEL) { my $i = ($path->get_indices)[0]; if (-f $new_text) { $listpxe[$i]{kernel} = $new_text; $model->set($iter, $column, $listpxe[$i]{kernel}); } } elsif ($column == COLUMN_INITRD) { my $i = ($path->get_indices)[0]; if (-f $new_text) { $listpxe[$i]{initrd} = $new_text; $model->set($iter, $column, $listpxe[$i]{initrd}); } } elsif ($column == COLUMN_AUTOMATIC) { my $i = ($path->get_indices)[0]; if (!member($new_text, @list_method) or ($listpxe[$i]{kernel} =~ /memdisk/)) { return; } else { $listpxe[$i]{automatic} = $new_text; $model->set($iter, $column, $listpxe[$i]{automatic}); } } elsif ($column == COLUMN_INTERFACE) { my $i = ($path->get_indices)[0]; if (member($new_text, @list_eth) or ($listpxe[$i]{kernel} != /memdisk/)) { $listpxe[$i]{interface} = $new_text; $model->set($iter, $column, $listpxe[$i]{interface}); } } elsif ($column == COLUMN_NETWORK) { my $i = ($path->get_indices)[0]; if ($listpxe[$i]{kernel} != /memdisk/) { $listpxe[$i]{network} = $new_text; $model->set($iter, $column, $listpxe[$i]{network}); } } elsif ($column == COLUMN_SERVER) { my $i = ($path->get_indices)[0]; if ($listpxe[$i]{kernel} != /memdisk/) { $listpxe[$i]{server} = $new_text; $model->set($iter, $column, $listpxe[$i]{server}); } } elsif ($column == COLUMN_DIRECTORY) { my $i = ($path->get_indices)[0]; if (-d $new_text || ($listpxe[$i]{kernel} != /memdisk/)) { $listpxe[$i]{directory} = $new_text; $model->set($iter, $column, $listpxe[$i]{directory}); } } elsif ($column == COLUMN_RAMDISK) { my $i = ($path->get_indices)[0]; if (member($new_text, @list_ram) || ($listpxe[$i]{kernel} != /memdisk/)) { $listpxe[$i]{ramdisk} = $new_text; $model->set($iter, $column, $listpxe[$i]{ramdisk}); } } elsif ($column == COLUMN_VGA) { my $i = ($path->get_indices)[0]; if (member($new_text, @list_vga) || ($listpxe[$i]{kernel} != /memdisk/)) { $listpxe[$i]{vga} = $new_text; $model->set($iter, $column, $listpxe[$i]{vga}); } } elsif ($column == COLUMN_DISPLAY) { my $i = ($path->get_indices)[0]; if ($listpxe[$i]{kernel} != /memdisk/) { $listpxe[$i]{display} = $new_text; $model->set($iter, $column, $listpxe[$i]{display}); } } elsif ($column == COLUMN_OPTION) { my $i = ($path->get_indices)[0]; $listpxe[$i]{option} = $new_text; $model->set($iter, $column, $listpxe[$i]{option}); } write_conf_pxe; } sub show_help { info_dialog("Help", $help) } sub add_columns { my $treeview = shift; my $model = $treeview->get_model; # horrible hack to avoid: GLib-GObject-CRITICAL **: file gobject.c: line 1019 (g_object_set_property): assertion `G_IS_VALUE (value)' failed at drakpxe2.pl line 640. my $t = "0"; my @j = qw/Label Info Kernel Initrd Method Interface Network Server Directory Ramdisk vga Display Extra Options/; each_index { my $renderer = Gtk2::CellRendererText->new; $renderer->set(editable => 1); $renderer->signal_connect(edited => \&cell_edited, $model); $renderer->set_data(column => $::i); $treeview->insert_column_with_attributes(-1, $j[$t], $renderer, 'text' => $::i); $t++; } (qw/x x x x x x x x x x x x x/); #(("Label"), ("Info"), ("Kernel"), ("Initrd"), ("Method"), ("Interface"), ("Network"), ("Server"), ("Directory"), ("Ramdisk"), ("vga"), ("Display"), ("Extra"), ("Options")); } # # Main # create model my $model = create_model(); my $window = ugtk2->new('Drakpxe2'); $window->{rwindow}->set_size_request(800, 400) unless $::isEmbedded; my $W = $window->{window}; $W->signal_connect(delete_event => sub { ugtk2->exit }); my $treeview = Gtk2::TreeView->new_with_model($model); $treeview->set_rules_hint(TRUE); $treeview->get_selection->set_mode('single'); add_columns($treeview); my $labels = new Gtk2::Combo(); my @labels = list_label_pxe; my $defaultlabel = get_default_pxe; $labels->entry->set_text("$defaultlabel"); $labels->entry->signal_connect("changed", sub { list_label_pxe; my $new_default = $labels->entry->get_text; set_new_default($new_default); } ); $labels->set_popdown_strings(@labels); $labels->entry->set_text("$defaultlabel"); $W->add(gtkpack_(Gtk2::VBox->new(0,0), 0, Gtk2::Banner->new('wiz_default_up', ("DrakPXE default configuration file")), 1, create_scrolled_window($treeview), 0, gtkadd(gtkset_border_width(Gtk2::VBox->new, 0,0), gtkadd(Gtk2::HBox->new(0,0), $labels, gtkpack(gtkset_layout(new Gtk2::HButtonBox, 'spread'), 0, (map { my ($label, $sub, $widg) = @$_; gtksignal_connect(Gtk2::Button->new($label), clicked => sub { $sub->($model, $widg); }) } ([ ("Help"), \&show_help ], [ ("Add a PXE entry"), \&add_item, $model ], [ ("Remove PXE entry"), \&remove_item, $treeview ], [ ("Edit a PXE entry"), \&edit_box_item, $treeview ], ) ), ), ), ), ), ); $W->show_all; Gtk2->main;