/[soft]/drakpxelinux/trunk/drakpxelinux.pl
ViewVC logotype

Contents of /drakpxelinux/trunk/drakpxelinux.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 412 - (show annotations) (download)
Thu Feb 3 20:40:29 2011 UTC (13 years, 2 months ago) by ahmad
File MIME type: text/plain
File size: 48927 byte(s)
- Mageia Linux => Mageia
1 #!/usr/bin/perl
2 #
3 # Copyright (C) 2004-2005 by Mandriva aginies _ateuh_ mandriva.com
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2, or (at your option)
8 # any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 # 02111-1307, USA.
19
20 # Quick configuration of PXE menu parameters
21 # thx R1 for test and some debug
22 # svn.mandriva.com/svn/soft/drakpxelinux
23
24
25 # i18n: IMPORTANT: to get correct namespace (drakpxelinux instead of libDrakX)
26 BEGIN { unshift @::textdomains, 'drakpxelinux' }
27
28 use lib qw(/usr/lib/libDrakX);
29 use standalone;
30 use strict;
31 use common;
32 use services;
33 use network::network;
34 use network::pxe;
35 use network::tools;
36 use interactive;
37 # must come *after* definition of textdomains for proper initialisation
38 use ugtk2 qw(:ask :helpers :wrappers :create :dialogs);
39 use mygtk2 qw(gtknew);
40 use Gtk2::SimpleList;
41 use Gtk2::Helper;
42 use run_program;
43 use Data::Dumper;
44
45 our $model = create_model();
46 our $treeview = Gtk2::TreeView->new_with_model($model);
47
48 # ie of entry menu in PXE:
49 #label linux
50 # KERNEL images/vmlinuz
51 # 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
52
53 # default VAR
54 my $SYSLINUXPATH = '/usr/lib/syslinux/';
55 my $MEMDISK = $SYSLINUXPATH . '/memdisk';
56 my $XINETDDIR = "/etc/xinetd.d";
57 my $conf_mac_profiles_name = "/var/lib/tftpboot/X86PC/conf_mac_profiles";
58
59 my $net = {};
60 network::network::read_net_conf($net);
61
62 my $sys_wizard_pxe = "/etc/sysconfig/drak_pxe";
63 my ($interface) = cat_($sys_wizard_pxe) =~ /INTERFACE=(.*)/;
64 $interface ||= $net->{net_interface};
65 link_default_path();
66
67 my $help = "" .
68 N("PXE Label: the name to be displayed in the PXE menu (an ASCII word/number)") . "\n" .
69 N("Server: IP address of server, that contains the installation directory") . "\n" .
70 N("Kernel: memdisk or vmlinuz") . "\n" .
71 N("Initrd: network boot image (network.img) or all.rdz") . "\n" .
72 N("Interface: network interface used for the installation process") . "\n" .
73 N("Network: DHCP or an IP address") . "\n" .
74 N("Directory: full path to Mageia install server directory") . "\n" .
75 N("Installation method: NFS or HTTP") . "\n" .
76 N("Ramsize: ramsize parameter on boot image") . "\n" .
77 N("Display: export display to another computer (e.g.: 10.0.1.33:0)") . "\n" .
78 N("VGA: if you encounter any problem with VGA, please adjust") . "\n" .
79 "";
80
81
82 my %help = (
83 'initrd' => N("network boot image (network.img) or all.rdz"),
84 'kernel' => N("memdisk in case of network.img, or vmlinuz"),
85 'vga' => N("if you encounter any problem with VGA, please adjust"),
86 'interface' => N("network interface used for the installation process"),
87 'info' => N("Information displayed in PXE help (F1 key)"),
88 'network' => N("DHCP or an IP address"),
89 'directory' => N("full path to Mageia install server directory"),
90 'automatic' => N("installation method: choose NFS or HTTP"),
91 'ramsize' => N("ramsize parameter on boot image"),
92 'display' => N("export display on another computer (e.g.: 10.0.1.33:0)"),
93 'other' => "apic nolapic acpi=off initrd=/bin/shell",
94 'server' => N("IP address of server, that contains the installation directory"),
95 'labels' => N("lists all PXE entries, the default boot is the selected one"),
96 'wizardsrv' => N("launches a wizard to setup a PXE server"),
97 'editb' => N("edits the PXE entry selected with a dialog box"),
98 'removepxe' => N("removes the selected PXE entry"),
99 'apply' => N("apply change to configuration file"),
100 'addpxe' => N("launches a wizard to add a PXE entry "),
101 'helponline' => N("get help from online documentation"),
102 'auto_install' => "http://your_ip:3712/auto_<profil>_<label>.pl",
103 );
104
105 sub get_items {
106 my @items = (
107 [ "/_File", undef, undef, undef, '<Branch>', ],
108 # [ "/_File/_Write conf", undef, \&write_conf, 1, '<StockItem>', 'gtk-execute' ],
109 [ "/_File/_Exit", undef, sub { ugtk2->exit }, 1, '<StockItem>', 'gtk-quit' ],
110
111 [ "/_PXE Server", undef, undef, undef, '<Branch>', ],
112 [ "/_PXE Server/_Restart", undef, \&restart_dialog, 1, '<StockItem>', 'gtk-execute' ],
113 [ "/_PXE Server/_Reconfigure", undef, sub {
114 eval { wizard_pxe_server() };
115 my $err = $@;
116 $::WizardWindow->destroy if defined $::WizardWindow;
117 undef $::WizardWindow;
118 if ($err && $err !~ /wizcancel/) {
119 err_dialog(N("Error"), N("The PXE server wizard has unexpectedly failed:")
120 . "\n\n" . $err);
121 }
122 }, 1, '<StockItem>', 'gtk-execute' ],
123
124 [ "/_Help/Help", undef, \&show_help, 1, '<StockItem>', 'gtk-help' ],
125 );
126 return @items;
127 }
128
129 my $in = 'interactive'->vnew('su');
130
131 sub restart_dialog {
132 my $cmd = "service pxe restart";
133 my $w = $in->wait_message(N("PXE server"), N("Restarting PXE server..."));
134 run_program::get_stdout($cmd) !~ /unknown|error/ or err_dialog(N("Error!"), N("Error Restarting PXE server")) and return;
135 undef $w;
136 }
137
138 sub set_help_tip {
139 my ($entry, $key) = @_;
140 gtkset_tip(new Gtk2::Tooltips, $entry, formatAlaTeX($help{$key}));
141 }
142
143 if (!$::testing && !$in->do_pkgs->ensure_is_installed('pxe', $network::pxe::pxe_config_file)) {
144 err_dialog(N("Error!"), N("missing %s\n\nPlease install the pxe package.", $network::pxe::pxe_config_file));
145 $in->exit(-1);
146 }
147
148 save_config($network::pxe::pxelinux_config_file);
149
150 my @list_method = qw(nfs http ka dolly); push @list_method, "";
151 my @list_ram = qw(32000 48000 64000 96000 128000);
152 my @list_eth = qw(auto eth0 eth1 eth2); push @list_eth, "";
153
154 use constant COLUMN_LABEL => 0;
155 use constant COLUMN_INFO => 1;
156 use constant COLUMN_KERNEL => 2;
157 use constant COLUMN_INITRD => 3;
158 use constant COLUMN_METHOD => 4;
159 use constant COLUMN_INTERFACE => 5;
160 use constant COLUMN_NETWORK => 6;
161 use constant COLUMN_SERVER => 7;
162 use constant COLUMN_DIRECTORY => 8;
163 use constant COLUMN_RAMDISK_SIZE => 9;
164 use constant COLUMN_VGA => 10;
165 use constant COLUMN_DISPLAY => 11;
166 use constant COLUMN_OTHERS => 12;
167 use constant COLUMN_AUTO_INSTALL => 13;
168 use constant NUM_COLUMNS => 14;
169
170 my ($profile, $type);
171 foreach (@ARGV) {
172 if (/^--profile=(\w+)$/) {
173 $profile = $1;
174 } elsif (/^--type=(\w+)$/) {
175 $type = $1;
176 }
177 }
178
179 my ($config_file, $help_file); # = $profile && $type ?
180 # network::pxe::get_pxelinux_profile_path($profile, $type) :
181 # ($network::pxe::pxelinux_config_file, $network::pxe::pxelinux_help_file);
182 my $pxelinux_conf;# = network::pxe::read_pxelinux_conf($config_file, $help_file);
183
184 sub link_default_path() {
185 # need to quick fix pb of duplicate default (network::pxe need various adjustement).
186 if (!-f "$network::pxe::pxelinux_client_root/pxelinux.cfg/profiles/boot/default") {
187 mkdir_p("$network::pxe::pxelinux_client_root/pxelinux.cfg/profiles/boot/");
188 system("ln -sf $network::pxe::pxelinux_config_file $network::pxe::pxelinux_client_root/pxelinux.cfg/profiles/boot/default");
189 }
190 }
191
192
193 sub update_pxelinux_conf_from_treeview {
194 my ($pxelinux_conf, $treeview) = @_;
195 my $profile = get_selected_profile();
196 ($config_file, $help_file) = network::pxe::get_pxelinux_profile_path($profile, 'boot');
197 my $model = $treeview->get_model;
198 my $iter = $model->get_iter_first;
199 splice @{$pxelinux_conf->{entries}};
200 while ($iter) {
201 my ($label, $info, $kernel, $initrd, $method, $interface, $network, $server, $directory, $ramdisk_size, $vga, $display, $others, $auto_install) = $model->get($iter, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
202 my $entry = {
203 label => $label,
204 info => $info,
205 kernel => $kernel,
206 initrd => $initrd,
207 method => $method,
208 interface => $interface,
209 network => $network,
210 server => $server,
211 directory => $directory,
212 ramdisk_size => $ramdisk_size,
213 vga => $network::pxe::vga_resolution_to_bios{$vga},
214 display => $display,
215 others => $others,
216 auto_install => $auto_install,
217 };
218 if ($entry->{label} eq "local") {
219 $entry = {
220 label => "local",
221 localboot => "0",
222 };
223 push @{$pxelinux_conf->{entries}}, $entry;
224 } else {
225 push @{$pxelinux_conf->{entries}}, $entry;
226 }
227 $iter = $model->iter_next($iter);
228 }
229 }
230
231
232
233 sub write_conf {
234 my ($pxelinux_conf, $treeview) = @_;
235 update_pxelinux_conf_from_treeview($pxelinux_conf, $treeview);
236 if (basename($config_file) ne "local") {
237 #print "write conf PXE\n";
238 network::pxe::write_pxelinux_conf($pxelinux_conf, $config_file);
239 }
240 }
241
242 sub set_pxelinux_entry_at_iter {
243 my ($model, $iter, $entry) = @_;
244 $model->set($iter,
245 COLUMN_LABEL, $entry->{label},
246 COLUMN_INFO, $entry->{info},
247 COLUMN_KERNEL, $entry->{kernel},
248 COLUMN_INITRD, $entry->{initrd},
249 COLUMN_METHOD, $entry->{method},
250 COLUMN_INTERFACE, $entry->{interface},
251 COLUMN_NETWORK, $entry->{network},
252 COLUMN_SERVER, $entry->{server},
253 COLUMN_DIRECTORY, $entry->{directory},
254 COLUMN_RAMDISK_SIZE, $entry->{ramdisk_size},
255 COLUMN_VGA, $network::pxe::vga_bios_to_resolution{$entry->{vga}},
256 COLUMN_DISPLAY, $entry->{display},
257 COLUMN_OTHERS, $entry->{others},
258 COLUMN_AUTO_INSTALL, $entry->{auto_install},
259 );
260 }
261
262
263 sub create_model() {
264 # my $model = Gtk2::ListStore->new(("Glib::String") x NUM_COLUMNS);
265 my $model = Gtk2::ListStore->new("Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String", "Glib::String");
266 # set_pxelinux_entry_at_iter($model, $model->append, $_) foreach @{$pxelinux_conf->{entries}};
267 set_pxelinux_entry_at_iter($model, $model->append, $_) foreach @{$pxelinux_conf->{entries}};
268 return $model;
269 }
270
271
272 sub add_local_profil_entry {
273 my $local_conf = $network::pxe::pxelinux_client_root . "/pxelinux.cfg/profiles/boot/local";
274 if (!-f $local_conf) {
275 output($local_conf, <<EOF);
276 PROMPT 10
277 DEFAULT local
278 TIMEOUT 50
279
280 label local
281 LOCALBOOT 0
282 EOF
283 }
284 }
285
286 # wizard to add an entry in PXE menu
287 sub wizard_add_entry {
288 my ($_widget, $treeview, $pxelinux_conf, $profiles) = @_;
289 my $model = $treeview->get_model;
290
291 local $::isEmbedded = 0;
292 undef $::WizardTable;
293 undef $::WizardWindow;
294 $::isWizard = 1;
295 use wizards;
296 my $WPXENAME = "Mageia";
297 my $WINFO = "install Mageia";
298 my $WALLRDZ = "/mnt/nfs/isolinux/alt0/all.rdz";
299 # my $WALLRDZ = "/tmp/all.rdz";
300 my $WVMLINUZ = "/mnt/nfs/isolinux/alt0/vmlinuz";
301 # my $WVMLINUZ = "/tmp/vmlinuz";
302 my $wiz = wizards->new({
303 name => N("Add a PXE entry"),
304 pages => {
305 welcome => {
306 name => N("Add an all.rdz boot image") . "\n" . N("To boot through the network, the networked computer needs a boot image. Morever we need to name this image, so each boot image is related to a name in the PXE menu. Thus, the user can choose which image he wants to boot through PXE.") . "\n\n" . N("For technical reasons, in case of multiple boot images, it's simpler to boot the networked computer through a kernel (vmlinuz), and to provide one file with all needed drivers (in our case all.rdz)."),
307 next => 'addimg',
308 no_back => 1,
309 },
310 addimg => {
311 name => N("When this wizard has finished, the all.rdz image and kernel vmlinuz will be copied into \n%s.\n\nThe PXE menu list will be updated with this new entry.", $network::pxe::pxelinux_images),
312 data => [
313 { label => N("PXE label:"), val => \$WPXENAME,
314 help => N("name displayed in PXE menu (please provide an ASCII word or a number, without spaces)") },
315 { label => N("PXE information:"), val => \$WINFO,
316 help => N("The PXE information is used to explain the role of the boot image,\ne.g.:\nMageai Linux 10 rescue disk\nMageia cauldron install via http") },
317 { label => N("Full path to all.rdz image source:"), type => 'file', val => \$WALLRDZ,
318 help => N("Provide the full path to all.rdz image location") },
319 { label => N("Full path to vmlinuz source:"), type => 'file', val => \$WVMLINUZ,
320 help => N("Provide the full path to vmlinuz kernel location") },
321 ],
322 complete => sub {
323 test_similar_label($WPXENAME, $pxelinux_conf) or return 'addimg';
324 if (($WPXENAME) !~ /^\w+$/) {
325 err_dialog(N("Error!"), N("PXE label should be an ASCII word/number without space. Please adjust")) and return 'addimg';
326 }
327 if (! -f $WALLRDZ) {
328 err_dialog(N("Error!"), N("Please enter a correct path to all.rdz")) and return 'addimg';
329 }
330 if (! -f $WVMLINUZ) {
331 err_dialog(N("Error!"), N("Please enter a correct path to vmlinuz")) and return 'addimg';
332 }
333 },
334 next => 'endadd',
335 post => sub {
336 my $w = $in->wait_message(N("add a PXE entry"), N("add a PXE entry in your PXE server configuration..."));
337 network::pxe::add_in_help($WPXENAME, $WINFO);
338 my $vmlinuzpxe = basename($WVMLINUZ) . "-$WPXENAME";
339 cp_af($WVMLINUZ, $network::pxe::pxelinux_images . "/$vmlinuzpxe");
340 cp_af($WALLRDZ, $network::pxe::pxelinux_images . "/$WPXENAME.rdz");
341 my $entry = {
342 label => $WPXENAME,
343 info => $WINFO,
344 kernel => "images/$vmlinuzpxe",
345 initrd => "images/$WPXENAME.rdz",
346 ramdisk_size => "128000",
347 vga => "788",
348 others => "root=/dev/ram3 rw",
349 };
350 push @{$pxelinux_conf->{entries}}, $entry;
351 set_pxelinux_entry_at_iter($model, $model->append, $entry);
352 # set default boot for profile if none
353 if (!$pxelinux_conf->{default}) {
354 $pxelinux_conf->{default} = $WPXENAME;
355 $pxelinux_conf->{display} = 'messages';
356 $pxelinux_conf->{timeout} = '50';
357 $pxelinux_conf->{prompt} = '10';
358 # $pxelinux_conf->{f1} = '';
359 }
360 refresh_menu();
361 undef $w;
362 return;
363 },
364 no_back => 1,
365 },
366 endadd => {
367 name => N("Congratulations"),
368 data => [ { label => N("The wizard successfully added the PXE boot image.") } ],
369 no_back => 1,
370 end => 1,
371 },
372 }
373 });
374 $wiz->process($in);
375 $::isWizard = 0;
376 gtkset_mousecursor_normal();
377 }
378
379 # remove an entry in PXE menu
380 sub remove_item {
381 my ($_widget, $treeview, $pxelinux_conf) = @_;
382 $::isWizard = 0;
383 my $model = $treeview->get_model;
384 my $selection = $treeview->get_selection;
385 my $iter = $selection->get_selected;
386 if ($iter) {
387 my $path = $model->get_path($iter);
388 my $i = ($path->get_indices)[0];
389 my $entry = $pxelinux_conf->{entries}[$i];
390
391 $entry->{label} =~ /local/ and info_dialog(N("Local"), N("You can't remove local entry.")) and return 0;
392 ask_okcancel("Info", "Remove $entry->{label} PXE entry ?") or return;
393 network::pxe::remove_in_help($entry->{label});
394 my $ke = $network::pxe::pxelinux_client_root . "/$entry->{kernel}";
395 my $initrdf = $network::pxe::pxelinux_client_root . "/$entry->{initrd}";
396 if (basename($entry->{kernel} ne "memdisk")) {
397 print "kernel: $ke\n";
398 print "initrd: $initrdf\n";
399 #system("rm -vf $ke");
400 #system("rm -vf $initrdf");
401 } else {
402 print "initrd: $initrdf\n";
403 #system("rm -vf $initrdf");
404 }
405 $model->remove($iter);
406 splice @{$pxelinux_conf->{entries}}, $i, 1;
407 write_conf($pxelinux_conf, $treeview);
408 refresh_menu();
409 }
410
411 }
412
413 sub test_similar_label {
414 my ($label, $pxelinux_conf) = @_;
415 if (any { $_->{label} eq $label } @{$pxelinux_conf->{entries}}) {
416 err_dialog(N("Error!"), N("Found a similar entry in PXE list labeled: %s.\nChoose another label please", $label)) and return 0;
417 } else { return 1 }
418 }
419
420 sub clone_box_item {
421 my ($_widget, $treeview, $pxelinux_conf) = @_;
422 $::isWizard = 0;
423 my $model = $treeview->get_model;
424 my $iter = $treeview->get_selection->get_selected;
425 if ($iter) {
426 my $path = $model->get_path($iter);
427 my $i = ($path->get_indices)[0];
428 my $entry = $pxelinux_conf->{entries}[$i];
429 my $w = ugtk2->new(N("Clone %s entry", $entry->{label}));
430 my ($entry_box);
431 $w->{window}->set_position('center');
432 $w->{ok_clicked} = sub {
433 my $new_entry = $entry_box->get_text;
434 if ($new_entry !~ m/^\w+$/) { err_dialog(N("Error!"), N("PXE label should be an ASCII word/number without space. Please adjust")) and return }
435 test_similar_label($new_entry, $pxelinux_conf) or return;
436 my $newentry_data = $entry;
437 $newentry_data->{label} = $new_entry;
438 push @{$pxelinux_conf->{entries}}, $newentry_data;
439 set_pxelinux_entry_at_iter($model, $model->append, $newentry_data);
440 write_conf($pxelinux_conf, $treeview);
441 Gtk2->main_quit;
442 };
443 gtkadd($w->{window},
444 gtknew('VBox', children_loose => [
445 $entry_box = gtknew('Entry', text => ''),
446 create_okcancel($w),
447 ])
448 );
449 $w->main;
450 refresh_menu();
451 }
452 }
453
454 # dialog box to edit a PXE entry
455 sub edit_box_item {
456 my ($_widget, $treeview, $pxelinux_conf) = @_;
457 $::isWizard = 0;
458 my $model = $treeview->get_model;
459 my $selection = $treeview->get_selection;
460
461 my $iter = $selection->get_selected;
462 if ($iter) {
463 my $path = $model->get_path($iter);
464 my $i = ($path->get_indices)[0];
465 my $entry = $pxelinux_conf->{entries}[$i];
466
467 my $dialog = new Gtk2::Dialog();
468 $dialog->set_modal(1);
469 $dialog->set_resizable(0);
470
471 $entry->{label} =~ /local/ and info_dialog(N("Local"), N("You can't modify local entry.")) and return 0;
472 my $label = Gtk2::Label->new($entry->{label});
473 # my $oldlabel = $label;
474
475 my $info = Gtk2::Entry->new;
476 $info->set_text($entry->{info});
477 # $info->set_sensitive(0);
478 set_help_tip($info, 'info');
479
480 # create file dialog widget, with file or directory selection
481 my $fdwidget = sub {
482 my ($data, $test, $filetotest, $label, $profile) = @_;
483 if ($filetotest eq "auto_install") {
484 chdir($network::pxe::pxelinux_client_root . "/pxelinux.cfg/profiles/");
485 } else { chdir($network::pxe::pxelinux_client_root);
486 }
487 my $fd = new Gtk2::FileSelection(N("Selection"));
488 $fd->set_modal(1);
489 $fd->signal_connect("destroy", sub { $fd->hide });
490 $fd->ok_button->signal_connect(clicked => sub {
491 my $file = $fd->get_filename;
492 if ($test eq "dir") {
493 -d $file or err_dialog(N("Error!"), N("Should be a directory.")) and return;
494 } else {
495 -f $file or err_dialog(N("Error!"), N("Should be a file")) and return;
496 }
497 if ($filetotest eq "kernel") {
498 if (basename($file) ne "memdisk") {
499 run_program::get_stdout("file $file") =~ /boot sector/ or err_dialog(N("Error!"), N("Should be a boot sector file")) and return;
500 run_program::get_stdout("cp -avf $file " . $network::pxe::pxelinux_images . "/vmlinuz-$label");
501 $data->set_text("images/vmlinuz-$label");
502 } else { $data->set_text("memdisk") }
503 } elsif ($filetotest eq "initrd") {
504 if (basename($file) !~ /^\w+\.img$/) {
505 run_program::get_stdout("file $file") =~ /initrd/ or err_dialog(N("Error!"), N("Should be an initrd file")) and return;
506 system("cp -avf $file " . $network::pxe::pxelinux_images . "/$label.rdz");
507 $data->set_text("images/$label.rdz");
508 } else {
509 system("cp -avf $file " . $network::pxe::pxelinux_images . "/$label.img");
510 $data->set_text("images/$label.img");
511 }
512 } elsif ($filetotest eq "auto_install") {
513 run_program::get_stdout("file $file") =~ /perl/ or err_dialog(N("Error!"), N("Should be a perl script")) and return;
514 my $ip_address = network::tools::get_interface_ip_address($net, $interface);
515 my $auto_cfg = $network::pxe::pxelinux_client_root . "/pxelinux.cfg/profiles/auto_" . $profile . "_" . $label . ".pl";
516 cp_af($file, $auto_cfg);
517 substInFile {
518 s/^.*deploy_server.*\n//g;
519 $_ .= "\t'deploy_server' => \"$ip_address:3710\",\n" if /^\s*\$o\s*=\s*{$/;
520 } $auto_cfg;
521 $data->set_text("http://$ip_address:3712/auto_" . $profile . "_" . $label . ".pl");
522 }
523 $fd->hide;
524 }, $fd);
525 $fd->cancel_button->signal_connect(clicked => sub { $fd->hide });
526 return $fd;
527 };
528
529
530 my $kernel = Gtk2::Entry->new;
531 $kernel->set_text($entry->{kernel});
532 $kernel->set_sensitive(0);
533 set_help_tip($kernel, 'kernel');
534
535 my $file_dialogk = $fdwidget->($kernel, "", "kernel", $entry->{label});
536 # button kernel
537 my $buttonkernel = Gtk2::Button->new(N("Select kernel to boot"));
538 $buttonkernel->signal_connect(clicked => sub { $file_dialogk->show });
539
540 my $initrd = Gtk2::Entry->new;
541 $initrd->set_sensitive(0);
542 $initrd->set_text($entry->{initrd});
543 set_help_tip($initrd, 'initrd');
544
545 my $auto_install = Gtk2::Entry->new;
546 $auto_install->set_text($entry->{auto_install});
547 set_help_tip($auto_install, 'auto_install');
548 my $profile = get_selected_profile();
549 my $profile_selection = $fdwidget->($auto_install, "", "auto_install", $entry->{label}, $profile);
550 my $buttonprofil = Gtk2::Button->new("Select auto_install.pl");
551 $buttonprofil->signal_connect(clicked => sub { $profile_selection->show });
552
553 my $file_dialog = $fdwidget->($initrd, "", "initrd", $entry->{label});
554 my $buttoninitrd = Gtk2::Button->new(N("Select associated initrd"));
555 $buttoninitrd->signal_connect(clicked => sub { $file_dialog->show });
556
557 # combo box to pop down automatic installation
558 my $automatic = Gtk2::OptionMenu->new;
559 $automatic->set_popdown_strings(@list_method);
560 $automatic->entry->set_text($entry->{method});
561 set_help_tip($automatic, 'automatic');
562
563 # combo box to pop down list of network interface
564 my $interface = new Gtk2::OptionMenu();
565 $interface->set_popdown_strings(@list_eth);
566 $interface->entry->set_text($entry->{interface});
567 set_help_tip($interface, 'interface');
568
569 # my $network = Gtk2::Entry->new;
570 # $network->set_text($entry->{network});
571 # set_help_tip($network, 'network');
572
573 my $server = Gtk2::Entry->new;
574 $server->set_text($entry->{server});
575 set_help_tip($server, 'server');
576
577 my $directory = Gtk2::Entry->new;
578 $directory->set_text($entry->{directory});
579 set_help_tip($directory, 'directory');
580
581 my $file_dialogd = $fdwidget->($directory, "dir");
582 my $buttondir = Gtk2::Button->new(N("Select directory"));
583 $buttondir->signal_connect(clicked => sub { $file_dialogd->show });
584
585 my $ramdisk_size = new Gtk2::OptionMenu();
586 $ramdisk_size->set_popdown_strings(@list_ram);
587 if ($entry->{ramdisk_size} eq "") { $entry->{ramdisk_size} = "128000" }
588 $ramdisk_size->entry->set_text($entry->{ramdisk_size});
589 set_help_tip($ramdisk_size, 'ramsize');
590
591 my $vga = new Gtk2::OptionMenu();
592 $vga->set_popdown_strings(sort keys %network::pxe::vga_resolution_to_bios);
593 $vga->entry->set_text($network::pxe::vga_bios_to_resolution{$entry->{vga}});
594 set_help_tip($vga, 'vga');
595
596 my $display = Gtk2::Entry->new;
597 $display->set_text($entry->{display});
598 set_help_tip($display, 'display');
599
600 my $others = Gtk2::Entry->new;
601 if ($entry->{others} eq "") { $entry->{others} = "root=/dev/ram3 rw" }
602 $others->set_text($entry->{others});
603 set_help_tip($others, 'others');
604
605 my %size_groups = map { $_ => Gtk2::SizeGroup->new('horizontal') } qw(label widget button);
606 my $label_and_widgets = sub {
607 my ($label, $widget, $button) = @_;
608 gtkpack_(Gtk2::HBox->new(0,5),
609 0, gtkadd_widget($size_groups{label}, $label),
610 1, gtkadd_widget($size_groups{widget}, $widget),
611 2, gtkadd_widget($size_groups{button}, $button),
612 );
613 };
614
615 # display IPADDRESS only if dhcp is not selected
616 my $ipaddr = Gtk2::Entry->new;
617 my $toggledhcp = Gtk2::CheckButton->new(N("DHCP or IP address"));
618 if ($entry->{network} eq "dhcp") { $toggledhcp->set_active(1);
619 $ipaddr->set_sensitive(0);
620 } else {
621 $toggledhcp->set_active(0);
622 $ipaddr->set_sensitive(1);
623 $ipaddr->set_text($entry->{network});
624 }
625
626 $toggledhcp->signal_connect(clicked => sub {
627 my $s = $toggledhcp->get_active;
628 if ($s eq "1") {
629 $ipaddr->set_sensitive(0);
630 } else {
631 $ipaddr->set_sensitive(1);
632 }
633 });
634
635 # ok, lets create the dialog box :-)
636 gtkpack_($dialog->vbox,
637 0, gtkadd(Gtk2::Frame->new(N("PXE entry")),
638 gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5),
639 0, $label_and_widgets->(N("Label"), $label, ""),
640 0, $label_and_widgets->(N("Entry description"), $info, ""),
641 0, Gtk2::VSeparator->new,
642 0, $label_and_widgets->(N("Kernel image: ") . $network::pxe::pxelinux_client_root . "/", $kernel, $buttonkernel),
643 0, $label_and_widgets->(N("Initrd image: ") . $network::pxe::pxelinux_client_root . "/", $initrd, $buttoninitrd),
644 ),
645 ),
646
647 0, gtkadd(Gtk2::Frame->new(N("Mageia installer options")),
648 gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5),
649 0, $label_and_widgets->(N("Ramdisk size"), $ramdisk_size, ""),
650 0, $label_and_widgets->(N("Custom options"), $others, ""),
651 0, $label_and_widgets->(N("Frame buffer resolution"), $vga, ""),
652 0, $label_and_widgets->(N("Remote IP of X server"), $display, ""),
653 0, gtkadd(Gtk2::Frame->new(N("Automatic Options")),
654 gtkpack_(gtkset_border_width(Gtk2::VBox->new, 5),
655 0, $label_and_widgets->(N("Installation method"), $automatic, ""),
656 0, $label_and_widgets->(N("Network interface"), $interface, ""),
657 0, gtkpack_(Gtk2::HBox->new(0,5),
658 0, gtkadd_widget($size_groups{label}, $toggledhcp),
659 1, gtkadd_widget($size_groups{widget}, $ipaddr),
660 2, gtkadd_widget($size_groups{button}, ""),
661 ),
662 0, $label_and_widgets->(N("Remote server name"), $server, ""),
663 0, $label_and_widgets->("auto_install", $auto_install, $buttonprofil),
664 0, $label_and_widgets->(N("Remote installation directory"), $directory, ""),
665 ),
666 ),
667 ),
668 ),
669 0, create_okcancel({
670 cancel_clicked => sub { $dialog->destroy },
671 ok_clicked => sub {
672 #ask_okcancel("are you sure you want to update all those values ?");
673 $entry->{label} = $label->get_text;
674 $entry->{info} = $info->get_text;
675 $entry->{kernel} = $kernel->get_text;
676 $entry->{initrd} = $initrd->get_text;
677 $entry->{method} = $automatic->entry->get_text;
678 $entry->{interface} = $interface->entry->get_text;
679 # check dhcp or ipaddress
680 if ($toggledhcp->get_active) {
681 $entry->{network} = "dhcp";
682 } else {
683 $entry->{network} = $ipaddr->get_text;
684 if ($entry->{kernel} !~ /memdisk/) {
685 is_ip($entry->{network}) or err_dialog(N("Error!"), N("Please enter a valid IP address.")) and return;
686 }
687 }
688 $entry->{server} = $server->get_text;
689 $entry->{directory} = $directory->get_text;
690 $entry->{ramdisk_size} = $ramdisk_size->entry->get_text;
691 $entry->{vga} = $network::pxe::vga_resolution_to_bios{$vga->entry->get_text};
692 $entry->{display} = $display->get_text;
693 $entry->{others} = $others->get_text;
694 $entry->{auto_install} = $auto_install->get_text;
695
696 # update value in cells
697 set_pxelinux_entry_at_iter($model, $iter, $entry);
698 write_conf($pxelinux_conf, $treeview);
699 $dialog->destroy;
700 network::pxe::add_in_help($entry->{label}, $entry->{info});
701 },
702 },
703 ),
704 );
705 $dialog->show_all;
706 }
707 }
708
709 sub show_help() { info_dialog("help",
710 gtkpack_(gtkset_border_width(Gtk2::VBox->new, 3),
711 0, $help,
712 0, gtksignal_connect(set_help_tip(Gtk2::Button->new(N("online PXE documentation")), 'helponline'),
713 clicked => sub { system("/usr/bin/www-browser http://people.mandriva.com/~aginies/doc/pxe/ &") }
714 ),
715 ),
716 );
717 }
718
719 sub check_pxe_conf() {
720 my $ip_address = network::tools::get_interface_ip_address($net, $interface);
721 if (! any { /default_address=$ip_address/ } cat_($network::pxe::pxe_config_file)) {
722 # pxe.conf doesnt matche system, relaunch wizard_pxe_server
723 err_dialog(N("Error!"), N("Your %s doesn't match your actual IP address configuration. Relaunching the PXE server wizard to readjust it.", $network::pxe::pxe_config_file)) and launch_pxe_server();
724 }
725 }
726
727 # launch wizard to setup a PXE server
728 sub wizard_pxe_server() {
729 local $::isEmbedded = 0;
730 my $in = 'interactive'->vnew('su');
731 undef $::WizardTable;
732 undef $::WizardWindow;
733 $::isWizard = 1;
734 use wizards;
735 my $wiz = wizards->new({
736 name => N("PXE Wizard"),
737 needed => { "tftp-server", "pxe", "dhcpd" },
738 pages => {
739 welcome => {
740 name => N("PXE wizard") . "\n\n" . N("Set a PXE server.") . "\n" . N("This wizard will help you to configure the PXE server, and PXE boot image management. PXE (Pre-boot eXecution Environment) is a protocol designed by Intel that allows computers to boot through the network. PXE is stored in the ROM of new generation network cards. When the computer boots up, the BIOS loads the PXE ROM in the memory and executes it. A menu is displayed, allowing the computer to boot an operating system loaded through the network."),
741 no_back => 1,
742 next => 'pxeserver',
743 },
744 pxeserver => {
745 name => N("Set PXE server") . "\n\n" . N("We need to use a special dhcpd.conf file with PXE parameter. To set up such a DHCP server, launch the DHCP wizard and check the box 'Enable PXE'. If you don't do that, PXE query will not be answered by this server.") . "\n" . N("Now the wizard will configure all needed default configuration files to allow computers to boot through the network."),
746 no_back => 1,
747 next => 'interface',
748 },
749 interface => {
750 name => N("PXE server Interface"),
751 data => [
752 { list => [ sort keys %{$net->{ifcfg}} ], val => \$interface },
753 ],
754 no_back => 1,
755 next => 'summaryserver'
756 },
757 summaryserver => {
758 name => N("The wizard will now prepare all default files to set up your PXE server"),
759 pre => sub {
760 output($sys_wizard_pxe, "INTERFACE=$interface\n");
761 },
762 data => [
763 { label => N("TFTP directory: %s", $network::pxe::tftp_root) },
764 { label => N("Boot image path: %s", $network::pxe::pxelinux_images) },
765 { label => N("PXE config file: %s", $network::pxe::pxe_config_file) },
766 { label => N("PXE help file: %s", $network::pxe::pxelinux_help_file) },
767 ],
768 post => \&do_it_pxe,
769 no_back => 1,
770 next => 'endserver',
771 },
772 endserver => {
773 name => N("End of PXE server configuration"),
774 data => [ { label => N("The wizard successfully configured your PXE server. Now you can configure the PXE menu entry.") } ],
775 no_back => 1,
776 end => 1,
777 },
778 },
779 });
780 $wiz->process($in);
781 gtkset_mousecursor_normal();
782 }
783
784 # save old config with date
785 sub save_config {
786 my ($old) = @_;
787 my $DATE = chomp_(`date +%d-%m-20%y`);
788 if (-f $old) {
789 print " - Backup of $old configuration\n";
790 cp_af($old, $old . '.' . $DATE);
791 }
792 }
793
794 # can adjust block size in tftp server (ita64)
795 sub tftp_blksize {
796 # $o should be with W or not N
797 my ($o) = @_;
798 if ($o =~ /W/) {
799 substInFile { s/server_args.*/server_args = -r blksize -s $network::pxe::tftp_root/ } "$XINETDDIR/tftp";
800 } else {
801 substInFile { s/server_args.*/server_args = -s $network::pxe::tftp_root/ } "$XINETDDIR/tftp";
802 }
803 }
804
805 # enable tftp server in xinetd conf
806 sub enable_tftps() {
807 substInFile { s/disable.*/disable = no/ } "$XINETDDIR/tftp";
808 }
809
810 sub memlinux_prep() {
811 if (!-f ($network::pxe::pxelinux_client_root . "/memdisk")) {
812 cp_af($MEMDISK, $network::pxe::pxelinux_client_root);
813 }
814 }
815
816 # main procedure to setup PXE server
817 sub do_it_pxe() {
818 return if $::testing;
819 my $w = $in->wait_message(N("PXE server"), N("Configuring a PXE server on your system..."));
820 output($network::pxe::pxelinux_client_root . "/drakwizard_pxe", <<EOF);
821 do not remove
822 use to check if drakwizard PXE set server
823 has been launch.
824 EOF
825
826 mkdir_p($network::pxe::pxelinux_images);
827 memlinux_prep();
828
829 my $default_conf = network::pxe::read_pxelinux_conf($network::pxe::pxelinux_config_file, $network::pxe::pxelinux_help_file);
830
831 #- restore default pxe settings
832 put_in_hash($default_conf, {
833 'prompt' => 1,
834 'default' => 'local',
835 'display' => 'messages',
836 'timeout' => '50',
837 'f1' => 'help.txt',
838 });
839 network::pxe::write_pxelinux_conf($default_conf, $network::pxe::pxelinux_config_file);
840
841 save_config($network::pxe::pxelinux_help_file);
842 network::pxe::write_default_pxe_help();
843
844 save_config($network::pxe::pxelinux_message_file);
845 network::pxe::write_default_pxe_messages($net);
846
847 network::pxe::write_pxe_conf($net, $interface);
848
849 enable_tftps();
850 tftp_blksize('N');
851 services::enable($_) foreach qw(xinetd pxe);
852 }
853
854 # add colum to model
855 # fixed :-)
856 sub add_columns {
857 my $treeview = shift;
858 my $model = $treeview->get_model;
859 each_index {
860 my $renderer = Gtk2::CellRendererText->new;
861 $renderer->set(editable => 0);
862 $renderer->set_data(column => $::i);
863 $treeview->insert_column_with_attributes(-1, $_, $renderer, 'text' => $::i);
864 } N("Label"), N("Entry description"), N("Kernel image"), N("Initrd image"), N("Installation method"), N("Network interface"), N("DHCP or IP address"), N("Remote server name"), N("Remote installation directory"), N("Ramdisk size"), N("Frame buffer resolution"), N("Remote IP of X server"), N("Custom options"), "Auto_install";
865 }
866
867
868 # drakdeploy code from blino
869 my $mac_regexp = '(?:[0-9a-f]{2}:){5}[0-9a-f]{2}';
870 my $profiles_conf = network::pxe::read_profiles();
871
872 sub create_systems_list() {
873 my $systems = Gtk2::SimpleList->new(
874 N("MAC address") => 'text',
875 N("Installation profile") => 'text',
876 N("Boot profile") => 'text',
877 N("Computer Name") => 'text',
878 );
879
880 foreach ($systems->get_columns) { $_->set_resizable(1) }
881 $systems->set_headers_clickable(1);
882 $systems->set_rules_hint(1);
883 $systems->get_selection->set_mode('multiple');
884 $systems->get_model->set_sort_column_id(0, 'ascending');
885 foreach (0..2) {
886 $systems->get_column($_)->signal_connect('clicked', \&sort_by_column, $systems->get_model);
887 $systems->get_column($_)->set_sort_column_id($_ == 0 ? 1 : $_ + 2);
888 }
889 $systems->get_column(1)->get_cell_renderers->set_property('mode', 'inert');
890 $systems->set_column_editable(3, 1);
891 return $systems;
892 }
893
894 sub sort_by_column {
895 my ($column, $model) = @_;
896 my $col_id = $column->get_sort_column_id;
897 my ($old_id, $old_order) = $model->get_sort_column_id;
898 $model->set_sort_column_id($col_id, $old_id == $col_id && $old_order ne 'descending' ? 'ascending' : 'descending');
899 }
900
901 sub create_profiles_list() {
902 my $profiles = Gtk2::SimpleList->new("Profile name" => 'text');
903 $profiles->set_headers_visible(1);
904 $profiles->get_selection->set_mode('browse');
905 $profiles->get_selection->signal_connect(changed => sub {
906 my $pxelinux_conf = get_pxelinux_conf_from_profile();
907 refresh_menu();
908 update_treeview($pxelinux_conf);
909 });
910 return $profiles;
911 }
912
913 my $profiles = create_profiles_list;
914 my $systems = create_systems_list;
915 my $log_text = gtknew('TextView');
916
917 sub get_selected_profile() {
918 my $model_profiles = $profiles->get_model;
919 my $iter = $profiles->get_selection->get_selected;
920 if ($iter) {
921 my $profile = $model_profiles->get($iter, 0);
922 return $profile;
923 }
924 }
925
926 sub get_pxelinux_conf_from_profile() {
927 my $model_profiles = $profiles->get_model;
928 my $iter = $profiles->get_selection->get_selected;
929 if ($iter) {
930 ($config_file, $help_file) = network::pxe::get_pxelinux_profile_path($model_profiles->get($iter, 0), 'boot');
931 my $pxelinux_conf = profile_selected($model_profiles->get($iter, 0));
932 return $pxelinux_conf;
933 }
934 }
935
936 sub system_entry_set_profile2 {
937 my ($entry, $profile) = @_;
938 $entry->[2] = $profile || N("None");
939 }
940
941 sub system_entry_set_profile {
942 my ($entry, $profile) = @_;
943 $entry->[1] = $profile || N("None");
944 }
945
946 sub system_entry_set_name {
947 my ($entry, $name) = @_;
948 $entry->[3] = $name || "";
949 }
950
951 sub find_system_entry_for_mac_address {
952 my ($mac_address) = @_;
953 find { $_->[0] eq $mac_address } @{$systems->{data}};
954 }
955
956 sub get_name_from_mac {
957 my ($mac) = @_;
958 foreach (cat_($conf_mac_profiles_name)) {
959 return $3 if m/$mac\|(\w+|)\|(\w+|)\|(.*|)/;
960 }
961 }
962
963 sub get_profile2_from_mac {
964 my ($mac) = @_;
965 foreach (cat_($conf_mac_profiles_name)) {
966 return $2 if m/$mac\|(\w+|)\|(\w+|)\|(.*|)/;
967 }
968 }
969
970 sub update_systems_data_from_file {
971 my ($mac , $entry);
972 foreach $a (@{$systems->{data}}) {
973 $mac = $a->[0];
974 $entry = [ $mac ];
975 my $profile2 = get_profile2_from_mac($mac);
976 my $name = get_name_from_mac($mac);
977 $profile2 and $a->[2] = $profile2;
978 $name and $a->[3] = $name;
979 }
980 }
981
982
983 sub add_configured_mac_addresses() {
984 my ($name);
985 while (my ($mac_address, $conf) = each %{$profiles_conf->{per_mac}}) {
986 my $entry = [ $mac_address ];
987 system_entry_set_profile($entry, $conf->{profile});
988 push @{$systems->{data}}, $entry;
989 gtktext_append($log_text, "Detected new system: $mac_address\n");
990 }
991 }
992
993 sub get_mac_addresses_from_dhcp_log() {
994 my %addresses;
995 foreach (cat_("/var/log/daemons/info")) {
996 /dhcpd:\s+DHCP(?:DISCOVER|REQUEST).*\s+from\s+($mac_regexp)\b/ and $addresses{$1} = 1;
997 }
998 foreach (difference2([ keys %addresses ], [ map { $_->[0] } @{$systems->{data}} ])) {
999 my $entry = [ $_ ];
1000 system_entry_set_profile($entry, '');
1001 push @{$systems->{data}}, $entry;
1002 gtktext_append($log_text, "Detected new system: $_\n");
1003 }
1004 1; #- run callback on next timeout
1005 }
1006
1007 my ($profiles_combo, $install_button, $menu_combo);
1008
1009 sub refresh_profiles() {
1010 my @profiles = network::pxe::list_profiles($profiles_conf);
1011 mygtk2::gtkset($profiles_combo, list => [ '', @profiles ]);
1012 @{$profiles->{data}} = @profiles;
1013 }
1014
1015 sub refresh_menu() {
1016 my $pxelinux_conf = get_pxelinux_conf_from_profile();
1017 my @menu = network::pxe::list_pxelinux_labels($pxelinux_conf);
1018 mygtk2::gtkset($menu_combo, list => [ '', @menu ]);
1019 my $defaultlabel = $pxelinux_conf->{default};
1020 my $c = 1;
1021 foreach (@menu) {
1022 if ($_ eq $defaultlabel) {
1023 $menu_combo->set_active($c);
1024 } else { $c++ }
1025 }
1026 $menu_combo->signal_connect(changed => sub {
1027 my $model_profiles = $profiles->get_model;
1028 my $iter = $profiles->get_selection->get_selected;
1029 if ($iter) {
1030 ($config_file, $help_file) = network::pxe::get_pxelinux_profile_path($model_profiles->get($iter, 0), 'boot');
1031 my $new_default = $menu_combo->get_active_text;
1032 substInFile {
1033 s/DEFAULT.*/DEFAULT $new_default/;
1034 } $config_file;
1035 }
1036 });
1037 }
1038
1039 sub add_profile() {
1040 my $w = ugtk2->new(N("Add profile"));
1041 my ($entry);
1042 $w->{window}->set_position('center');
1043 $w->{ok_clicked} = sub {
1044 my $profile = $entry->get_text;
1045 network::pxe::profile_exists($profiles_conf, $profile) and err_dialog(N("Add profile"), N("The %s profile already exists!", $profile)), return;
1046 network::pxe::add_empty_profile($profiles_conf, $profile);
1047 refresh_profiles();
1048 Gtk2->main_quit;
1049 };
1050 gtkadd($w->{window},
1051 gtknew('VBox', children_loose => [
1052 $entry = gtknew('Entry', text => network::pxe::find_next_profile_name($profiles_conf, 'profile_name')),
1053 create_okcancel($w),
1054 ]));
1055 $w->main;
1056 }
1057
1058 sub set_global_pxe_settings {
1059 my ($profiles_conf, $profile) = @_;
1060 put_in_hash($pxelinux_conf, {
1061 'prompt' => 1,
1062 'default' => '',
1063 'display' => 'messages',
1064 'timeout' => '50',
1065 'f1' => 'help-$profile.txt',
1066 });
1067 }
1068
1069 sub write_profile_conf {
1070 my ($mac, $profile, $profile2, $name);
1071 output($conf_mac_profiles_name, "# auto generated by drakpxelinux\n");
1072 foreach $a (@{$systems->{data}}) {
1073 append_to_file($conf_mac_profiles_name, "$a->[0]|$a->[1]|$a->[2]|$a->[3]\n");
1074 }
1075 }
1076
1077 sub profile_selected {
1078 my ($profile) = @_;
1079 # if ($profile eq 'default') {
1080 # ($config_file, $help_file) = ($network::pxe::pxelinux_config_file, $network::pxe::pxelinux_help_file);
1081 # } else {
1082 # force type = boot
1083 my $type = "boot";
1084 ($config_file, $help_file) = network::pxe::get_pxelinux_profile_path($profile, $type);
1085 # undef $pxelinux_conf;
1086 # }
1087 my $pxelinux_conf = network::pxe::read_pxelinux_conf($config_file, $help_file);
1088 return $pxelinux_conf;
1089 }
1090
1091 sub update_treeview {
1092 my ($pxelinux_conf) = @_;
1093 $model->clear;
1094 set_pxelinux_entry_at_iter($model, $model->append, $_) foreach @{$pxelinux_conf->{entries}};
1095 }
1096
1097 ###############
1098 # Main Program
1099 ###############
1100 # check if first launch
1101 if (!-f ($network::pxe::pxelinux_client_root . "/drakwizard_pxe")) {
1102 info_dialog(N("Please configure a PXE server"), N("It seems this is the first time you run this tool.\nA wizard will appear to configure your PXE server."));
1103 launch_pxe_server();
1104 }
1105 check_pxe_conf();
1106
1107 sub launch_pxe_server() {
1108 eval { wizard_pxe_server() };
1109 my $err = $@;
1110 $::WizardWindow->destroy if defined $::WizardWindow;
1111 undef $::WizardWindow;
1112 if ($err && $err !~ /wizcancel/) {
1113 err_dialog(N("Error"), N("The PXE server wizard has unexpectedly failed:") . "\n\n" . $err);
1114 }
1115 }
1116
1117 # disable wizard
1118 $::isWizard = 0;
1119
1120 my $w = ugtk2->new(N("Drakpxelinux"));
1121 $treeview->set_rules_hint(1);
1122 $treeview->get_selection->set_mode('single');
1123 add_columns($treeview);
1124
1125 # labels that list pxe menu entry
1126 $treeview->signal_connect(button_press_event => sub {
1127 my (undef, $event) = @_;
1128 my $model = $treeview->get_model;
1129 my $selection = $treeview->get_selection;
1130 my $iter = $selection->get_selected;
1131 if ($iter) {
1132 # get pxelinux_conf file
1133 my $pxelinux_conf = get_pxelinux_conf_from_profile();
1134 edit_box_item($model, $treeview, $pxelinux_conf) if $event->type eq '2button-press';
1135 }
1136 });
1137
1138 my @items = get_items();
1139 my $factory = Gtk2::ItemFactory->new('Gtk2::MenuBar', '<main>', undef);
1140 $factory->create_items('menu', @items);
1141 my $menu = $factory->get_widget('<main>');
1142
1143 my $okcancel = create_okcancel({
1144 cancel_clicked => sub { ugtk2->exit },
1145 ok_clicked => sub {
1146 my $pxe_conf = get_pxelinux_conf_from_profile();
1147 $pxe_conf and write_conf($pxe_conf, $treeview);
1148 write_profile_conf();
1149 ugtk2->exit },
1150 },
1151 );
1152
1153 # main interface
1154 gtkpack($w->{window}, gtknew('VBox', spacing => 0, children => [
1155 0, $menu,
1156 if_(!$::isEmbedded, 0, Gtk2::Banner->new('IC-Dhost-48', N("Drakpxelinux manage your PXE server"))),
1157 if_($::isEmbedded, 0, Gtk2::Label->new("Here you can manage your PXE server.")),
1158 1, gtknew('Notebook', children => [
1159 gtknew('Label', text => N("PXE configuration file")),
1160 gtknew('VBox', spacing => 0, children => [
1161 1, gtknew('HBox', spacing => 1, children => [
1162 1, gtknew('ScrolledWindow', width => 500, height => 300, child => $treeview),
1163 0, gtknew('VBox', children => [
1164 0, gtknew('Label', text => N("Profiles list")),
1165 1, gtknew('ScrolledWindow', child => $profiles),
1166 0, gtknew('VButtonBox', layout => 'start', children_loose => [
1167 gtksignal_connect(gtknew('Button', text => N("Add profile")), clicked => \&add_profile),
1168 gtksignal_connect(gtknew('Button', text => N("Clone profile")), clicked => sub {
1169 foreach ($profiles->get_selected_indices) {
1170 $profiles->{data}[$_][0] !~ /local/ ? network::pxe::clone_profile($profiles_conf, $profiles->{data}[$_][0]) : $in->ask_warn(N("Info"), N("No need to clone local profile."));
1171 }
1172 refresh_profiles();
1173 }),
1174 gtksignal_connect(gtknew('Button', text => N("Remove profile")), clicked => sub {
1175 foreach ($profiles->get_selected_indices) {
1176 $profiles->{data}[$_][0] !~ /local/ ? network::pxe::remove_profile($profiles_conf, $profiles->{data}[$_][0]) : $in->ask_warn(N("Info"), N("Can't remove local profile."));
1177 }
1178 refresh_profiles();
1179 }),
1180 ]
1181 ),
1182 0, gtknew('VButtonBox', layout => 'start', children_loose => [
1183 gtknew('Label', text => N("Default boot:")),
1184 $menu_combo = gtknew('ComboBox'),
1185 ]
1186 ),
1187 ]
1188 ),
1189 ]
1190 ),
1191 0, gtknew('HButtonBox', layout => 'start', children => [
1192 0, gtksignal_connect(set_help_tip(Gtk2::Button->new(N("Add a PXE entry")), 'addpxe'), clicked => sub {
1193 my $pxelinux_conf = get_pxelinux_conf_from_profile();
1194 my $profile = get_selected_profile;
1195 if ($profile eq "local") { $in->ask_warn(N("Info"), N("Local profile is special, and doesn't need a new entry.")) and return };
1196 $pxelinux_conf and eval { wizard_add_entry($model, $treeview, $pxelinux_conf);
1197 write_conf($pxelinux_conf, $treeview);
1198 };
1199 my $err = $@;
1200 $::WizardWindow->destroy if defined $::WizardWindow;
1201 undef $::WizardWindow;
1202 if ($err && $err !~ /wizcancel/) {
1203 err_dialog(N("Error"), N("The PXE entry wizard has unexpectedly failed:") . "\n\n" . $err);
1204 }
1205 }),
1206 0, gtksignal_connect(set_help_tip(Gtk2::Button->new(N("Remove PXE entry")), 'removepxe'), clicked => sub {
1207 my $pxelinux_conf = get_pxelinux_conf_from_profile();
1208 remove_item($model, $treeview, $pxelinux_conf);
1209 #write_conf($pxelinux_conf, $treeview);
1210 }),
1211 0, gtksignal_connect(set_help_tip(Gtk2::Button->new(N("Edit PXE entry")), 'editb'), clicked => sub {
1212 my $pxelinux_conf = get_pxelinux_conf_from_profile();
1213 edit_box_item($model, $treeview, $pxelinux_conf);
1214 #write_conf($pxelinux_conf, $treeview);
1215 }),
1216 0, gtksignal_connect(Gtk2::Button->new(N("Clone PXE entry")), clicked => sub {
1217 my $pxelinux_conf = get_pxelinux_conf_from_profile();
1218 clone_box_item($model, $treeview, $pxelinux_conf);
1219 }),
1220 ]),
1221 ]),
1222 gtknew('Label', text => N("Systems")),
1223 gtknew('VBox', spacing => 1,
1224 children => [
1225 1, gtknew('ScrolledWindow', child => $systems),
1226 0, gtknew('HBox',
1227 children_loose => [
1228 gtksignal_connect(gtknew('Button', text => N("Set installation profile")), clicked => sub {
1229 my $profile = $profiles_combo->get_active_text;
1230 my $to_install = exists $profiles_conf->{profiles}{install}{$profile};
1231 foreach ($systems->get_selected_indices) {
1232 my $entry = $systems->{data}[$_];
1233 network::pxe::set_profile_for_mac_address($profile, $to_install, $entry->[0]);
1234 system_entry_set_profile($entry, $profile);
1235 }
1236 write_profile_conf();
1237 }),
1238 gtksignal_connect(gtknew('Button', text => N("Set boot profile")), clicked => sub {
1239 my $profile = $profiles_combo->get_active_text;
1240 foreach ($systems->get_selected_indices) {
1241 my $entry = $systems->{data}[$_];
1242 system_entry_set_profile2($entry, $profile);
1243 }
1244 write_profile_conf();
1245 }),
1246 $profiles_combo = gtknew('ComboBox'),
1247 ]),
1248 ]),
1249 gtknew('Label', text => N("Log")),
1250 gtknew('VBox', spacing => 1, children_loose => [
1251 gtknew('ScrolledWindow', width => 600, height => 400, child => $log_text),
1252 ]),
1253 ]),
1254 0, $okcancel,
1255 ]),
1256 );
1257
1258 add_local_profil_entry();
1259 add_configured_mac_addresses();
1260 get_mac_addresses_from_dhcp_log();
1261 update_systems_data_from_file();
1262 $SIG{USR1} = sub {
1263 update_systems_data_from_file();
1264 };
1265 Glib::Timeout->add(60000, \&get_mac_addresses_from_dhcp_log);
1266 refresh_profiles();
1267 $w->show;
1268
1269 Gtk2->main;

  ViewVC Help
Powered by ViewVC 1.1.30