diff --git a/gosa-si/gosa-si-server b/gosa-si/gosa-si-server
index 61528f048d6522cff65ef50d52481509ca95b314..a6daf3fe11c0202a8767961dbb0858fcc11a3bc2 100755 (executable)
--- a/gosa-si/gosa-si-server
+++ b/gosa-si/gosa-si-server
# REVISION: ---
#===============================================================================
-
-# TODO
-#
-# max_children wird momentan nicht mehr verwendet, jede eingehende nachricht bekommt ein eigenes POE child
+my $server_version = '$HeadURL: https://oss.gonicus.de/repositories/gosa/trunk/gosa-si/gosa-si-server $:$Rev$';
use strict;
use warnings;
use Config::IniFiles;
use POSIX;
-use Fcntl;
+use Fcntl qw/:flock/;
use IO::Socket::INET;
use IO::Handle;
use IO::Select;
use XML::Simple;
use Data::Dumper;
use Sys::Syslog qw( :DEFAULT setlogsock);
+use Time::HiRes qw( usleep);
use Cwd;
use File::Spec;
use File::Basename;
use POE qw(Component::Server::TCP Wheel::Run Filter::Reference);
use Net::LDAP;
use Net::LDAP::Util qw(:escape);
-use Time::HiRes qw( usleep);
+use ResourcePool;
+use ResourcePool::Factory::Net::LDAP;
+
+# revision number of server and program name
+my $server_headURL;
+my $server_revision;
+my $server_status;
+our $prg= basename($0);
my $db_module = "DBsqlite";
{
my $modules_path = "/usr/lib/gosa-si/modules";
use lib "/usr/lib/gosa-si/modules";
-# revision number of server and program name
-my $server_version = '$HeadURL: https://oss.gonicus.de/repositories/gosa/trunk/gosa-si/gosa-si-server $:$Rev: 10826 $';
-my $server_headURL;
-my $server_revision;
-my $server_status;
-our $prg= basename($0);
-
our $global_kernel;
my ($foreground, $ping_timeout);
my ($server);
my ($gosa_server, $job_queue_timeout, $job_queue_loop_delay);
my ($messaging_db_loop_delay);
my ($procid, $pid);
-my ($arp_fifo);
+my ($arp_fifo, $ldap_pool, $ldap_factory);
my ($xml);
my $sources_list;
my $max_clients;
our $verbose;
our $forground;
our $cfg_file;
-our ($ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password, $ldap_server_dn);
+our ($ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password, $ldap_server_dn, $ldap_version);
our ($mysql_username, $mysql_password, $mysql_database, $mysql_host);
our $known_modules;
our $root_uid;
our $incoming_db;
our $incoming_tn = 'incoming';
my $incoming_file_name;
-my @incoming_col_names = ("id INTEGER PRIMARY KEY auto_increment",
+my @incoming_col_names = ("id INTEGER PRIMARY KEY",
"timestamp VARCHAR(14) DEFAULT 'none'",
"headertag VARCHAR(255) DEFAULT 'none'",
"targettag VARCHAR(255) DEFAULT 'none'",
our $job_db;
our $job_queue_tn = 'jobs';
my $job_queue_file_name;
-my @job_queue_col_names = ("id INTEGER PRIMARY KEY auto_increment",
+my @job_queue_col_names = ("id INTEGER PRIMARY KEY",
"timestamp VARCHAR(14) DEFAULT 'none'",
"status VARCHAR(255) DEFAULT 'none'",
"result TEXT",
@@ -180,7 +178,7 @@ my @foreign_clients_col_names = ("hostname VARCHAR(255)", "macaddress VARCHAR(17
our $login_users_db;
our $login_users_tn = "login_users";
my $login_users_file_name;
-my @login_users_col_names = ("client VARCHAR(255)", "user VARCHAR(255)", "timestamp VARCHAR(14)");
+my @login_users_col_names = ("client VARCHAR(255)", "user VARCHAR(255)", "timestamp VARCHAR(14)", "regserver VARCHAR(255) DEFAULT 'localhost'");
# holds all fai server, the debian release and tag
our $fai_server_db;
"ldap-base" => [\$ldap_base, ""],
"ldap-admin-dn" => [\$ldap_admin_dn, ""],
"ldap-admin-password" => [\$ldap_admin_password, ""],
+ "ldap-version" => [\$ldap_version, 3],
"gosa-unit-tag" => [\$gosa_unit_tag, ""],
"max-clients" => [\$max_clients, 10],
"wol-password" => [\$wake_on_lan_passwd, ""],
- "mysql-username" => [\$mysql_username, "gosa_si"],
- "mysql-password" => [\$mysql_password, ""],
- "mysql-database" => [\$mysql_database, "gosa_si"],
- "mysql-host" => [\$mysql_host, "127.0.0.1"],
+ "mysql-username" => [\$mysql_username, "gosa_si"],
+ "mysql-password" => [\$mysql_password, ""],
+ "mysql-database" => [\$mysql_database, "gosa_si"],
+ "mysql-host" => [\$mysql_host, "127.0.0.1"],
},
"GOsaPackages" => {
"job-queue" => [\$job_queue_file_name, '/var/lib/gosa-si/jobs.db'],
if(not defined $msg) { return }
if(not defined $level) { $level = 1 }
if(defined $log_file){
- open(LOG_HANDLE, ">>$log_file");
- if(not defined open( LOG_HANDLE, ">>$log_file" )) {
+ my $open_log_fh = sysopen(LOG_HANDLE, $log_file, O_WRONLY | O_CREAT | O_APPEND , 0440);
+ if(not $open_log_fh) {
print STDERR "cannot open $log_file: $!";
- return
+ return;
+ }
+ # check owner and group of log_file and update settings if necessary
+ my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat($log_file);
+ if((not $uid eq $root_uid) || (not $gid eq $adm_gid)) {
+ chown($root_uid, $adm_gid, $log_file);
}
+
chomp($msg);
#$msg =~s/\n//g; # no newlines are allowed in log messages, this is important for later log parsing
if($level <= $verbose){
my $name = $prg;
my $log_msg = "$month $monthday $hours:$minutes:$seconds $name $msg\n";
+ flock(LOG_HANDLE, LOCK_EX);
+ seek(LOG_HANDLE, 0, 2);
print LOG_HANDLE $log_msg;
+ flock(LOG_HANDLE, LOCK_UN);
if( $foreground ) {
print STDERR $log_msg;
}
}
opendir (DIR, $modules_path) or die "ERROR while loading modules from directory $modules_path : $!\n";
+
+ my $ldap_handle = &get_ldap_handle;
while (defined (my $file = readdir (DIR))) {
if (not $file =~ /(\S*?).pm$/) {
next;
daemon_log("$@", 1);
exit;
} else {
- my $info = eval($mod_name.'::get_module_info()');
+ my $info = eval($mod_name.'::get_module_info($ldap_handle)');
# Only load module if get_module_info() returns a non-null object
if( $info ) {
my ($input_address, $input_key, $event_hash) = @{$info};
}
}
}
-
+ &release_ldap_handle($ldap_handle);
close (DIR);
}
}
-#sub get_local_ip_for_remote_ip {
-# my $remote_ip= shift;
-# my $result="0.0.0.0";
-#
-# if($remote_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
-# if($remote_ip eq "127.0.0.1") {
-# $result = "127.0.0.1";
-# } else {
-# my $PROC_NET_ROUTE= ('/proc/net/route');
-#
-# open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
-# or die "Could not open $PROC_NET_ROUTE";
-#
-# my @ifs = <PROC_NET_ROUTE>;
-#
-# close(PROC_NET_ROUTE);
-#
-# # Eat header line
-# shift @ifs;
-# chomp @ifs;
-# foreach my $line(@ifs) {
-# my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
-# my $destination;
-# my $mask;
-# my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
-# $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
-# ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
-# $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
-# if(new NetAddr::IP($remote_ip)->within(new NetAddr::IP($destination, $mask))) {
-# # destination matches route, save mac and exit
-# $result= &get_ip($Iface);
-# last;
-# }
-# }
-# }
-# } else {
-# daemon_log("0 WARNING: get_local_ip_for_remote_ip() was called with a non-ip parameter: '$remote_ip'", 1);
-# }
-# return $result;
-#}
-
-
sub send_msg_to_target {
my ($msg, $address, $encrypt_key, $msg_header, $session_id) = @_ ;
my $error = 0;
sub update_jobdb_status_for_send_msgs {
- my ($answer, $error) = @_;
+ my ($session_id, $answer, $error) = @_;
+ &daemon_log("$session_id DEBUG: try to update job status", 7);
if( $answer =~ /<jobdb_id>(\d+)<\/jobdb_id>/ ) {
my $jobdb_id = $1;
+
+ $answer =~ /<header>(.*)<\/header>/;
+ my $job_header = $1;
+
+ $answer =~ /<target>(.*)<\/target>/;
+ my $job_target = $1;
- # sending msg faild
+ # Sending msg failed
if( $error ) {
- if (not $answer =~ /<header>trigger_action_reinstall<\/header>/) {
+
+ # Set jobs to done, jobs do not need to deliver their message in any case
+ if (($job_header eq "trigger_action_localboot")
+ ||($job_header eq "trigger_action_lock")
+ ||($job_header eq "trigger_action_halt")
+ ) {
+ my $sql_statement = "UPDATE $job_queue_tn SET status='done' WHERE id=$jobdb_id";
+ &daemon_log("$session_id DEBUG: $sql_statement", 7);
+ my $res = $job_db->update_dbentry($sql_statement);
+
+ # Reactivate jobs, jobs need to deliver their message
+ } elsif (($job_header eq "trigger_action_activate")
+ ||($job_header eq "trigger_action_update")
+ ||($job_header eq "trigger_action_reinstall")
+ ||($job_header eq "trigger_activate_new")
+ ) {
+ &reactivate_job_with_delay($session_id, $job_target, $job_header, 30 );
+
+ # For all other messages
+ } else {
my $sql_statement = "UPDATE $job_queue_tn ".
"SET status='error', result='can not deliver msg, please consult log file' ".
"WHERE id=$jobdb_id";
+ &daemon_log("$session_id DEBUG: $sql_statement", 7);
my $res = $job_db->update_dbentry($sql_statement);
}
- # sending msg was successful
+ # Sending msg was successful
} else {
- my $sql_statement = "UPDATE $job_queue_tn ".
- "SET status='done' ".
- "WHERE id=$jobdb_id AND status='processed'";
- my $res = $job_db->update_dbentry($sql_statement);
- }
+ # Set jobs localboot, lock, activate, halt, reboot and wake to done
+ # jobs reinstall, update, inst_update do themself setting to done
+ if (($job_header eq "trigger_action_localboot")
+ ||($job_header eq "trigger_action_lock")
+ ||($job_header eq "trigger_action_activate")
+ ||($job_header eq "trigger_action_halt")
+ ||($job_header eq "trigger_action_reboot")
+ ||($job_header eq "trigger_action_wake")
+ ||($job_header eq "trigger_wake")
+ ) {
+
+ my $sql_statement = "UPDATE $job_queue_tn ".
+ "SET status='done' ".
+ "WHERE id=$jobdb_id AND status='processed'";
+ &daemon_log("$session_id DEBUG: $sql_statement", 7);
+ my $res = $job_db->update_dbentry($sql_statement);
+ } else {
+ &daemon_log("$session_id DEBUG: sending message succeed but cannot update job status.", 7);
+ }
+ }
+ } else {
+ &daemon_log("$session_id DEBUG: cannot update job status, msg has no jobdb_id-tag: $answer", 7);
}
}
+sub reactivate_job_with_delay {
+ my ($session_id, $target, $header, $delay) = @_ ;
+ # Sometimes the client is still booting or does not wake up, in this case reactivate the job (if it exists) with a delay of n sec
+
+ if (not defined $delay) { $delay = 30 } ;
+ my $delay_timestamp = &calc_timestamp(&get_time(), "plus", $delay);
+
+ my $sql = "UPDATE $job_queue_tn Set timestamp='$delay_timestamp', status='waiting' WHERE (macaddress='$target' AND headertag='$header')";
+ my $res = $job_db->update_dbentry($sql);
+ daemon_log("$session_id INFO: '$header'-job will be reactivated at '$delay_timestamp' ".
+ "cause client '$target' is currently not available", 5);
+ daemon_log("$session_id $sql", 7);
+ return;
+}
+
sub sig_handler {
my ($kernel, $signal) = @_[KERNEL, ARG0] ;
my ($msg, $msg_hash, $module);
my $error = 0;
- # hole neue msg aus @msgs_to_decrypt
- my $next_msg = shift @msgs_to_decrypt;
+ # fetch new msg out of @msgs_to_decrypt
+ my $tmp_next_msg = shift @msgs_to_decrypt;
+ my ($next_msg, $msg_source) = split(/;/, $tmp_next_msg);
# msg is from a new client or gosa
($msg, $msg_hash, $module) = &input_from_unknown_host($next_msg, $session_id);
if(( !$msg ) || ( !$msg_hash ) || ( !$module )){
# if an incoming msg could not be decrypted (maybe a wrong key), send client a ping. If the client
# could not understand a msg from its server the client cause a re-registering process
+ my $remote_ip = $heap->{'remote_ip'};
+ my $remote_port = $heap->{'remote_port'};
+ my $ping_msg = "<xml> <header>gosa_ping</header> <source>$server_address</source><target>$msg_source</target></xml>";
+ my ($test_error, $test_error_string) = &send_msg_to_target($ping_msg, "$msg_source", "dummy-key", "gosa_ping", $session_id);
+
daemon_log("$session_id WARNING cannot understand incoming msg, send 'ping'-msg to all host with ip '".$heap->{remote_ip}.
"' to cause a re-registering of the client if necessary", 3);
- my $sql_statement = "SELECT * FROM $main::known_clients_tn WHERE (hostname LIKE '".$heap->{'remote_ip'}."%')";
- my $query_res = $known_clients_db->select_dbentry( $sql_statement );
- while( my ($hit_num, $hit) = each %{ $query_res } ) {
- my $host_name = $hit->{'hostname'};
- my $host_key = $hit->{'hostkey'};
- my $ping_msg = "<xml> <header>gosa_ping</header> <source>$server_address</source> <target>$host_name</target></xml>";
- my $error = &send_msg_to_target($ping_msg, $host_name, $host_key, "gosa_ping", $session_id);
- &update_jobdb_status_for_send_msgs($ping_msg, $error);
- }
$error++;
}
&& $not_found_in_known_server_db
&& $not_found_in_known_clients_db) {
&daemon_log("$session_id DEBUG: target is not in foreign_clients_db, known_server_db or known_clients_db, maybe it is a complete new one -> process here", 7);
+ if ($header =~ /^gosa_/ || $header =~ /^job_/) {
+ $module = "GosaPackages";
+ }
my $res = $incoming_db->add_dbentry( {table=>$incoming_tn,
primkey=>[],
headertag=>$header,
sub next_task {
- my ($session, $heap, $task) = @_[SESSION, HEAP, ARG0];
+ my ($session, $heap, $task, $ldap_handle) = @_[SESSION, HEAP, ARG0, ARG1];
my $running_task = POE::Wheel::Run->new(
- Program => sub { process_task($session, $heap, $task) },
+ Program => sub { process_task($session, $heap, $task, $ldap_handle) },
StdioFilter => POE::Filter::Reference->new(),
StdoutEvent => "task_result",
StderrEvent => "task_debug",
CloseEvent => "task_done",
);
$heap->{task}->{ $running_task->ID } = $running_task;
+ $heap->{ldap_handle}->{$running_task->ID} = $ldap_handle;
}
sub handle_task_result {
sub handle_task_done {
my ( $kernel, $heap, $task_id ) = @_[ KERNEL, HEAP, ARG0 ];
delete $heap->{task}->{$task_id};
+ if (exists $heap->{ldap_handle}->{$task_id}) {
+ &release_ldap_handle($heap->{ldap_handle}->{$task_id});
+ }
}
sub process_task {
no strict "refs";
#CHECK: Not @_[...]?
- my ($session, $heap, $task) = @_;
+ my ($session, $heap, $task, $ldap_handle) = @_;
my $error = 0;
my $answer_l;
my ($answer_header, @answer_target_l, $answer_source);
# set timestamp of incoming client uptodate, so client will not
# be deleted from known_clients because of expiration
- my $act_time = &get_time();
- my $sql = "UPDATE $known_clients_tn SET timestamp='$act_time' WHERE hostname='$source'";
+ my $cur_time = &get_time();
+ my $sql = "UPDATE $known_clients_tn SET timestamp='$cur_time' WHERE hostname='$source'";
my $res = $known_clients_db->exec_statement($sql);
######################
if( $error == 0) {
daemon_log("$session_id INFO: Incoming msg (session_id=$session_id) with header '".@{$msg_hash->{'header'}}[0]."'", 5);
daemon_log("$session_id DEBUG: Processing module ".$module, 7);
- $answer_l = &{ $module."::process_incoming_msg" }($msg, $msg_hash, $session_id);
+ $answer_l = &{ $module."::process_incoming_msg" }($msg, $msg_hash, $session_id, $ldap_handle);
if ( 0 < @{$answer_l} ) {
my $answer_str = join("\n", @{$answer_l});
my $host_name = $hit->{hostname};
my $host_key = $hit->{hostkey};
my $error = &send_msg_to_target($answer, $host_name, $host_key, $answer_header, $session_id);
- &update_jobdb_status_for_send_msgs($answer, $error);
+ &update_jobdb_status_for_send_msgs($session_id, $answer, $error);
}
}
my $host_key = $hit->{hostkey};
$answer =~ s/<target>\S+<\/target>/<target>$host_name<\/target>/g;
my $error = &send_msg_to_target($answer, $host_name, $host_key, $answer_header, $session_id);
- &update_jobdb_status_for_send_msgs($answer, $error);
+ &update_jobdb_status_for_send_msgs($session_id, $answer, $error);
}
}
my $header;
if( defined $1 ) { $header = $1; }
my $error = &send_msg_to_target($answer, $server_address, $GosaPackages_key, $header, $session_id);
- &update_jobdb_status_for_send_msgs($answer, $error);
+ &update_jobdb_status_for_send_msgs($session_id, $answer, $error);
}
# Target of msg is a mac address
elsif( $answer_target =~ /^([0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2})$/i ) {
daemon_log("$session_id INFO: target is mac address '$answer_target', looking for host in known_clients and foreign_clients", 5);
+
+ # Looking for macaddress in known_clients
my $sql_statement = "SELECT * FROM known_clients WHERE macaddress LIKE '$answer_target'";
my $query_res = $known_clients_db->select_dbentry( $sql_statement );
my $found_ip_flag = 0;
$answer =~ s/$answer_target/$host_name/g;
daemon_log("$session_id INFO: found host '$host_name', associated to '$answer_target'", 5);
my $error = &send_msg_to_target($answer, $host_name, $host_key, $answer_header, $session_id);
- &update_jobdb_status_for_send_msgs($answer, $error);
+ &update_jobdb_status_for_send_msgs($session_id, $answer, $error);
$found_ip_flag++ ;
}
+
+ # Looking for macaddress in foreign_clients
if ($found_ip_flag == 0) {
my $sql = "SELECT * FROM $foreign_clients_tn WHERE macaddress LIKE '$answer_target'";
my $res = $foreign_clients_db->select_dbentry($sql);
if (defined $reg_server_key) {
$answer =~ s/$answer_target/$host_name/g;
my $error = &send_msg_to_target($answer, $reg_server, $reg_server_key, $answer_header, $session_id);
- &update_jobdb_status_for_send_msgs($answer, $error);
+ &update_jobdb_status_for_send_msgs($session_id, $answer, $error);
$found_ip_flag++ ;
}
}
}
+
+ # No mac to ip matching found
if( $found_ip_flag == 0) {
- daemon_log("$session_id WARNING: no host found in known_clients with mac address '$answer_target'", 3);
+ daemon_log("$session_id WARNING: no host found in known_clients or foreign_clients with mac address '$answer_target'", 3);
+ &reactivate_job_with_delay($session_id, $answer_target, $answer_header, 30);
}
# Answer is for one specific host
next;
}
my $error = &send_msg_to_target($answer, $answer_target, $encrypt_key, $answer_header,$session_id);
- &update_jobdb_status_for_send_msgs($answer, $error);
+ &update_jobdb_status_for_send_msgs($session_id, $answer, $error);
}
}
}
sub watch_for_done_jobs {
- #CHECK: $heap for what?
- my ($kernel,$heap) = @_[KERNEL, HEAP];
+ #CHECK: $heap for what?
+ my ($kernel,$heap) = @_[KERNEL, HEAP];
- my $sql_statement = "SELECT * FROM ".$job_queue_tn." WHERE ((status='done') AND (modified='0'))";
+ my $sql_statement = "SELECT * FROM ".$job_queue_tn." WHERE ((status='done') AND (modified='0'))";
my $res = $job_db->select_dbentry( $sql_statement );
- while( my ($id, $hit) = each %{$res} ) {
- my $jobdb_id = $hit->{id};
- my $sql_statement = "DELETE FROM $job_queue_tn WHERE id=$jobdb_id";
- my $res = $job_db->del_dbentry($sql_statement);
- }
+ while( my ($id, $hit) = each %{$res} ) {
+ my $jobdb_id = $hit->{id};
+ my $sql_statement = "DELETE FROM $job_queue_tn WHERE id=$jobdb_id";
+ my $res = $job_db->del_dbentry($sql_statement);
+ }
- $kernel->delay_set('watch_for_done_jobs',$job_queue_loop_delay);
+ $kernel->delay_set('watch_for_done_jobs',$job_queue_loop_delay);
}
sub watch_for_modified_jobs {
my ($kernel,$heap) = @_[KERNEL, HEAP];
- my $sql_statement = "SELECT * FROM $job_queue_tn WHERE ((siserver='localhost') AND (modified='1'))";
+ my $sql_statement = "SELECT * FROM $job_queue_tn WHERE (modified='1')";
my $res = $job_db->select_dbentry( $sql_statement );
# if db contains no jobs which should be update, do nothing
if(defined($res_2) and defined @{$res_2}[0]) {
# Set status from goto-activation to 'waiting' and update timestamp
$job_db->exec_statement("UPDATE $job_queue_tn SET status='waiting' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
- $job_db->exec_statement("UPDATE $job_queue_tn SET timestamp='".&get_time(30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
+ $job_db->exec_statement("UPDATE $job_queue_tn SET timestamp='".&calc_timestamp(&get_time(), 'plus', 30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'");
}
}
next;
$job_msg =~ /<header>(\S+)<\/header>/;
my $header = $1 ;
- my $func_error = &send_msg_to_target($job_msg, $server_address, $GosaPackages_key, $header, "J");
+ my $func_error = &send_msg_to_target($job_msg, $server_address, $GosaPackages_key, $header, "J");
+
+ # update status in job queue to ...
+ # ... 'processing', for jobs: 'reinstall', 'update'
+ if (($header =~ /gosa_trigger_action_reinstall/)
+ || ($header =~ /gosa_trigger_activate_new/)
+ || ($header =~ /gosa_trigger_action_update/)) {
+ my $sql_statement = "UPDATE $job_queue_tn SET status='processing' WHERE id=$jobdb_id";
+ my $dbres = $job_db->update_dbentry($sql_statement);
+ }
- # update status in job queue to 'processing'
- $sql_statement = "UPDATE $job_queue_tn SET status='processing' WHERE id=$jobdb_id";
- my $res = $job_db->update_dbentry($sql_statement);
-# TODO: abfangen ob alles in ordnung ist oder nicht, wenn nicht error schmeißen
+ # ... 'done', for all other jobs, they are no longer needed in the jobqueue
+ else {
+ my $sql_statement = "UPDATE $job_queue_tn SET status='done' WHERE id=$jobdb_id";
+ my $dbres = $job_db->update_dbentry($sql_statement);
+ }
+
# We don't want parallel processing
last;
attrs => ['memberUid'],
filter => "cn=$group_name",
);
+ &release_ldap_handle($ldap_handle);
if ($mesg->count) {
my @entries = $mesg->entries;
foreach my $entry (@entries) {
my @receivers= $entry->get_value("memberUid");
foreach my $receiver (@receivers) {
- $receiver_h{$1} = 0;
+ $receiver_h{$receiver} = 0;
}
}
}
#&daemon_log("0 DEBUG: $sql", 7);
my $res = $login_users_db->exec_statement($sql);
- # reciver is logged in nowhere
+ # receiver is logged in nowhere
if (not ref(@$res[0]) eq "ARRAY") { next; }
+ # receiver ist logged in at a client registered at local server
my $send_succeed = 0;
foreach my $hit (@$res) {
my $receiver_host = @$hit[0];
my $sql_statement = "SELECT * FROM $known_clients_tn";
my $res = $known_clients_db->select_dbentry( $sql_statement );
- my $act_time = int(&get_time());
+ my $cur_time = int(&get_time());
while ( my ($hit_num, $hit) = each %$res) {
my $expired_timestamp = int($hit->{'timestamp'});
$dt->add( seconds => 2 * int($hit->{'keylifetime'}) );
$expired_timestamp = $dt->ymd('').$dt->hms('');
- if ($act_time > $expired_timestamp) {
+ if ($cur_time > $expired_timestamp) {
my $hostname = $hit->{'hostname'};
my $del_sql = "DELETE FROM $known_clients_tn WHERE hostname='$hostname'";
my $del_res = $known_clients_db->exec_statement($del_sql);
my $message_id = $hit->{'id'};
my $session_id = $hit->{'sessionid'};
&daemon_log("$session_id DEBUG: start processing for message with incoming id: '$message_id'", 7);
- $kernel->yield('next_task', $hit);
+
+ my $ldap_handle = &get_ldap_handle();
+ if (not defined $ldap_handle) { next; }
+ $kernel->yield('next_task', $hit, $ldap_handle);
my $sql = "DELETE FROM $incoming_tn WHERE id=$message_id";
my $res = $incoming_db->exec_statement($sql);
sub get_ldap_handle {
my ($session_id) = @_;
my $heap;
- my $ldap_handle;
if (not defined $session_id ) { $session_id = 0 };
if ($session_id =~ /[^0-9]*/) { $session_id = 0 };
- if ($session_id == 0) {
- daemon_log("$session_id DEBUG: get_ldap_handle invoked without a session_id, create a new ldap_handle", 7);
- $ldap_handle = Net::LDAP->new( $ldap_uri );
- if (defined $ldap_handle) {
- $ldap_handle->bind($ldap_admin_dn, password => $ldap_admin_password) or daemon_log("$session_id ERROR: Bind to LDAP $ldap_uri as $ldap_admin_dn failed!");
- } else {
- daemon_log("$session_id ERROR: creation of a new LDAP handle failed (ldap_uri '$ldap_uri')");
- }
-
- } else {
- my $session_reference = $global_kernel->ID_id_to_session($session_id);
- if( defined $session_reference ) {
- $heap = $session_reference->get_heap();
- }
-
- if (not defined $heap) {
- daemon_log("$session_id DEBUG: cannot get heap for session_id '$session_id'", 7);
- return;
- }
+ (my $package, my $file, my $row, my $subroutine, my $hasArgs, my $wantArray, my $evalText, my $isRequire) = caller(1);
+ my $caller_text = "subroutin $subroutine";
+ if ($subroutine eq "(eval)") {
+ $caller_text = "eval block within file '$file' for '$evalText'";
+ }
+ daemon_log("$session_id INFO: new ldap handle for $caller_text required");
- # TODO: This "if" is nonsense, because it doesn't prove that the
- # used handle is still valid - or if we've to reconnect...
- #if (not exists $heap->{ldap_handle}) {
- $ldap_handle = Net::LDAP->new( $ldap_uri );
- $ldap_handle->bind($ldap_admin_dn, password => $ldap_admin_password) or daemon_log("$session_id ERROR: Bind to LDAP $ldap_uri as $ldap_admin_dn failed!");
- $heap->{ldap_handle} = $ldap_handle;
- #}
+ my $ldap_handle = $ldap_pool->get();
+
+ if (not defined $ldap_handle) {
+ daemon_log("$session_id INFO: ldap handle for $caller_text not available");
}
+ daemon_log("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
return $ldap_handle;
}
+sub release_ldap_handle {
+ my ($ldap_handle) = @_ ;
+ $ldap_pool->free($ldap_handle);
+ daemon_log("0 INFO: ldap handle released!\n-------------------------------------------------------------------------------");
+ return;
+}
+
sub change_fai_state {
my ($st, $targets, $session_id) = @_;
my $state= $mapActions{ $st };
- my $ldap_handle = &get_ldap_handle($session_id);
- if( defined($ldap_handle) ) {
+ #if( defined($ldap_handle) ) {
# Build search filter for hosts
my $search= "(&(objectClass=GOhard)";
return;
}
+ my $ldap_handle = &get_ldap_handle($session_id);
# Perform search for Unit Tag
my $mesg = $ldap_handle->search(
base => $ldap_base,
my %tmp = map { $_ => 1 } $entry->get_value("objectClass");
if (exists $tmp{'FAIobject'}){
if ($state eq ''){
- $result= $ldap_handle->modify($entry->dn, changes => [
- delete => [ FAIstate => [] ] ]);
+ $result= $ldap_handle->modify($entry->dn, changes => [ delete => [ FAIstate => [] ] ]);
} else {
- $result= $ldap_handle->modify($entry->dn, changes => [
- replace => [ FAIstate => $state ] ]);
+ $result= $ldap_handle->modify($entry->dn, changes => [ replace => [ FAIstate => $state ] ]);
}
} elsif ($state ne ''){
- $result= $ldap_handle->modify($entry->dn, changes => [
- add => [ objectClass => 'FAIobject' ],
- add => [ FAIstate => $state ] ]);
+ $result= $ldap_handle->modify($entry->dn, changes => [ add => [ objectClass => 'FAIobject' ], add => [ FAIstate => $state ] ]);
}
# Errors?
} else {
daemon_log("$session_id ERROR: LDAP search failed: ldap_base=$ldap_base, filter=$search", 1);
}
+ &release_ldap_handle($ldap_handle);
# if no ldap handle defined
- } else {
- daemon_log("$session_id ERROR: no LDAP handle defined for update FAIstate", 1);
- }
+ #} else {
+ # daemon_log("$session_id ERROR: no LDAP handle defined for update FAIstate", 1);
+ #}
return;
}
daemon_log("$session_id INFO: Setting gotoMode to '$state' for ".$entry->dn, 5);
my $result;
- $result= $ldap_handle->modify($entry->dn, changes => [
- replace => [ gotoMode => $state ] ]);
+ $result= $ldap_handle->modify($entry->dn, changes => [replace => [ gotoMode => $state ] ]);
# Errors?
if ($result->code){
}
}
+ &release_ldap_handle($ldap_handle);
+ return;
}
sub run_create_fai_server_db {
my ($kernel, $session, $heap, $table_name) = @_[KERNEL, SESSION, HEAP, ARG0];
my $session_id = $session->ID;
+ my $ldap_handle = &get_ldap_handle();
+ if (not defined $ldap_handle) {
+ $kernel->delay_set('create_fai_server_db', 1, $table_name);
+ return;
+ }
my $task = POE::Wheel::Run->new(
- Program => sub { &create_fai_server_db($table_name,$kernel, undef, $session_id) },
+ Program => sub { &create_fai_server_db($table_name,$kernel, undef, $session_id, $ldap_handle) },
StdoutEvent => "session_run_result",
StderrEvent => "session_run_debug",
CloseEvent => "session_run_done",
);
$heap->{task}->{ $task->ID } = $task;
+ $heap->{ldap_handle}->{$task->ID} = $ldap_handle;
return;
}
sub create_fai_server_db {
- my ($table_name, $kernel, $dont_create_packages_list, $session_id) = @_;
+ my ($table_name, $kernel, $dont_create_packages_list, $session_id, $ldap_handle) = @_;
my $result;
if (not defined $session_id) { $session_id = 0; }
- my $ldap_handle = &get_ldap_handle();
if(defined($ldap_handle)) {
daemon_log("$session_id INFO: create_fai_server_db: start", 5);
my $mesg= $ldap_handle->search(
# TODO: Find a way to post the 'create_packages_list_db' event
if(not defined($dont_create_packages_list)) {
- &create_packages_list_db(undef, undef, $session_id);
+ &create_packages_list_db(undef, $session_id);
}
}
- $ldap_handle->disconnect;
return $result;
}
sub run_create_fai_release_db {
- my ($session, $heap, $table_name) = @_[SESSION, HEAP, ARG0];
+ my ($kernel, $session, $heap, $table_name) = @_[KERNEL, SESSION, HEAP, ARG0];
my $session_id = $session->ID;
+ my $ldap_handle = &get_ldap_handle();
+ if (not defined $ldap_handle) {
+ $kernel->delay_set('create_fai_release_db', 1, $table_name);
+ return;
+ }
my $task = POE::Wheel::Run->new(
- Program => sub { &create_fai_release_db($table_name, $session_id) },
+ Program => sub { &create_fai_release_db($table_name, $session_id, $ldap_handle) },
StdoutEvent => "session_run_result",
StderrEvent => "session_run_debug",
CloseEvent => "session_run_done",
);
$heap->{task}->{ $task->ID } = $task;
+ $heap->{ldap_handle}->{$task->ID} = $ldap_handle;
return;
}
sub create_fai_release_db {
- my ($table_name, $session_id) = @_;
+ my ($table_name, $session_id, $ldap_handle) = @_;
my $result;
# used for logging
if (not defined $session_id) { $session_id = 0; }
- my $ldap_handle = &get_ldap_handle();
+ #my $ldap_handle = &get_ldap_handle();
if(defined($ldap_handle)) {
daemon_log("$session_id INFO: create_fai_release_db: start",5);
my $mesg= $ldap_handle->search(
attrs => [],
filter => "(&(objectClass=organizationalUnit)(ou=fai))",
);
- if($mesg->{'resultCode'} == 0 &&
- $mesg->count != 0) {
+ if(($mesg->code == 0) && ($mesg->count != 0))
+ {
+ daemon_log("$session_id DEBUG: create_fai_release_db: count " . $mesg->count,8);
+
# Walk through all possible FAI container ou's
my @sql_list;
my $timestamp= &get_time();
}
}
- daemon_log("$session_id DEBUG: Inserting ".scalar @sql_list." entries to DB",8);
+ daemon_log("$session_id DEBUG: create_fai_release_db: Inserting ".scalar @sql_list." entries to DB",8);
if(@sql_list) {
+ unshift @sql_list, "VACUUM";
unshift @sql_list, "DELETE FROM $table_name";
$fai_release_db->exec_statementlist(\@sql_list);
}
- daemon_log("$session_id DEBUG: Done with inserting",7);
+ daemon_log("$session_id DEBUG: create_fai_release_db: Done with inserting",7);
+ } else {
+ daemon_log("$session_id INFO: create_fai_release_db: error: " . $mesg->code, 5);
}
daemon_log("$session_id INFO: create_fai_release_db: finished",5);
}
- $ldap_handle->disconnect;
+ #&release_ldap_handle($ldap_handle);
return $result;
}
foreach my $entry (@{$mesg->{entries}}) {
if($entry->exists('cn')) {
my $tmp_dn= $entry->dn();
+ $tmp_dn= substr( $tmp_dn, 0, length($tmp_dn)
+ - length($fai_base) - 1 );
# Skip classname and ou dn parts for class
- my $tmp_release = ($1) if $tmp_dn =~ /^[^,]+,[^,]+,(.*?),$fai_base$/;
+ my $tmp_release = ($1) if $tmp_dn =~ /^[^,]+,[^,]+,(.*?)$/;
# Skip classes without releases
if((!defined($tmp_release)) || length($tmp_release)==0) {
}
} elsif (!$entry->exists('cn')) {
my $tmp_dn= $entry->dn();
- my $tmp_release = ($1) if $tmp_dn =~ /^(.*?),$fai_base$/;
+ $tmp_dn= substr( $tmp_dn, 0, length($tmp_dn)
+ - length($fai_base) - 1 );
+ my $tmp_release = ($1) if $tmp_dn =~ /^(.*?)$/;
# Skip classes without releases
if((!defined($tmp_release)) || length($tmp_release)==0) {
sub session_run_done {
my ( $kernel, $heap, $task_id ) = @_[ KERNEL, HEAP, ARG0 ];
delete $heap->{task}->{$task_id};
+ if (exists $heap->{ldap_handle}->{$task_id}) {
+ &release_ldap_handle($heap->{ldap_handle}->{$task_id});
+ }
+ delete $heap->{ldap_handle}->{$task_id};
}
sub create_sources_list {
my $session_id = shift;
- my $ldap_handle = &main::get_ldap_handle;
my $result="/tmp/gosa_si_tmp_sources_list";
# Remove old file
return undef;
}
if(defined($main::ldap_server_dn) and length($main::ldap_server_dn) > 0) {
+ my $ldap_handle = &get_ldap_handle();
my $mesg=$ldap_handle->search(
base => $main::ldap_server_dn,
scope => 'base',
attrs => 'FAIrepository',
filter => 'objectClass=FAIrepositoryServer'
);
+ &release_ldap_handle($ldap_handle);
if($mesg->count) {
foreach my $entry(@{$mesg->{'entries'}}) {
foreach my $value(@{$entry->get_value('FAIrepository', asref => 1)}) {
sub run_create_packages_list_db {
my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
my $session_id = $session->ID;
-
my $task = POE::Wheel::Run->new(
Priority => +20,
- Program => sub {&create_packages_list_db(undef, undef, $session_id)},
+ Program => sub {&create_packages_list_db(undef, $session_id)},
StdoutEvent => "session_run_result",
StderrEvent => "session_run_debug",
CloseEvent => "session_run_done",
sub create_packages_list_db {
- my ($ldap_handle, $sources_file, $session_id) = @_;
+ my ($sources_file, $session_id) = @_;
# it should not be possible to trigger a recreation of packages_list_db
# while packages_list_db is under construction, so set flag packages_list_under_construction
}
if (not defined $session_id) { $session_id = 0; }
- if (not defined $ldap_handle) {
- $ldap_handle= &get_ldap_handle();
- if (not defined $ldap_handle) {
- daemon_log("$session_id ERROR: no ldap_handle available to create_packages_list_db", 1);
- unlink($packages_list_under_construction);
- return;
- }
- }
if (not defined $sources_file) {
&main::daemon_log("$session_id INFO: no sources_file given for creating packages list so trigger creation of it", 5);
$sources_file = &create_sources_list($session_id);
close (CONFIG);
-
if(keys(%repo_dirs)) {
find(\&cleanup_and_extract, keys( %repo_dirs ));
&main::strip_packages_list_statements();
# This function should do some intensive task to minimize the db-traffic
sub strip_packages_list_statements {
- my @existing_entries= @{$packages_list_db->exec_statement("SELECT * FROM $main::packages_list_tn")};
+ my @existing_entries= @{$packages_list_db->exec_statement("SELECT * FROM $main::packages_list_tn")};
my @new_statement_list=();
my $hash;
my $insert_hash;
my $update_hash;
my $delete_hash;
+ my $known_packages_hash;
my $local_timestamp=get_time();
foreach my $existing_entry (@existing_entries) {
(! (@{$hash->{$distribution}->{$package}->{$version}}[4] eq $description))
) {
@{$update_hash->{$distribution}->{$package}->{$version}} = ($distribution,$package,$version,$section,$description,undef);
+ } else {
+ # package is already present in database. cache this knowledge for later use
+ @{$known_packages_hash->{$distribution}->{$package}->{$version}} = ($distribution,$package,$version,$section,$description,$template);
}
} else {
# Insert a non-existing entry to db
}
}
- # TODO: Check for orphaned entries
+ # Check for orphaned entries
+ foreach my $existing_entry (@existing_entries) {
+ my $distribution= @{$existing_entry}[0];
+ my $package= @{$existing_entry}[1];
+ my $version= @{$existing_entry}[2];
+ my $section= @{$existing_entry}[3];
+
+ if(
+ exists($insert_hash->{$distribution}->{$package}->{$version}) ||
+ exists($update_hash->{$distribution}->{$package}->{$version}) ||
+ exists($known_packages_hash->{$distribution}->{$package}->{$version})
+ ) {
+ next;
+ } else {
+ # Insert entry to delete hash
+ @{$delete_hash->{$distribution}->{$package}->{$version}} = ($distribution,$package,$version,$section);
+ }
+ }
- # unroll the insert_hash
+ # unroll the insert hash
foreach my $distribution (keys %{$insert_hash}) {
foreach my $package (keys %{$insert_hash->{$distribution}}) {
foreach my $version (keys %{$insert_hash->{$distribution}->{$package}}) {
next;
}
push @new_statement_list,
- "UPDATE $main::packages_list_tn SET $set WHERE"
- ." distribution = '$distribution'"
- ." AND package = '$package'"
- ." AND version = '$version'";
+ "UPDATE $main::packages_list_tn SET $set WHERE"
+ ." distribution = '$distribution'"
+ ." AND package = '$package'"
+ ." AND version = '$version'";
}
}
}
+
+ # unroll the delete hash
+ foreach my $distribution (keys %{$delete_hash}) {
+ foreach my $package (keys %{$delete_hash->{$distribution}}) {
+ foreach my $version (keys %{$delete_hash->{$distribution}->{$package}}) {
+ my $section = @{$delete_hash->{$distribution}->{$package}->{$version}}[3];
+ push @new_statement_list, "DELETE FROM $main::packages_list_tn WHERE distribution='$distribution' AND package='$package' AND version='$version' AND section='$section'";
+ }
+ }
+ }
+
+ unshift(@new_statement_list, "VACUUM");
@packages_list_statements = @new_statement_list;
}
unlink($dest);
daemon_log("$session_id DEBUG: delete file '$dest'", 5);
} else {
- daemon_log("$session_id ERROR: create_packages_list_db: get_packages: fetching '$url' failed!", 1);
+ daemon_log("$session_id ERROR: create_packages_list_db: get_packages: fetching '$url' into '$dest' failed!", 1);
}
return 0;
}
if( -f "$dir/DEBIAN/templates" ) {
- daemon_log("DEBUG: Found debconf templates in '$package' - $newver", 7);
+ daemon_log("0 DEBUG: Found debconf templates in '$package' - $newver", 7);
my $tmpl= ""; {
local $/=undef;
} else {
$server_status = "developmental" ;
}
-
-# Prepare log file
+# Prepare log file and set permissions
$root_uid = getpwnam('root');
$adm_gid = getgrnam('adm');
-chmod(0640, $log_file);
+open(FH, ">>$log_file");
+close FH;
+chmod(0440, $log_file);
chown($root_uid, $adm_gid, $log_file);
chown($root_uid, $adm_gid, "/var/lib/gosa-si");
daemon_log("status: $server_status", 1);
daemon_log($server_status_hash->{$server_status}.": $server_revision", 1);
+# Create a pool of LDAP handles
+$ldap_factory = ResourcePool::Factory::Net::LDAP->new($ldap_uri, version => $ldap_version);
+$ldap_factory->bind($ldap_admin_dn, password=>$ldap_admin_password);
+$ldap_pool = ResourcePool->new($ldap_factory,
+ Max => 10,
+ #MaxTry => 1,
+ #SleepOnFail => [0, 0, 1, 1],
+ PreCreate => 5,
+);
+
+
+# Buildup data bases
{
no strict "refs";
# connect to gosa-si job queue
unlink($job_queue_file_name); ## just for debugging
$job_db = GOSA::DBsqlite->new($job_queue_file_name);
- chmod(0660, $job_queue_file_name);
+ chmod(0640, $job_queue_file_name);
chown($root_uid, $adm_gid, $job_queue_file_name);
# connect to known_clients_db
unlink($known_clients_file_name); ## just for debugging
$known_clients_db = GOSA::DBsqlite->new($known_clients_file_name);
- chmod(0660, $known_clients_file_name);
+ chmod(0640, $known_clients_file_name);
chown($root_uid, $adm_gid, $known_clients_file_name);
# connect to foreign_clients_db
unlink($foreign_clients_file_name);
$foreign_clients_db = GOSA::DBsqlite->new($foreign_clients_file_name);
- chmod(0660, $foreign_clients_file_name);
+ chmod(0640, $foreign_clients_file_name);
chown($root_uid, $adm_gid, $foreign_clients_file_name);
# connect to known_server_db
unlink($known_server_file_name);
$known_server_db = GOSA::DBsqlite->new($known_server_file_name);
- chmod(0660, $known_server_file_name);
+ chmod(0640, $known_server_file_name);
chown($root_uid, $adm_gid, $known_server_file_name);
# connect to login_usr_db
unlink($login_users_file_name);
$login_users_db = GOSA::DBsqlite->new($login_users_file_name);
- chmod(0660, $login_users_file_name);
+ chmod(0640, $login_users_file_name);
chown($root_uid, $adm_gid, $login_users_file_name);
# connect to fai_server_db
unlink($fai_server_file_name);
$fai_server_db = GOSA::DBsqlite->new($fai_server_file_name);
- chmod(0660, $fai_server_file_name);
+ chmod(0640, $fai_server_file_name);
chown($root_uid, $adm_gid, $fai_server_file_name);
# connect to fai_release_db
unlink($fai_release_file_name);
$fai_release_db = GOSA::DBsqlite->new($fai_release_file_name);
- chmod(0660, $fai_release_file_name);
+ chmod(0640, $fai_release_file_name);
chown($root_uid, $adm_gid, $fai_release_file_name);
# connect to packages_list_db
#unlink($packages_list_file_name);
unlink($packages_list_under_construction);
$packages_list_db = GOSA::DBsqlite->new($packages_list_file_name);
- chmod(0660, $packages_list_file_name);
+ chmod(0640, $packages_list_file_name);
chown($root_uid, $adm_gid, $packages_list_file_name);
# connect to messaging_db
unlink($messaging_file_name);
$messaging_db = GOSA::DBsqlite->new($messaging_file_name);
- chmod(0660, $messaging_file_name);
+ chmod(0640, $messaging_file_name);
chown($root_uid, $adm_gid, $messaging_file_name);
}
}
+
# Creating tables
$messaging_db->create_table($messaging_tn, \@messaging_col_names);
$packages_list_db->create_table($packages_list_tn, \@packages_list_col_names);
@@ -3291,7 +3395,6 @@ $known_clients_db->create_table($known_clients_tn, \@known_clients_col_names);
$incoming_db->create_table($incoming_tn, \@incoming_col_names);
$job_db->create_table($job_queue_tn, \@job_queue_col_names);
-
# create xml object used for en/decrypting
$xml = new XML::Simple();
daemon_log("0 INFO: found foreign server in config file and DNS: '$all_foreign_server'", 5);
# add all found foreign servers to known_server
-my $act_timestamp = &get_time();
+my $cur_timestamp = &get_time();
foreach my $foreign_server (@foreign_server_list) {
# do not add myself to known_server_db
primkey=>['hostname'],
hostname=>$foreign_server,
macaddress=>"",
- status=>'not_jet_registered',
+ status=>'not_yet_registered',
hostkey=>"none",
loaded_modules => "none",
- timestamp=>$act_timestamp,
+ timestamp=>$cur_timestamp,
} );
}