From: <fcr...@us...> - 2011-12-30 09:27:28
|
Revision: 784 http://safekeep.svn.sourceforge.net/safekeep/?rev=784&view=rev Author: fcrawford Date: 2011-12-30 09:27:22 +0000 (Fri, 30 Dec 2011) Log Message: ----------- Add the ability to have the script file on either the client or the server. Note that it is still only run on the client, just that for a server located one, a temporary copy is sent to the client to run. At present, it is designed around passing scripts, not binaries, as it passes the file line by line. The protocol version has been bumped to 1.2, due to an addition to rund the script after it is copied. Modified Paths: -------------- safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/safekeep Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2011-12-30 08:50:25 UTC (rev 783) +++ safekeep/trunk/doc/safekeep.backup.txt 2011-12-30 09:27:22 UTC (rev 784) @@ -47,7 +47,7 @@ <snapshot device="/path/to/volume" size="500M" /> <!-- location of a script to be executed at different stages of the run --> - <script path="/path/to/script" /> + <script path="server:/path/to/script" /> </setup> @@ -248,15 +248,21 @@ tag. Optional for a `<snapshot>` element. -/backup/setup/script/@path:: - Execute the script specified path on the client at certain steps - of the backup process. - This script is executed with three arguments: - - Backup id (/backup/@id) - - Backup step - - Backup root directory (valid after creation of a snapshot) - See the `CLIENT SCRIPT` section for more information. - Mandatory for a `<script>` element. +/backup/setup/script/@location:: + Execute the script specified path on the client at certain steps + of the backup process. + This script is executed with three arguments: + - Backup id (/backup/@id) + - Backup step + - Backup root directory (valid after creation of a snapshot) + The `location` optionally consists of an optional `host` and + a mandatory `path`, separated by a ":", where the host part is + either "client" or "server". If no host part is specified then + it is first looked for on the server, and if not found, then is + looked for on the client. If it not found on either, then a + warning is raised. + See the `CLIENT SCRIPT` section for more information. + Mandatory for a `<script>` element. /backup/data/@exclude-devices:: One of "true" or "false". If "true", the dump file will @@ -343,6 +349,15 @@ `safekeep(1)` support the optional execution of a script or program on the client system at different steps during execution of the backup. +The script may be located on either the server or the client. If it is +located on the server, then the file is copied to the client into a +temporary directory before execution. Note that this directory is located +where ever the system normally creates temporary files, and it is possible +that the execution of scripts are disallowed. In that case it is recommended +that a client based script is used. In addition, the script is copied from +the server on a line by line basis, and so it is not suitable to pass binary +files. + Note: specification of a script which does not exist is not considered an error, and is treated as the same as not specifying a script. However, if the specified path does match a file or directory, the security tests listed Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2011-12-30 08:50:25 UTC (rev 783) +++ safekeep/trunk/safekeep 2011-12-30 09:27:22 UTC (rev 784) @@ -68,7 +68,7 @@ default_bandwidth = {} cmd = "<Missing>" -PROTOCOL = "1.1" +PROTOCOL = "1.2" VERSION = "1.3.3" VEBOSITY_BY_CLASS = {'DBG': 3, 'INFO': 2, 'WARN': 1, 'ERR': 0} @@ -431,6 +431,8 @@ script_el = setup_el[0].getElementsByTagName('script') if len(script_el) == 1: script = script_el[0].getAttribute('path') + if not ':' in script and os.path.isfile(script): + script = 'server:' + script elif len(script_el) > 1: raise ConfigException('Can not have more than one setup script element') @@ -771,6 +773,19 @@ finally: dom.unlink() +def do_client_remote_script(script_file, cfg, cmd): + (cfg_cmd, server_file, cnt_str) = cmd.split(':', 2) + debug("do_client_remote_script: %s -> %s: cnt_str = %s" % (server_file, cfg['script'], cnt_str.strip())) + try: + for i in xrange(int(cnt_str)): + line = sys.stdin.readline() + if not line: raise Exception('Unexpected end of file') + script_file.write(line) + finally: + script_file.close() + + os.chmod(cfg['script'], stat.S_IXUSR | stat.S_IRUSR) + def do_client_setup(cfg): debug('Do setup of %s' % cfg['host']) @@ -892,7 +907,7 @@ warn('Can not tear down snapshot: %s' % device) scrubbed = True - # Now cleanup any safekeep directories still hanging around + # Now cleanup any safekeep directories and script files still hanging around debug("Cleaning up remaining safekeep directories") if os.path.isdir('/mnt'): @@ -905,6 +920,33 @@ except OSError, e: warn('Failed to remove: %s: %s' % (mountpoint, e)) + debug("Cleaning up remaining safekeep script files") + script_dir = tempfile.gettempdir() + if os.path.isdir(script_dir): + for ent in os.listdir(script_dir): + if fnmatch.fnmatch(ent, 'safekeep-[0-9][0-9]*-') and not fnmatch.fnmatch(ent, 'safekeep-%d-' % current_pid): + script_file = '%s/%s' % (script_dir, ent) + if os.path.isdir(script_file): + temp_dir = script_file + for ent in os.listdir(temp_dir): + script_file = '%s/%s' % (temp_dir, ent) + info("Removing script file %s" % script_file) + try: + os.remove('%s' % script_file) + except OSError, e: + warn('Failed to remove: %s: %s' % (script_file, e)) + info("Removing script directory %s" % temp_dir) + try: + os.rmdir(temp_dir) + except OSError, e: + warn('Failed to remove: %s: %s' % (temp_dir, e)) + else: + info("Removing script file %s" % script_file) + try: + os.remove('%s' % script_file) + except OSError, e: + warn('Failed to remove: %s: %s' % (script_file, e)) + if not scrubbed: info('No cleanup required') @@ -921,6 +963,8 @@ bdir = '/' cfg = do_client_config_parse('<backup/>', 'def') ex = None + script_file = None + script_dir = None try: while True: try: @@ -930,6 +974,29 @@ send('OK %s, %s' % (PROTOCOL, VERSION)) elif line.startswith('CONFIG'): cfg = do_client_config(line) + if ':' in cfg['script']: + (script_loc, script) = cfg['script'].split(':', 1) + else: + (script_loc, script) = ('client', cfg['script']) + if script_loc == 'server': + if not script_dir: + script_dir = tempfile.mkdtemp(prefix="safekeep-%d-" % current_pid) + script = os.path.basename(script) + (fd, cfg['script']) = tempfile.mkstemp(prefix="%s-" % script, dir=script_dir) + script_file = os.fdopen(fd, 'w') + send('OK %s' % cfg['script']) + elif script_loc == 'client': + cfg['script'] = script + ret = client_side_script('STARTUP', cfg, bdir) + if ret: + send('ERROR Client-side setup script failed: %s' % ret) + else: + send('OK') + else: + warn('Unknown script location %s for script %s' % (script_loc, script)) + send('OK') + elif line.startswith('SCRIPT'): + do_client_remote_script(script_file, cfg, line) ret = client_side_script('STARTUP', cfg, bdir) if ret: send('ERROR Client-side setup script failed: %s' % ret) @@ -961,6 +1028,14 @@ finally: if should_cleanup: do_client_cleanup(cfg, bdir) + if script_file: + if not script_file.closed: script_file.close() + os.remove(cfg['script']) + if script_dir: + try: + os.rmdir(script_dir) + except OSError, e: + warn('Failed to remove: %s: %s' % (script_dir, e)) if ex: send('TRACEBACK ' + str(ex) + '>>>' + stacktrace().replace('\n', '###')) @@ -1156,7 +1231,17 @@ cin.write('CONFIG: %d: %s\n' % (len(cfg['text'].splitlines()), id)) cin.write(cfg['text'] + '\n') cin.flush() - do_server_getanswer(cout) + remote_script = do_server_getanswer(cout) + if cfg['script'].startswith('server:') and remote_script: + local_script = cfg['script'].split(':', 1)[1] + debug("Transferring script: %s -> %s" % (local_script, remote_script)) + fscript = open(local_script) + lines = fscript.readlines() + fscript.close() + cin.write('SCRIPT: %s: %d\n' % (local_script, len(lines))) + cin.writelines(lines) + cin.flush() + do_server_getanswer(cout) if cleanup: cleaned_up = False cin.write('SCRUB\n') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2012-01-01 03:28:22
|
Revision: 785 http://safekeep.svn.sourceforge.net/safekeep/?rev=785&view=rev Author: fcrawford Date: 2012-01-01 03:28:15 +0000 (Sun, 01 Jan 2012) Log Message: ----------- Added option to set SSH port for each host as requested by Ken Bass Modified Paths: -------------- safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/safekeep Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2011-12-30 09:27:22 UTC (rev 784) +++ safekeep/trunk/doc/safekeep.backup.txt 2012-01-01 03:28:15 UTC (rev 785) @@ -88,6 +88,12 @@ This is different from leaving it blank, as it will establish a SSH session and use the user specified by `/backup/host/@user`. Optional, defaults to local access. + +/backup/host/@port:: + The network port to use when connecting to the client. This must + be a number and is passed to the network connection agent, usually + SSH. + Optional, default to not passing any port specification. /backup/host/@user:: The user name to use when connecting to the client. This user Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2011-12-30 09:27:22 UTC (rev 784) +++ safekeep/trunk/safekeep 2012-01-01 03:28:15 UTC (rev 785) @@ -364,12 +364,15 @@ host_el = backup_el.getElementsByTagName('host') if host_el: host = host_el[0].getAttribute('name') + port = host_el[0].getAttribute('port') user = host_el[0].getAttribute('user') nice = host_el[0].getAttribute('nice') key_ctrl = host_el[0].getAttribute('key-ctrl') key_data = host_el[0].getAttribute('key-data') else: - host = user = nice = key_ctrl = key_data = None + host = port = user = nice = key_ctrl = key_data = None + if host and port and not port.isdigit(): + raise ConfigException('Host port must be a number: "%s"' % port) if host and not user: user = 'root' if host and not key_ctrl: @@ -459,7 +462,7 @@ '/var/named/chroot/var/run', '/var/named/chroot/var/tmp' ] cludes = [{ 'type' : 'exclude', 'path' : path, 'glob' : None, 'regexp' : None } for path in path_xcludes] - return { 'id': id, 'host' : host, 'nice' : nice, 'user' : user, 'key_ctrl' : key_ctrl, 'key_data' : key_data, + return { 'id': id, 'host' : host, 'port' : port, 'nice' : nice, 'user' : user, 'key_ctrl' : key_ctrl, 'key_data' : key_data, 'dir' : dir, 'retention' : retention, 'dumps' : dumps, 'snaps' : snaps, 'script' : script, 'cludes' : cludes, 'data_options' : data_options, 'options' : options, 'bw' : bw} @@ -1110,7 +1113,9 @@ args.extend(['rdiff-backup']) if cfg['host']: - schema = 'ssh %s -i %s %%s rdiff-backup --server' % (verbosity_ssh, cfg['key_data']) + basessh = 'ssh' + if cfg['port']: basessh += ' -p %s' % cfg['port'] + schema = '%s %s -i %s %%s rdiff-backup --server' % (basessh, verbosity_ssh, cfg['key_data']) args.extend(['--remote-schema', schema]) if force: @@ -1213,6 +1218,7 @@ if cfg['host']: cmd.extend(['ssh']) if verbosity_ssh: cmd.extend([verbosity_ssh]) + if cfg['port']: cmd.extend(['-p', cfg['port']]) cmd.extend(['-T', '-i', cfg['key_ctrl'], '-l', cfg['user'], cfg['host']]) cmd.extend(['safekeep', '--client']) @@ -1409,6 +1415,7 @@ print output basessh = 'ssh' + if cfg['port']: basessh += ' -p %s' % cfg['port'] if identity: basessh += ' -i %s' % (commands.mkarg(identity)) if status or deploy: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2012-01-01 08:00:01
|
Revision: 788 http://safekeep.svn.sourceforge.net/safekeep/?rev=788&view=rev Author: fcrawford Date: 2012-01-01 07:59:55 +0000 (Sun, 01 Jan 2012) Log Message: ----------- Improved coding for script location, including change of default location to be client first and then server, test of permissions on server based script and notification of errors and missing file on the server side. Modified Paths: -------------- safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/safekeep Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2012-01-01 04:58:17 UTC (rev 787) +++ safekeep/trunk/doc/safekeep.backup.txt 2012-01-01 07:59:55 UTC (rev 788) @@ -264,8 +264,8 @@ The `location` optionally consists of an optional `host` and a mandatory `path`, separated by a ":", where the host part is either "client" or "server". If no host part is specified then - it is first looked for on the server, and if not found, then is - looked for on the client. If it not found on either, then a + it is first looked for on the client, and if not found, then is + looked for on the server. If it not found on either, then a warning is raised. See the `CLIENT SCRIPT` section for more information. Mandatory for a `<script>` element. Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2012-01-01 04:58:17 UTC (rev 787) +++ safekeep/trunk/safekeep 2012-01-01 07:59:55 UTC (rev 788) @@ -434,8 +434,12 @@ script_el = setup_el[0].getElementsByTagName('script') if len(script_el) == 1: script = script_el[0].getAttribute('path') - if not ':' in script and os.path.isfile(script): - script = 'server:' + script + if not ':' in script: + if is_client and os.path.isfile(script): + warn('Assuming client based script: %s' % script) + script = 'client:' + script + else: + script = 'server:' + script elif len(script_el) > 1: raise ConfigException('Can not have more than one setup script element') @@ -779,15 +783,22 @@ def do_client_remote_script(script_file, cfg, cmd): (cfg_cmd, server_file, cnt_str) = cmd.split(':', 2) debug("do_client_remote_script: %s -> %s: cnt_str = %s" % (server_file, cfg['script'], cnt_str.strip())) - try: - for i in xrange(int(cnt_str)): - line = sys.stdin.readline() - if not line: raise Exception('Unexpected end of file') - script_file.write(line) - finally: + if int(cnt_str) > 0: + try: + for i in xrange(int(cnt_str)): + line = sys.stdin.readline() + if not line: raise Exception('Unexpected end of file') + script_file.write(line) + finally: + script_file.close() + + os.chmod(cfg['script'], stat.S_IXUSR | stat.S_IRUSR) + return True + else: script_file.close() + os.remove(cfg['script']) - os.chmod(cfg['script'], stat.S_IXUSR | stat.S_IRUSR) + return False def do_client_setup(cfg): debug('Do setup of %s' % cfg['host']) @@ -999,11 +1010,14 @@ warn('Unknown script location %s for script %s' % (script_loc, script)) send('OK') elif line.startswith('SCRIPT'): - do_client_remote_script(script_file, cfg, line) - ret = client_side_script('STARTUP', cfg, bdir) - if ret: - send('ERROR Client-side setup script failed: %s' % ret) + if do_client_remote_script(script_file, cfg, line): + ret = client_side_script('STARTUP', cfg, bdir) + if ret: + send('ERROR Client-side setup script failed: %s' % ret) + else: + send('OK') else: + cfg['script'] = None send('OK') elif line.startswith('SETUP'): client_side_script('PRE-SETUP', cfg, bdir) @@ -1240,12 +1254,21 @@ remote_script = do_server_getanswer(cout) if cfg['script'].startswith('server:') and remote_script: local_script = cfg['script'].split(':', 1)[1] - debug("Transferring script: %s -> %s" % (local_script, remote_script)) - fscript = open(local_script) - lines = fscript.readlines() - fscript.close() - cin.write('SCRIPT: %s: %d\n' % (local_script, len(lines))) - cin.writelines(lines) + if os.path.isfile(local_script): + ret = check_script_permissions(local_script) + if not ret: + debug("Transferring script: %s -> %s" % (local_script, remote_script)) + fscript = open(local_script) + lines = fscript.readlines() + fscript.close() + cin.write('SCRIPT: %s: %d\n' % (local_script, len(lines))) + cin.writelines(lines) + else: + error('Illegal script specified: %s: %s' % (local_script, ret)) + cin.write('SCRIPT: %s: %d\n' % ('-', 0)) + else: + warn('No server based script found: %s' % local_script) + cin.write('SCRIPT: %s: %d\n' % ('-', 0)) cin.flush() do_server_getanswer(cout) if cleanup: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2012-01-20 12:25:21
|
Revision: 792 http://safekeep.svn.sourceforge.net/safekeep/?rev=792&view=rev Author: fcrawford Date: 2012-01-20 12:25:15 +0000 (Fri, 20 Jan 2012) Log Message: ----------- Allow snapshot tag item to take a comma separated list of tags Modified Paths: -------------- safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/safekeep Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2012-01-13 11:47:11 UTC (rev 791) +++ safekeep/trunk/doc/safekeep.backup.txt 2012-01-20 12:25:15 UTC (rev 792) @@ -249,9 +249,10 @@ Mandatory for a `<snapshot>` element. /backup/setup/snapshot/@tag:: - A tag to be added to the snapshot, with the `--addtag` argument - to `lvcreate`. An `@` is automatically added to the generated - tag. + A list of tags to be added to the snapshot, with the `--addtag` + argument to `lvcreate`. The @tag entry consists of a `,` + separated list of tags. + An `@` is automatically added to each generated tag. Optional for a `<snapshot>` element. /backup/setup/script/@location:: Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2012-01-13 11:47:11 UTC (rev 791) +++ safekeep/trunk/safekeep 2012-01-20 12:25:15 UTC (rev 792) @@ -327,8 +327,16 @@ size = snap_el.getAttribute('size') if not size: raise ConfigException('Please specify the size for the snapshot') - tag = snap_el.getAttribute('tag') - return { 'device' : device, 'size' : size, 'tag' : tag } + tags = [] + tag_el = snap_el.getAttribute('tag') + if tag_el: + for tag in tag_el.split(','): + if tag: + if not tag.startswith('@'): tag = '@' + tag.lstrip() + tags.append(tag.strip()) + else: + warn('Device: %s: empty tag in taglist: %s' % (device, tag_el)) + return { 'device' : device, 'size' : size, 'tags' : tags } def parse_clude(clude_el): path = clude_el.getAttribute('path') @@ -690,14 +698,12 @@ if not snapmnt: warn('Cannot find the mountpoint for: %s' % device) continue - tag = snap['tag'] - if tag: - args = ['lvcreate', '--addtag', '@' + tag, - '--snapshot', '--size', snap['size'], - '--name', os.path.basename(snapdev), lvmdev] - else: - args = ['lvcreate', '--snapshot', '--size', snap['size'], - '--name', os.path.basename(snapdev), lvmdev] + args = ['lvcreate'] + if snap['tags']: + for tag in snap['tags']: + args.extend(['--addtag', tag.strip()]) + args.extend(['--snapshot', '--size', snap['size'], + '--name', os.path.basename(snapdev), lvmdev]) ec = spawn(args) if ec: warn('Can not snapshot the device: %s' % device) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2012-02-11 06:05:35
|
Revision: 797 http://safekeep.svn.sourceforge.net/safekeep/?rev=797&view=rev Author: fcrawford Date: 2012-02-11 06:05:29 +0000 (Sat, 11 Feb 2012) Log Message: ----------- Prepared for 1.4.0 release Modified Paths: -------------- safekeep/trunk/ANNOUNCE safekeep/trunk/safekeep.spec.in Modified: safekeep/trunk/ANNOUNCE =================================================================== --- safekeep/trunk/ANNOUNCE 2012-02-11 05:57:17 UTC (rev 796) +++ safekeep/trunk/ANNOUNCE 2012-02-11 06:05:29 UTC (rev 797) @@ -1,34 +1,40 @@ -This is release 1.3.3 of SafeKeep, a centralized and easy to use +This is release 1.4.0 of SafeKeep, a centralized and easy to use backup application that combines the best features of a mirror and an incremental backup. What's new in this release: - - More fixes for dealing with LVM snapshots. - - Better handling of other failure conditions. - - Updates for Python syntax issues and changes. - - Allow specification of a sender address in e-mail messages. - - Better handling of ionice(1). + - Add the ability to store script files on either client or server. + - Rewritten snapshot creation to remove use of "rbind". + - Automatic cleanup on next run after an abort. + - Support of LVM tagging for snapshots. + - Better handling of messages and tracebacks. + - A number of other code cleanups and bug fixes. + - Updated minimum Python support to Python 2.3. -Many thanks to Marco Bozzolan and Harald Nehring for the fixes -that made this release possible, and to Dimi Paun for his continual -work with SafeKeep, who is currently having a life away from computers. +Many thanks to Andres Toomsalu, Ken Bass, Joe Steele and Alexander List +for the fixes that made this release possible, and to Dimi Paun for his +continual work with SafeKeep. Sources and binaries are available from the following locations: - - RedHat EL/CentOS 3,4,5,6 Fedora 8,9,10,11,12,13,14,15,16: - http://prdownloads.sourceforge.net/safekeep/safekeep-common-1.3.3-1.noarch.rpm - http://prdownloads.sourceforge.net/safekeep/safekeep-client-1.3.3-1.noarch.rpm - http://prdownloads.sourceforge.net/safekeep/safekeep-server-1.3.3-1.noarch.rpm + - RedHat EL/CentOS 4,5,6 Fedora 8,9,10,11,12,13,14,15,16: + http://prdownloads.sourceforge.net/safekeep/safekeep-common-1.4.0-1.noarch.rpm + http://prdownloads.sourceforge.net/safekeep/safekeep-client-1.4.0-1.noarch.rpm + http://prdownloads.sourceforge.net/safekeep/safekeep-server-1.4.0-1.noarch.rpm - - Ubuntu Edgy, Dapper, Breezy, Hardy, Karmic, Lucid, Maverick, and Natty: - http://prdownloads.sourceforge.net/safekeep/safekeep-common_1.3.3_all.deb - http://prdownloads.sourceforge.net/safekeep/safekeep-client_1.3.3_all.deb - http://prdownloads.sourceforge.net/safekeep/safekeep-server_1.3.3_all.deb + - Ubuntu Dapper, Breezy, Hardy, Lucid, Maverick, Natty, Oneiric and Precise: + http://prdownloads.sourceforge.net/safekeep/safekeep-common_1.4.0_all.deb + http://prdownloads.sourceforge.net/safekeep/safekeep-client_1.4.0_all.deb + http://prdownloads.sourceforge.net/safekeep/safekeep-server_1.4.0_all.deb - Source: - http://prdownloads.sourceforge.net/safekeep/safekeep-1.3.3.tar.gz - http://prdownloads.sourceforge.net/safekeep/safekeep-1.3.3-1.src.rpm + http://prdownloads.sourceforge.net/safekeep/safekeep-1.4.0.tar.gz + http://prdownloads.sourceforge.net/safekeep/safekeep-1.4.0-1.src.rpm +NOTE: The minimum version of Python now supported is Python 2.3. If you +require support of an older version of Python, then you should select an +earlier release of Safekeep. + To find out more about the project visit on our website: http://safekeep.sourceforge.net Modified: safekeep/trunk/safekeep.spec.in =================================================================== --- safekeep/trunk/safekeep.spec.in 2012-02-11 05:57:17 UTC (rev 796) +++ safekeep/trunk/safekeep.spec.in 2012-02-11 06:05:29 UTC (rev 797) @@ -25,7 +25,7 @@ Summary: The SafeKeep backup system (common component) Group: Applications/System Requires: rdiff-backup -Requires: python >= 2.2 +Requires: python >= 2.3 %description common SafeKeep is a client/server backup system which enhances the @@ -107,6 +107,15 @@ %doc samples/sample.backup %changelog +* Sun Feb 12 2012 Frank Crawford <fr...@cr...> 1.4.0-1 + - Add the ability to store script files on either client or server. + - Rewritten snapshot creation to remove use of "rbind". + - Automatic cleanup on next run after an abort. + - Support of LVM tagging for snapshots. + - Better handling of messages and tracebacks. + - A number of other code cleanups and bug fixes. + - Updated minimum Python support to Python 2.3. + * Sun Nov 20 2011 Frank Crawford <fr...@cr...> 1.3.3-1 - More fixes for dealing with LVM snapshots. - Better handling of other failure conditions. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <di...@us...> - 2012-02-14 20:38:25
|
Revision: 804 http://safekeep.svn.sourceforge.net/safekeep/?rev=804&view=rev Author: dimi Date: 2012-02-14 20:38:19 +0000 (Tue, 14 Feb 2012) Log Message: ----------- Get rid of the package signing, it's not the proper place here. This complicates the test unnecessarily, making it more likely that it will bitrot. Modified Paths: -------------- safekeep/trunk/safekeep safekeep/trunk/safekeep-test Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2012-02-11 10:14:31 UTC (rev 803) +++ safekeep/trunk/safekeep 2012-02-14 20:38:19 UTC (rev 804) @@ -474,6 +474,9 @@ '/var/named/chroot/dev', '/var/named/chroot/proc', '/var/named/chroot/var/run', '/var/named/chroot/var/tmp' ] cludes = [{ 'type' : 'exclude', 'path' : path, 'glob' : None, 'regexp' : None } for path in path_xcludes] + + for dump in dumps: + cludes.insert(0, { 'type' : 'include', 'path' : dump['file'], 'glob' : None, 'regexp' : None }) return { 'id': cfg_id, 'host' : host, 'port' : port, 'nice' : nice, 'user' : user, 'key_ctrl' : key_ctrl, 'key_data' : key_data, 'dir' : repo_dir, 'retention' : retention, 'dumps' : dumps, 'snaps' : snaps, 'script' : script, Modified: safekeep/trunk/safekeep-test =================================================================== --- safekeep/trunk/safekeep-test 2012-02-11 10:14:31 UTC (rev 803) +++ safekeep/trunk/safekeep-test 2012-02-14 20:38:19 UTC (rev 804) @@ -5,7 +5,6 @@ from commands import mkarg ssh_id_file_keys = None -sign_packages = 0 perform_snapshots = True safekeep_args = '' test_reps=2 @@ -208,8 +207,8 @@ baseurl=http://lattica.com/repos/lattica/devel/%s/$releasever gpgkey=http://lattica.com/keys/RPM-GPG-KEY-lattica-devel enabled=1 - gpgcheck=%s - """ % (distro, sign_packages) + gpgcheck=0 + """ % (distro) lattica_repo = '\n'.join([line.strip() for line in lattica_repo.splitlines()]) cmd = 'echo %s > /etc/yum.repos.d/safekeep-test-lattica-devel.repo' % (mkarg(lattica_repo).strip()) rcmd(cmd, 'root', host, 'install Lattica Repo') @@ -277,13 +276,6 @@ if not os.path.isfile(binrpm): raise TestFailure('Failed to find binary rpm: %s' % binrpm) - if sign_packages: - cmd = 'rpm --define %s --addsign %s' % \ - (mkarg('_gpg_name ' + keyname), ' '.join(binrpm_list)) - print cmd - if os.system(cmd): - raise TestFailure('Failed to sign rpms') - for repodir in repodirs: cmd = '%s %s %s@%s:%s/noarch' % \ (mkssh('scp'), ' '.join(binrpm_list), user, host, repodir) @@ -297,7 +289,7 @@ return ver + '-' + rel def remoteTest(tmproot, client, server): - # build, sign and upload the .rpm + # build and upload the .rpm repodirs = [ '/var/www/repos/lattica/devel/fedora/6', '/var/www/repos/lattica/devel/fedora/7', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2012-11-25 07:14:28
|
Revision: 825 http://safekeep.svn.sourceforge.net/safekeep/?rev=825&view=rev Author: fcrawford Date: 2012-11-25 07:14:22 +0000 (Sun, 25 Nov 2012) Log Message: ----------- Added configuration for client user from patch by Riley Revels <ril...@gm...> Modified Paths: -------------- safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/doc/safekeep.conf.txt safekeep/trunk/safekeep safekeep/trunk/safekeep.conf Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2012-05-04 13:14:16 UTC (rev 824) +++ safekeep/trunk/doc/safekeep.backup.txt 2012-11-25 07:14:22 UTC (rev 825) @@ -99,7 +99,8 @@ The user name to use when connecting to the client. This user must have read permissions for the files that will be backed up, so it most likely needs to be 'root'. - Optional, defaults to 'root'. + Optional, defaults to the value given by `client.user` in + `safekeep.conf`. /backup/host/@nice:: The nice adjustment for the client. This settings is normally Modified: safekeep/trunk/doc/safekeep.conf.txt =================================================================== --- safekeep/trunk/doc/safekeep.conf.txt 2012-05-04 13:14:16 UTC (rev 824) +++ safekeep/trunk/doc/safekeep.conf.txt 2012-11-25 07:14:22 UTC (rev 825) @@ -35,6 +35,12 @@ If not specified, it defaults to the home directory of the backup user. +client.user:: + The default Unix user which will be used on the client. + This can be overridden on a host by host basis in the `.backup` + file. + If not specified, it defaults to `root`. + email.from:: The email address to be used as sender when sending the logs. If not specified `safekeep` will use SafeKeep@<hostname fqdn>. Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2012-05-04 13:14:16 UTC (rev 824) +++ safekeep/trunk/safekeep 2012-11-25 07:14:22 UTC (rev 825) @@ -64,6 +64,7 @@ verbosity_trickle = '' work_user = getpass.getuser() backup_user = None +client_user = 'root' home_dir = None base_dir = None current_pid = os.getpid() @@ -396,7 +397,7 @@ if host and port and not port.isdigit(): raise ConfigException('Host port must be a number: "%s"' % port) if host and not user: - user = 'root' + user = client_user if host and not key_ctrl: key_ctrl = os.path.join('.ssh', 'safekeep-server-ctrl-key') if host and not key_data: @@ -1660,7 +1661,7 @@ except getopt.GetoptError: usage(2) - global backup_user, home_dir, base_dir + global backup_user, client_user, home_dir, base_dir global verbosity_level mode = None @@ -1792,6 +1793,8 @@ backup_user = props['backup.user'] if 'base.dir' in props: base_dir = props['base.dir'] + if 'client.user' in props: + client_user = props['client.user'] if 'email.smtp.server' in props: smtp = props['email.smtp.server'] if 'email.to' in props: Modified: safekeep/trunk/safekeep.conf =================================================================== --- safekeep/trunk/safekeep.conf 2012-05-04 13:14:16 UTC (rev 824) +++ safekeep/trunk/safekeep.conf 2012-11-25 07:14:22 UTC (rev 825) @@ -10,6 +10,9 @@ # the base directory for data repository relative paths base.dir = /var/lib/safekeep +# the default user under which the client will run +# client.user = root + # by default, be nice during backup # you can control the server/client nice level via # nice.adjustment.server and nice.adjustment.client This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2013-01-01 08:03:13
|
Revision: 834 http://safekeep.svn.sourceforge.net/safekeep/?rev=834&view=rev Author: fcrawford Date: 2013-01-01 08:03:06 +0000 (Tue, 01 Jan 2013) Log Message: ----------- - Allow default snapshot size to be set in safekeep.conf. - Enable all lvcreate(8) size options, including %age to be given. Modified Paths: -------------- safekeep/trunk/TODO safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/doc/safekeep.conf.txt safekeep/trunk/safekeep safekeep/trunk/safekeep.conf Modified: safekeep/trunk/TODO =================================================================== --- safekeep/trunk/TODO 2013-01-01 07:04:07 UTC (rev 833) +++ safekeep/trunk/TODO 2013-01-01 08:03:06 UTC (rev 834) @@ -16,7 +16,7 @@ Future (post 1.0): * Modify the test to not rely on Lattica's servers - * Decide how big the snapshot size should be automagically + * Decide how big the snapshot size should be automagically (Partially DONE) * Fully automatic shapshotting mode * Configuration inheritance * Transactional ops on server side, and automagic recovery from errors (Partially DONE) Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2013-01-01 07:04:07 UTC (rev 833) +++ safekeep/trunk/doc/safekeep.backup.txt 2013-01-01 08:03:06 UTC (rev 834) @@ -255,12 +255,16 @@ /backup/setup/snapshot/@size:: The size of the snapshot. Unallocated space must exist on the volume group. It is recommended that it is about 15-20% - of the original device's size. - Mandatory for a `<snapshot>` element. + of the original device's size. This can be specified as a + percentage, e.g. `20%`, which is equivalent to 20% of the + logical volume. Other values as listed for `lvcreate(8)` + can also be given. + Mandatory for a `<snapshot>` element, unless a default value + has been specified in `safekeep.conf`. /backup/setup/snapshot/@tag:: A list of tags to be added to the snapshot, with the `--addtag` - argument to `lvcreate`. The @tag entry consists of a `,` + argument to `lvcreate(8)`. The @tag entry consists of a `,` separated list of tags. An `@` is automatically added to each generated tag. Optional for a `<snapshot>` element. Modified: safekeep/trunk/doc/safekeep.conf.txt =================================================================== --- safekeep/trunk/doc/safekeep.conf.txt 2013-01-01 07:04:07 UTC (rev 833) +++ safekeep/trunk/doc/safekeep.conf.txt 2013-01-01 08:03:06 UTC (rev 834) @@ -121,6 +121,15 @@ the value set in `bandwidth.overall` (refer to it for more informatio). This value is optional. +snapshot.size:: + This is the default size to be used for any snapshots without a + `size` value specified. + It is passed to 'lvcreate(8)' (LVM2), including the specification of + a percentage (`%`). If not otherwise specified, the percentage is + based on unallocated space (i.e. LVM2 `%FREE'), which is different + to the interpretation within the `<snapshot>` option. + This value is optional and there is no default. + NOTES ----- Safekeep uses `trickle` to implement bandwidth throttling (see Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2013-01-01 07:04:07 UTC (rev 833) +++ safekeep/trunk/safekeep 2013-01-01 08:03:06 UTC (rev 834) @@ -70,6 +70,7 @@ client_defaults = [] current_pid = os.getpid() default_bandwidth = {} +default_snapshot = None statistics = [] # Default mount options, overridden elsewhere: # Key is a file system type, or 'snapshot' for default for snapshot mount @@ -461,12 +462,13 @@ 'opts' : opts, 'file' : dbfile, 'cleanup' : cleanup } def parse_snap(snap_el): + global default_snapshot device = snap_el.getAttribute('device') if not device: raise ConfigException('Please specify the device to be snapshot') if device.rfind('/') == -1 or device.endswith('/'): raise ConfigException('The device name seems incorrect: ' + device) - size = snap_el.getAttribute('size') + size = snap_el.getAttribute('size') or default_snapshot if not size: raise ConfigException('Please specify the size for the snapshot') tags = [] @@ -858,8 +860,13 @@ if snap['tags']: for tag in snap['tags']: args.extend(['--addtag', tag.strip()]) - args.extend(['--snapshot', '--size', snap['size'], - '--name', os.path.basename(snapdev), lvmdev]) + size = snap['size'] + if size.count('%'): + if size.endswith('%'): size += 'ORIGIN' + args.extend(['--snapshot', '--extents', size]) + else: + args.extend(['--snapshot', '--size', size]) + args.extend(['--name', os.path.basename(snapdev), lvmdev]) ec = spawn(args) if ec: warn('Can not snapshot the device: %s' % device) @@ -1979,6 +1986,13 @@ default_bandwidth['download'] = get_int('bandwidth.limit.download') or 0 default_bandwidth['upload'] = get_int('bandwidth.limit.upload') or 0 + global default_snapshot, client_defaults + default_snapshot = props.get('snapshot.size') + if default_snapshot: + if default_snapshot.endswith('%'): + default_snapshot += 'FREE' + client_defaults.append('snapshot.size=%s' % default_snapshot) + if len(cfglocs) == 0: locs = os.path.join(os.path.dirname(cfgfile), 'backup.d') if os.path.isdir(locs): cfglocs.append(locs) Modified: safekeep/trunk/safekeep.conf =================================================================== --- safekeep/trunk/safekeep.conf 2013-01-01 07:04:07 UTC (rev 833) +++ safekeep/trunk/safekeep.conf 2013-01-01 08:03:06 UTC (rev 834) @@ -49,3 +49,7 @@ # Generate a summary with the email message # email.summary = yes|no +# Default size for LVM snapshots +# This follows the rules for lvcreate(8), so can be a fixed size or +# a % of either logical volume or free space. +# snapshot.size = 2G This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2013-01-01 10:35:24
|
Revision: 835 http://safekeep.svn.sourceforge.net/safekeep/?rev=835&view=rev Author: fcrawford Date: 2013-01-01 10:35:18 +0000 (Tue, 01 Jan 2013) Log Message: ----------- Use ~/.safekeep/ for non-root user if it exists Modified Paths: -------------- safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/doc/safekeep.conf.txt safekeep/trunk/doc/safekeep.txt safekeep/trunk/safekeep Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2013-01-01 08:03:06 UTC (rev 834) +++ safekeep/trunk/doc/safekeep.backup.txt 2013-01-01 10:35:18 UTC (rev 835) @@ -11,7 +11,8 @@ SYNOPSIS -------- -These files are usually placed in `/etc/safekeep/backup.d/` to be picked +These files are usually placed in `/etc/safekeep/backup.d/`, or optionally +in `~/.safekeep/backup.d/` for non-root users, to be picked up automatically by 'safekeep(1)'. They must have a `.backup` extension. DESCRIPTION @@ -430,6 +431,7 @@ FILES ----- /etc/safekeep/backup.d/ + ~/.safekeep/backup.d/ SEE ALSO -------- Modified: safekeep/trunk/doc/safekeep.conf.txt =================================================================== --- safekeep/trunk/doc/safekeep.conf.txt 2013-01-01 08:03:06 UTC (rev 834) +++ safekeep/trunk/doc/safekeep.conf.txt 2013-01-01 10:35:18 UTC (rev 835) @@ -11,7 +11,8 @@ SYNOPSIS -------- -This file resides in `/etc/safekeep/` from where it +This file resides in `/etc/safekeep/`, or optionally in +`~/.safekeep/` for non-root users, from where it will be automatically picked up by 'safekeep(1)'. DESCRIPTION @@ -148,6 +149,7 @@ FILES ----- /etc/safekeep/safekeep.conf + ~/.safekeep/safekeep.conf SEE ALSO -------- Modified: safekeep/trunk/doc/safekeep.txt =================================================================== --- safekeep/trunk/doc/safekeep.txt 2013-01-01 08:03:06 UTC (rev 834) +++ safekeep/trunk/doc/safekeep.txt 2013-01-01 10:35:18 UTC (rev 835) @@ -88,7 +88,8 @@ -c, --conf=FILE:: Specifies the configuration file location. If not specified at all, SafeKeep will default to - `/etc/safekeep/safekeep.conf` if it exists. + `/etc/safekeep/safekeep.conf`, or optionally in + `~/.safekeep/safekeep.conf` for non-root users, if it exists. Simply using this default is the recommended usage. -h, --help:: @@ -194,7 +195,8 @@ ------------- Normally the configuration files are placed in the `/etc/safekeep/backup.d/` -directory from where they will get picked up automatically by SafeKeep. +directory, or optionally in `~/.safekeep/backup.d/` for non-root users, +from where they will get picked up automatically by SafeKeep. Each backup client is described by a configuration file in XML format. The minimum configuration file is: ------------------------------------------------------------------------ Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2013-01-01 08:03:06 UTC (rev 834) +++ safekeep/trunk/safekeep 2013-01-01 10:35:18 UTC (rev 835) @@ -1822,7 +1822,7 @@ except getopt.GetoptError: usage(2) - global backup_user, client_user, home_dir, base_dir + global backup_user, client_user, home_dir, base_dir, config_file global verbosity_level mode = None @@ -1842,6 +1842,12 @@ keys_print = False keys_deploy = False nice_srv = None + + if os.getuid(): + user_path = os.path.expanduser('~/.safekeep') + if os.path.exists(user_path) and os.path.isdir(user_path): + config_file = user_path + '/safekeep.conf' + for o, a in opts: if o in ('-c', '--conf'): if os.path.isdir(a) or a.endswith(config_ext): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2013-01-05 01:38:55
|
Revision: 838 http://safekeep.svn.sourceforge.net/safekeep/?rev=838&view=rev Author: fcrawford Date: 2013-01-05 01:38:42 +0000 (Sat, 05 Jan 2013) Log Message: ----------- Generate a summary for a 'list' mode run Modified Paths: -------------- safekeep/trunk/doc/safekeep.conf.txt safekeep/trunk/safekeep Modified: safekeep/trunk/doc/safekeep.conf.txt =================================================================== --- safekeep/trunk/doc/safekeep.conf.txt 2013-01-02 19:48:22 UTC (rev 837) +++ safekeep/trunk/doc/safekeep.conf.txt 2013-01-05 01:38:42 UTC (rev 838) @@ -72,7 +72,7 @@ Possible options are 'true', 'yes' or '1'. Anything elses as taken as 'false'. NB: This requires 'email.format' set and currently only used - for 'server' run type. + for 'server' and 'list' run types. nice.adjustment:: The default nice level adjustment for safekeep. Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2013-01-02 19:48:22 UTC (rev 837) +++ safekeep/trunk/safekeep 2013-01-05 01:38:42 UTC (rev 838) @@ -208,9 +208,8 @@ lines = [] for line in child_out: - if stdout: - lines.append(line) - else: + lines.append(line) + if not stdout: info(line.rstrip()) child_out.close() @@ -250,7 +249,7 @@ rc, out = _spawn(args) return rc -# this spawans an external program (optionally through a shell), +# this spawns an external program (optionally through a shell), # feeds it any input via stdin, captures the output and returns it. # if it fails it returns None, otherwise it returns the output def call(args, stdin=None): @@ -268,7 +267,10 @@ return None return out or '' -def print_stats_table_list_text(stats): +# +# Statistics format routines for the "server" type +# +def print_stats_table_server_text(stats): result = '|{:<8}|{:<8}'.format(stats['id'], stats['state']) if (len(stats) > 2): result += '|{:>6}|{:<24}|{:<24}|{:>24}|{:>12}|{:>12}|{:>13}|'.format( @@ -283,7 +285,7 @@ result += '|{0:>6}|{0:<24}|{0:<24}|{0:>24}|{0:>12}|{0:>12}|{0:>13}|'.format('') return result -def print_stats_table_list_html(stats): +def print_stats_table_server_html(stats): if (stats.get('state') == 'OK'): color = ' bgcolor="#81F7BE"' else: @@ -324,7 +326,7 @@ '-' * 141 + '\r\n'] for stats in statistics: - result.append(print_stats_table_list_text(stats) + '\r\n' + '-' * 141 + '\r\n') + result.append(print_stats_table_server_text(stats) + '\r\n' + '-' * 141 + '\r\n') return result @@ -342,13 +344,78 @@ '</tr>'] for stats in statistics: + result.append(print_stats_table_server_html(stats)) + + result.append('</table></html>') + return result + +# +# Statistics format routines for the "list" type +# +def print_stats_table_list_text(stats): + result = '|{:<8}|{:<8}'.format(stats['id'], stats['state']) + if (len(stats) > 2): + result += '|{:<24}|{:<24}|{:>10}|'.format( + stats['CurrentMirror'], + stats['OldestIncrement'], + stats['Increments']) + else: + result += '|{0:<24}|{0:<24}|{0:>10}|'.format('') + return result + +def print_stats_table_list_html(stats): + if (stats.get('state') == 'OK'): + color = ' bgcolor="#81F7BE"' + else: + color = ' bgcolor="#F78181"' + result = '<tr' + color + '><td>' + stats['id'] + '</td><td>' + stats['state'] + '</td>' + if (len(stats) > 2): + result += '<td>' + stats['CurrentMirror'] + '</td>' + \ + '<td>' + stats['OldestIncrement'] + '</td>' + \ + '<td align="right">' + stats['Increments'] + '</td>' + else: + result += '<td></td>' + \ + '<td></td>' + \ + '<td align="right"></td>' + result += '</tr>' + return result + +def stats_to_table_list_text(): + result = ['-' * 80 + '\r\n', + '|{:<8}|{:<8}|{:<24}|{:<24}|{:<10}|'.format( + 'Name', + 'State', + 'Current Mirror', + 'Oldest Increment', + 'Increments') + \ + '\r\n', + '-' * 80 + '\r\n'] + + for stats in statistics: + result.append(print_stats_table_list_text(stats) + '\r\n' + '-' * 80 + '\r\n') + + return result + +def stats_to_table_list_html(): + result = ['<html><body><table border="1"><tr>' + '<th>Name</th>' + '<th>State</th>' + '<th>Current Mirror</th>' + '<th>Oldest Increment</th>' + '<th>Increments</th>' + '</tr>'] + + for stats in statistics: result.append(print_stats_table_list_html(stats)) result.append('</table></html>') return result +# +# Main statistics printing functions +# def stats_to_table(mode, fmt): - if not mode in ('server'): return 'Mode: %s: not currently supported' % mode + if not mode in ('server', 'list'): return 'Mode: %s: not currently supported' % mode if not fmt in ('html', 'text'): return 'Format: %s: not currently supported' % fmt if len(statistics) == 0: return 'No statistics available' @@ -379,7 +446,7 @@ msg += '\r\n' + '\r\n'.join(logbuf) + '\r\n' else: msg += 'Content-Type: multipart/mixed;boundary=safebounder001\r\n' - if 'summary' in email and mode in ('server'): + if 'summary' in email and mode in ('server', 'list'): msg += '\r\n--safebounder001\r\n' if email['format'] == 'text': msg += 'Content-type: text/plain;charset=utf-8\r\n' @@ -1607,16 +1674,19 @@ debug('Server backup done') def do_list(cfgs, ids, list_type, list_date, list_parsable): + global statistics debug("Do server listing main loop") output_done = False for cfg in cfgs.itervalues(): cfg_id = cfg['id'] if ids and cfg_id not in ids: continue + stats = {} if list_parsable: info('Client: %s' % cfg_id) else: info('------------------------------------------------------------------') info('Server listing for client %s' % cfg_id) + stats['id'] = cfg_id output_done = True args = ['rdiff-backup'] @@ -1636,10 +1706,31 @@ args.extend(['--parsable-output']) args.extend([cfg['dir']]) - ret = spawn(args) + # Call a low level routine to get the data back as well. + ret, lines = _spawn(args) if ret: error('Failed to run rdiff-backup') + stats['state'] = 'FAILED' + else: + stats['state'] = 'OK' + if list_type == 'increments': + if list_parsable: + stats['Increments'] = str(len(lines) - 1) + date_time = lines[len(lines) - 1].split(None, 1)[0] + stats['CurrentMirror'] = time.ctime(int(date_time)) + date_time = lines[0].split(None, 1)[0] + stats['OldestIncrement'] = time.ctime(int(date_time)) + else: + stats['Increments'] = str(len(lines) - 2) + stats['CurrentMirror'] = lines[len(lines) - 1].strip().split(None, 2)[2] + stats['OldestIncrement'] = lines[1].strip().split(None, 1)[1] + elif list_type == 'sizes': + stats['Increments'] = str(len(lines) - 3) + stats['CurrentMirror'] = lines[2].split(' ', 1)[0] + stats['OldestIncrement'] = lines[len(lines) - 1].split(' ', 1)[0] + statistics.append(stats) + if output_done and not list_parsable: info('------------------------------------------------------------------') debug('Server listing done') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <di...@us...> - 2013-01-05 18:23:58
|
Revision: 839 http://safekeep.svn.sourceforge.net/safekeep/?rev=839&view=rev Author: dimi Date: 2013-01-05 18:23:52 +0000 (Sat, 05 Jan 2013) Log Message: ----------- Specify a default size for a snapshot (set to 20% of the free space) Modified Paths: -------------- safekeep/trunk/doc/safekeep.backup.txt safekeep/trunk/doc/safekeep.conf.txt safekeep/trunk/safekeep Modified: safekeep/trunk/doc/safekeep.backup.txt =================================================================== --- safekeep/trunk/doc/safekeep.backup.txt 2013-01-05 01:38:42 UTC (rev 838) +++ safekeep/trunk/doc/safekeep.backup.txt 2013-01-05 18:23:52 UTC (rev 839) @@ -260,8 +260,7 @@ percentage, e.g. `20%`, which is equivalent to 20% of the logical volume. Other values as listed for `lvcreate(8)` can also be given. - Mandatory for a `<snapshot>` element, unless a default value - has been specified in `safekeep.conf`. + Optional, defaults to 'snapshot.size' as specified in `safekeep.conf`. /backup/setup/snapshot/@tag:: A list of tags to be added to the snapshot, with the `--addtag` Modified: safekeep/trunk/doc/safekeep.conf.txt =================================================================== --- safekeep/trunk/doc/safekeep.conf.txt 2013-01-05 01:38:42 UTC (rev 838) +++ safekeep/trunk/doc/safekeep.conf.txt 2013-01-05 18:23:52 UTC (rev 839) @@ -129,7 +129,7 @@ a percentage (`%`). If not otherwise specified, the percentage is based on unallocated space (i.e. LVM2 `%FREE'), which is different to the interpretation within the `<snapshot>` option. - This value is optional and there is no default. + This value is optional, it defaults to '20%FREE'. NOTES ----- Modified: safekeep/trunk/safekeep =================================================================== --- safekeep/trunk/safekeep 2013-01-05 01:38:42 UTC (rev 838) +++ safekeep/trunk/safekeep 2013-01-05 18:23:52 UTC (rev 839) @@ -70,7 +70,7 @@ client_defaults = [] current_pid = os.getpid() default_bandwidth = {} -default_snapshot = None +default_snapshot = '20%FREE' statistics = [] # Default mount options, overridden elsewhere: # Key is a file system type, or 'snapshot' for default for snapshot mount This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fcr...@us...> - 2013-01-19 12:42:04
|
Revision: 841 http://safekeep.svn.sourceforge.net/safekeep/?rev=841&view=rev Author: fcrawford Date: 2013-01-19 10:10:07 +0000 (Sat, 19 Jan 2013) Log Message: ----------- Prepared for 1.4.1 release Modified Paths: -------------- safekeep/trunk/ANNOUNCE safekeep/trunk/safekeep.spec.in Modified: safekeep/trunk/ANNOUNCE =================================================================== --- safekeep/trunk/ANNOUNCE 2013-01-19 10:09:16 UTC (rev 840) +++ safekeep/trunk/ANNOUNCE 2013-01-19 10:10:07 UTC (rev 841) @@ -1,35 +1,35 @@ -This is release 1.4.0 of SafeKeep, a centralized and easy to use +This is release 1.4.1 of SafeKeep, a centralized and easy to use backup application that combines the best features of a mirror and an incremental backup. What's new in this release: - - Add the ability to store script files on either client or server. - - Rewritten snapshot creation to remove use of "rbind". - - Automatic cleanup on next run after an abort. - - Support of LVM tagging for snapshots. - - Better handling of messages and tracebacks. - - A number of other code cleanups and bug fixes. - - Updated minimum Python support to Python 2.3. + - A major rework of LVM snapshot handling. + - Generate MIME emails with summary reports. + - Better handling of PostgreSQL passwords. + - Added ability to use LVM snapshots with XFS filesystems. + - Allow use of ~/.safekeep for non-root users. + - Allow default and automatic snapshot sizes. -Many thanks to Andres Toomsalu, Ken Bass, Joe Steele and Alexander List -for the fixes that made this release possible, and to Dimi Paun for his -continual work with SafeKeep. +Many thanks to Andres Toomsalu, Marco Bozzolan, Robert Jordan, Alexander +'Leo' Bergolth, Bryan Talbot, Riley Revels, Walery Wysotsky and Raúl +Wegmann for the suggestions and fixes that made this release possible, +and to Dimi Paun for his continual work with SafeKeep. Sources and binaries are available from the following locations: - - RedHat EL/CentOS 4,5,6 Fedora 8,9,10,11,12,13,14,15,16: - http://prdownloads.sourceforge.net/safekeep/safekeep-common-1.4.0-1.noarch.rpm - http://prdownloads.sourceforge.net/safekeep/safekeep-client-1.4.0-1.noarch.rpm - http://prdownloads.sourceforge.net/safekeep/safekeep-server-1.4.0-1.noarch.rpm + - RedHat EL/CentOS 4,5,6 Fedora 8,9,10,11,12,13,14,15,16,17,18: + http://prdownloads.sourceforge.net/safekeep/safekeep-common-1.4.1-1.noarch.rpm + http://prdownloads.sourceforge.net/safekeep/safekeep-client-1.4.1-1.noarch.rpm + http://prdownloads.sourceforge.net/safekeep/safekeep-server-1.4.1-1.noarch.rpm - Ubuntu Dapper, Breezy, Hardy, Lucid, Maverick, Natty, Oneiric and Precise: - http://prdownloads.sourceforge.net/safekeep/safekeep-common_1.4.0_all.deb - http://prdownloads.sourceforge.net/safekeep/safekeep-client_1.4.0_all.deb - http://prdownloads.sourceforge.net/safekeep/safekeep-server_1.4.0_all.deb + http://prdownloads.sourceforge.net/safekeep/safekeep-common_1.4.1_all.deb + http://prdownloads.sourceforge.net/safekeep/safekeep-client_1.4.1_all.deb + http://prdownloads.sourceforge.net/safekeep/safekeep-server_1.4.1_all.deb - Source: - http://prdownloads.sourceforge.net/safekeep/safekeep-1.4.0.tar.gz - http://prdownloads.sourceforge.net/safekeep/safekeep-1.4.0-1.src.rpm + http://prdownloads.sourceforge.net/safekeep/safekeep-1.4.1.tar.gz + http://prdownloads.sourceforge.net/safekeep/safekeep-1.4.1-1.src.rpm The GPG Signing Key can be found in the following location: @@ -42,7 +42,7 @@ uid SafeKeep (Signing Key) <saf...@li...> sub 1024g/6AA3270F 2012-02-17 -NOTE: The minimum version of Python now supported is Python 2.3. If you +NOTE: The minimum version of Python supported is Python 2.3. If you require support of an older version of Python, then you should select an earlier release of Safekeep. Modified: safekeep/trunk/safekeep.spec.in =================================================================== --- safekeep/trunk/safekeep.spec.in 2013-01-19 10:09:16 UTC (rev 840) +++ safekeep/trunk/safekeep.spec.in 2013-01-19 10:10:07 UTC (rev 841) @@ -107,6 +107,14 @@ %doc samples/sample.backup %changelog +* Sat Jan 19 2013 Frank Crawford <fr...@cr...> 1.4.1-1 + - A major rework of LVM snapshot handling. + - Generate MIME emails with summary reports. + - Better handling of PostgreSQL passwords. + - Added ability to use LVM snapshots with XFS filesystems. + - Allow use of ~/.safekeep for non-root users. + - Allow default and automatic snapshot sizes. + * Sun Feb 12 2012 Frank Crawford <fr...@cr...> 1.4.0-1 - Add the ability to store script files on either client or server. - Rewritten snapshot creation to remove use of "rbind". This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |