From 703b3d64b0e5a9f754340397149d5f820f6a08b6 Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Tue, 15 Dec 2009 16:31:13 +0000 Subject: [PATCH] New feature : convertConfig --- build/lemonldap-ng/Makefile | 3 +- build/lemonldap-ng/debian/README.Debian | 10 +- .../debian/liblemonldap-ng-conf-perl.install | 2 +- modules/lemonldap-ng-common/MANIFEST | 4 +- modules/lemonldap-ng-common/Makefile.PL | 2 +- .../lib/Lemonldap/NG/Common/Conf.pm | 16 +- .../lib/Lemonldap/NG/Common/Conf/DBI.pm | 3 +- .../lib/Lemonldap/NG/Common/Conf/RDBI.pm | 144 ++++++++++++++++++ .../Lemonldap/NG/Common/Conf/Serializer.pm | 7 +- .../lemonldap-ng-common/scripts/convertConfig | 66 ++++++++ .../scripts/lmConfig_File2LDIF | 109 ------------- .../scripts/lmConfig_File2MySQL | 111 -------------- 12 files changed, 232 insertions(+), 245 deletions(-) create mode 100644 modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/RDBI.pm create mode 100755 modules/lemonldap-ng-common/scripts/convertConfig delete mode 100755 modules/lemonldap-ng-common/scripts/lmConfig_File2LDIF delete mode 100755 modules/lemonldap-ng-common/scripts/lmConfig_File2MySQL diff --git a/build/lemonldap-ng/Makefile b/build/lemonldap-ng/Makefile index d1fd549a9..60ee3858f 100644 --- a/build/lemonldap-ng/Makefile +++ b/build/lemonldap-ng/Makefile @@ -202,8 +202,7 @@ install_bin: install_libs install_conf_dir @cp --preserve=mode --remove-destination \ ${SRCPORTALDIR}/example/scripts/purgeCentralCache \ ${SRCPORTALDIR}/example/scripts/buildPortalWSDL \ - ${SRCCOMMONDIR}/scripts/lmConfig_File2MySQL \ - ${SRCCOMMONDIR}/scripts/lmConfig_File2LDIF \ + ${SRCCOMMONDIR}/scripts/convertConfig \ ${SRCMANAGERDIR}/example/scripts/lmConfigEditor \ $(RBINDIR) chmod +x $(RBINDIR)/* diff --git a/build/lemonldap-ng/debian/README.Debian b/build/lemonldap-ng/debian/README.Debian index 6a0a21af9..5d4cd11ca 100644 --- a/build/lemonldap-ng/debian/README.Debian +++ b/build/lemonldap-ng/debian/README.Debian @@ -54,13 +54,5 @@ Modify /etc/lemonldap-ng/storage.conf to change configuration storage. 1.1 - Migrating from 'File' to 'DBI' -To use DBI mechanism to store configuration, you have to create database. An -example is given for MySQL in the file -/usr/share/doc/liblemonldap-ng-conf-perl/examples/lmConfig.mysql. -If you have a running configuration, use this to populate SQL database : - - perl /usr/share/lemonldap-ng/bin/lmConfig_File2MySQL -c \ - /var/lib/lemonldap-ng/conf/lmConf- - -"-c" options adds "create table" instruction. +Use the script /usr/share/lemonldap-ng/bin/convertConfig diff --git a/build/lemonldap-ng/debian/liblemonldap-ng-conf-perl.install b/build/lemonldap-ng/debian/liblemonldap-ng-conf-perl.install index 9e5cd89e9..ad1d44217 100644 --- a/build/lemonldap-ng/debian/liblemonldap-ng-conf-perl.install +++ b/build/lemonldap-ng/debian/liblemonldap-ng-conf-perl.install @@ -3,5 +3,5 @@ debian/tmp/etc/lemonldap-ng/for_etc_hosts debian/tmp/usr/share/perl5/Lemonldap/NG/Common* debian/tmp/usr/share/man/man3/Lemonldap::NG::Common* debian/tmp/usr/share/lemonldap-ng/ressources -debian/tmp/usr/share/lemonldap-ng/bin/lmConfig_File2MySQL +debian/tmp/usr/share/lemonldap-ng/bin/convertConfig debian/tmp/var/lib/lemonldap-ng/conf/ diff --git a/modules/lemonldap-ng-common/MANIFEST b/modules/lemonldap-ng-common/MANIFEST index 6d8cf145f..8f4c2fff8 100644 --- a/modules/lemonldap-ng-common/MANIFEST +++ b/modules/lemonldap-ng-common/MANIFEST @@ -12,6 +12,7 @@ lib/Lemonldap/NG/Common/Conf/CDBI.pm lib/Lemonldap/NG/Common/Conf/DBI.pm lib/Lemonldap/NG/Common/Conf/File.pm lib/Lemonldap/NG/Common/Conf/LDAP.pm +lib/Lemonldap/NG/Common/Conf/RDBI.pm lib/Lemonldap/NG/Common/Conf/SOAP.pm lib/Lemonldap/NG/Common/Conf/Serializer.pm lib/Lemonldap/NG/Common/Crypto.pm @@ -20,8 +21,7 @@ Makefile.PL MANIFEST META.yml Module meta-data (added by MakeMaker) README -scripts/lmConfig_File2LDIF -scripts/lmConfig_File2MySQL +scripts/convertConfig lemonldap-ng.ini t/01-Common-Conf.t t/02-Common-Conf-File.t diff --git a/modules/lemonldap-ng-common/Makefile.PL b/modules/lemonldap-ng-common/Makefile.PL index fa15cd881..080c1cfcb 100644 --- a/modules/lemonldap-ng-common/Makefile.PL +++ b/modules/lemonldap-ng-common/Makefile.PL @@ -34,7 +34,7 @@ WriteMakefile( 'HTTP::Headers' => 0, 'Config::IniFiles' => 0, }, # e.g., Module::Name => 1.1 - #EXE_FILES => [ 'scripts/lmConfig_File2MySQL', ], + #EXE_FILES => [ 'scripts/convertConfig', ], ( $] >= 5.005 ? ## Add these new keywords supported since 5.005 diff --git a/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm index 0f9155486..558a1573c 100644 --- a/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm +++ b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm @@ -10,7 +10,8 @@ package Lemonldap::NG::Common::Conf; use strict; no strict 'refs'; use Lemonldap::NG::Common::Conf::Constants; #inherits -use Lemonldap::NG::Common::Crypto; #link protected cipher Object "cypher" in configuration hash +use Lemonldap::NG::Common::Crypto + ; #link protected cipher Object "cypher" in configuration hash use Regexp::Assemble; use Config::IniFiles; @@ -100,9 +101,10 @@ sub saveConf { # If configuration was modified, return an error return CONFIG_WAS_CHANGED - if ( $conf->{cfgNum} != $self->lastCfg or $self->isLocked ); + if ( not( $self->{force} ) + and ( $conf->{cfgNum} != $self->lastCfg or $self->isLocked ) ); $self->lock or return DATABASE_LOCKED; - $conf->{cfgNum}++; + $conf->{cfgNum}++ unless ( $self->{cfgNumFixed} ); $msg = "Configuration $conf->{cfgNum} stored"; return $self->store($conf); } @@ -190,9 +192,7 @@ sub getLocalConf { } # Parse ini file - my $cfg = Config::IniFiles->new( - -file => $file, - ); + my $cfg = Config::IniFiles->new( -file => $file, ); unless ( defined $cfg ) { $msg = "Local config error: " . @Config::IniFiles::errors; @@ -351,6 +351,10 @@ sub delete { return &{ $self->{type} . '::delete' }( $self, $a[ $#a + $c ] ); } +sub logError { + return &{ $_[0]->{type} . '::logError' }(@_); +} + 1; __END__ diff --git a/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DBI.pm b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DBI.pm index e6d20198e..dfe13fffe 100644 --- a/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DBI.pm +++ b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DBI.pm @@ -91,11 +91,10 @@ sub store { $self->logError; return UNKNOWN_ERROR; } + eval { $self->dbh->do("COMMIT"); }; unless ( $self->unlock ) { $self->logError; - return UNKNOWN_ERROR; } - eval { $self->dbh->do("COMMIT"); }; return $fields->{cfgNum}; } diff --git a/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/RDBI.pm b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/RDBI.pm new file mode 100644 index 000000000..4fdc589c3 --- /dev/null +++ b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/RDBI.pm @@ -0,0 +1,144 @@ +package Lemonldap::NG::Common::Conf::RDBI; + +use strict; +use DBI; +use Lemonldap::NG::Common::Conf::Constants; #inherits +use Lemonldap::NG::Common::Conf::Serializer; + +our $VERSION = 0.17; + +BEGIN { + *Lemonldap::NG::Common::Conf::dbh = \&dbh; +} + +sub prereq { + my $self = shift; + unless ( $self->{dbiChain} ) { + $Lemonldap::NG::Common::Conf::msg = + '"dbiChain" is required in RDBI configuration type'; + return 0; + } + print STDERR __PACKAGE__ . 'Warning: "dbiUser" parameter is not set' + unless ( $self->{dbiUser} ); + $self->{dbiTable} ||= "lmConfig"; + 1; +} + +sub available { + my $self = shift; + my $sth = + $self->dbh->prepare( "SELECT DISTINCT cfgNum from " + . $self->{dbiTable} + . " order by cfgNum" ); + $sth->execute(); + my @conf; + while ( my @row = $sth->fetchrow_array ) { + push @conf, $row[0]; + } + return @conf; +} + +sub lastCfg { + my $self = shift; + my @row = $self->dbh->selectrow_array( + "SELECT max(cfgNum) from " . $self->{dbiTable} ); + return $row[0]; +} + +sub dbh { + my $self = shift; + $self->{dbiTable} ||= "lmConfig"; + return $self->{dbh} if ( $self->{dbh} and $self->{dbh}->ping ); + return DBI->connect_cached( + $self->{dbiChain}, $self->{dbiUser}, + $self->{dbiPassword}, { RaiseError => 1 } + ); +} + +sub lock { + my $self = shift; + my $sth = $self->dbh->prepare_cached( q{SELECT GET_LOCK(?, 5)}, {}, 1 ); + $sth->execute('lmconfrdbi'); + my @row = $sth->fetchrow_array; + return $row[0] || 0; +} + +sub isLocked { + my $self = shift; + my $sth = $self->dbh->prepare_cached( q{SELECT IS_FREE_LOCK(?)}, {}, 1 ); + $sth->execute('lmconfrdbi'); + my @row = $sth->fetchrow_array; + return $row[0] ? 0 : 1; +} + +sub unlock { + my $self = shift; + my $sth = $self->dbh->prepare_cached( q{SELECT RELEASE_LOCK(?)}, {}, 1 ); + $sth->execute('lmconfrdbi'); + my @row = $sth->fetchrow_array; + return $row[0] || 0; +} + +sub store { + my ( $self, $fields ) = @_; + $self->{noQuotes} = 1; + $fields = $self->serialize($fields); + my $errors = 0; + eval { $self->dbh->do('BEGIN'); }; + while ( my ( $k, $v ) = each %$fields ) { + unless ( + $self->dbh->do( + "insert into " + . $self->{dbiTable} + . " (cfgNum,field,value) values (" + . join( ',', $fields->{cfgNum}, "'$k'", "'$v'" ) . ')' + ) + ) + { + $self->logError; + $errors++; + last; + } + } + eval { $errors ? $self->dbh->do("ROLLBACK") : $self->dbh->do("COMMIT"); }; + unless ( $self->unlock ) { + $self->logError; + } + return $errors ? UNKNOWN_ERROR : $fields->{cfgNum}; +} + +sub load { + my ( $self, $cfgNum, $fields ) = @_; + $fields = $fields ? join( ",", @$fields ) : '*'; + my $sth = + $self->dbh->prepare( "SELECT cfgNum,field,value from " + . $self->{dbiTable} + . " WHERE cfgNum=$cfgNum" ); + $sth->execute(); + my ( $res, @row ); + while ( @row = $sth->fetchrow_array ) { + $res->{ $row[1] } = $row[2]; + } + unless($res) { + $Lemonldap::NG::Common::Conf::msg .= "No configuration $cfgNum found"; + return 0; + } + $res->{cfgNum} = $cfgNum; + return $self->unserialize($res); +} + +sub delete { + my ( $self, $cfgNum ) = @_; + $self->dbh->do( + "DELETE from " . $self->{dbiTable} . " WHERE cfgNum=$cfgNum" ); +} + +sub logError { + my $self = shift; + $Lemonldap::NG::Common::Conf::msg .= + "Database error: " . $self->dbh->errstr . "\n"; +} + +1; +__END__ + diff --git a/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm index 10c215bfb..9b065a927 100644 --- a/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm +++ b/modules/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm @@ -17,7 +17,7 @@ sub serialize { if ( ref($v) ) { $fields->{$k} = Dumper($v); $fields->{$k} =~ s/'/'/g; - $fields->{$k} = "'$fields->{$k}'"; + $fields->{$k} = "'$fields->{$k}'" unless ( $self->{noQuotes} ); } elsif ( $v =~ /^\d+$/ ) { $fields->{$k} = "$v"; @@ -29,7 +29,9 @@ sub serialize { # trim $v =~ s/^\s*(.*?)\s*$/$1/; - $fields->{$k} = "'$v'"; + $v =~ s/'/'/g; + $v = "'$v'" unless ( $self->{noQuotes} ); + $fields->{$k} = $v; } } return $fields; @@ -68,6 +70,7 @@ sub unserialize { } } else { + $v =~ s/&#?39;/'/g; $conf->{$k} = $v; } } diff --git a/modules/lemonldap-ng-common/scripts/convertConfig b/modules/lemonldap-ng-common/scripts/convertConfig new file mode 100755 index 000000000..b390173c7 --- /dev/null +++ b/modules/lemonldap-ng-common/scripts/convertConfig @@ -0,0 +1,66 @@ +#!/usr/bin/perl + +use strict; +use Getopt::Long; +use Lemonldap::NG::Common::Conf; + +my %opts; +my $result = GetOptions ( \%opts, 'help|h', 'current|c=s', 'new|n=s', 'latest|l' ); + +if( $opts{help} or not ( $opts{current} and $opts{new} ) ) { + print STDERR "Usage: $0 --current=/current/lemonldap-ng.ini --new=/new/lemonldap-ng.ini\n"; + print STDERR "# other parameters: + --latest -l + convert only last configuration +"; + exit 1; +} + +foreach( $opts{current}, $opts{new} ) { + unless( -e $_ ) { + print STDERR "$_ does not exist\n"; + exit 2; + } + unless( -r $_ ) { + print STDERR "$_ is not readable\n"; + exit 3; + } +} +my $old = Lemonldap::NG::Common::Conf->new({ + confFile => $opts{current}, + noCache=>1, +}); +unless($old) { + print STDERR "Failed to get current conf : $Lemonldap::NG::Common::Conf::msg\n"; + exit 4; +} +my $new = Lemonldap::NG::Common::Conf->new({ + confFile => $opts{new}, + force=>1, + noCache=>1, + cfgNumFixed=>1, +}); +unless($new) { + print STDERR "Failed to create new conf object : $Lemonldap::NG::Common::Conf::msg\n"; + exit 5; +} +my @available; +if($opts{lastest}){ + @available = $old->lastCfg(); + }else{ + @available = $old->available(); + } +foreach(@available) { + my $conf = $old->getConf({cfgNum=>$_}); + eval { delete $conf->{reVHosts}; + delete $conf->{cipher}; + }; + unless($conf){ + print STDERR "\nFailed to get conf $_ : $Lemonldap::NG::Common::Conf::msg\n"; + exit 6; + } + print "Conf $conf->{cfgNum}:"; + my $r = $new->saveConf($conf); + print ($r ? "stored" : "failed: $Lemonldap::NG::Common::Conf::msg"); + print "\n"; +} diff --git a/modules/lemonldap-ng-common/scripts/lmConfig_File2LDIF b/modules/lemonldap-ng-common/scripts/lmConfig_File2LDIF deleted file mode 100755 index dd2e52ae6..000000000 --- a/modules/lemonldap-ng-common/scripts/lmConfig_File2LDIF +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/perl - -eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' - if 0; # not running under some shell - -use Getopt::Std; -use Lemonldap::NG::Common::Conf; -use File::Basename; -use strict; - -# Get ARGS -my %opts; -getopts( 'b:c', \%opts ); - -&usage("configuration file required") - unless ( $ARGV[0] ); -&usage(qq#$ARGV[0] is not readable#) - unless ( -r $ARGV[0] ); -&usage("configuration branch required") - unless ( $opts{b} ); - -# Internal varibales -my $branch = $opts{b}; -my ( $branchname ) = ( $branch =~ /^ou=(.+?),/ ); -my ($filename, $directories, $suffix) = fileparse ( $ARGV[0] ); - - -# LDIF header -print "# LemonLDAP::NG configuration (converted from files)\n"; - -# Create configuration branch -if($opts{c}) { - print "dn: $branch -objectClass: top -objectClass: organizationalUnit -ou: $branchname\n\n"; -} - -# Create configuration entry -open FILE, $ARGV[0]; -$/ = ""; - -print "dn: cn=$filename,$branch -objectClass: top -objectClass: applicationProcess -cn: $filename\n"; - -while () { - my ( $k, $v ) = split /\n\s+/; - chomp $k; - next unless($k); - $v =~ s/\n*$//; - print "description: {$k}$v\n"; -} - -print "\n"; - -sub usage { - print STDERR shift; - print STDERR "\nusage: $0 file -Options: - -b branch : name of the configuration branch - -c : add 'create table' instruction\n\n"; - exit 1; -} -1; -__END__ - -=head1 NAME - -lmConfig_File2LDIF - Perl utility to convert Lemonldap::NG configuration file -into LDIF file. - -=head1 SYNOPSIS - - lmConf_File2LDIF /path/to/lmConf-1 - -=head1 DESCRIPTION - -Use this software to convert Lemonldap::NG configuration file into LDIF. - -=head2 Options - -=over - -=item * -b : name of the configuration branch - -=item * -c : create the configuration branch (organizationalUnit) - -=back - -=head1 SEE ALSO - -Lemonldap::NG::Manager - -=head1 AUTHOR - -Clement Oudot, Eclement@oodo.netE - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2007 by Xavier Guimard -Copyright (C) 2009 by Clement Oudot - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.8 or, -at your option, any later version of Perl 5 you may have available. - -=cut diff --git a/modules/lemonldap-ng-common/scripts/lmConfig_File2MySQL b/modules/lemonldap-ng-common/scripts/lmConfig_File2MySQL deleted file mode 100755 index 802c2ddaa..000000000 --- a/modules/lemonldap-ng-common/scripts/lmConfig_File2MySQL +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/perl - -use Getopt::Std; -use Lemonldap::NG::Common::Conf; -use strict; - -# Get ARGS -my %opts; -getopts( 'ct:', \%opts ); - - -usage("configuration file required") - unless ( $ARGV[0] ); -usage(qq#$ARGV[0] is not readable#) - unless ( -r $ARGV[0] ); - -my $table = $opts{t} || 'lmConfig'; -if($opts{c}) { - print "CREATE TABLE $table ( - cfgNum int not null primary key, - locationRules text, - exportedHeaders text, - globalStorage text, - globalStorageOptions text, - macros text, - groups text, - portal text, - domain text, - ldapServer text, - ldapPort int, - ldapBase text, - securedCookie int, - cookieName text, - authentication text, - exportedVars text, - managerDn text, - managerPassword text, - timeout int, - whatToTrace text\n);\n"; -} - -my $fields; -open FILE, $ARGV[0]; -$/ = ""; -while () { - my ( $k, $v ) = split /\n\s+/; - chomp $k; - next unless($k); - $v =~ s/\n*$//; - $fields->{$k} = $v; -} -print "INSERT INTO " - . $table . " (\n\t" - . join( ",\n\t", keys(%$fields) ) - . ")\n VALUES (\n\t" - . join( ",\n\t", values(%$fields) ) - . "\n );\n"; -close FILE; - -sub usage { - print STDERR shift; - print STDERR "\nusage: $0 file -Options: - -t table : name of the table (default: lmConfig) - -c : add 'create table' instruction\n"; - exit 1; -} -1; -__END__ - -=head1 NAME - -lmConfig_File2MySQL - Perl utility to convert Lemonldap::NG configuration file -into MySQL SQL file. - -=head1 SYNOPSIS - - lmConf_File2MySQL /path/to/lmConf-1 - -=head1 DESCRIPTION - -Use this software to convert Lemonldap::NG configuration file into SQL -instructions. - -=head2 Options - -=over - -=item * -c : add "create table" instruction - -=item * -t : name of the table (lmConfig by default) - -=back - -=head1 SEE ALSO - -Lemonldap::NG::Manager - -=head1 AUTHOR - -Xavier Guimard, Ex.guimard@free.frE - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2007 by Xavier Guimard - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.8 or, -at your option, any later version of Perl 5 you may have available. - -=cut