Bug 8188 - Mechanism for taking an rsync server down for maintenance
Summary: Mechanism for taking an rsync server down for maintenance
Status: RESOLVED FIXED
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 3.1.0
Hardware: All All
: P5 enhancement (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-30 22:11 UTC by Andrew Pollock
Modified: 2011-06-06 15:36 UTC (History)
0 users

See Also:


Attachments
Proof of concept patch (577 bytes, patch)
2011-06-02 04:34 UTC, Andrew Pollock
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pollock 2011-05-30 22:11:54 UTC
Hi,

I run a mirror, which provides content over rsync, amongst other protocols.

I'm looking for a nicer way to take the rsync component down when I need to make the mirror unavailable for maintenance. Currently for Apache, I can put up a server that returns a 503 HTTP response, for FTP, I can use ProFTPd's ftpshut command, which puts a file in place that makes ProFTPd return 500 responses for new connections.

To the best of my reading of the rsync source (start_daemon in clientserver.c), there doesn't seem to be any such functionality for rsync. I currently have to simply stop the rsync daemon, which doesn't convey a useful message to the user.

I was thinking if for every new connection, the rsync daemon checked for the existence of a file in /etc (perhaps /etc/rsync.shutdown?) and if this was present, displayed the contents of the file to the remote user and closed the connection.

From my limited understanding of rsync, I presume this would require extending the protocol to allow for sending such a message back to the remote client.
Comment 1 Wayne Davison 2011-05-31 05:15:51 UTC
You could just setup something to echo a one-line message on the socket and disconnect.  If you're using xinetd, tweak the program to be anything that outputs a message to stdout.  To replace an rsync daemon, you may want to code up a C program or use a simple perl script, like this (and run it instead of the daemon):

#!/usr/bin/perl
use strict;
use warnings;
use Socket;

my $PORT = 873;

local *S;
socket(S, PF_INET, SOCK_STREAM , getprotobyname('tcp'))
    or die "couldn't open socket: $!\n";
setsockopt(S, SOL_SOCKET, SO_REUSEADDR, 1);
bind(S, sockaddr_in($PORT, INADDR_ANY));
listen(S, 25) or die "listen failed: $!\n";

while (1) {
    accept(CON, S);
    print CON "The rsync server is down for maintenance.\n";
    close CON;
}

Any connecting rsync will then output this:


rsync: server sent "The rsync server is down for maintenance." rather than greeting
Comment 2 Andrew Pollock 2011-06-02 04:34:54 UTC
Created attachment 6513 [details]
Proof of concept patch

This is purely a proof of concept patch and not production-grade.
Comment 3 Andrew Pollock 2011-06-02 04:36:12 UTC
(In reply to comment #1)

That's very cute, but not quite what I had in mind.

I just attached a proof of concept patch that I surprised myself by being able to hack together the other night.

The real thing probably needs to be configurable, and it'd probably be better to get the message from the contents of the file (if there was any).
Comment 4 Brian K. White 2011-06-02 21:47:32 UTC
(In reply to comment #3)
> (In reply to comment #1)
> 
> That's very cute, but not quite what I had in mind.
> 
> I just attached a proof of concept patch that I surprised myself by being able
> to hack together the other night.
> 
> The real thing probably needs to be configurable, and it'd probably be better
> to get the message from the contents of the file (if there was any).

Someone else emailed me an untested idea to just use exclude file and place/remove/edit the exclude file to toggle the access.

That doesn't provide the truly graceful/informative response code or message, but:
* toggles the access
* avoids downing the service even momentarily
* potentially avoids requiring a host admin to even do anything, since a user may have permission to place/remove the exclude file
* it's at least distinct from failed to connect
* uses already existing features
* does not require any, let alone two different, wrapper layers in the form of the perl (or other) wrapper script and (x)inetd to run it.

I haven't finished playing around with that to see just how close that can come to the desired fully graceful process but I felt it should be mentioned as another workaround option.

-- 
bkw
Comment 5 Andrew Pollock 2011-06-03 03:56:14 UTC
(In reply to comment #4)
> (In reply to comment #3)
> > (In reply to comment #1)
> > 
> > That's very cute, but not quite what I had in mind.
> > 
> > I just attached a proof of concept patch that I surprised myself by being able
> > to hack together the other night.
> > 
> > The real thing probably needs to be configurable, and it'd probably be better
> > to get the message from the contents of the file (if there was any).
> 
> Someone else emailed me an untested idea to just use exclude file and
> place/remove/edit the exclude file to toggle the access.
> 
> That doesn't provide the truly graceful/informative response code or message,
> but:
> * toggles the access
> * avoids downing the service even momentarily
> * potentially avoids requiring a host admin to even do anything, since a user
> may have permission to place/remove the exclude file
> * it's at least distinct from failed to connect
> * uses already existing features
> * does not require any, let alone two different, wrapper layers in the form of
> the perl (or other) wrapper script and (x)inetd to run it.
> 
> I haven't finished playing around with that to see just how close that can come
> to the desired fully graceful process but I felt it should be mentioned as
> another workaround option.

The same could be said for my "patch". If the file that is checked is configurable, and the contents of the file are used to obtain the message, then it also

* toggles the access
* avoids downing the service even momentarily
* can potentially avoid the host admin having to do anything if the file is in a user-writable location (I personally don't consider this to be a desirable feature)
* doesn't require wrappers

I'm prepared to continue futzing around with my patch if it has merit, I'm just not a very competent C programmer.
Comment 6 Wayne Davison 2011-06-04 19:00:14 UTC
I've committed a change to 3.1.0dev git that allows a pre-xfer exec script to send an error message to go with its non-zero exit status.  This will allow someone to tweak their rsyncd.conf file to add a global option like the following (assuming that they don't override pre-xfer exec elsewhere):

pre-xfer exec = /usr/local/bin/output-rsyncd-downtime-message

That script may output a message to stdout and then exit with a non-zero status.

You could also choose to leave the pre-xfer exec configured, and make the script do your file-check:

#!/bin/sh
if [ -f /rsyncd.downtime ]; then
    cat /rsyncd.downtime
    exit 1
fi
Comment 7 Andrew Pollock 2011-06-05 16:24:01 UTC
(In reply to comment #6)
> I've committed a change to 3.1.0dev git that allows a pre-xfer exec script to
> send an error message to go with its non-zero exit status.  This will allow
> someone to tweak their rsyncd.conf file to add a global option like the
> following (assuming that they don't override pre-xfer exec elsewhere):
> 
> pre-xfer exec = /usr/local/bin/output-rsyncd-downtime-message
> 
> That script may output a message to stdout and then exit with a non-zero
> status.
> 
> You could also choose to leave the pre-xfer exec configured, and make the
> script do your file-check:
> 
> #!/bin/sh
> if [ -f /rsyncd.downtime ]; then
>     cat /rsyncd.downtime
>     exit 1
> fi

Sweet! Thanks!
Comment 8 Brian K. White 2011-06-06 15:36:52 UTC
(In reply to comment #6)
> I've committed a change to 3.1.0dev git that allows a pre-xfer exec script to
> send an error message to go with its non-zero exit status.  This will allow
> someone to tweak their rsyncd.conf file to add a global option like the
> following (assuming that they don't override pre-xfer exec elsewhere):
> 
> pre-xfer exec = /usr/local/bin/output-rsyncd-downtime-message
> 
> That script may output a message to stdout and then exit with a non-zero
> status.
> 
> You could also choose to leave the pre-xfer exec configured, and make the
> script do your file-check:
> 
> #!/bin/sh
> if [ -f /rsyncd.downtime ]; then
>     cat /rsyncd.downtime
>     exit 1
> fi

Sometimes, you ask for an inch, they give you a mile. ;)

-- 
bkw