Patch 4/4

This patch adds the ability to notify ldirectord that a system should be
forced down for maintenance (or other reasons) even though the service
check passes.

This patch introduces a new option "maintenancedir" which allows the
administrator to specify a directory in which ldirectord will check
for the existence of files indicating if the realserver should be
forcibly set down (irrespective of and bypassing the normal service
check).

If a site is using a management tool such as cfengine or Puppet that
watches and manages the ldirectord configuration file it may not be
possible or practical to modify the configuration file to remove a
realserver or weight it to 0 during maintenance.  This mechanism
provides a quick and simple way to signal ldirectord that a real server
should be set down without having to modify any configuration files.

Thanks,
Sean
# HG changeset patch
# User Sean E. Millichamp <[email protected]>
# Date 1242335637 14400
# Node ID f63eaa5274c6c6036fe090ddc6181672efdece46
# Parent  c5f037878efa07946d2b8772db41901ea62c3442
Add the ability to notify ldirectord that a system should be forced down for
maintenance.

This patch introduces a new option "maintenancedir" which allows the
administrator to specify a directory in which ldirectord will check
for the existence of files indicating if the realserver should be
forcibly set down (irrespective of and bypassing the normal service check).

Signed-Off-By: Sean E. Millichamp <[email protected]>

diff -r c5f037878efa -r f63eaa5274c6 ldirectord/ldirectord.in
--- a/ldirectord/ldirectord.in	Mon May 11 16:43:14 2009 -0400
+++ b/ldirectord/ldirectord.in	Thu May 14 17:13:57 2009 -0400
@@ -349,6 +349,48 @@
 Default: I<yes>
 
 
+B<maintenancedir = >I<directoryname>
+
+If this option is set ldirectord will look for a special file in the specified
+directory and, if found, force the status of the real server identified by the
+file to down, skipping the normal health check.  This would be useful if you
+wish to force servers down for maintenance without having to modify the actual
+ldirectord configuration file.
+
+For example, given a realserver with IP 172.16.1.2, service on port 4444, and
+a resolvable reverse DNS entry pointing to "realserver2.example.com" ldirectord
+will check for the existance of the following files:
+
+=over
+
+=item 172.16.1.2:4444
+
+=item 172.16.1.2
+
+=item realserver2.example.com:4444
+
+=item realserver2.example.com
+
+=item realserver2:4444
+
+=item realserver2
+
+=back
+
+If any one of those files is found then ldirectord will immediately force the
+status of the server to down as if the check had failed.
+
+Note: Since it checks for the IP/hostname without the port this means you can
+decide to place an entire realserver into maintenance across a large number of
+virtual service pools with a single file (if you were going to reboot the server,
+for instance) or include the port number and put just a particular service into
+maintenance.
+
+This option is not valid in a virtual server section.
+
+Default: disabled
+
+
 =head2 Section virtual
 
 The following commands must follow a B<virtual> entry and must be indented
@@ -696,6 +738,7 @@
 	    $EMAILALERTFROM
 	    $SMTP
 	    $CLEANSTOP
+	    $MAINTDIR
 
 	    $CALLBACK
 	    $CFGNAME
@@ -1188,6 +1231,7 @@
 	$FALLBACKCOMMAND  = undef;
 	$FORKING          = "no";
 	$LDIRLOG          = "/var/log/ldirectord.log";
+	$MAINTDIR         = undef;
 	$NEGOTIATETIMEOUT = -1;
 	$QUIESCENT        = "no";
 	$SUPERVISED       = "no";
@@ -1606,6 +1650,12 @@
 			$1 =~ /(^([0-9A-Za-z._+-]+))/ or &config_error($line,
 					"invalid SMTP server address");
 			$SMTP = $1;
+		} elsif  ($linedata  =~ /^maintenancedir\s*=\s*(.*)/) {
+			$1 =~ /(.+)/ or &config_error($line,
+					"maintenance directory not specified");
+			$MAINTDIR = $1;
+			-d $MAINTDIR or &config_warn($line,
+					"maintenance directory does not exist");
 		} else {
 			if ($linedata  =~ /^timeout\s*=\s*(.*)/) {
 				&config_error($line, 
@@ -2540,10 +2590,14 @@
         my $v = shift;
         my $r = shift;
 
+
         my $real_id = get_real_id_str($r, $v);
         my $virtual_id = get_virtual_id_str($v);
 
-        if ($$v{checktype} eq "negotiate" || $$r{num_connects}>=$$v{num_connects}) {
+	if (_check_real_for_maintenance($r)) {
+		service_set($v, $r, "down", {do_log => 1, force => 1}, "Server in maintenance");
+		return;
+	} elsif ($$v{checktype} eq "negotiate" || $$r{num_connects}>=$$v{num_connects}) {
                 &ld_debug(2, "Checking negotiate: real server=$real_id (virtual=$virtual_id)");
                 if (grep $$v{service} eq $_, ("http", "https", "http_proxy")) {
                         $$r{num_connects} = 0 if (check_http($v, $r) == $SERVICE_UP);
@@ -2613,6 +2667,40 @@
         }
 }
 
+sub _check_real_for_maintenance
+{
+	my $r = shift;
+
+	return undef if(!$MAINTDIR);
+
+	my $servername = ld_gethostbyaddr($$r{server});
+
+	# Extract just the first component of the full name so we can match short or FQDN names
+	$servername =~ /^([a-z][a-z0-9\-]+)\./;
+	my $servershortname = $1;
+
+	if (-e "$MAINTDIR/$$r{server}:$$r{port}") {
+		&ld_debug(2, "Server maintenance: Found file $$r{server}:$$r{port}");
+		return 1;
+	} elsif (-e "$MAINTDIR/$$r{server}") {
+		&ld_debug(2, "Server maintenance: Found file $$r{server}");
+		return 1;
+	} elsif ($servername && -e "$MAINTDIR/$servername:$$r{port}") {
+		&ld_debug(2, "Server maintenance: Found file $servername:$$r{port}");
+		return 1;
+	} elsif ($servername && -e "$MAINTDIR/$servername") {
+		&ld_debug(2, "Server maintenance: Found file $servername");
+		return 1;
+	} elsif ($servershortname && -e "$MAINTDIR/$servershortname:$$r{port}") {
+		&ld_debug(2, "Server maintenance: Found file $servershortname:$$r{port}");
+		return 1;
+	} elsif ($servershortname && -e "$MAINTDIR/$servershortname") {
+		&ld_debug(2, "Server maintenance: Found file $servershortname");
+		return 1;
+	}	
+	return undef;
+}
+
 sub check_http
 {
 	use LWP::UserAgent;
@@ -4854,6 +4942,26 @@
 	return $ret[0];
 }
 
+# ld_gethostbyaddr
+# Wrapper to gethostbyaddr. Look up the hostname from an IP address.
+# If no reverse DNS record is found, return undef
+# pre: ip: IP address of host to lookup
+# post: gethostbyaddr is called to find a hostname for IP $ip
+# return: hostname
+#         undef on error
+
+sub ld_gethostbyaddr
+{
+	my ($ip)=(@_);
+
+	my @host = getaddrinfo($ip,0);
+	if (!defined($host[3])) {
+		return undef;
+	}
+	my @ret = getnameinfo($host[3], NI_NAMEREQD);
+	return undef unless(scalar(@ret) == 2);
+	return $ret[0];
+}
 
 # ld_getservbyname
 # Wraper for getservbyname. Look up the port for a service name
_______________________________________________
Please read the documentation before posting - it's available at:
http://www.linuxvirtualserver.org/

LinuxVirtualServer.org mailing list - [email protected]
Send requests to [email protected]
or go to http://lists.graemef.net/mailman/listinfo/lvs-users

Reply via email to