diff options
Diffstat (limited to 'perl-install/standalone/drakups')
| -rwxr-xr-x | perl-install/standalone/drakups | 410 | 
1 files changed, 410 insertions, 0 deletions
diff --git a/perl-install/standalone/drakups b/perl-install/standalone/drakups new file mode 100755 index 000000000..427216069 --- /dev/null +++ b/perl-install/standalone/drakups @@ -0,0 +1,410 @@ +#!/usr/bin/perl + +use strict; +use lib qw(/usr/lib/libDrakX); +use standalone; +use common; +use mouse; +use detect_devices; +use ugtk3 qw(:create :dialogs :helpers :wrappers); +use interactive; +use Libconf qw(:functions); +use Libconf::Glueconf::NUT::Ups_conf; + +# config files: +my %files = (devices => "/etc/ups/ups.conf", +             access => "/etc/ups/upsd.conf", +             users => "/etc/ups/upsd.users", +            ); + + +my ($struct, $users); # NUT configuration +my ($w, $in); # GUI +my %indexes; + + +sub writeconf() { +    info_dialog(N("Warning"), "Write support for users is incomplete\n\nIt lacks some support for some extra fields that would be lost else"); +    log::explanations("Updating NUT configuration accordingly"); +    $struct->writeConf($files{devices}); + +    if ($users) { +        log::explanations("Updating NUT users configuration accordingly"); +        $users->writeConf($files{users}); +    } + +    require services; +    services::restart("upsd"); +} + +sub read_nut_config() { +    $struct = Libconf::Glueconf::NUT::Ups_conf->new({ filename => $files{devices} }); +} + +sub readDriversList() { +    my (%ups, @ups); +    local $_; +    foreach (cat_(first(glob("/usr/share/doc/nut/docs/driver.list")))) { +        /^#/ and next; +        if (my ($vendor, $model, $extra, $driver) = /^"(.*)"\s+"(.*)"\s+"(.*)"\s+"(.*)"/) { +            $ups{$vendor}{$model . $extra} = { +                                     driver => $driver, +                                     extra => $extra, +                                    }; +            push @ups, "$vendor|$model ($extra)"; +        } +    } +    \%ups, \@ups; +} + +my %models; + +sub add_device_wizard { +    my ($in, $config) = @_; +    my ($ups_models, $model_list) = readDriversList(); + +    my ($ups, $vendor, $model, $extra, $name, $driver, $port, @new_devices, $opts); +    my %methods = ( +                   # network => N("Connected through the network"), # need SNMP probe +                   # serial => N("Connected through a serial port"), +                   # usb => N("Connected through an usb cable"), +                   auto => N("Connected through a serial port or an usb cable"), +                   manual => N("Manual configuration"), +                  ); +    my $method = $methods{auto}; +    require wizards; +    my $wiz = wizards->new({ +            #defaultimage => "logdrake.png",    # FIXME +            name => N("Add an UPS device"), +            pages => { +                      welcome => { +                                  name => N("Welcome to the UPS configuration utility. + +Here, you'll add a new UPS to your system.\n"), +                                  no_back => 1, +                                  next => 'method' +                                 }, +                      method => { +                                 name => N("We're going to add an UPS device. + +Do you want to autodetect UPS devices connected to this machine or to manually select them?"), +                                 data => [ { label => N("Autodetection"), val => \$method, type => "list", +                                             list => [ values %methods ] } ], +                                 post => sub { +{ reverse %methods }->{$method} }, +                                }, +                      auto => { +                               end => 1, +                               pre => sub { +                                   local $::isWizard; +                                   my $_wait = $in->wait_message(N("Please wait"), N("Detection in progress")); +                                   # UPS autoconfig: +                                   detect_devices::probeSerialDevices() if !$::testing; +                                   @new_devices = (); +                                    +                                   foreach my $ups_device (detect_devices::getUPS()) { +                                       my $str = $ups_device->{name} || $ups_device->{DESCRIPTION}; +                                       $str =~ s/ /_/g; +                                       $name = $str; +                                        +                                       if (!exists $struct->{$str}) { +                                           $port   = $struct->{$str}{port} = $ups_device->{port} || $ups_device->{DEVICE}; +                                           $driver = $struct->{$str}{driver} = $ups_device->{driver}; +                                           push @new_devices, $str; +                                       } +                                   } +                               }, +                               name => sub { +                                   if (@new_devices) { +                                       N("Congratulations") . "\n\n" .  +                                         N("The wizard successfully added the following UPS devices:") . join("\n\n-", @new_devices); +                                     } else { +                                         N("No new UPS devices was found"); +                                     } +                               }, +                              }, +                      manual => { +                                name => N("UPS driver configuration")  . "\n\n" . N("Please select your UPS model."), +                                data => [ { label => N("Manufacturer / Model:"), val => \$ups, list => $model_list, +                                            type => 'combo', sort => 1, separator => '|' }, ], +                                post => sub { +                                    ($vendor, $model, $extra) = ($1, $2, $3) if $ups =~ /(.*)\|(.*) \((.*)\)$/; +                                    ($name, $driver, $port) = ("myups", $ups_models->{$vendor}{$model . $extra}{driver}, ""); +                                    ($driver, $opts) = split(/\s+/, $driver); +                                    "driver"; +                                }, +                               }, +                      driver => { +                                 name => sub { +                                     N("UPS driver configuration") . "\n\n" . N("We are configuring the \"%s\" UPS from \"%s\". +Please fill in its name, its driver and its port.", $model, $vendor); +                                 }, +                                 data => sub { +                                     [ +                                      { label => N("Name:"),   val => \$name, help => N("The name of your ups") }, +                                      { label => N("Driver:"), val => \$driver, help => N("The driver that manages your ups") }, +                                      { label => N("Port:"),   val => \$port, format => \&detect_devices::serialPort2text, type => "combo", +                                        list => [ &detect_devices::serialPorts() ], not_edit => 0,  +                                        help => N("The port on which is connected your ups") }, +                                     ]; +                                 }, +                                 post => sub { +                                     $port = '/dev/' . $port if $port !~ m!/dev/!; +                                     return 'end'; +                                 }, +                                }, +                      end => { +                              name => sub {  +                                  N("Congratulations") . "\n\n" . N("The wizard successfully configured the new \"%s\" UPS device.", +                                                                    $model . "|" . $vendor); +                              }, +                              end => 1, +                              no_back => 1, +                              next => 0 +                             }, +                     }, +           }); +    $wiz->process($in); + +    $config->{$name}{driver} = $driver; +    $config->{$name}{port} = $port; +    $config->{$name}{$1} = $2 if $opts =~ /\b(.*)=(.*)\b/; +    # refresh the GUI when needed: +    $models{ups}->append_set(1 => $name, 2 => $driver, 3 => $port) if $models{ups}; + +    log::explanations(qq(Configuring "$name" UPS)); +} + +my (@acls, @rules); + +sub load_access_conf() { +    foreach (cat_($files{access})) { +        s/#.*//; +        if (/^\s*ACL\s*(\S*)\s*(\S*)/) { +            my ($ip, $mask) = split('/', $2); +            push @acls, [ $1, $ip, $mask ]; +        } elsif (/^\s*ACCESS\s*(\S*)\s*(\S*)\s*(\S*)/) { +            push @rules, [ $1, $2, $3 ]; +        } +    } +} + + + +#------------------------------------------------------------------ +# misc gui data + +sub edit_row { +    my ($model, $o_iter) = @_; +    # create new item if needed (that is when adding a new one) at end of list +    my $iter = $o_iter || $model->append; +    my $dialog = Gtk3::Dialog->new; +    $dialog->set_transient_for($w->{real_window}); +    $dialog->set_modal(1); + +    gtkpack_($dialog->get_child, +             #map { +             #} +            ); + +    gtkadd($dialog->get_action_area, +           gtksignal_connect(Gtk3::Button->new(N("Ok")), clicked => sub { +                                 # create new item if needed (that is when adding a new one) at end of list +                                 $iter ||= $model->append; +                                 # $model->set($iter, 1 => $file->get_text); # FILL ME +                                 $dialog->destroy; +                                 # $modified++; +                             }), +           gtksignal_connect(Gtk3::Button->new(N("Cancel")), clicked => sub { $dialog->destroy }), +          ); +      +    $dialog->show_all; + +} + + +sub add_callback { +    my ($model, $_list, $_getindex) = @_; +    edit_row($model); +} + +sub edit_callback { +    my ($model, $list) = @_; +    my ($iter) = $list->get_selection->get_selected; +    return unless $iter; +    edit_row($model, $iter); +} + +sub del_callback { +    my ($model, $list) = @_; +    #my (undef, $iter) = $list->get_selection->get_selected; +    #my $removed_idx = $model->get($iter, 0); # 1st column is index +    #@rules = grep { $_->{index} ne $removed_idx } @rules; +    #$tree->remove($iter); +    #sensitive_buttons(0); +    #$modified++; +} + +my @pages = ( +             { name => N("UPS devices"), +               columns => [ N("Name"), N("Driver"), N("Port") ], # N("Manufacturer"), N("Model"),  +               callbacks => { +                             add => sub { +                                 eval { add_device_wizard($in, $struct) }; +                                 my $err = $@; +                                 die $err if $err && $err !~ /wizcancel/; +                                 $::WizardWindow->destroy if defined $::WizardWindow; +                                 undef $::WizardWindow; +                             }, +                             edit => sub {}, +                             remove => sub {}, +                            }, +               load => sub { +                   read_nut_config(); +                   map { [ $_, @{$struct->{$_}}{qw(driver port)} ] } keys %$struct; +               }, +               id => "ups", +             }, +             { name => N("UPS users"), +               columns => [ N("Name") ], +               callbacks => { +                             add => sub { +                                 my ($name) = @_; +                                 $users->{$name} = {}; +                             }, +                             edit => sub {}, +                             remove => sub {}, +                            }, +               load => sub { +                   $users = Libconf::Glueconf::NUT::Ups_conf->new({ filename => $files{users} }); +                   map { [ $_ ] } keys %$users; +               }, +               id => "users", +             }, +             { name => N("Access Control Lists"), +               columns => [ N("Name"), N("IP address"), N("IP mask") ], +               callbacks => { +                             add => sub {}, +                             edit => sub {}, +                             remove => sub {}, +                            }, +               load => sub {  +                   load_access_conf(); +                   @acls; +               }, +               id => "acls", +             }, +             { name => N("Rules"), +               columns => [ N("Action"), N("Level"), N("ACL name"), N("Password") ], +               callbacks => { +                             N("Add") => sub {}, +                             N("Edit") => sub {}, +                             N("Remove") => sub {}, +                            }, +                       +               load => sub { @rules }, # already loaded when we loaded acls +               id => "rules", +             }, +            ); + + +#------------------------------------------------------------------ +# initialize: + +#$in = 'interactive'->vnew('su'); # require_root_capability(); +$in = 'interactive'->vnew; + +$ugtk3::wm_icon = "drakups"; + +if (!$::testing) { +    $in->do_pkgs->ensure_is_installed('nut-server', '/usr/sbin/upsd') or $in->exit(1); +} + +if (member('--wizard', @ARGV)) { +    read_nut_config(); +    add_device_wizard($in, $struct); +    writeconf(); +    $in->exit($@ ? 1 : 0); +} + +$w = ugtk3->new(N("UPS Management")); +if (!$::isEmbedded) { +    mygtk3::register_main_window($w->{real_window}); +    $w->{window}->set_size_request(500, 550); +    $w->{rwindow}->set_title(N("DrakUPS")); +} + +#------------------------------------------------------------------ +# main window: + +my $_msg = N("Welcome to the UPS configuration tools"); + +$w->{window}->add(gtkpack_(Gtk3::VBox->new, +                           if_(!$::isEmbedded, 0, Gtk3::Banner->new('drakups', N("DrakUPS"))), +                           1, my $nb = Gtk3::Notebook->new, +                           0, create_okcancel(  +                                               { +                                                ok_clicked => sub {  +                                                    #$_->{save}->() foreach @pages; +                                                    writeconf(); +                                                    $w->exit; +                                                }, +                                                cancel_clicked => sub { $w->exit }, +                                               }, +                                             ), +                          ), +                 ); + +#------------------------------------------------------------------ +# build the notebook + +foreach my $i (@pages) { +    my $model = $models{$i->{id}} = Gtk3::ListStore->new("Glib::Int", ("Glib::String") x listlength(@{$i->{columns}})); +    my (%buttons, $list); +    $indexes{$i->{name}} = 0; +    my $idx = \$indexes{$i->{name}}; +    my $getindex = sub { $$idx++ }; +    $nb->append_page(gtkpack_(Gtk3::VBox->new, +                              1, create_scrolled_window($list = Gtk3::TreeView->new_with_model($model), +                                                        [ 'automatic', 'automatic' ]), +                              0, gtkpack(Gtk3::HButtonBox->new, +                                         (map {  +                                             my ($id, $label, $sub) = @$_; +                                             gtksignal_connect($buttons{$id} = Gtk3::Button->new($label), clicked => sub {  +								 $sub->($model, $list, $getindex); +							       }); +                                         } ([ 'add', N("Add"), $i->{callbacks}{add} || \&add_callback ], +                                            [ 'edit', N("Edit"), \&edit_callback ], +                                            [ 'remove', N("Remove"), \&del_callback ], +                                           ) +                                         ) +                                         #(map { +                                         #    gtksignal_connect(Gtk3::Button->new($_), clicked => $i->{callbacks}{$_}), +                                         #} keys %{$i->{callbacks}}) +                                        ), +                             ), +                     Gtk3::Label->new($i->{name}), +                    ); +    #$i->{list} = $list; +    each_index { +        $list->append_column(Gtk3::TreeViewColumn->new_with_attributes($_, Gtk3::CellRendererText->new, 'text' => $::i + 1)); +    } @{$i->{columns}}; +    my @u = $i->{load}->(); +    foreach my $line (@u) { +        $model->append_set(0 => $getindex->(), map_index { $::i + 1 => $_ } @$line); +    } +    my $set_sensitive = sub { +      my ($bool) = @_; +      $buttons{$_}->set_sensitive($bool) foreach qw(remove edit); +    }; +    $set_sensitive->(0); +    $list->get_selection->signal_connect('changed' => sub { +	my ($select) = @_; +	my (undef, $iter) = $select->get_selected; +	$set_sensitive->(defined $iter); +      }); +} + +#------------------------------------------------------------------ +# let's start the show: +$w->{rwindow}->show_all; +$w->main;  | 
