X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=gosa-si%2Fgosa-si-server;h=f1e33172f6f830ac16bc535e8481f4d85a9030d2;hb=48802a3e0c3e3dc4a26332bf8edd39bab8612eea;hp=8848ebef7d570ba77505c5db455b9f0ada1be337;hpb=06309a31075c2115ced1f68d46f154ab227a36b9;p=gosa.git diff --git a/gosa-si/gosa-si-server b/gosa-si/gosa-si-server index 8848ebef7..f1e33172f 100755 --- a/gosa-si/gosa-si-server +++ b/gosa-si/gosa-si-server @@ -1,9 +1,9 @@ #!/usr/bin/perl #=============================================================================== # -# FILE: gosa-sd +# FILE: gosa-si-server # -# USAGE: ./gosa-sd +# USAGE: ./gosa-si-server # # DESCRIPTION: # @@ -20,10 +20,7 @@ # 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; @@ -31,7 +28,7 @@ use Getopt::Long; use Config::IniFiles; use POSIX; -use Fcntl; +use Fcntl qw/:flock/; use IO::Socket::INET; use IO::Handle; use IO::Select; @@ -42,28 +39,35 @@ use Digest::MD5 qw(md5 md5_hex md5_base64); use XML::Simple; use Data::Dumper; use Sys::Syslog qw( :DEFAULT setlogsock); +use Time::HiRes qw( usleep clock_gettime ); use Cwd; use File::Spec; use File::Basename; use File::Find; use File::Copy; use File::Path; -use GOSA::DBsqlite; use GOSA::GosaSupportDaemon; use POE qw(Component::Server::TCP Wheel::Run Filter::Reference); use Net::LDAP; use Net::LDAP::Util qw(:escape); -use Time::HiRes qw( usleep); -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 $verbose= 0; + +my $db_module = "DBsqlite"; +{ +no strict "refs"; +require ("GOSA/".$db_module.".pm"); +("GOSA/".$db_module)->import; +} + +my $modules_path = "/usr/lib/gosa-si/modules"; +use lib "/usr/lib/gosa-si/modules"; our $global_kernel; my ($foreground, $ping_timeout); @@ -71,7 +75,9 @@ 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; +my $debug_parts = 0; +my $debug_parts_bitstring; my ($xml); my $sources_list; my $max_clients; @@ -84,11 +90,12 @@ our (%cfg_defaults, $log_file, $pid_file, $server_ip, $server_port, $ClientPackages_key, $dns_lookup, $arp_activ, $gosa_unit_tag, $GosaPackages_key, $gosa_timeout, - $foreign_server_string, $server_domain, $ServerPackages_key, $foreign_servers_register_delay, + $serverPackages_enabled, $foreign_server_string, $server_domain, $ServerPackages_key, $foreign_servers_register_delay, $wake_on_lan_passwd, $job_synchronization, $modified_jobs_loop_delay, $arp_enabled, $arp_interface, $opsi_enabled, $opsi_server, $opsi_admin, $opsi_password, - $new_systems_ou, + $new_systems_ou, + $arch, ); # additional variable which should be globaly accessable @@ -96,18 +103,15 @@ our $server_address; our $server_mac_address; our $gosa_address; our $no_arp; -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, $ldap_retry_sec); +our ($mysql_username, $mysql_password, $mysql_database, $mysql_host); our $known_modules; +our $known_functions; our $root_uid; our $adm_gid; - -# specifies the verbosity of the daemon_log -$verbose = 0 ; - # if foreground is not null, script will be not forked to background $foreground = 0 ; @@ -123,88 +127,88 @@ my $watch_for_new_jobs_in_progress = 0; our $incoming_db; our $incoming_tn = 'incoming'; my $incoming_file_name; -my @incoming_col_names = ("id INTEGER PRIMARY KEY", - "timestamp DEFAULT 'none'", - "headertag DEFAULT 'none'", - "targettag DEFAULT 'none'", - "xmlmessage DEFAULT 'none'", - "module DEFAULT 'none'", - "sessionid DEFAULT '0'", - ); +my @incoming_col_names = ("id INTEGER PRIMARY KEY", + "timestamp VARCHAR(14) DEFAULT 'none'", + "headertag VARCHAR(255) DEFAULT 'none'", + "targettag VARCHAR(255) DEFAULT 'none'", + "xmlmessage TEXT", + "module VARCHAR(255) DEFAULT 'none'", + "sessionid VARCHAR(255) DEFAULT '0'", +); # holds all gosa jobs our $job_db; our $job_queue_tn = 'jobs'; my $job_queue_file_name; -my @job_queue_col_names = ("id INTEGER PRIMARY KEY", - "timestamp DEFAULT 'none'", - "status DEFAULT 'none'", - "result DEFAULT 'none'", - "progress DEFAULT 'none'", - "headertag DEFAULT 'none'", - "targettag DEFAULT 'none'", - "xmlmessage DEFAULT 'none'", - "macaddress DEFAULT 'none'", - "plainname DEFAULT 'none'", - "siserver DEFAULT 'none'", - "modified DEFAULT '0'", - ); +my @job_queue_col_names = ("id INTEGER PRIMARY KEY", + "timestamp VARCHAR(14) DEFAULT 'none'", + "status VARCHAR(255) DEFAULT 'none'", + "result TEXT", + "progress VARCHAR(255) DEFAULT 'none'", + "headertag VARCHAR(255) DEFAULT 'none'", + "targettag VARCHAR(255) DEFAULT 'none'", + "xmlmessage TEXT", + "macaddress VARCHAR(17) DEFAULT 'none'", + "plainname VARCHAR(255) DEFAULT 'none'", + "siserver VARCHAR(255) DEFAULT 'none'", + "modified INTEGER DEFAULT '0'", + "periodic VARCHAR(6) DEFAULT 'none'", +); # holds all other gosa-si-server our $known_server_db; our $known_server_tn = "known_server"; my $known_server_file_name; -my @known_server_col_names = ("hostname", "macaddress", "status", "hostkey", "loaded_modules", "timestamp"); +my @known_server_col_names = ("hostname VARCHAR(255)", "macaddress VARCHAR(17)", "status VARCHAR(255)", "hostkey VARCHAR(255)", "loaded_modules TEXT", "timestamp VARCHAR(14)", "update_time VARCHAR(14)"); # holds all registrated clients our $known_clients_db; our $known_clients_tn = "known_clients"; my $known_clients_file_name; -my @known_clients_col_names = ("hostname", "status", "hostkey", "timestamp", "macaddress", "events", "keylifetime"); +my @known_clients_col_names = ("hostname VARCHAR(255)", "status VARCHAR(255)", "hostkey VARCHAR(255)", "timestamp VARCHAR(14)", "macaddress VARCHAR(17)", "events TEXT", "keylifetime VARCHAR(255)"); # holds all registered clients at a foreign server our $foreign_clients_db; our $foreign_clients_tn = "foreign_clients"; my $foreign_clients_file_name; -my @foreign_clients_col_names = ("hostname", "macaddress", "regserver", "timestamp"); +my @foreign_clients_col_names = ("hostname VARCHAR(255)", "macaddress VARCHAR(17)", "regserver VARCHAR(255)", "timestamp VARCHAR(14)"); # holds all logged in user at each client our $login_users_db; our $login_users_tn = "login_users"; my $login_users_file_name; -my @login_users_col_names = ("client", "user", "timestamp"); +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; our $fai_server_tn = "fai_server"; my $fai_server_file_name; -our @fai_server_col_names = ("timestamp", "server", "release", "sections", "tag"); +our @fai_server_col_names = ("timestamp VARCHAR(14)", "server VARCHAR(255)", "fai_release VARCHAR(255)", "sections VARCHAR(255)", "tag VARCHAR(255)"); our $fai_release_db; our $fai_release_tn = "fai_release"; my $fai_release_file_name; -our @fai_release_col_names = ("timestamp", "release", "class", "type", "state"); +our @fai_release_col_names = ("timestamp VARCHAR(14)", "fai_release VARCHAR(255)", "class VARCHAR(255)", "type VARCHAR(255)", "state VARCHAR(255)"); # holds all packages available from different repositories our $packages_list_db; our $packages_list_tn = "packages_list"; my $packages_list_file_name; -our @packages_list_col_names = ("distribution", "package", "version", "section", "description", "template", "timestamp"); +our @packages_list_col_names = ("distribution VARCHAR(255)", "package VARCHAR(255)", "version VARCHAR(255)", "section VARCHAR(255)", "description TEXT", "template LONGBLOB", "timestamp VARCHAR(14)"); my $outdir = "/tmp/packages_list_db"; -my $arch = "i386"; # holds all messages which should be delivered to a user our $messaging_db; our $messaging_tn = "messaging"; -our @messaging_col_names = ("id INTEGER", "subject", "message_from", "message_to", - "flag", "direction", "delivery_time", "message", "timestamp" ); +our @messaging_col_names = ("id INTEGER", "subject TEXT", "message_from VARCHAR(255)", "message_to VARCHAR(255)", + "flag VARCHAR(255)", "direction VARCHAR(255)", "delivery_time VARCHAR(255)", "message TEXT", "timestamp VARCHAR(14)" ); my $messaging_file_name; # path to directory to store client install log files our $client_fai_log_dir = "/var/log/fai"; # queue which stores taskes until one of the $max_children children are ready to process the task -my @tasks = qw(); +#my @tasks = qw(); my @msgs_to_decrypt = qw(); my $max_children = 2; @@ -219,6 +223,12 @@ our $opsi_url; # of this, the user is deleted from login_users_db our $logged_in_user_date_of_expiry = 600; +# List of month names, used in function daemon_log +my @monthnames = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); + +# List of accepted periodical xml tags related to cpan modul DateTime +our $check_periodic = {"months"=>'', "weeks"=>'', "days"=>'', "hours"=>'', "minutes"=>''}; + %cfg_defaults = ( "general" => { @@ -239,36 +249,44 @@ our $logged_in_user_date_of_expiry = 600; "foreign-clients" => [\$foreign_clients_file_name, '/var/lib/gosa-si/foreign_clients.db'], "source-list" => [\$sources_list, '/etc/apt/sources.list'], "repo-path" => [\$repo_path, '/srv/www/repository'], + "debian-arch" => [\$arch, 'i386'], "ldap-uri" => [\$ldap_uri, ""], "ldap-base" => [\$ldap_base, ""], "ldap-admin-dn" => [\$ldap_admin_dn, ""], "ldap-admin-password" => [\$ldap_admin_password, ""], + "ldap-version" => [\$ldap_version, 3], + "ldap-retry-sec" => [\$ldap_retry_sec, 10], "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"], }, "GOsaPackages" => { "job-queue" => [\$job_queue_file_name, '/var/lib/gosa-si/jobs.db'], "job-queue-loop-delay" => [\$job_queue_loop_delay, 3], "messaging-db-loop-delay" => [\$messaging_db_loop_delay, 3], "key" => [\$GosaPackages_key, "none"], - "new-systems-ou" => [\$new_systems_ou, 'ou=workstations,ou=systems'], + "new-systems-ou" => [\$new_systems_ou, 'ou=workstations,ou=systems'], }, "ClientPackages" => { "key" => [\$ClientPackages_key, "none"], "user-date-of-expiry" => [\$logged_in_user_date_of_expiry, 600], }, "ServerPackages"=> { + "enabled" => [\$serverPackages_enabled, "true"], "address" => [\$foreign_server_string, ""], - "dns-lookup" => [\$dns_lookup, "true"], - "domain" => [\$server_domain, ""], - "key" => [\$ServerPackages_key, "none"], + "dns-lookup" => [\$dns_lookup, "true"], + "domain" => [\$server_domain, ""], + "key" => [\$ServerPackages_key, "none"], "key-lifetime" => [\$foreign_servers_register_delay, 120], "job-synchronization-enabled" => [\$job_synchronization, "true"], "synchronization-loop" => [\$modified_jobs_loop_delay, 5], }, "ArpHandler" => { - "enabled" => [\$arp_enabled, "true"], + "enabled" => [\$arp_enabled, "false"], "interface" => [\$arp_interface, "all"], }, "Opsi" => { @@ -289,16 +307,30 @@ our $logged_in_user_date_of_expiry = 600; #=============================================================================== sub usage { print STDERR << "EOF" ; -usage: $prg [-hvf] [-c config] +usage: $prg [-hvf] [-c config] [-d number] -h : this (help) message -c : config file -f : foreground, process will not be forked to background -v : be verbose (multiple to increase verbosity) + 'v': error logs + 'vvv': warning plus error logs + 'vvvvv': info plus warning logs + 'vvvvvvv': debug plus info logs -no-arp : starts $prg without connection to arp module - + -d : if verbose level is higher than 7x 'v' specified parts can be debugged + 1 : report incoming messages + 2 : report unencrypted outgoing messages + 4 : report encrypting key for messages + 8 : report decrypted incoming message and verification if the message complies gosa-si requirements + 16 : message processing + 32 : ldap connectivity + 64 : database status and connectivity + 128 : main process + 256 : creation of packages_list_db + 512 : ARP debug information EOF - print "\n" ; + exit(0); } @@ -311,38 +343,69 @@ EOF # DESCRIPTION: function for logging #=============================================================================== sub daemon_log { - # log into log_file my( $msg, $level ) = @_; - 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" )) { - print STDERR "cannot open $log_file: $!"; - return - } - chomp($msg); - #$msg =~s/\n//g; # no newlines are allowed in log messages, this is important for later log parsing - if($level <= $verbose){ - my ($seconds, $minutes, $hours, $monthday, $month, - $year, $weekday, $yearday, $sommertime) = localtime(time); - $hours = $hours < 10 ? $hours = "0".$hours : $hours; - $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes; - $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds; - my @monthnames = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); - $month = $monthnames[$month]; - $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday; - $year+=1900; - my $name = $prg; - - my $log_msg = "$month $monthday $hours:$minutes:$seconds $name $msg\n"; - print LOG_HANDLE $log_msg; - if( $foreground ) { - print STDERR $log_msg; - } - } - close( LOG_HANDLE ); - } + if (not defined $msg) { return } + if (not defined $level) { $level = 1 } + my $to_be_logged = 0; + + # Write log line if line level is lower than verbosity given in commandline + if ($level <= $verbose) + { + $to_be_logged = 1 ; + } + + # Write if debug flag is set and bitstring matches + if ($debug_parts > 0) + { + my $tmp_level = ($level - 10 >= 0) ? $level - 10 : 0 ; + my $tmp_level_bitstring = unpack("B32", pack("N", $tmp_level)); + if (int($debug_parts_bitstring & $tmp_level_bitstring)) + { + $to_be_logged = 1; + } + } + + if ($to_be_logged) + { + if(defined $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; + } + # 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); + } + + # Prepare time string for log message + my ($seconds,$minutes,$hours,$monthday,$month,$year,$weekday,$yearday,$sommertime) = localtime(time); + $hours = $hours < 10 ? $hours = "0".$hours : $hours; + $minutes = $minutes < 10 ? $minutes = "0".$minutes : $minutes; + $seconds = $seconds < 10 ? $seconds = "0".$seconds : $seconds; + $month = $monthnames[$month]; + $monthday = $monthday < 10 ? $monthday = "0".$monthday : $monthday; + $year+=1900; + + # Microseconds since epoch + my $microSeconds = sprintf("%.2f", &Time::HiRes::clock_gettime()); + $microSeconds =~ s/^\d*(.\d\d)$/$1/; + + # Build log message and write it to log file and commandline + chomp($msg); + my $log_msg = "$month $monthday $hours:$minutes:$seconds$microSeconds $prg $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; + } + close( LOG_HANDLE ); + } + } } @@ -353,21 +416,33 @@ sub daemon_log { # DESCRIPTION: validates commandline parameter #=============================================================================== sub check_cmdline_param () { - my $err_config; my $err_counter = 0; + + # Check configuration file if(not defined($cfg_file)) { $cfg_file = "/etc/gosa-si/server.conf"; if(! -r $cfg_file) { - $err_config = "please specify a config file"; - $err_counter += 1; + print STDERR "Please specify a config file.\n"; + $err_counter++; } } - if( $err_counter > 0 ) { - &usage( "", 1 ); - if( defined( $err_config)) { print STDERR "$err_config\n"} - print STDERR "\n"; - exit( -1 ); - } + + # Prepare identification which gosa-si parts should be debugged and which not + if (defined $debug_parts) + { + if ($debug_parts =~ /^\d+$/) + { + $debug_parts_bitstring = unpack("B32", pack("N", $debug_parts)); + } + else + { + print STDERR "Value '$debug_parts' invalid for option d (number expected)\n"; + $err_counter++; + } + } + + # Exit if an error occour + if( $err_counter > 0 ) { &usage( "", 1 ); } } @@ -387,7 +462,7 @@ sub check_pid { if( -f "/proc/$pid/stat" ) { my($stat) = `cat /proc/$pid/stat` =~ m/$pid \((.+)\).*/; if( $stat ) { - daemon_log("ERROR: Already running",1); + print STDERR "\nERROR: Already running!\n"; close( LOCK_FILE ); exit -1; } @@ -429,13 +504,12 @@ sub check_pid { # state is on is imported by "require 'file';" #=============================================================================== sub import_modules { - daemon_log(" ", 1); - if (not -e $modules_path) { daemon_log("0 ERROR: cannot find directory or directory is not readable: $modules_path", 1); } opendir (DIR, $modules_path) or die "ERROR while loading modules from directory $modules_path : $!\n"; + while (defined (my $file = readdir (DIR))) { if (not $file =~ /(\S*?).pm$/) { next; @@ -446,11 +520,19 @@ sub import_modules { if( $file =~ /ArpHandler.pm/ ) { if( $arp_enabled eq "false" ) { next; } } + + # ServerPackages switch + if ($file eq "ServerPackages.pm" && $serverPackages_enabled eq "false") + { + $dns_lookup = "false"; + next; + } eval { require $file; }; if ($@) { daemon_log("0 ERROR: gosa-si-server could not load module $file", 1); - daemon_log("$@", 5); + daemon_log("$@", 1); + exit; } else { my $info = eval($mod_name.'::get_module_info()'); # Only load module if get_module_info() returns a non-null object @@ -461,7 +543,6 @@ sub import_modules { } } } - close (DIR); } @@ -522,14 +603,14 @@ sub check_key_and_xml_validity { if ($msg =~ //i){ $msg =~ s/\s+/ /g; # just for better daemon_log - daemon_log("$session_id DEBUG: decrypted_msg: \n$msg", 8); + daemon_log("$session_id DEBUG: decrypted_msg: \n$msg", 18); $msg_hash = $xml->XMLin($msg, ForceArray=>1); ############## # check header if( not exists $msg_hash->{'header'} ) { die "no header specified"; } my $header_l = $msg_hash->{'header'}; - if( 1 > @{$header_l} ) { die 'empty header tag'; } + if( (1 > @{$header_l}) || ( ( 'HASH' eq ref @{$header_l}[0]) && (1 > keys %{@{$header_l}[0]}) ) ) { die 'empty header tag'; } if( 1 < @{$header_l} ) { die 'more than one header specified'; } my $header = @{$header_l}[0]; if( 0 == length $header) { die 'empty string in header tag'; } @@ -538,7 +619,7 @@ sub check_key_and_xml_validity { # check source if( not exists $msg_hash->{'source'} ) { die "no source specified"; } my $source_l = $msg_hash->{'source'}; - if( 1 > @{$source_l} ) { die 'empty source tag'; } + if( (1 > @{$source_l}) || ( ( 'HASH' eq ref @{$source_l}[0]) && (1 > keys %{@{$source_l}[0]}) ) ) { die 'empty source tag'; } if( 1 < @{$source_l} ) { die 'more than one source specified'; } my $source = @{$source_l}[0]; if( 0 == length $source) { die 'source error'; } @@ -547,7 +628,7 @@ sub check_key_and_xml_validity { # check target if( not exists $msg_hash->{'target'} ) { die "no target specified"; } my $target_l = $msg_hash->{'target'}; - if( 1 > @{$target_l} ) { die 'empty target tag'; } + if( (1 > @{$target_l}) || ( ('HASH' eq ref @{$target_l}[0]) && (1 > keys %{@{$target_l}[0]}) ) ) { die 'empty target tag'; } } }; if($@) { @@ -588,8 +669,20 @@ sub check_outgoing_xml_validity { if( 0 == length $source) { die 'source has length 0'; } + + # Check if source contains hostname instead of ip address + if($source =~ /^[a-z][\w\-\.]+:\d+$/i) { + my ($hostname,$port) = split(/:/, $source); + my $ip_address = inet_ntoa(scalar gethostbyname($hostname)); + if(defined($ip_address) && $ip_address =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/ && $port =~ /^\d+$/) { + # Write ip address to $source variable + $source = "$ip_address:$port"; + $msg_hash->{source}[0] = $source ; + $msg =~ s/.*<\/source>/$source<\/source>/; + } + } unless( $source =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/ || - $source =~ /^GOSA$/i ) { + $source =~ /^GOSA$/i) { die "source '$source' is neither a complete ip-address with port nor 'GOSA'"; } @@ -619,7 +712,7 @@ sub check_outgoing_xml_validity { $msg_hash = undef; } - return ($msg_hash); + return ($msg, $msg_hash); } @@ -636,26 +729,27 @@ sub input_from_known_server { next; } my $host_key = $hit->{hostkey}; - daemon_log("$session_id DEBUG: input_from_known_server: host_name: $host_name", 7); - daemon_log("$session_id DEBUG: input_from_known_server: host_key: $host_key", 7); + daemon_log("$session_id DEBUG: input_from_known_server: host_name: $host_name", 14); + daemon_log("$session_id DEBUG: input_from_known_server: host_key: $host_key", 14); # check if module can open msg envelope with module key my ($tmp_msg, $tmp_msg_hash) = &check_key_and_xml_validity($input, $host_key, $session_id); if( (!$tmp_msg) || (!$tmp_msg_hash) ) { - daemon_log("$session_id DEBUG: input_from_known_server: deciphering raise error", 7); - daemon_log("$@", 8); + daemon_log("$session_id DEBUG: input_from_known_server: deciphering raise error", 14); + daemon_log("$@", 14); next; } else { $msg = $tmp_msg; $msg_hash = $tmp_msg_hash; $module = "ServerPackages"; + daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 14); last; } } if( (!$msg) || (!$msg_hash) || (!$module) ) { - daemon_log("$session_id DEBUG: Incoming message is not from a known server", 7); + daemon_log("$session_id DEBUG: Incoming message is not from a known server", 14); } return ($msg, $msg_hash, $module); @@ -670,29 +764,29 @@ sub input_from_known_client { my $query_res = $known_clients_db->select_dbentry( $sql_statement ); while( my ($hit_num, $hit) = each %{ $query_res } ) { my $host_name = $hit->{hostname}; - if( not $host_name =~ /^$remote_ip:\d*$/) { + if( not $host_name =~ /^$remote_ip/) { next; } my $host_key = $hit->{hostkey}; - &daemon_log("$session_id DEBUG: input_from_known_client: host_name: $host_name", 7); - &daemon_log("$session_id DEBUG: input_from_known_client: host_key: $host_key", 7); + &daemon_log("$session_id DEBUG: input_from_known_client: host_name: $host_name", 14); + &daemon_log("$session_id DEBUG: input_from_known_client: host_key: $host_key", 14); # check if module can open msg envelope with module key ($msg, $msg_hash) = &check_key_and_xml_validity($input, $host_key, $session_id); if( (!$msg) || (!$msg_hash) ) { - &daemon_log("$session_id DEGUG: input_from_known_client: deciphering raise error", 7); - &daemon_log("$@", 8); + &daemon_log("$session_id DEGUG: input_from_known_client: deciphering raise error", 14); next; } else { $module = "ClientPackages"; + daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 14); last; } } if( (!$msg) || (!$msg_hash) || (!$module) ) { - &daemon_log("$session_id DEBUG: Incoming message is not from a known client", 7); + &daemon_log("$session_id DEBUG: Incoming message is not from a known client", 14); } return ($msg, $msg_hash, $module); @@ -718,7 +812,7 @@ sub input_from_unknown_host { daemon_log("$session_id ERROR: no key specified in config file for $mod", 1); next; } - daemon_log("$session_id DEBUG: $mod: $module_key", 7); + daemon_log("$session_id DEBUG: $mod: $module_key", 14); # check if module can open msg envelope with module key ($msg, $msg_hash) = &check_key_and_xml_validity($input, $module_key, $session_id); @@ -726,12 +820,13 @@ sub input_from_unknown_host { next; } else { $module = $mod; + daemon_log("$session_id DEBUG: check_key_and_xml_validity... ok", 18); last; } } if( (!$msg) || (!$msg_hash) || (!$module)) { - daemon_log("$session_id DEBUG: Incoming message is not from an unknown host", 7); + daemon_log("$session_id DEBUG: Incoming message is not from an unknown host", 14); } return ($msg, $msg_hash, $module); @@ -842,48 +937,6 @@ sub open_socket { } -#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 = ; -# -# 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; @@ -899,11 +952,14 @@ sub send_msg_to_target { $header = ""; } - # Patch the source ip - if($msg =~ /0\.0\.0\.0:\d*?<\/source>/) { - my $remote_ip = &get_local_ip_for_remote_ip(sprintf("%s", $address =~ /^([0-9\.]*?):.*$/)); - $msg =~ s/(0\.0\.0\.0):(\d*?)<\/source>/$remote_ip:$2<\/source>/s; - } + # Memorize own source address + my $own_source_address = &get_local_ip_for_remote_ip(sprintf("%s", $address =~ /^([0-9\.]*?):.*$/)); + $own_source_address .= ":".$server_port; + + # Patch 0.0.0.0 source to real address + $msg =~ s/(0\.0\.0\.0):(\d*?)<\/source>/$own_source_address<\/source>/s; + # Patch GOSA source to real address and add forward_to_gosa tag + $msg =~ s/GOSA<\/source>/$own_source_address<\/source> $own_source_address,$session_id<\/forward_to_gosa>/ ; # encrypt xml msg my $crypted_msg = &encrypt_msg($msg, $encrypt_key); @@ -911,16 +967,15 @@ sub send_msg_to_target { # opensocket my $socket = &open_socket($address); if( !$socket ) { - daemon_log("$session_id WARNING: cannot send ".$header."msg to $address , host not reachable", 3); + daemon_log("$session_id ERROR: Cannot open socket to host '$address'. Message processing aborted!", 1); $error++; } if( $error == 0 ) { # send xml msg - print $socket $crypted_msg."\n"; - + print $socket $crypted_msg.";$own_source_address\n"; daemon_log("$session_id INFO: send ".$header."msg to $address", 5); - daemon_log("$session_id DEBUG: message:\n$msg", 9); + daemon_log("$session_id DEBUG: message:\n$msg", 12); } @@ -948,7 +1003,7 @@ sub send_msg_to_target { if($new_status eq "down"){ daemon_log("$session_id WARNING: set '$address' from status '$act_status' to '$new_status'", 3); } else { - daemon_log("$session_id INFO: set '$address' from status '$act_status' to '$new_status'", 5); + daemon_log("$session_id DEBUG: set '$address' from status '$act_status' to '$new_status'", 138); } } } @@ -969,7 +1024,7 @@ sub send_msg_to_target { if($new_status eq "down"){ daemon_log("$session_id WARNING: set '$address' from status '$act_status' to '$new_status'", 3); } else { - daemon_log("$session_id INFO: set '$address' from status '$act_status' to '$new_status'", 5); + daemon_log("$session_id DEBUG: set '$address' from status '$act_status' to '$new_status'", 138); } } } @@ -978,29 +1033,93 @@ sub send_msg_to_target { sub update_jobdb_status_for_send_msgs { - my ($answer, $error) = @_; + my ($session_id, $answer, $error) = @_; if( $answer =~ /(\d+)<\/jobdb_id>/ ) { + &daemon_log("$session_id DEBUG: try to update job status", 138); my $jobdb_id = $1; + + $answer =~ /
(.*)<\/header>/; + my $job_header = $1; + + $answer =~ /(.*)<\/target>/; + my $job_target = $1; - # sending msg faild + # Sending msg failed if( $error ) { - if (not $answer =~ /
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"; + 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") + ) { + if ($job_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) { + &reactivate_job_with_delay($session_id, $job_target, $job_header, 30 ); + } else { + # If we don't have the mac adress at this time, we use the plainname + my $plainname_result = $job_db->select_dbentry("SELECT plainname from jobs where id=$jobdb_id"); + my $plainname = $job_target; + if ((keys(%$plainname_result) > 0) ) { + $plainname = $plainname_result->{1}->{$job_target}; + } + &reactivate_job_with_delay($session_id, $plainname, $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"; 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'"; + my $res = $job_db->update_dbentry($sql_statement); + } else { + &daemon_log("$session_id DEBUG: sending message succeed but cannot update job status.", 138); + } + } + } else { + &daemon_log("$session_id DEBUG: cannot update job status, msg has no jobdb_id-tag.", 138); } } +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 LIKE '$target' OR plainname LIKE '$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); + return; +} + sub sig_handler { my ($kernel, $signal) = @_[KERNEL, ARG0] ; @@ -1011,268 +1130,340 @@ sub sig_handler { sub msg_to_decrypt { - my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP]; - my $session_id = $session->ID; - my ($msg, $msg_hash, $module); - my $error = 0; + my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP]; + my $session_id = $session->ID; + my ($msg, $msg_hash, $module); + my $error = 0; - # hole neue msg aus @msgs_to_decrypt - my $next_msg = shift @msgs_to_decrypt; - - # entschlüssle sie + # 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); - # msg is from a gosa-si-server - if(( !$msg ) || ( !$msg_hash ) || ( !$module )){ - ($msg, $msg_hash, $module) = &input_from_known_server($next_msg, $heap->{'remote_ip'}, $session_id); - } - # msg is from a gosa-si-client - if(( !$msg ) || ( !$msg_hash ) || ( !$module )){ - ($msg, $msg_hash, $module) = &input_from_known_client($next_msg, $heap->{'remote_ip'}, $session_id); - } - # an error occurred - 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 - 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 = "
gosa_ping
$server_address $host_name
"; - 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++; - } + # msg is from a new client or gosa + ($msg, $msg_hash, $module) = &input_from_unknown_host($next_msg, $session_id); + # msg is from a gosa-si-server + if(((!$msg) || (!$msg_hash) || (!$module)) && ($serverPackages_enabled eq "true")){ + if (not defined $msg_source) + { + # Only needed, to be compatible with older gosa-si-server versions + ($msg, $msg_hash, $module) = &input_from_known_server($next_msg, $heap->{'remote_ip'}, $session_id); + } + else + { + ($msg, $msg_hash, $module) = &input_from_known_server($next_msg, $msg_source, $session_id); + } + } + # msg is from a gosa-si-client + if(( !$msg ) || ( !$msg_hash ) || ( !$module )){ + if (not defined $msg_source) + { + # Only needed, to be compatible with older gosa-si-server versions + ($msg, $msg_hash, $module) = &input_from_known_client($next_msg, $heap->{'remote_ip'}, $session_id); + } + else + { + ($msg, $msg_hash, $module) = &input_from_known_client($next_msg, $msg_source, $session_id); + } + } + # an error occurred + if(( !$msg ) || ( !$msg_hash ) || ( !$module )){ + # If an incoming msg could not be decrypted (maybe a wrong key), decide if msg comes from a client + # or a server. In case of a client, send a ping. If the client could not understand a msg from its + # server the client cause a re-registering process. In case of a server, decrease update_time in kown_server_db + # and trigger a re-registering process for servers + if (defined $msg_source && $msg_source =~ /:$server_port$/ && $serverPackages_enabled eq "true") + { + daemon_log("$session_id WARNING: Cannot understand incoming msg from server '$msg_source'. Cause re-registration process for servers.", 3); + my $update_statement = "UPDATE $known_server_tn SET update_time='19700101000000' WHERE hostname='$msg_source'"; + daemon_log("$session_id DEBUG: $update_statement", 7); + my $upadte_res = $known_server_db->exec_statement($update_statement); + $kernel->yield("register_at_foreign_servers"); + } + elsif ((defined $msg_source) && (not $msg_source =~ /:$server_port$/)) + { + daemon_log("$session_id WARNING: Cannot understand incoming msg from client '$msg_source'. Send ping-msg to cause a re-registering of the client if necessary", 3); + #my $remote_ip = $heap->{'remote_ip'}; + #my $remote_port = $heap->{'remote_port'}; + my $ping_msg = "
gosa_ping
$server_address$msg_source
"; + 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: Sending msg to cause re-registering: $ping_msg", 3); + } + else + { + my $foreign_host = defined $msg_source ? $msg_source : $heap->{'remote_ip'}; + daemon_log("$session_id ERROR: Incoming message from host '$foreign_host' cannot be understood. Processing aborted!", 1); + daemon_log("$session_id DEBUG: Aborted message: $tmp_next_msg", 11); + } - my $header; - my $target; - my $source; - my $done = 0; - my $sql; - my $res; - - # check whether this message should be processed here - if ($error == 0) { - $header = @{$msg_hash->{'header'}}[0]; - $target = @{$msg_hash->{'target'}}[0]; - $source = @{$msg_hash->{'source'}}[0]; + $error++ + } + + + my $header; + my $target; + my $source; + my $done = 0; + my $sql; + my $res; + + # check whether this message should be processed here + if ($error == 0) { + $header = @{$msg_hash->{'header'}}[0]; + $target = @{$msg_hash->{'target'}}[0]; + $source = @{$msg_hash->{'source'}}[0]; my $not_found_in_known_clients_db = 0; my $not_found_in_known_server_db = 0; my $not_found_in_foreign_clients_db = 0; - my $local_address; - my $local_mac; - my ($target_ip, $target_port) = split(':', $target); - - # Determine the local ip address if target is an ip address + my $local_address; + my $local_mac; + my ($target_ip, $target_port) = split(':', $target); + + # Determine the local ip address if target is an ip address if ($target =~ /^\d+\.\d+\.\d+\.\d+:\d+$/) { $local_address = &get_local_ip_for_remote_ip($target_ip).":$server_port"; } else { - $local_address = $server_address; - } + $local_address = $server_address; + } - # Determine the local mac address if target is a mac address - if ($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) { - my $loc_ip = &get_local_ip_for_remote_ip($heap->{'remote_ip'}); - my $network_interface= &get_interface_for_ip($loc_ip); - $local_mac = &get_mac_for_interface($network_interface); - } else { - $local_mac = $server_mac_address; - } + # Determine the local mac address if target is a mac address + if ($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) { + my $loc_ip = &get_local_ip_for_remote_ip($heap->{'remote_ip'}); + my $network_interface= &get_interface_for_ip($loc_ip); + $local_mac = &get_mac_for_interface($network_interface); + } else { + $local_mac = $server_mac_address; + } - # target and source is equal to GOSA -> process here - if (not $done) { - if ($target eq "GOSA" && $source eq "GOSA") { - $done = 1; - &daemon_log("$session_id DEBUG: target and source is 'GOSA' -> process here", 7); - } - } + # target and source is equal to GOSA -> process here + if (not $done) { + if ($target eq "GOSA" && $source eq "GOSA") { + $done = 1; + &daemon_log("$session_id DEBUG: target and source is 'GOSA' -> process '$header' here", 11); + } + } - # target is own address without forward_to_gosa-tag -> process here - if (not $done) { - #if ((($target eq $local_address) || ($target eq $local_mac) ) && (not exists $msg_hash->{'forward_to_gosa'})) { - if (($target eq $local_address) && (not exists $msg_hash->{'forward_to_gosa'})) { - $done = 1; - if ($source eq "GOSA") { - $msg =~ s/<\/xml>/$local_address,$session_id<\/forward_to_gosa><\/xml>/; - } - &daemon_log("$session_id DEBUG: target is own address without forward_to_gosa-tag -> process here", 7); - } - } + # target is own address without forward_to_gosa-tag -> process here + if (not $done) { + #if ((($target eq $local_address) || ($target eq $local_mac) ) && (not exists $msg_hash->{'forward_to_gosa'})) { + if (($target eq $local_address) && (not exists $msg_hash->{'forward_to_gosa'})) { + $done = 1; + if ($source eq "GOSA") { + $msg =~ s/<\/xml>/$local_address,$session_id<\/forward_to_gosa><\/xml>/; + } + &daemon_log("$session_id DEBUG: target is own address without forward_to_gosa-tag -> process '$header' here", 11); + } + } - # target is a client address in known_clients -> process here + # target is own address with forward_to_gosa-tag not pointing to myself -> process here if (not $done) { - $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; - $res = $known_clients_db->select_dbentry($sql); - if (keys(%$res) > 0) { - $done = 1; - my $hostname = $res->{1}->{'hostname'}; - $msg =~ s/$target<\/target>/$hostname<\/target>/; - my $local_address = &get_local_ip_for_remote_ip($target_ip).":$server_port"; - if ($source eq "GOSA") { - $msg =~ s/<\/xml>/$local_address,$session_id<\/forward_to_gosa><\/xml>/; - } - &daemon_log("$session_id DEBUG: target is a client address in known_clients -> process here", 7); + my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0]; + my $gosa_at; + my $gosa_session_id; + if (($target eq $local_address) && (defined $forward_to_gosa)){ + my ($gosa_at, $gosa_session_id) = split(/,/, $forward_to_gosa); + if ($gosa_at ne $local_address) { + $done = 1; + &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag not pointing to myself -> process '$header' here", 11); + } + } + } - } else { - $not_found_in_known_clients_db = 1; + # Target is a client address and there is a processing function within a plugin -> process loaclly + if (not $done) + { + # Check if target is a client address + $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; + $res = $known_clients_db->select_dbentry($sql); + if ((keys(%$res) > 0) ) + { + my $hostname = $res->{1}->{'hostname'}; + my $reduced_header = $header; + $reduced_header =~ s/gosa_//; + # Check if there is a processing function within a plugin + if (exists $known_functions->{$reduced_header}) + { + $msg =~ s/\S*<\/target>/$hostname<\/target>/; + $done = 1; + &daemon_log("$session_id DEBUG: Target is client address with processing function within a plugin -> process '$header' here", 11); } + } + } + + # If header has a 'job_' prefix, do always process message locally + # which means put it into job queue + if ((not $done) && ($header =~ /job_/)) + { + $done = 1; + &daemon_log("$session_id DEBUG: Header has a 'job_' prefix. Put it into job queue. -> process '$header' here", 11); } - - # target ist own address with forward_to_gosa-tag not pointing to myself -> process here - if (not $done) { - my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0]; - my $gosa_at; - my $gosa_session_id; - if (($target eq $local_address) && (defined $forward_to_gosa)){ - my ($gosa_at, $gosa_session_id) = split(/,/, $forward_to_gosa); - if ($gosa_at ne $local_address) { - $done = 1; - &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag not pointing to myself -> process here", 7); - } - } - } - # if message should be processed here -> add message to incoming_db + # if message should be processed here -> add message to incoming_db if ($done) { - # if a job or a gosa message comes from a foreign server, fake module to GosaPackages - # so gosa-si-server knows how to process this kind of messages - if ($header =~ /^gosa_/ || $header =~ /^job_/) { - $module = "GosaPackages"; - } + # if a 'job_' or a 'gosa_' message comes from a foreign server, fake module from + # ServerPackages to GosaPackages so gosa-si-server knows how to process this kind of messages + if ($header =~ /^gosa_/ || $header =~ /^job_/) { + $module = "GosaPackages"; + } - my $res = $incoming_db->add_dbentry( {table=>$incoming_tn, - primkey=>[], - headertag=>$header, - targettag=>$target, - xmlmessage=>&encode_base64($msg), - timestamp=>&get_time, - module=>$module, - sessionid=>$session_id, - } ); + my $res = $incoming_db->add_dbentry( {table=>$incoming_tn, + primkey=>[], + headertag=>$header, + targettag=>$target, + xmlmessage=>&encode_base64($msg), + timestamp=>&get_time, + module=>$module, + sessionid=>$session_id, + } ); + $kernel->yield('watch_for_next_tasks'); } - # target is own address with forward_to_gosa-tag pointing at myself -> forward to gosa - if (not $done) { - my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0]; - my $gosa_at; - my $gosa_session_id; - if (($target eq $local_address) && (defined $forward_to_gosa)){ - my ($gosa_at, $gosa_session_id) = split(/,/, $forward_to_gosa); - if ($gosa_at eq $local_address) { - my $session_reference = $kernel->ID_id_to_session($gosa_session_id); - if( defined $session_reference ) { - $heap = $session_reference->get_heap(); - } - if(exists $heap->{'client'}) { - $msg = &encrypt_msg($msg, $GosaPackages_key); - $heap->{'client'}->put($msg); - &daemon_log("$session_id INFO: incoming '$header' message forwarded to GOsa", 5); - } - $done = 1; - &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag pointing at myself -> forward to gosa", 7); - } - } + # target is own address with forward_to_gosa-tag pointing at myself -> forward to gosa + if (not $done) { + my $forward_to_gosa = @{$msg_hash->{'forward_to_gosa'}}[0]; + my $gosa_at; + my $gosa_session_id; + if (($target eq $local_address) && (defined $forward_to_gosa)){ + my ($gosa_at, $gosa_session_id) = split(/,/, $forward_to_gosa); + if ($gosa_at eq $local_address) { + my $session_reference = $kernel->ID_id_to_session($gosa_session_id); + if( defined $session_reference ) { + $heap = $session_reference->get_heap(); + } + if(exists $heap->{'client'}) { + $msg = &encrypt_msg($msg, $GosaPackages_key); + $heap->{'client'}->put($msg); + &daemon_log("$session_id DEBUG: incoming '$header' message forwarded to GOsa", 11); + } + $done = 1; + &daemon_log("$session_id DEBUG: target is own address with forward_to_gosa-tag pointing at myself -> forward '$header' to gosa", 11); + } + } - } + } - # target is a client address in foreign_clients -> forward to registration server - if (not $done) { - $sql = "SELECT * FROM $foreign_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; - $res = $foreign_clients_db->select_dbentry($sql); - if (keys(%$res) > 0) { - my $hostname = $res->{1}->{'hostname'}; - my ($host_ip, $host_port) = split(/:/, $hostname); - my $local_address = &get_local_ip_for_remote_ip($host_ip).":$server_port"; - my $regserver = $res->{1}->{'regserver'}; - my $sql = "SELECT * FROM $known_server_tn WHERE hostname='$regserver'"; - my $res = $known_server_db->select_dbentry($sql); - if (keys(%$res) > 0) { - my $regserver_key = $res->{1}->{'hostkey'}; - $msg =~ s/GOSA<\/source>/$local_address<\/source>/; - $msg =~ s/$target<\/target>/$hostname<\/target>/; - if ($source eq "GOSA") { - $msg =~ s/<\/xml>/$local_address,$session_id<\/forward_to_gosa><\/xml>/; - } - &send_msg_to_target($msg, $regserver, $regserver_key, $header, $session_id); - } - $done = 1; - &daemon_log("$session_id DEBUG: target is a client address in foreign_clients -> forward to registration server", 7); - } else { + # target is a client address in known_clients -> forward to client + if (not $done) { + $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; + $res = $known_clients_db->select_dbentry($sql); + if (keys(%$res) > 0) + { + $done = 1; + &daemon_log("$session_id DEBUG: target is a client address in known_clients -> forward '$header' to client", 11); + my $hostkey = $res->{1}->{'hostkey'}; + my $hostname = $res->{1}->{'hostname'}; + $msg =~ s/\S*<\/target>/$hostname<\/target>/; + $msg =~ s/
gosa_/
/; + my $error= &send_msg_to_target($msg, $hostname, $hostkey, $header, $session_id); + if ($error) { + &daemon_log("$session_id ERROR: Some problems occurred while trying to send msg to client '$hostname': $msg", 1); + } + } + else + { + $not_found_in_known_clients_db = 1; + } + } + + # target is a client address in foreign_clients -> forward to registration server + if (not $done) { + $sql = "SELECT * FROM $foreign_clients_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; + $res = $foreign_clients_db->select_dbentry($sql); + if (keys(%$res) > 0) { + my $hostname = $res->{1}->{'hostname'}; + my ($host_ip, $host_port) = split(/:/, $hostname); + my $local_address = &get_local_ip_for_remote_ip($host_ip).":$server_port"; + my $regserver = $res->{1}->{'regserver'}; + my $sql = "SELECT * FROM $known_server_tn WHERE hostname='$regserver'"; + my $res = $known_server_db->select_dbentry($sql); + if (keys(%$res) > 0) { + my $regserver_key = $res->{1}->{'hostkey'}; + $msg =~ s/GOSA<\/source>/$local_address<\/source>/; + $msg =~ s/$target<\/target>/$hostname<\/target>/; + if ($source eq "GOSA") { + $msg =~ s/<\/xml>/$local_address,$session_id<\/forward_to_gosa><\/xml>/; + } + my $error= &send_msg_to_target($msg, $regserver, $regserver_key, $header, $session_id); + if ($error) { + &daemon_log("$session_id ERROR: some problems occurred while trying to send msg to registration server: $msg", 1); + } + } + $done = 1; + &daemon_log("$session_id DEBUG: target is a client address in foreign_clients -> forward '$header' to registration server", 11); + } else { $not_found_in_foreign_clients_db = 1; } - } + } - # target is a server address -> forward to server - if (not $done) { - $sql = "SELECT * FROM $known_server_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; - $res = $known_server_db->select_dbentry($sql); - if (keys(%$res) > 0) { - my $hostkey = $res->{1}->{'hostkey'}; + # target is a server address -> forward to server + if (not $done) { + $sql = "SELECT * FROM $known_server_tn WHERE (hostname='$target' OR macaddress LIKE '$target')"; + $res = $known_server_db->select_dbentry($sql); + if (keys(%$res) > 0) { + my $hostkey = $res->{1}->{'hostkey'}; - if ($source eq "GOSA") { - $msg =~ s/GOSA<\/source>/$local_address<\/source>/; - $msg =~ s/<\/xml>/$local_address,$session_id<\/forward_to_gosa><\/xml>/; + if ($source eq "GOSA") { + $msg =~ s/GOSA<\/source>/$local_address<\/source>/; + $msg =~ s/<\/xml>/$local_address,$session_id<\/forward_to_gosa><\/xml>/; - } + } - &send_msg_to_target($msg, $target, $hostkey, $header, $session_id); - $done = 1; - &daemon_log("$session_id DEBUG: target is a server address -> forward to server", 7); - } else { + &send_msg_to_target($msg, $target, $hostkey, $header, $session_id); + $done = 1; + &daemon_log("$session_id DEBUG: target is a server address -> forward '$header' to server", 11); + } else { $not_found_in_known_server_db = 1; } - } + } + - # target is not in foreign_clients_db, known_server_db or known_clients_db, maybe it is a complete new one -> process here if ( $not_found_in_foreign_clients_db - && $not_found_in_known_server_db - && $not_found_in_known_clients_db) { - my $res = $incoming_db->add_dbentry( {table=>$incoming_tn, - primkey=>[], - headertag=>$header, - targettag=>$target, - xmlmessage=>&encode_base64($msg), - timestamp=>&get_time, - module=>$module, - sessionid=>$session_id, - } ); - $done = 1; - &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); + && $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 '$header' here", 11); + if ($header =~ /^gosa_/ || $header =~ /^job_/) { + $module = "GosaPackages"; + } + my $res = $incoming_db->add_dbentry( {table=>$incoming_tn, + primkey=>[], + headertag=>$header, + targettag=>$target, + xmlmessage=>&encode_base64($msg), + timestamp=>&get_time, + module=>$module, + sessionid=>$session_id, + } ); + $done = 1; + $kernel->yield('watch_for_next_tasks'); } - if (not $done) { - daemon_log("$session_id ERROR: do not know what to do with this message: $msg", 1); - if ($source eq "GOSA") { - my %data = ('error_msg' => &encode_base64($msg), 'error_string' => "Do not know what to do with this message!"); - my $error_msg = &build_msg("error", $local_address, "GOSA", \%data ); - - my $session_reference = $kernel->ID_id_to_session($session_id); - if( defined $session_reference ) { - $heap = $session_reference->get_heap(); - } - if(exists $heap->{'client'}) { - $error_msg = &encrypt_msg($error_msg, $GosaPackages_key); - $heap->{'client'}->put($error_msg); - } - } - } + if (not $done) { + daemon_log("$session_id ERROR: do not know what to do with this message: $msg", 1); + if ($source eq "GOSA") { + my %data = ('error_msg' => &encode_base64($msg), 'error_string' => "Do not know what to do with this message!"); + my $error_msg = &build_msg("error", $local_address, "GOSA", \%data ); + + my $session_reference = $kernel->ID_id_to_session($session_id); + if( defined $session_reference ) { + $heap = $session_reference->get_heap(); + } + if(exists $heap->{'client'}) { + $error_msg = &encrypt_msg($error_msg, $GosaPackages_key); + $heap->{'client'}->put($error_msg); + } + } + } - } + } - return; + return; } sub next_task { - my ($session, $heap, $task) = @_[SESSION, HEAP, ARG0]; + my ($session, $heap, $task) = @_[SESSION, HEAP, ARG0, ARG1]; my $running_task = POE::Wheel::Run->new( Program => sub { process_task($session, $heap, $task) }, StdioFilter => POE::Filter::Reference->new(), @@ -1310,6 +1501,9 @@ sub handle_task_debug { 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 { @@ -1328,30 +1522,35 @@ sub process_task { my $module = $task->{'module'}; my $header = $task->{'headertag'}; my $session_id = $task->{'sessionid'}; - my $msg_hash = $xml->XMLin($msg, ForceArray=>1); + my $msg_hash; + eval { + $msg_hash = $xml->XMLin($msg, ForceArray=>1); + }; + daemon_log("ERROR: XML failure '$@'") if ($@); my $source = @{$msg_hash->{'source'}}[0]; # 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); ###################### # process incoming msg 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); + daemon_log("$session_id DEBUG: Processing module ".$module, 26); $answer_l = &{ $module."::process_incoming_msg" }($msg, $msg_hash, $session_id); if ( 0 < @{$answer_l} ) { my $answer_str = join("\n", @{$answer_l}); + my @headers; while ($answer_str =~ /
(\w+)<\/header>/g) { - daemon_log("$session_id INFO: got answer message with header '$1'", 5); + push(@headers, $1); } - daemon_log("$session_id DEBUG: $module: got answer from module: \n".$answer_str,9); + daemon_log("$session_id DEBUG: got answer message(s) with header: '".join("', '", @headers)."'", 26); } else { - daemon_log("$session_id DEBUG: $module: got no answer from module!" ,7); + daemon_log("$session_id DEBUG: $module: got no answer from module!" ,26); } } @@ -1363,7 +1562,7 @@ sub process_task { foreach my $answer ( @{$answer_l} ) { # check outgoing msg to xml validity - my $answer_hash = &check_outgoing_xml_validity($answer, $session_id); + my ($answer, $answer_hash) = &check_outgoing_xml_validity($answer, $session_id); if( not defined $answer_hash ) { next; } $answer_header = @{$answer_hash->{'header'}}[0]; @@ -1382,7 +1581,7 @@ sub process_task { 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); } } @@ -1396,7 +1595,7 @@ sub process_task { my $host_key = $hit->{hostkey}; $answer =~ s/\S+<\/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); } } @@ -1407,6 +1606,9 @@ sub process_task { if( defined $session_id ) { $add_on = ".session_id=$session_id"; } + my $header = ($1) if $answer =~ /
(\S*)<\/header>/; + daemon_log("$session_id INFO: send ".$header." message to GOsa", 5); + daemon_log("$session_id DEBUG: message:\n$answer", 12); # answer is for GOSA and has to returned to connected client my $gosa_answer = &encrypt_msg($answer, $GosaPackages_key); $client_answer = $gosa_answer.$add_on; @@ -1418,12 +1620,14 @@ sub process_task { 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); + daemon_log("$session_id DEBUG: target is mac address '$answer_target', looking for host in known_clients and foreign_clients", 138); + + # 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; @@ -1433,9 +1637,11 @@ sub process_task { $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); @@ -1460,13 +1666,16 @@ sub process_task { 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 @@ -1479,7 +1688,7 @@ sub process_task { 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); } } } @@ -1503,7 +1712,6 @@ sub session_start { $kernel->yield('register_at_foreign_servers'); $kernel->yield('create_fai_server_db', $fai_server_tn ); $kernel->yield('create_fai_release_db', $fai_release_tn ); - $kernel->yield('watch_for_next_tasks'); $kernel->sig(USR1 => "sig_handler"); $kernel->sig(USR2 => "recreate_packages_db"); $kernel->delay_set('watch_for_new_jobs', $job_queue_loop_delay); @@ -1523,25 +1731,43 @@ sub session_start { sub watch_for_done_jobs { - #CHECK: $heap for what? - my ($kernel,$heap) = @_[KERNEL, HEAP]; + my $kernel = $_[KERNEL]; - 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 ($number, $hit) = each %{$res} ) + { + # Non periodical jobs can be deleted. + if ($hit->{periodic} eq "none") + { + 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); + # Periodical jobs should not be deleted but reactivated with new timestamp instead. + else + { + my ($p_time, $periodic) = split("_", $hit->{periodic}); + my $reactivated_ts = $hit->{timestamp}; + my $act_ts = int(&get_time()); + while ($act_ts > int($reactivated_ts)) # Redo calculation to avoid multiple jobs in the past + { + $reactivated_ts = &calc_timestamp($reactivated_ts, "plus", $p_time, $periodic); + } + my $sql = "UPDATE $job_queue_tn SET status='waiting', timestamp='$reactivated_ts' WHERE id='".$hit->{id}."'"; + my $res = $job_db->exec_statement($sql); + &daemon_log("J INFO: Update periodical job '".$hit->{headertag}."' for client '".$hit->{targettag}."'. New execution time '$reactivated_ts'.", 5); + } + } + + $kernel->delay_set('watch_for_done_jobs',$job_queue_loop_delay); } sub watch_for_opsi_jobs { my ($kernel) = $_[KERNEL]; - # This is not very nice to look for opsi install jobs, but headertag has to be trigger_action_reinstall. The only way to identify a # opsi install job is to parse the xml message. There is still the correct header. my $sql_statement = "SELECT * FROM ".$job_queue_tn." WHERE ((xmlmessage LIKE '%opsi_install_client
%') AND (status='processing') AND (siserver='localhost'))"; @@ -1565,10 +1791,14 @@ sub watch_for_opsi_jobs { }; my $hres = $opsi_client->call($opsi_url, $callobj); - #my ($hres_err, $hres_err_string) = &check_opsi_res($hres); + # TODO : move all opsi relevant statments to opsi plugin + # The following 3 lines must be tested befor they can replace the rubbish above and below !!! + #my ($res, $err) = &opsi_com::_getProductStates_hash(hostId=>$hostId) + #if (not $err) { + # my $htmp = $res->{$hostId}; + # if (not &check_opsi_res($hres)) { my $htmp= $hres->result->{$hostId}; - # Check state != not_installed or action == setup -> load and add my $products= 0; my $installed= 0; @@ -1619,7 +1849,7 @@ sub watch_for_opsi_jobs { } if ($progress ne $result->{'progress'} ) { # Updating progress and result - my $update_statement = "UPDATE $job_queue_tn SET modified='1', progress='".$result->{'progress'}."', result='$act_status' WHERE macaddress='$macaddress' AND siserver='localhost'"; + my $update_statement = "UPDATE $job_queue_tn SET modified='1', progress='".$result->{'progress'}."', result='$act_status' WHERE macaddress LIKE '$macaddress' AND siserver='localhost'"; my $update_res = $job_db->update_dbentry($update_statement); } if ($progress eq 100) { @@ -1630,7 +1860,7 @@ sub watch_for_opsi_jobs { } else { $done_statement .= "status='done'"; } - $done_statement .= " WHERE macaddress='$macaddress' AND siserver='localhost'"; + $done_statement .= " WHERE macaddress LIKE '$macaddress' AND siserver='localhost'"; my $done_res = $job_db->update_dbentry($done_statement); } @@ -1646,7 +1876,7 @@ sub watch_for_opsi_jobs { 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 @@ -1674,9 +1904,9 @@ sub watch_for_new_jobs { $watch_for_new_jobs_in_progress = 1; my ($kernel,$heap) = @_[KERNEL, HEAP]; - # check gosa job quaeue for jobs with executable timestamp + # check gosa job queue for jobs with executable timestamp my $timestamp = &get_time(); - my $sql_statement = "SELECT * FROM $job_queue_tn WHERE status='waiting' AND (CAST (timestamp AS INTEGER)) < $timestamp ORDER BY timestamp"; + my $sql_statement = "SELECT * FROM $job_queue_tn WHERE siserver='localhost' AND status='waiting' AND (CAST(timestamp AS UNSIGNED)) < $timestamp ORDER BY timestamp"; my $res = $job_db->exec_statement( $sql_statement ); # Merge all new jobs that would do the same actions @@ -1730,8 +1960,7 @@ sub watch_for_new_jobs { my $res_2 = $job_db->exec_statement( $sql_statement_2 ); 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 status='waiting', timestamp='".&calc_timestamp(&get_time(), 'plus', 30)."' WHERE macaddress LIKE '$macaddress' AND headertag = 'trigger_action_reinstall'"); } } next; @@ -1757,12 +1986,23 @@ sub watch_for_new_jobs { $job_msg =~ /
(\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', activate_new + 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->exec_statement($sql_statement); + } + # We don't want parallel processing last; @@ -1782,7 +2022,7 @@ sub watch_for_new_messages { # check messaging_db for new incoming messages with executable timestamp my $timestamp = &get_time(); - my $sql_statement = "SELECT * FROM $messaging_tn WHERE ( (CAST(timestamp AS INTEGER))<$timestamp AND flag='n' AND direction='in' )"; + my $sql_statement = "SELECT * FROM $messaging_tn WHERE ( (CAST(timestamp AS UNSIGNED))<$timestamp AND flag='n' AND direction='in' )"; my $res = $messaging_db->exec_statement( $sql_statement ); foreach my $hit (@{$res}) { @@ -1810,7 +2050,7 @@ sub watch_for_new_messages { foreach my $entry (@entries) { my @receivers= $entry->get_value("memberUid"); foreach my $receiver (@receivers) { - $receiver_h{$1} = 0; + $receiver_h{$receiver} = 0; } } } @@ -1818,6 +2058,7 @@ sub watch_for_new_messages { if ($mesg->code) { daemon_log("M ERROR: unable to translate group '$group_name' to user list for message delivery: $mesg->error", 1); } + &release_ldap_handle($ldap_handle); # ldap handle error ? } else { daemon_log("M ERROR: unable to translate group '$group_name' to user list for message delivery: no ldap handle available", 1); @@ -1868,7 +2109,6 @@ sub watch_for_delivery_messages { # select outgoing messages my $sql_statement = "SELECT * FROM $messaging_tn WHERE ( flag='p' AND direction='out' )"; - #&daemon_log("0 DEBUG: $sql", 7); my $res = $messaging_db->exec_statement( $sql_statement ); # build out msg for each usr @@ -1880,12 +2120,12 @@ sub watch_for_delivery_messages { # resolve usr -> host where usr is logged in my $sql = "SELECT * FROM $login_users_tn WHERE (user='$receiver')"; - #&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]; @@ -1969,21 +2209,18 @@ sub watch_for_done_messages { my ($kernel,$heap) = @_[KERNEL, HEAP]; my $sql = "SELECT * FROM $messaging_tn WHERE (flag='p' AND direction='in')"; - #&daemon_log("0 DEBUG: $sql", 7); my $res = $messaging_db->exec_statement($sql); foreach my $hit (@{$res}) { my $msg_id = @{$hit}[0]; my $sql = "SELECT * FROM $messaging_tn WHERE (id='$msg_id' AND direction='out' AND (NOT flag='s'))"; - #&daemon_log("0 DEBUG: $sql", 7); my $res = $messaging_db->exec_statement($sql); # not all usr msgs have been seen till now if ( ref(@$res[0]) eq "ARRAY") { next; } $sql = "DELETE FROM $messaging_tn WHERE (id='$msg_id')"; - #&daemon_log("0 DEBUG: $sql", 7); $res = $messaging_db->exec_statement($sql); } @@ -1999,7 +2236,7 @@ sub watch_for_old_known_clients { 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'}); @@ -2014,7 +2251,7 @@ sub watch_for_old_known_clients { $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); @@ -2033,7 +2270,7 @@ sub watch_for_next_tasks { my $sql = "SELECT * FROM $incoming_tn"; my $res = $incoming_db->select_dbentry($sql); - + while ( my ($hit_num, $hit) = each %$res) { my $headertag = $hit->{'headertag'}; if ($headertag =~ /^answer_(\d+)/) { @@ -2041,142 +2278,138 @@ sub watch_for_next_tasks { next; } my $message_id = $hit->{'id'}; + my $session_id = $hit->{'sessionid'}; + &daemon_log("$session_id DEBUG: start processing for message with incoming id: '$message_id'", 11); + $kernel->yield('next_task', $hit); my $sql = "DELETE FROM $incoming_tn WHERE id=$message_id"; my $res = $incoming_db->exec_statement($sql); } - - $kernel->delay_set('watch_for_next_tasks', 0.1); } 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 ); - $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!"); - + my ($package, $file, $row, $subroutine, $hasArgs, $wantArray, $evalText, $isRequire) = caller(1); + my $caller_text = "subroutine $subroutine"; + if ($subroutine eq "(eval)") { + $caller_text = "eval block within file '$file' for '$evalText'"; + } + daemon_log("$session_id DEBUG: new ldap handle for '$caller_text' required!", 42); + +get_handle: + my $ldap_handle = Net::LDAP->new( $ldap_uri ); + if (not ref $ldap_handle) { + daemon_log("$session_id ERROR: Connection to LDAP URI '$ldap_uri' failed! Retrying in $ldap_retry_sec seconds.", 1); + sleep($ldap_retry_sec); + goto get_handle; } 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; - } - - # 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; - #} + daemon_log("$session_id DEBUG: Connection to LDAP URI '$ldap_uri' established.", 42); } + + $ldap_handle->bind($ldap_admin_dn, password => $ldap_admin_password) or &daemon_log("$session_id ERROR: Could not bind as '$ldap_admin_dn' to LDAP URI '$ldap_uri'!", 1); return $ldap_handle; } +sub release_ldap_handle { + my ($ldap_handle, $session_id) = @_ ; + if (not defined $session_id ) { $session_id = 0 }; + + if(ref $ldap_handle) { + $ldap_handle->disconnect(); + } + &main::daemon_log("$session_id DEBUG: Released a ldap handle!", 42); + return; +} + + sub change_fai_state { - my ($st, $targets, $session_id) = @_; - $session_id = 0 if not defined $session_id; - # Set FAI state to localboot - my %mapActions= ( - reboot => '', - update => 'softupdate', - localboot => 'localboot', - reinstall => 'install', - rescan => '', - wake => '', - memcheck => 'memcheck', - sysinfo => 'sysinfo', - install => 'install', - ); + my ($st, $targets, $session_id) = @_; + $session_id = 0 if not defined $session_id; + # Set FAI state to localboot + my %mapActions= ( + reboot => '', + update => 'softupdate', + localboot => 'localboot', + reinstall => 'install', + rescan => '', + wake => '', + memcheck => 'memcheck', + sysinfo => 'sysinfo', + install => 'install', + ); - # Return if this is unknown - if (!exists $mapActions{ $st }){ - daemon_log("$session_id ERROR: unknown action '$st', can not translate ot FAIstate", 1); - return; - } + # Return if this is unknown + if (!exists $mapActions{ $st }){ + daemon_log("$session_id ERROR: unknown action '$st', can not translate ot FAIstate", 1); + return; + } - my $state= $mapActions{ $st }; + my $state= $mapActions{ $st }; - my $ldap_handle = &get_ldap_handle($session_id); - if( defined($ldap_handle) ) { + # Build search filter for hosts + my $search= "(&(objectClass=GOhard)"; + foreach (@{$targets}){ + $search.= "(macAddress=$_)"; + } + $search.= ")"; - # Build search filter for hosts - my $search= "(&(objectClass=GOhard)"; - foreach (@{$targets}){ - $search.= "(macAddress=$_)"; - } - $search.= ")"; + # If there's any host inside of the search string, procress them + if (!($search =~ /macAddress/)){ + daemon_log("$session_id ERROR: no macAddress found in filter statement for LDAP search: '$search'", 1); + return; + } - # If there's any host inside of the search string, procress them - if (!($search =~ /macAddress/)){ - daemon_log("$session_id ERROR: no macAddress found in filter statement for LDAP search: '$search'", 1); - return; - } + my $ldap_handle = &get_ldap_handle($session_id); + # Perform search for Unit Tag + my $mesg = $ldap_handle->search( + base => $ldap_base, + scope => 'sub', + attrs => ['dn', 'FAIstate', 'objectClass'], + filter => "$search" + ); - # Perform search for Unit Tag - my $mesg = $ldap_handle->search( - base => $ldap_base, - scope => 'sub', - attrs => ['dn', 'FAIstate', 'objectClass'], - filter => "$search" - ); + if ($mesg->count) { + my @entries = $mesg->entries; + if (0 == @entries) { + daemon_log("$session_id ERROR: ldap search failed: ldap_base=$ldap_base, filter=$search", 1); + } - if ($mesg->count) { - my @entries = $mesg->entries; - if (0 == @entries) { - daemon_log("$session_id ERROR: ldap search failed: ldap_base=$ldap_base, filter=$search", 1); - } - - foreach my $entry (@entries) { - # Only modify entry if it is not set to '$state' - if ($entry->get_value("FAIstate") ne "$state"){ - daemon_log("$session_id INFO: Setting FAIstate to '$state' for ".$entry->dn, 5); - my $result; - my %tmp = map { $_ => 1 } $entry->get_value("objectClass"); - if (exists $tmp{'FAIobject'}){ - if ($state eq ''){ - $result= $ldap_handle->modify($entry->dn, changes => [ - delete => [ FAIstate => [] ] ]); - } else { - $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 ] ]); - } - - # Errors? - if ($result->code){ - daemon_log("$session_id Error: Setting FAIstate to '$state' for ".$entry->dn. "failed: ".$result->error, 1); - } - } else { - daemon_log("$session_id DEBUG FAIstate at host '".$entry->dn."' already at state '$st'", 7); - } - } - } else { - daemon_log("$session_id ERROR: LDAP search failed: ldap_base=$ldap_base, filter=$search", 1); - } + foreach my $entry (@entries) { + # Only modify entry if it is not set to '$state' + if ($entry->get_value("FAIstate") ne "$state"){ + daemon_log("$session_id INFO: Setting FAIstate to '$state' for ".$entry->dn, 5); + my $result; + my %tmp = map { $_ => 1 } $entry->get_value("objectClass"); + if (exists $tmp{'FAIobject'}){ + if ($state eq ''){ + $result= $ldap_handle->modify($entry->dn, changes => [ delete => [ FAIstate => [] ] ]); + } else { + $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 ] ]); + } - # if no ldap handle defined - } else { - daemon_log("$session_id ERROR: no LDAP handle defined for update FAIstate", 1); - } + # Errors? + if ($result->code){ + daemon_log("$session_id Error: Setting FAIstate to '$state' for ".$entry->dn. "failed: ".$result->error, 1); + } + } else { + daemon_log("$session_id DEBUG FAIstate at host '".$entry->dn."' already at state '$st'", 42); + } + } + } else { + daemon_log("$session_id ERROR: LDAP search failed: ldap_base=$ldap_base, filter=$search", 1); + } + &release_ldap_handle($ldap_handle, $session_id); return; } @@ -2201,6 +2434,7 @@ sub change_goto_state { # If there's any host inside of the search string, procress them if (!($search =~ /macAddress/)){ + &release_ldap_handle($ldap_handle); return; } @@ -2221,8 +2455,7 @@ sub change_goto_state { 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){ @@ -2236,6 +2469,8 @@ sub change_goto_state { } } + &release_ldap_handle($ldap_handle, $session_id); + return; } @@ -2265,11 +2500,11 @@ sub run_create_fai_server_db { 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) = @_; my $result; if (not defined $session_id) { $session_id = 0; } - my $ldap_handle = &get_ldap_handle(); + my $ldap_handle = &get_ldap_handle($session_id); if(defined($ldap_handle)) { daemon_log("$session_id INFO: create_fai_server_db: start", 5); my $mesg= $ldap_handle->search( @@ -2279,50 +2514,50 @@ sub create_fai_server_db { filter => "(&(FAIrepository=*)(objectClass=FAIrepositoryServer))", ); if($mesg->{'resultCode'} == 0 && - $mesg->count != 0) { - foreach my $entry (@{$mesg->{entries}}) { - if($entry->exists('FAIrepository')) { - # Add an entry for each Repository configured for server - foreach my $repo(@{$entry->get_value('FAIrepository', asref => 1)}) { - my($tmp_url,$tmp_server,$tmp_release,$tmp_sections) = split(/\|/, $repo); - my $tmp_tag= $entry->get_value('gosaUnitTag') || ""; - $result= $fai_server_db->add_dbentry( { - table => $table_name, - primkey => ['server', 'release', 'tag'], - server => $tmp_url, - release => $tmp_release, - sections => $tmp_sections, - tag => (length($tmp_tag)>0)?$tmp_tag:"", - } ); - } - } - } - } + $mesg->count != 0) { + foreach my $entry (@{$mesg->{entries}}) { + if($entry->exists('FAIrepository')) { + # Add an entry for each Repository configured for server + foreach my $repo(@{$entry->get_value('FAIrepository', asref => 1)}) { + my($tmp_url,$tmp_server,$tmp_release,$tmp_sections) = split(/\|/, $repo); + my $tmp_tag= $entry->get_value('gosaUnitTag') || ""; + $result= $fai_server_db->add_dbentry( { + table => $table_name, + primkey => ['server', 'fai_release', 'tag'], + server => $tmp_url, + fai_release => $tmp_release, + sections => $tmp_sections, + tag => (length($tmp_tag)>0)?$tmp_tag:"", + } ); + } + } + } + } daemon_log("$session_id INFO: create_fai_server_db: finished", 5); + &release_ldap_handle($ldap_handle); # 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; + + 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 $task = POE::Wheel::Run->new( - Program => sub { &create_fai_release_db($table_name, $session_id) }, - StdoutEvent => "session_run_result", - StderrEvent => "session_run_debug", - CloseEvent => "session_run_done", - ); + my $task = POE::Wheel::Run->new( + Program => sub { &create_fai_release_db($table_name, $session_id) }, + StdoutEvent => "session_run_result", + StderrEvent => "session_run_debug", + CloseEvent => "session_run_done", + ); - $heap->{task}->{ $task->ID } = $task; - return; + $heap->{task}->{ $task->ID } = $task; + return; } @@ -2330,10 +2565,10 @@ sub create_fai_release_db { my ($table_name, $session_id) = @_; my $result; - # used for logging - if (not defined $session_id) { $session_id = 0; } + # used for logging + if (not defined $session_id) { $session_id = 0; } - my $ldap_handle = &get_ldap_handle(); + my $ldap_handle = &get_ldap_handle($session_id); if(defined($ldap_handle)) { daemon_log("$session_id INFO: create_fai_release_db: start",5); my $mesg= $ldap_handle->search( @@ -2342,8 +2577,10 @@ sub create_fai_release_db { 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,138); + # Walk through all possible FAI container ou's my @sql_list; my $timestamp= &get_time(); @@ -2356,7 +2593,7 @@ sub create_fai_release_db { if(defined($entry) && ref($entry) eq 'HASH') { my $sql= "INSERT INTO $table_name " - ."(timestamp, release, class, type, state) VALUES (" + ."(timestamp, fai_release, class, type, state) VALUES (" .$timestamp."," ."'".$entry->{'release'}."'," ."'".$entry->{'class'}."'," @@ -2369,17 +2606,19 @@ sub create_fai_release_db { } } - 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",138); + &release_ldap_handle($ldap_handle); 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",138); + } 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; return $result; } @@ -2424,23 +2663,25 @@ sub resolve_fai_classes { my $fai_filter= "(|(&(objectClass=FAIclass)(|(objectClass=".join(")(objectClass=", @possible_fai_classes).")))(objectClass=FAIbranch))"; my $fai_classes; - daemon_log("$session_id DEBUG: Searching for FAI entries in base $fai_base",7); + daemon_log("$session_id DEBUG: Searching for FAI entries in base $fai_base", 138); my $mesg= $ldap_handle->search( base => $fai_base, scope => 'sub', attrs => ['cn','objectClass','FAIstate'], filter => $fai_filter, ); - daemon_log("$session_id DEBUG: Found ".$mesg->count()." FAI entries",7); + daemon_log("$session_id DEBUG: Found ".$mesg->count()." FAI entries", 138); if($mesg->{'resultCode'} == 0 && $mesg->count != 0) { 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) { @@ -2475,7 +2716,9 @@ sub resolve_fai_classes { } } 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) { @@ -2620,12 +2863,15 @@ sub session_run_debug { 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 $session_id = shift || 0; my $result="/tmp/gosa_si_tmp_sources_list"; # Remove old file @@ -2641,6 +2887,7 @@ sub create_sources_list { return undef; } if(defined($main::ldap_server_dn) and length($main::ldap_server_dn) > 0) { + my $ldap_handle = &get_ldap_handle($session_id); my $mesg=$ldap_handle->search( base => $main::ldap_server_dn, scope => 'base', @@ -2658,6 +2905,7 @@ sub create_sources_list { } } } + &release_ldap_handle($ldap_handle); } else { if (defined $main::ldap_server_dn){ &main::daemon_log("$session_id ERROR: something wrong with ldap_server_dn '$main::ldap_server_dn', abort create_sources_list", 1); @@ -2674,10 +2922,9 @@ sub create_sources_list { 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", @@ -2687,7 +2934,7 @@ sub run_create_packages_list_db { 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 @@ -2703,15 +2950,7 @@ sub create_packages_list_db { } 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); @@ -2758,11 +2997,11 @@ sub create_packages_list_db { close (CONFIG); - - find(\&cleanup_and_extract, keys( %repo_dirs )); - &main::strip_packages_list_statements(); - unshift @packages_list_statements, "VACUUM"; - $packages_list_db->exec_statementlist(\@packages_list_statements); + if(keys(%repo_dirs)) { + find(\&cleanup_and_extract, keys( %repo_dirs )); + &main::strip_packages_list_statements(); + $packages_list_db->exec_statementlist(\@packages_list_statements); + } unlink($packages_list_under_construction); daemon_log("$session_id INFO: create_packages_list_db: finished", 5); return; @@ -2770,12 +3009,13 @@ sub create_packages_list_db { # 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) { @@ -2794,6 +3034,9 @@ sub strip_packages_list_statements { (! (@{$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 @@ -2824,9 +3067,26 @@ sub strip_packages_list_statements { } } - # 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}}) { @@ -2859,14 +3119,26 @@ sub strip_packages_list_statements { 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; } @@ -2879,7 +3151,7 @@ sub parse_package_info { $repo_dirs{ "${repo_path}/pool" } = 1; foreach $package ("Packages.gz"){ - daemon_log("$session_id DEBUG: create_packages_list: fetch $baseurl, $dist, $section", 7); + daemon_log("$session_id DEBUG: create_packages_list: fetch $baseurl, $dist, $section", 266); get_package( "$baseurl/dists/$dist/$section/binary-$arch/$package", "$outdir/$dist/$section", $session_id ); parse_package( "$outdir/$dist/$section", $dist, $path, $session_id ); } @@ -2897,11 +3169,11 @@ sub get_package { # This is ugly, but I've no time to take a look at "how it works in perl" if(0 == system("wget '$url' -O '$dest' 2>/dev/null") ) { system("gunzip -cd '$dest' > '$dest.in'"); - daemon_log("$session_id DEBUG: run command: gunzip -cd '$dest' > '$dest.in'", 5); + daemon_log("$session_id DEBUG: run command: gunzip -cd '$dest' > '$dest.in'", 266); unlink($dest); - daemon_log("$session_id DEBUG: delete file '$dest'", 5); + daemon_log("$session_id DEBUG: delete file '$dest'", 266); } 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; } @@ -2993,24 +3265,22 @@ sub store_fileinfo { sub cleanup_and_extract { - my $fileinfo = $repo_files{ $File::Find::name }; - - if( defined $fileinfo ) { + my $fileinfo = $repo_files{ $File::Find::name }; - my $dir = "$outdir/$fileinfo->{ 'dist' }/debconf.d"; - my $sql; - my $package = $fileinfo->{ 'package' }; - my $newver = $fileinfo->{ 'version' }; + if( defined $fileinfo ) { + my $dir = "$outdir/$fileinfo->{ 'dist' }/debconf.d"; + my $sql; + my $package = $fileinfo->{ 'package' }; + my $newver = $fileinfo->{ 'version' }; - mkpath($dir); - system( "dpkg -e '$File::Find::name' '$dir/DEBIAN'" ); + mkpath($dir); + system( "dpkg -e '$File::Find::name' '$dir/DEBIAN'" ); 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", 266); - my $tmpl= ""; - { + my $tmpl= ""; { local $/=undef; open FILE, "$dir/DEBIAN/templates"; $tmpl = &encode_base64(); @@ -3019,65 +3289,171 @@ sub cleanup_and_extract { rmtree("$dir/DEBIAN/templates"); $sql= "update $main::packages_list_tn set template = '$tmpl' where package = '$package' and version = '$newver';"; - push @packages_list_statements, $sql; + push @packages_list_statements, $sql; } - } + } - return; + return; } +sub prepare_server_registration +{ + # Add foreign server from cfg file + my @foreign_server_list; + if ($foreign_server_string ne "") { + my @cfg_foreign_server_list = split(",", $foreign_server_string); + foreach my $foreign_server (@cfg_foreign_server_list) { + push(@foreign_server_list, $foreign_server); + } + + daemon_log("0 INFO: found foreign server in config file: ".join(", ", @foreign_server_list), 5); + } + + # Perform a DNS lookup for server registration if flag is true + if ($dns_lookup eq "true") { + # Add foreign server from dns + my @tmp_servers; + if (not $server_domain) { + # Try our DNS Searchlist + for my $domain(get_dns_domains()) { + chomp($domain); + my ($tmp_domains, $error_string) = &get_server_addresses($domain); + if(@$tmp_domains) { + for my $tmp_server(@$tmp_domains) { + push @tmp_servers, $tmp_server; + } + } + } + if(@tmp_servers && length(@tmp_servers)==0) { + daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3); + } + } else { + @tmp_servers = &get_server_addresses($server_domain); + if( 0 == @tmp_servers ) { + daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3); + } + } + + daemon_log("0 INFO: found foreign server via DNS ".join(", ", @tmp_servers), 5); + + foreach my $server (@tmp_servers) { + unshift(@foreign_server_list, $server); + } + } else { + daemon_log("0 INFO: DNS lookup for server registration is disabled", 5); + } + + # eliminate duplicate entries + @foreign_server_list = &del_doubles(@foreign_server_list); + my $all_foreign_server = join(", ", @foreign_server_list); + 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 $cur_timestamp = &get_time(); + foreach my $foreign_server (@foreign_server_list) { + + # do not add myself to known_server_db + if (&is_local($foreign_server)) { next; } + ###################################### + + my $res = $known_server_db->add_dbentry( {table=>$known_server_tn, + primkey=>['hostname'], + hostname=>$foreign_server, + macaddress=>"", + status=>'not_yet_registered', + hostkey=>"none", + loaded_modules => "none", + timestamp=>$cur_timestamp, + update_time=>'19700101000000', + } ); + } +} + sub register_at_foreign_servers { my ($kernel) = $_[KERNEL]; - # hole alle bekannten server aus known_server_db - my $server_sql = "SELECT * FROM $known_server_tn"; - my $server_res = $known_server_db->exec_statement($server_sql); + # Update status and update-time of all si-server with expired update_time and + # block them for race conditional registration processes of other si-servers. + my $act_time = &get_time(); + my $block_statement = "UPDATE $known_server_tn SET status='new_server',update_time='19700101000000' WHERE (CAST(update_time AS UNSIGNED))<$act_time "; + my $block_res = $known_server_db->exec_statement($block_statement); - # no entries in known_server_db - if (not ref(@$server_res[0]) eq "ARRAY") { - # TODO - } + # Fetch all si-server from db where update_time is younger than act_time + my $fetch_statement = "SELECT * FROM $known_server_tn WHERE update_time='19700101000000'"; + my $fetch_res = $known_server_db->exec_statement($fetch_statement); - # detect already connected clients + # Detect already connected clients. Will be added to registration msg later. my $client_sql = "SELECT * FROM $known_clients_tn"; my $client_res = $known_clients_db->exec_statement($client_sql); - # send my server details to all other gosa-si-server within the network - foreach my $hit (@$server_res) { + # Send registration messag to all fetched si-server + foreach my $hit (@$fetch_res) { my $hostname = @$hit[0]; my $hostkey = &create_passwd; - # add already connected clients to registration message + # Add already connected clients to registration message my $myhash = &create_xml_hash('new_server', $server_address, $hostname); &add_content2xml_hash($myhash, 'key', $hostkey); map(&add_content2xml_hash($myhash, 'client', @{$_}[0].",".@{$_}[4]), @$client_res); - # add locally loaded gosa-si modules to registration message + # Add locally loaded gosa-si modules to registration message my $loaded_modules = {}; while (my ($package, $pck_info) = each %$known_modules) { - next if ((!defined(@$pck_info[2])) || (!(ref (@$pck_info[2]) eq 'HASH'))); - foreach my $act_module (keys(%{@$pck_info[2]})) { - $loaded_modules->{$act_module} = ""; - } - } - + next if ((!defined(@$pck_info[2])) || (!(ref (@$pck_info[2]) eq 'HASH'))); + foreach my $act_module (keys(%{@$pck_info[2]})) { + $loaded_modules->{$act_module} = ""; + } + } map(&add_content2xml_hash($myhash, "loaded_modules", $_), keys(%$loaded_modules)); - # add macaddress to registration message + # Add macaddress to registration message my ($host_ip, $host_port) = split(/:/, $hostname); my $local_ip = &get_local_ip_for_remote_ip($host_ip); my $network_interface= &get_interface_for_ip($local_ip); my $host_mac = &get_mac_for_interface($network_interface); &add_content2xml_hash($myhash, 'macaddress', $host_mac); - # build registration message and send it + # Build registration message and send it my $foreign_server_msg = &create_xml_string($myhash); my $error = &send_msg_to_target($foreign_server_msg, $hostname, $ServerPackages_key, "new_server", 0); } - - $kernel->delay_set("register_at_foreign_servers", $foreign_servers_register_delay); - return; + + + # After n sec perform a check of all server registration processes + $kernel->delay_set("control_server_registration", 2); + + return; +} + + +sub control_server_registration { + my ($kernel) = $_[KERNEL]; + + # Check if all registration processes succeed or not + my $select_statement = "SELECT * FROM $known_server_tn WHERE status='new_server'"; + my $select_res = $known_server_db->exec_statement($select_statement); + + # If at least one registration process failed, maybe in case of a race condition + # with a foreign registration process + if (@$select_res > 0) + { + # Release block statement 'new_server' to make the server accessible + # for foreign registration processes + my $update_statement = "UPDATE $known_server_tn SET status='waiting' WHERE status='new_server'"; + my $update_res = $known_server_db->exec_statement($update_statement); + + # Set a random delay to avoid the registration race condition + my $new_foreign_servers_register_delay = int(rand(4))+1; + $kernel->delay_set("register_at_foreign_servers", $new_foreign_servers_register_delay); + } + # If all registration processes succeed + else + { + $kernel->delay_set("register_at_foreign_servers", $foreign_servers_register_delay); + } + + return; } @@ -3089,7 +3465,8 @@ GetOptions("h|help" => \&usage, "f|foreground" => \$foreground, "v|verbose+" => \$verbose, "no-arp+" => \$no_arp, - ); + "d=s" => \$debug_parts, + ) or &usage("", 1); # read and set config parameters &check_cmdline_param ; @@ -3136,141 +3513,140 @@ if ($server_headURL =~ /\/tag\// || } 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(" ", 1); daemon_log("$0 started!", 1); daemon_log("status: $server_status", 1); daemon_log($server_status_hash->{$server_status}.": $server_revision", 1); -# connect to incoming_db -unlink($incoming_file_name); -$incoming_db = GOSA::DBsqlite->new($incoming_file_name); -$incoming_db->create_table($incoming_tn, \@incoming_col_names); +# Buildup data bases +{ + no strict "refs"; -# connect to gosa-si job queue -$job_db = GOSA::DBsqlite->new($job_queue_file_name); -$job_db->create_table($job_queue_tn, \@job_queue_col_names); + if ($db_module eq "DBmysql") { -# connect to known_clients_db -$known_clients_db = GOSA::DBsqlite->new($known_clients_file_name); -$known_clients_db->create_table($known_clients_tn, \@known_clients_col_names); + daemon_log("0 INFO: importing database module '$db_module'", 1); -# connect to foreign_clients_db -$foreign_clients_db = GOSA::DBsqlite->new($foreign_clients_file_name); -$foreign_clients_db->create_table($foreign_clients_tn, \@foreign_clients_col_names); + # connect to incoming_db + $incoming_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); -# connect to known_server_db -unlink($known_server_file_name); -$known_server_db = GOSA::DBsqlite->new($known_server_file_name); -$known_server_db->create_table($known_server_tn, \@known_server_col_names); + # connect to gosa-si job queue + $job_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); -# connect to login_usr_db -$login_users_db = GOSA::DBsqlite->new($login_users_file_name); -$login_users_db->create_table($login_users_tn, \@login_users_col_names); - -# connect to fai_server_db and fai_release_db -unlink($fai_server_file_name); -$fai_server_db = GOSA::DBsqlite->new($fai_server_file_name); -$fai_server_db->create_table($fai_server_tn, \@fai_server_col_names); + # connect to known_clients_db + $known_clients_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); -unlink($fai_release_file_name); -$fai_release_db = GOSA::DBsqlite->new($fai_release_file_name); -$fai_release_db->create_table($fai_release_tn, \@fai_release_col_names); - -# 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); -$packages_list_db->create_table($packages_list_tn, \@packages_list_col_names); + # connect to foreign_clients_db + $foreign_clients_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); -# connect to messaging_db -$messaging_db = GOSA::DBsqlite->new($messaging_file_name); -$messaging_db->create_table($messaging_tn, \@messaging_col_names); + # connect to known_server_db + $known_server_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); + # connect to login_usr_db + $login_users_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); -# create xml object used for en/decrypting -$xml = new XML::Simple(); + # connect to fai_server_db + $fai_server_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); + # connect to fai_release_db + $fai_release_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); -# foreign servers -my @foreign_server_list; + # connect to packages_list_db + $packages_list_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); -# add foreign server from cfg file -if ($foreign_server_string ne "") { - my @cfg_foreign_server_list = split(",", $foreign_server_string); - foreach my $foreign_server (@cfg_foreign_server_list) { - push(@foreign_server_list, $foreign_server); - } + # connect to messaging_db + $messaging_db = ("GOSA::".$db_module)->new($main::mysql_database, $main::mysql_host, $main::mysql_username, $main::mysql_password); - daemon_log("0 INFO: found foreign server in config file: ".join(", ", @foreign_server_list), 5); -} - -# Perform a DNS lookup for server registration if flag is true -if ($dns_lookup eq "true") { - # Add foreign server from dns - my @tmp_servers; - if (not $server_domain) { - # Try our DNS Searchlist - for my $domain(get_dns_domains()) { - chomp($domain); - my ($tmp_domains, $error_string) = &get_server_addresses($domain); - if(@$tmp_domains) { - for my $tmp_server(@$tmp_domains) { - push @tmp_servers, $tmp_server; - } - } - } - if(@tmp_servers && length(@tmp_servers)==0) { - daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3); - } - } else { - @tmp_servers = &get_server_addresses($server_domain); - if( 0 == @tmp_servers ) { - daemon_log("0 WARNING: no foreign gosa-si-server found in DNS for domain '$server_domain'", 3); - } - } + } elsif ($db_module eq "DBsqlite") { - daemon_log("0 INFO: found foreign server via DNS ".join(", ", @tmp_servers), 5); + daemon_log("0 INFO: importing database module '$db_module'", 1); - foreach my $server (@tmp_servers) { - unshift(@foreign_server_list, $server); + # connect to incoming_db + unlink($incoming_file_name); + $incoming_db = GOSA::DBsqlite->new($incoming_file_name); + chmod(0640, $incoming_file_name); + chown($root_uid, $adm_gid, $incoming_file_name); + + # connect to gosa-si job queue + $job_db = GOSA::DBsqlite->new($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); + $known_clients_db = GOSA::DBsqlite->new($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(0640, $foreign_clients_file_name); + chown($root_uid, $adm_gid, $foreign_clients_file_name); + + # connect to known_server_db + unlink($known_server_file_name); # do not delete, gosa-si-server should be forced to check config file and dns at each start + $known_server_db = GOSA::DBsqlite->new($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(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(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(0640, $fai_release_file_name); + chown($root_uid, $adm_gid, $fai_release_file_name); + + # connect to packages_list_db + unlink($packages_list_under_construction); + $packages_list_db = GOSA::DBsqlite->new($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(0640, $messaging_file_name); + chown($root_uid, $adm_gid, $messaging_file_name); } -} else { - daemon_log("0 INFO: DNS lookup for server registration is disabled", 5); } +# Creating tables -# eliminate duplicate entries -@foreign_server_list = &del_doubles(@foreign_server_list); -my $all_foreign_server = join(", ", @foreign_server_list); -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(); -foreach my $foreign_server (@foreign_server_list) { - - # do not add myself to known_server_db - if (&is_local($foreign_server)) { next; } - ###################################### +daemon_log("0 INFO: creating tables in database with '$db_module'", 1); - my $res = $known_server_db->add_dbentry( {table=>$known_server_tn, - primkey=>['hostname'], - hostname=>$foreign_server, - macaddress=>"", - status=>'not_jet_registered', - hostkey=>"none", - loaded_modules => "none", - timestamp=>$act_timestamp, - } ); -} +$messaging_db->create_table($messaging_tn, \@messaging_col_names); +$packages_list_db->create_table($packages_list_tn, \@packages_list_col_names); +$fai_release_db->create_table($fai_release_tn, \@fai_release_col_names); +$fai_server_db->create_table($fai_server_tn, \@fai_server_col_names); +$login_users_db->create_table($login_users_tn, \@login_users_col_names); +$known_server_db->create_table($known_server_tn, \@known_server_col_names); +$foreign_clients_db->create_table($foreign_clients_tn, \@foreign_clients_col_names); +$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(); # Import all modules &import_modules; @@ -3278,6 +3654,21 @@ foreach my $foreign_server (@foreign_server_list) { # Check wether all modules are gosa-si valid passwd check &password_check; +# Check DNS and config file for server registration +if ($serverPackages_enabled eq "true") { &prepare_server_registration; } + +# Create functions hash +while (my ($module, @mod_info) = each %$known_modules) +{ + while (my ($plugin, $functions) = each %{$mod_info[0][2]}) + { + while (my ($function, $nothing) = each %$functions ) + { + $known_functions->{$function} = $nothing; + } + } +} + # Prepare for using Opsi if ($opsi_enabled eq "true") { use JSON::RPC::Client; @@ -3288,37 +3679,52 @@ if ($opsi_enabled eq "true") { POE::Component::Server::TCP->new( - Alias => "TCP_SERVER", + Alias => "TCP_SERVER", Port => $server_port, ClientInput => sub { - my ($kernel, $input) = @_[KERNEL, ARG0]; - push(@tasks, $input); - push(@msgs_to_decrypt, $input); - $kernel->yield("msg_to_decrypt"); - }, - InlineStates => { - msg_to_decrypt => \&msg_to_decrypt, - next_task => \&next_task, - task_result => \&handle_task_result, - task_done => \&handle_task_done, - task_debug => \&handle_task_debug, - child_reap => sub { "Do nothing special. I'm just a comment, but i'm necessary!" }, - } + my ($kernel, $input, $heap, $session) = @_[KERNEL, ARG0, HEAP, SESSION]; + my $session_id = $session->ID; + if ($input =~ /;([\d\.]+):([\d]+)$/) + { + # Messages from other servers should be blocked if config option is set + if (($2 eq $server_port) && ($serverPackages_enabled eq "false")) + { + return; + } + &daemon_log("$session_id DEBUG: incoming message from '$1:$2'", 11); + } + else + { + my $remote_ip = $heap->{'remote_ip'}; + &daemon_log("$session_id DEBUG: incoming message from '$remote_ip'", 11); + } + push(@msgs_to_decrypt, $input); + $kernel->yield("msg_to_decrypt"); + }, + InlineStates => { + msg_to_decrypt => \&msg_to_decrypt, + watch_for_next_tasks => \&watch_for_next_tasks, + next_task => \&next_task, + task_result => \&handle_task_result, + task_done => \&handle_task_done, + task_debug => \&handle_task_debug, + child_reap => sub { "Do nothing special. I'm just a comment, but i'm necessary!" }, + } ); -daemon_log("start socket for incoming xml messages at port '$server_port' ", 1); +daemon_log("0 INFO: start socket for incoming xml messages at port '$server_port' ", 1); # create session for repeatedly checking the job queue for jobs POE::Session->create( inline_states => { _start => \&session_start, register_at_foreign_servers => \®ister_at_foreign_servers, + control_server_registration => \&control_server_registration, sig_handler => \&sig_handler, next_task => \&next_task, task_result => \&handle_task_result, task_done => \&handle_task_done, task_debug => \&handle_task_debug, - watch_for_next_tasks => \&watch_for_next_tasks, watch_for_new_messages => \&watch_for_new_messages, watch_for_delivery_messages => \&watch_for_delivery_messages, watch_for_done_messages => \&watch_for_done_messages,