diff --git a/gosa-si/gosa-si-server b/gosa-si/gosa-si-server
index 9f97a8a79043c69f69cf982d7920ef9d09d1f09c..99e02fdb491627812c2f21e8471a5d669134226b 100755 (executable)
--- a/gosa-si/gosa-si-server
+++ b/gosa-si/gosa-si-server
use Net::LDAP;
use Net::LDAP::Util qw(:escape);
use Time::HiRes qw( usleep);
-use DateTime;
my $modules_path = "/usr/lib/gosa-si/modules";
use lib "/usr/lib/gosa-si/modules";
my ($server);
my ($gosa_server, $job_queue_timeout, $job_queue_loop_delay);
my ($messaging_db_loop_delay);
-my ($known_modules);
my ($procid, $pid);
my ($arp_fifo);
my ($xml);
$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,
);
# additional variable which should be globaly accessable
our $forground;
our $cfg_file;
our ($ldap_uri, $ldap_base, $ldap_admin_dn, $ldap_admin_password, $ldap_server_dn);
+our $known_modules;
# specifies the verbosity of the daemon_log
$verbose = 0 ;
our $known_server_db;
our $known_server_tn = "known_server";
my $known_server_file_name;
-my @known_server_col_names = ("hostname", "status", "hostkey", "timestamp");
+my @known_server_col_names = ("hostname", "macaddress", "status", "hostkey", "loaded_modules", "timestamp");
# holds all registrated clients
our $known_clients_db;
our $opsi_client;
our $opsi_url;
+# Lifetime of logged in user information. If no update information comes after n seconds,
+# the user is expeceted to be no longer logged in or the host is no longer running. Because
+# of this, the user is deleted from login_users_db
+our $logged_in_user_date_of_expiry = 600;
%cfg_defaults = (
"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'],
},
"ClientPackages" => {
"key" => [\$ClientPackages_key, "none"],
+ "user-date-of-expiry" => [\$logged_in_user_date_of_expiry, 600],
},
"ServerPackages"=> {
"address" => [\$foreign_server_string, ""],
my $info = eval($mod_name.'::get_module_info()');
# Only load module if get_module_info() returns a non-null object
if( $info ) {
- my ($input_address, $input_key, $input, $input_active, $input_type) = @{$info};
+ my ($input_address, $input_key, $event_hash) = @{$info};
$known_modules->{$mod_name} = $info;
daemon_log("0 INFO: module $mod_name loaded", 5);
}
}
}
+
close (DIR);
}
}
};
if($@) {
- daemon_log("$session_id DEBUG: do not understand the message: $@", 7);
+ daemon_log("$session_id ERROR: do not understand the message: $@", 1);
$msg = undef;
$msg_hash = undef;
}
}
-sub get_local_ip_for_remote_ip {
- my $remote_ip= shift;
- my $result="0.0.0.0";
-
- if($remote_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
- if($remote_ip eq "127.0.0.1") {
- $result = "127.0.0.1";
- } else {
- my $PROC_NET_ROUTE= ('/proc/net/route');
-
- open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
- or die "Could not open $PROC_NET_ROUTE";
-
- my @ifs = <PROC_NET_ROUTE>;
-
- close(PROC_NET_ROUTE);
-
- # Eat header line
- shift @ifs;
- chomp @ifs;
- foreach my $line(@ifs) {
- my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
- my $destination;
- my $mask;
- my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
- $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
- ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
- $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
- if(new NetAddr::IP($remote_ip)->within(new NetAddr::IP($destination, $mask))) {
- # destination matches route, save mac and exit
- $result= &get_ip($Iface);
- last;
- }
- }
- }
- } else {
- daemon_log("0 WARNING: get_local_ip_for_remote_ip() was called with a non-ip parameter: '$remote_ip'", 1);
- }
- return $result;
-}
+#sub get_local_ip_for_remote_ip {
+# my $remote_ip= shift;
+# my $result="0.0.0.0";
+#
+# if($remote_ip =~ /^(\d\d?\d?\.){3}\d\d?\d?$/) {
+# if($remote_ip eq "127.0.0.1") {
+# $result = "127.0.0.1";
+# } else {
+# my $PROC_NET_ROUTE= ('/proc/net/route');
+#
+# open(PROC_NET_ROUTE, "<$PROC_NET_ROUTE")
+# or die "Could not open $PROC_NET_ROUTE";
+#
+# my @ifs = <PROC_NET_ROUTE>;
+#
+# close(PROC_NET_ROUTE);
+#
+# # Eat header line
+# shift @ifs;
+# chomp @ifs;
+# foreach my $line(@ifs) {
+# my ($Iface,$Destination,$Gateway,$Flags,$RefCnt,$Use,$Metric,$Mask,$MTU,$Window,$IRTT)=split(/\s/, $line);
+# my $destination;
+# my $mask;
+# my ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Destination);
+# $destination= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+# ($d,$c,$b,$a)=unpack('a2 a2 a2 a2', $Mask);
+# $mask= sprintf("%d.%d.%d.%d", hex($a), hex($b), hex($c), hex($d));
+# if(new NetAddr::IP($remote_ip)->within(new NetAddr::IP($destination, $mask))) {
+# # destination matches route, save mac and exit
+# $result= &get_ip($Iface);
+# last;
+# }
+# }
+# }
+# } else {
+# daemon_log("0 WARNING: get_local_ip_for_remote_ip() was called with a non-ip parameter: '$remote_ip'", 1);
+# }
+# return $result;
+#}
sub send_msg_to_target {
my $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
if ($target =~ /^\d+\.\d+\.\d+\.\d+:\d+$/) {
$local_address = &get_local_ip_for_remote_ip($target_ip).":$server_port";
} else {
$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;
+ }
+
# target and source is equal to GOSA -> process here
if (not $done) {
if ($target eq "GOSA" && $source eq "GOSA") {
# 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") {
$done = 1;
my $hostname = $res->{1}->{'hostname'};
$msg =~ s/<target>$target<\/target>/<target>$hostname<\/target>/;
- #print STDERR "target is a client address in known_clients -> process here\n";
+ #print STDERR "target is a client address in known_clients -> process here\n";
my $local_address = &get_local_ip_for_remote_ip($target_ip).":$server_port";
if ($source eq "GOSA") {
$msg =~ s/<\/xml>/<forward_to_gosa>$local_address,$session_id<\/forward_to_gosa><\/xml>/;
# target is a server address -> forward to server
if (not $done) {
- $sql = "SELECT * FROM $known_server_tn WHERE hostname='$target'";
+ $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'};
&send_msg_to_target($msg, $target, $hostkey, $header, $session_id);
$done = 1;
- #print STDERR "target is a server address -> forward to server\n";
} else {
$not_found_in_known_server_db = 1;
}
while ($answer_str =~ /<header>(\w+)<\/header>/g) {
daemon_log("$session_id INFO: got answer message with header '$1'", 5);
}
- daemon_log("$session_id DEBUG: $module: got answer from module: \n".$answer_str,8);
+ daemon_log("$session_id DEBUG: $module: got answer from module: \n".$answer_str,9);
} else {
- daemon_log("$session_id DEBUG: $module: got no answer from module!" ,8);
+ daemon_log("$session_id DEBUG: $module: got no answer from module!" ,7);
}
}
&update_jobdb_status_for_send_msgs($answer, $error);
}
- # target of msg is a mac address
+ # 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", 5);
+ daemon_log("$session_id INFO: target is mac address '$answer_target', looking for host in known_clients and foreign_clients", 5);
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;
&update_jobdb_status_for_send_msgs($answer, $error);
$found_ip_flag++ ;
}
+ 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);
+ while( my ($hit_num, $hit) = each %{ $res } ) {
+ my $host_name = $hit->{hostname};
+ my $reg_server = $hit->{regserver};
+ daemon_log("$session_id INFO: found host '$host_name' with mac '$answer_target', registered at '$reg_server'", 5);
+
+ # Fetch key for reg_server
+ my $reg_server_key;
+ my $sql = "SELECT * FROM $known_server_tn WHERE hostname='$reg_server'";
+ my $res = $known_server_db->select_dbentry($sql);
+ if (exists $res->{1}) {
+ $reg_server_key = $res->{1}->{'hostkey'};
+ } else {
+ daemon_log("$session_id ERROR: cannot find hostkey for '$host_name' in '$known_server_tn'", 1);
+ daemon_log("$session_id ERROR: unable to forward answer to correct registration server, processing is aborted!", 1);
+ $reg_server_key = undef;
+ }
+
+ # Send answer to server where client is registered
+ 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);
+ $found_ip_flag++ ;
+ }
+ }
+ }
if( $found_ip_flag == 0) {
daemon_log("$session_id WARNING: no host found in known_clients with mac address '$answer_target'", 3);
}
- # answer is for one specific host
+ # Answer is for one specific host
} else {
# get encrypt_key
my $encrypt_key = &get_encrypt_key($answer_target);
}
-sub check_opsi_res {
- my $res= shift;
- if($res) {
- if ($res->is_error) {
- &main::daemon_log("ERROR: opsi configed communication failed: ".$res->error_message, 1);
- } else {
- return 1;
- }
- } else {
- &main::daemon_log("ERROR: opsi configed communication failed: ".$opsi_client->status_line, 1);
- }
- return 0;
-}
-
-
sub watch_for_done_jobs {
#CHECK: $heap for what?
my ($kernel,$heap) = @_[KERNEL, HEAP];
sub watch_for_opsi_jobs {
my ($kernel) = $_[KERNEL];
- my $sql_statement = "SELECT * FROM ".$job_queue_tn." WHERE ((headertag='opsi_install_client') AND (status='processing'))";
+ # 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</header>%') AND (status='processing') AND (siserver='localhost'))";
my $res = $job_db->select_dbentry( $sql_statement );
+ # Ask OPSI for an update of the running jobs
while (my ($id, $hit) = each %$res ) {
-
# Determine current parameters of the job
my $hostId = $hit->{'plainname'};
my $macaddress = $hit->{'macaddress'};
my $progress = $hit->{'progress'};
- # Ask OPSI for an update of the running jobs
-#print STDERR "\n\n$hostId\n";
my $result= {};
# For hosts, only return the products that are or get installed
};
my $hres = $opsi_client->call($opsi_url, $callobj);
- if (&check_opsi_res($hres)){
+ #my ($hres_err, $hres_err_string) = &check_opsi_res($hres);
+ if (not &check_opsi_res($hres)) {
my $htmp= $hres->result->{$hostId};
- # check state != not_installed or action == setup -> load and add
+ # Check state != not_installed or action == setup -> load and add
my $products= 0;
my $installed= 0;
- my $error= 0;
+ my $installing = 0;
+ my $error= 0;
+ my @installed_list;
+ my @error_list;
+ my $act_status = "none";
foreach my $product (@{$htmp}){
if ($product->{'installationStatus'} ne "not_installed" or
$product->{'actionRequest'} eq "setup"){
- # Increase number of products for this host
+ # Increase number of products for this host
$products++;
if ($product->{'installationStatus'} eq "failed"){
$result->{$product->{'productId'}}= "error";
+ unshift(@error_list, $product->{'productId'});
$error++;
}
- if ($product->{'installationStatus'} eq "installed"){
+ if ($product->{'installationStatus'} eq "installed" && $product->{'actionRequest'} eq "none"){
$result->{$product->{'productId'}}= "installed";
+ unshift(@installed_list, $product->{'productId'});
$installed++;
}
if ($product->{'installationStatus'} eq "installing"){
$result->{$product->{'productId'}}= "installing";
+ $installing++;
+ $act_status = "installing - ".$product->{'productId'};
}
}
}
- # Estimate "rough" progress
- $result->{'progress'}= int($installed * 100 / $products);
- }
+ # Estimate "rough" progress, avoid division by zero
+ if ($products == 0) {
+ $result->{'progress'}= 0;
+ } else {
+ $result->{'progress'}= int($installed * 100 / $products);
+ }
+
+ # Set updates in job queue
+ if ((not $error) && (not $installing) && ($installed)) {
+ $act_status = "installed - ".join(", ", @installed_list);
+ }
+ if ($error) {
+ $act_status = "error - ".join(", ", @error_list);
+ }
+ 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_res = $job_db->update_dbentry($update_statement);
+ }
+ if ($progress eq 100) {
+ # Updateing status
+ my $done_statement = "UPDATE $job_queue_tn SET modified='1', ";
+ if ($error) {
+ $done_statement .= "status='error'";
+ } else {
+ $done_statement .= "status='done'";
+ }
+ $done_statement .= " WHERE macaddress='$macaddress' AND siserver='localhost'";
+ my $done_res = $job_db->update_dbentry($done_statement);
+ }
-#print STDERR Dumper($result);
-
- # Set updates to job queue
- if ($progress ne $result->{'progress'}) {
- my $update_statement = "UPDATE $job_queue_tn SET progress='".$result->{'progress'}."', modified='1' WHERE macaddress='$macaddress'";
- my $update_res = $job_db->update_dbentry($update_statement);
- }
+ }
}
$kernel->delay_set('watch_for_opsi_jobs', $job_queue_opsi_delay);
}
-# if a job got an update or was modified anyway, send to all other si-server an update message
-# of this jobs
+# If a job got an update or was modified anyway, send to all other si-server an update message of this jobs.
sub watch_for_modified_jobs {
my ($kernel,$heap) = @_[KERNEL, HEAP];
# Skip new jobs for host if there is a processing job
if(defined($res) and defined @{$res}[0]) {
+ # Prevent race condition if there is a trigger_activate job waiting and a goto-activation job processing
+ if(@{$res}[5] eq 'trigger_action_reinstall') {
+ my $sql_statement_2 = "SELECT * FROM $job_queue_tn WHERE macaddress LIKE '$macaddress' AND status='waiting' AND headertag = 'trigger_activate_new'";
+ my $res_2 = $job_db->exec_statement( $sql_statement_2 );
+ if(defined($res_2) and defined @{$res}[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'";
+ }
+ }
next;
}
my $send_succeed = 0;
foreach my $hit (@$res) {
my $receiver_host = @$hit[0];
+ my $delivered2host = 0;
&daemon_log("M DEBUG: user '$receiver' is logged in at host '$receiver_host'", 7);
- # fetch key to encrypt msg propperly for usr/host
+ # Looking for host in know_clients_db
my $sql = "SELECT * FROM $known_clients_tn WHERE (hostname='$receiver_host')";
- &daemon_log("0 DEBUG: $sql", 7);
my $res = $known_clients_db->exec_statement($sql);
- # host is already down
- if (not ref(@$res[0]) eq "ARRAY") { next; }
+ # Host is known in known_clients_db
+ if (ref(@$res[0]) eq "ARRAY") {
+ my $receiver_key = @{@{$res}[0]}[2];
+ my %data = ('subject' => $subject, 'message' => $message, 'usr' => $receiver);
+ my $out_msg = &build_msg("usr_msg", $server_address, $receiver_host, \%data );
+ my $error = &send_msg_to_target($out_msg, $receiver_host, $receiver_key, "usr_msg", 0);
+ if ($error == 0 ) {
+ $send_succeed++ ;
+ $delivered2host++ ;
+ &daemon_log("M DEBUG: send message for user '$receiver' to host '$receiver_host'", 7);
+ } else {
+ &daemon_log("M DEBUG: cannot send message for user '$receiver' to host '$receiver_host'", 7);
+ }
+ }
+
+ # Message already send, do not need to do anything more, otherwise ...
+ if ($delivered2host) { next;}
+
+ # ...looking for host in foreign_clients_db
+ $sql = "SELECT * FROM $foreign_clients_tn WHERE (hostname='$receiver_host')";
+ $res = $foreign_clients_db->exec_statement($sql);
+
+ # Host is known in foreign_clients_db
+ if (ref(@$res[0]) eq "ARRAY") {
+ my $registration_server = @{@{$res}[0]}[2];
+
+ # Fetch encryption key for registration server
+ my $sql = "SELECT * FROM $known_server_tn WHERE (hostname='$registration_server')";
+ my $res = $known_server_db->exec_statement($sql);
+ if (ref(@$res[0]) eq "ARRAY") {
+ my $registration_server_key = @{@{$res}[0]}[3];
+ my %data = ('subject' => $subject, 'message' => $message, 'usr' => $receiver);
+ my $out_msg = &build_msg("usr_msg", $server_address, $receiver_host, \%data );
+ my $error = &send_msg_to_target($out_msg, $registration_server, $registration_server_key, "usr_msg", 0);
+ if ($error == 0 ) {
+ $send_succeed++ ;
+ $delivered2host++ ;
+ &daemon_log("M DEBUG: send message for user '$receiver' to server '$registration_server'", 7);
+ } else {
+ &daemon_log("M ERROR: cannot send message for user '$receiver' to server '$registration_server'", 1);
+ }
- # host is on
- my $receiver_key = @{@{$res}[0]}[2];
- my %data = ('subject' => $subject, 'message' => $message, 'usr' => $receiver);
- my $out_msg = &build_msg("usr_msg", $server_address, $receiver_host, \%data );
- my $error = &send_msg_to_target($out_msg, $receiver_host, $receiver_key, "usr_msg", 0);
- if ($error == 0 ) {
- $send_succeed++ ;
- }
+ } else {
+ &daemon_log("M ERROR: host '$receiver_host' is reported to be ".
+ "registrated at server '$registration_server', ".
+ "but no data available in known_server_db ", 1);
+ }
+ }
+
+ if (not $delivered2host) {
+ &daemon_log("M ERROR: unable to send user message to host '$receiver_host'", 1);
+ }
}
if ($send_succeed) {
# set outgoing msg at db to deliverd
my $sql = "UPDATE $messaging_tn SET flag='d' WHERE (id='$msg_id' AND direction='out' AND message_to='$receiver')";
- &daemon_log("0 DEBUG: $sql", 7);
my $res = $messaging_db->exec_statement($sql);
- }
+ &daemon_log("M INFO: send message for user '$receiver' to logged in hosts", 5);
+ } else {
+ &daemon_log("M WARNING: failed to deliver message for user '$receiver'", 3);
+ }
}
$kernel->delay_set('watch_for_delivery_messages', $messaging_db_loop_delay);
);
$dt->add( seconds => 2 * int($hit->{'keylifetime'}) );
- $expired_timestamp = $dt->ymd('').$dt->hms('')."\n";
+ $expired_timestamp = $dt->ymd('').$dt->hms('');
if ($act_time > $expired_timestamp) {
my $hostname = $hit->{'hostname'};
my $del_sql = "DELETE FROM $known_clients_tn WHERE hostname='$hostname'";
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
+ 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} = "";
+ }
+ }
+
+ map(&add_content2xml_hash($myhash, "loaded_modules", $_), keys(%$loaded_modules));
+
+ # 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
my $foreign_server_msg = &create_xml_string($myhash);
# Try our DNS Searchlist
for my $domain(get_dns_domains()) {
chomp($domain);
- my @tmp_domains= &get_server_addresses($domain);
- if(@tmp_domains) {
- for my $tmp_server(@tmp_domains) {
+ my ($tmp_domains, $error_string) = &get_server_addresses($domain);
+ if(@$tmp_domains) {
+ for my $tmp_server(@$tmp_domains) {
push @tmp_servers, $tmp_server;
}
}
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,
} );
}