From 9f974f6a7a8dd9efa2229ba8cd80ae2fd9bdeb01 Mon Sep 17 00:00:00 2001 From: "matteo.guadrini" Date: Tue, 8 Jan 2019 16:36:51 +0100 Subject: [PATCH] Add export main function Add one-line option in list function Add Differential backup mode Add Code Of Conduct Add man page into command line Other fix --- .gitignore | 0 CODE_OF_CONDUCT.md | 52 +++ LICENSE.md | 0 README.md | 8 +- _config.yml | 0 bb.man | 179 +++++++++ bb.py | 365 ++++++++++++++---- docs/Makefile | 0 docs/build/doctrees/backup.doctree | Bin docs/build/doctrees/environment.pickle | Bin 8519 -> 16004 bytes docs/build/doctrees/index.doctree | Bin 136253 -> 162278 bytes docs/build/html/.buildinfo | 2 +- docs/build/html/_sources/backup.rst.txt | 0 docs/build/html/_sources/index.rst.txt | 204 +++++++--- docs/build/html/_static/ajax-loader.gif | Bin docs/build/html/_static/alabaster.css | 0 docs/build/html/_static/basic.css | 11 + docs/build/html/_static/comment-bright.png | Bin docs/build/html/_static/comment-close.png | Bin docs/build/html/_static/comment.png | Bin docs/build/html/_static/custom.css | 0 docs/build/html/_static/doctools.js | 6 +- .../html/_static/documentation_options.js | 291 +++++++++++++- docs/build/html/_static/down-pressed.png | Bin docs/build/html/_static/down.png | Bin docs/build/html/_static/file.png | Bin docs/build/html/_static/jquery-3.2.1.js | 0 docs/build/html/_static/jquery.js | 0 docs/build/html/_static/minus.png | Bin docs/build/html/_static/plus.png | Bin docs/build/html/_static/pygments.css | 0 docs/build/html/_static/searchtools.js | 351 ++--------------- docs/build/html/_static/underscore-1.3.1.js | 0 docs/build/html/_static/underscore.js | 0 docs/build/html/_static/up-pressed.png | Bin docs/build/html/_static/up.png | Bin docs/build/html/_static/websupport.js | 0 docs/build/html/genindex.html | 31 +- docs/build/html/index.html | 318 +++++++++++---- docs/build/html/objects.inv | Bin 374 -> 383 bytes docs/build/html/search.html | 33 +- docs/build/html/searchindex.js | 2 +- docs/source/conf.py | 0 docs/source/index.rst | 204 +++++++--- img/bb.png | Bin setup.py | 7 + utility.py | 2 + 47 files changed, 1447 insertions(+), 619 deletions(-) mode change 100644 => 100755 .gitignore create mode 100644 CODE_OF_CONDUCT.md mode change 100644 => 100755 LICENSE.md mode change 100644 => 100755 README.md mode change 100644 => 100755 _config.yml create mode 100644 bb.man mode change 100644 => 100755 bb.py mode change 100644 => 100755 docs/Makefile mode change 100644 => 100755 docs/build/doctrees/backup.doctree mode change 100644 => 100755 docs/build/doctrees/environment.pickle mode change 100644 => 100755 docs/build/doctrees/index.doctree mode change 100644 => 100755 docs/build/html/.buildinfo mode change 100644 => 100755 docs/build/html/_sources/backup.rst.txt mode change 100644 => 100755 docs/build/html/_sources/index.rst.txt mode change 100644 => 100755 docs/build/html/_static/ajax-loader.gif mode change 100644 => 100755 docs/build/html/_static/alabaster.css mode change 100644 => 100755 docs/build/html/_static/basic.css mode change 100644 => 100755 docs/build/html/_static/comment-bright.png mode change 100644 => 100755 docs/build/html/_static/comment-close.png mode change 100644 => 100755 docs/build/html/_static/comment.png mode change 100644 => 100755 docs/build/html/_static/custom.css mode change 100644 => 100755 docs/build/html/_static/doctools.js mode change 100644 => 100755 docs/build/html/_static/documentation_options.js mode change 100644 => 100755 docs/build/html/_static/down-pressed.png mode change 100644 => 100755 docs/build/html/_static/down.png mode change 100644 => 100755 docs/build/html/_static/file.png mode change 100644 => 100755 docs/build/html/_static/jquery-3.2.1.js mode change 100644 => 100755 docs/build/html/_static/jquery.js mode change 100644 => 100755 docs/build/html/_static/minus.png mode change 100644 => 100755 docs/build/html/_static/plus.png mode change 100644 => 100755 docs/build/html/_static/pygments.css mode change 100644 => 100755 docs/build/html/_static/searchtools.js mode change 100644 => 100755 docs/build/html/_static/underscore-1.3.1.js mode change 100644 => 100755 docs/build/html/_static/underscore.js mode change 100644 => 100755 docs/build/html/_static/up-pressed.png mode change 100644 => 100755 docs/build/html/_static/up.png mode change 100644 => 100755 docs/build/html/_static/websupport.js mode change 100644 => 100755 docs/build/html/genindex.html mode change 100644 => 100755 docs/build/html/index.html mode change 100644 => 100755 docs/build/html/objects.inv mode change 100644 => 100755 docs/build/html/search.html mode change 100644 => 100755 docs/source/conf.py mode change 100644 => 100755 docs/source/index.rst mode change 100644 => 100755 img/bb.png mode change 100644 => 100755 setup.py mode change 100644 => 100755 utility.py diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..2bc9774 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,52 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of +fostering an open and welcoming community, we pledge to respect all people who +contribute through reporting issues, posting feature requests, updating +documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free +experience for everyone, regardless of level of experience, gender, gender +identity and expression, sexual orientation, disability, personal appearance, +body size, race, ethnicity, age, religion, or nationality. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic + addresses, without explicit permission +* Other unethical or unprofessional conduct + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +By adopting this Code of Conduct, project maintainers commit themselves to +fairly and consistently applying these principles to every aspect of managing +this project. Project maintainers who do not follow or enforce the Code of +Conduct may be permanently removed from the project team. + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project maintainers at msfdev@metasploit.com. If +the incident involves a committer, you may report directly to +egypt@metasploit.com or todb@metasploit.com. + +All complaints will be reviewed and investigated and will result in a +response that is deemed necessary and appropriate to the circumstances. +Maintainers are obligated to maintain confidentiality with regard to the +reporter of an incident. + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 1.3.0, available at +[http://contributor-covenant.org/version/1/3/0/][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/3/0/ \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index b18f3a2..4e322cf --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ This list consists of only a few examples; applications can be endless: - Configuration for silently backup - All backup are organized into a catalog - List single or all backup by the catalog -- Backup single PC, with Full,Incremental and Mirror mode; -- Backup more PCs, with Full,Incremental and Mirror mode (with parallelism algorithm); +- Backup single PC, with Full,Incremental,Differential and Mirror mode; +- Backup more PCs, with Full,Incremental,Differential and Mirror mode (with parallelism algorithm); - Backup custom folder or predefined data (User,Config,Application,System,Log) - Restore backup on the same PC - Restore backup in other PC @@ -64,7 +64,7 @@ bb --help Backup a single PC or server is a everyday task. But most of the data may not change in the various backups made; then, in these cases, an incremental backup is needed. -Butterfly Backup natively supports incremental backups, starting from a full. +Butterfly Backup natively supports incremental and differential backups, starting from a full. In this case, the first backup to be performed on the machine will be as follows: ```bash bb backup --computer pc1 --destination /nas/mybackup --data User Config --type MacOS --mode Full @@ -148,7 +148,7 @@ bb --help ## One more thing The name butterfly, is born precisely because agent-less; like a butterfly takes the pollen from a flower and brings it elsewhere. -A backup or restore is performed without any iterationresponsibility on the part of the final machine. +A backup or restore is performed without any iteration responsibility on the part of the final machine. The performances are not altered. While all the operations of Butterfly Backup are carried out, the impacted machine can continuously work with peace of mind. diff --git a/_config.yml b/_config.yml old mode 100644 new mode 100755 diff --git a/bb.man b/bb.man new file mode 100644 index 0000000..49ae9f0 --- /dev/null +++ b/bb.man @@ -0,0 +1,179 @@ +.\" Manpage for Butterfly Backup. +.\" Contact matteo.guadrini@hotmail.it to correct errors or typos. +.TH man 1 "11 Dec 2018" "1.4.0" "bb man page" +.SH NAME +bb \- Butterfly Backup - backup/restore/archive tool , agentless +.SH SYNOPSIS +bb [ACTION] [OPTIONS] + +bb [-h] [--verbose] [--log] [--dry-run] [--version] + {config,backup,restore,archive,list,export} ... +.SH DESCRIPTION +Butterfly Backup is a simple command line wrapper of rsync for complex task, written in python. +.SH OPTIONS +.TP +action: + Valid action + + {config,backup,restore,archive,list,export} + Available actions + config Configuration options + backup Backup options + restore Restore options + archive Archive options + list List options + export Export options + +.B backup +[ACTION] + + --computer HOSTNAME, -c HOSTNAME + Hostname or ip address to backup + --list LIST, -L LIST File list of computers or ip addresses to backup + --destination DESTINATION, -d DESTINATION + Destination path + --mode {Full,Incremental,Differential,Mirror}, -m {Full,Incremental,Differential,Mirror} + Backup mode + --data {User,Config,Application,System,Log} [{User,Config,Application,System,Log} ...], -D {User,Config,Application,System,Log} [{User,Config,Application,System,Log} ...] + Data of which you want to backup + --custom-data, -D CUSTOMDATA [CUSTOMDATA ...], -C CUSTOMDATA [CUSTOMDATA ...] + Custom path of which you want to backup + --user USER, -u USER Login name used to log into the remote host (being + backed up) + --type {Unix,Windows,MacOS}, -t {Unix,Windows,MacOS} + Type of operating system to backup + --compress, -z Compress data + --retention RETENTION, -r RETENTION + Number of days of backup retention + --parallel PARALLEL, -p PARALLEL + Number of parallel jobs + --timeout TIMEOUT, -T TIMEOUT + I/O timeout in seconds + --skip-error, -e Skip error. + +.B list +[ACTION] + + --catalog CATALOG, -C CATALOG + Folder where is catalog file + --backup-id ID, -i ID + Backup-id of backup + --archived, -a List only archived backup + --cleaned, -c List only cleaned backup + --computer HOSTNAME, -H HOSTNAME + List only match hostname or ip + --oneline, -o One line output + +.B restore +[ACTION] + + --catalog CATALOG, -C CATALOG + Folder where is catalog file + --backup-id ID, -i ID + Backup-id of backup + --last, -L Last available backup + --user USER, -u USER Login name used to log into the remote host (where + you're restoring) + --computer HOSTNAME, -c HOSTNAME + Hostname or ip address to perform restore + --type {Unix,Windows,MacOS}, -t {Unix,Windows,MacOS} + Type of operating system to perform restore + --timeout TIMEOUT, -T TIMEOUT + I/O timeout in seconds + --mirror, -m Mirror mode + --skip-error, -e Skip error. + +.B config +[ACTION] + +Init configuration: + --new, -n Generate new configuration + --remove, -r Remove exist configuration + +Deploy configuration: + --deploy DEPLOY_HOST, -d DEPLOY_HOST + Deploy configuration to client: hostname or ip address + --user DEPLOY_USER, -u DEPLOY_USER + User of the remote machine + +.B archive +[ACTION] + + --catalog CATALOG, -C CATALOG + Folder where is catalog file + --days DAYS, -D DAYS Number of days of archive retention + --destination DESTINATION, -d DESTINATION + Archive destination path + +.B export +[ACTION] + --catalog CATALOG, -C CATALOG + Folder where is catalog file + --backup-id ID, -i ID + Backup-id of backup + --destination DESTINATION, -d DESTINATION + Destination path + --mirror, -m Mirror mode + --cut, -c Cut mode. Delete source + --include INCLUDE [INCLUDE ...], -I INCLUDE [INCLUDE ...] + Include pattern + --exclude EXCLUDE [EXCLUDE ...], -E EXCLUDE [EXCLUDE ...] + Exclude pattern + --timeout TIMEOUT, -T TIMEOUT + I/O timeout in seconds + --skip-error, -e Skip error + +.B optional arguments +[OPTIONS] + + -h, --help show help message and exit + --verbose, -v Enable verbosity + --log, -l Create a log + --dry-run, -N Dry run mode + --version, -V Print version + +.SH EXAMPLES +Show full help: + O_O>$ bb --help + +Backup single machine: + O_O>$ bb backup --computer host1 --destination /mnt/backup --data User Config --type MacOS + +Backup multiple machine: + O_O>$ > hosts.txt + host1 + host2 + host3 + ^D + O_O>$ bb backup --list hosts.txt --destination /mnt/backup --data User Config --type MacOS + +List catalog backups: + O_O>$ bb list --catalog /mnt/backup + +List backup details: + O_O>$ bb list --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 + +Restore machine with log: + O_O>$ bb restore --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 --computer host1 --log + +Archive backups older than 3 days: + O_O>$ bb archive --catalog /mnt/backup/ --days 3 --destination /mnt/archive/ --verbose + +Create configuration (RSA key): + O_O>$ bb config --new + +Deploy configuration to machine: + O_O>$ bb config --deploy host1 + +Export a backup to another path: + O_O>$ bb export --catalog /mnt/backup/ --backup-id f0f700e8-0435-11e9-9e78-005056a664e0 --destination /mnt/export + +.SH SEE ALSO +Full documentation is here: +https://butterfly-backup.readthedocs.io/en/latest/ +.SH BUGS +No known bugs. +.SH AUTHOR +Matteo Guadrini +.SH COPYRIGHT +(c) Matteo Guadrini. All rights reserved. \ No newline at end of file diff --git a/bb.py b/bb.py old mode 100644 new mode 100755 index 7d7f90e..fbe3383 --- a/bb.py +++ b/bb.py @@ -31,7 +31,7 @@ from utility import print_verbose # region Global Variables -VERSION = '1.2.0' +VERSION = '1.4.0' # endregion @@ -127,7 +127,7 @@ def run_in_parallel(fn, commands, limit): # Run the function proc = pool.apply_async(func=fn, args=(command, )) jobs.append(proc) - print('Start {0} on {1}'.format(args.action, plog['hostname'])) + print('Start {0} {1}'.format(args.action, plog['hostname'])) print_verbose(args.verbose, "rsync command: {0}".format(command)) utility.write_log(log_args['status'], plog['destination'], 'INFO', 'Start process {0} on {1}'.format( args.action, plog['hostname'] @@ -249,6 +249,7 @@ def compose_command(flags, host): print_verbose(args.verbose, 'Build a rsync command') # Set rsync binary command = ['rsync'] + catalog = read_catalog(catalog_path) if flags.action == 'backup': # Set mode option if flags.mode == 'Full': @@ -257,11 +258,11 @@ def compose_command(flags, host): # Write catalog file write_catalog(catalog_path, backup_id, 'type', 'Full') elif flags.mode == 'Incremental': - last_full = get_last_full(catalog_path) - if last_full: + last_bck = get_last_backup(catalog) + if last_bck: command.append('-ahu') command.append('--no-links') - command.append('--link-dest={0}'.format(last_full)) + command.append('--link-dest={0}'.format(last_bck[0])) # Write catalog file write_catalog(catalog_path, backup_id, 'type', 'Incremental') else: @@ -269,6 +270,19 @@ def compose_command(flags, host): command.append('--no-links') # Write catalog file write_catalog(catalog_path, backup_id, 'type', 'Full') + elif flags.mode == 'Differential': + last_full = get_last_full(catalog) + if last_full: + command.append('-ahu') + command.append('--no-links') + command.append('--link-dest={0}'.format(last_full[0])) + # Write catalog file + write_catalog(catalog_path, backup_id, 'type', 'Differential') + else: + command.append('-ah') + command.append('--no-links') + # Write catalog file + write_catalog(catalog_path, backup_id, 'type', 'Full') elif flags.mode == 'Mirror': command.append('-ah') command.append('--delete') @@ -277,6 +291,9 @@ def compose_command(flags, host): # Set verbosity if flags.verbose: command.append('-vP') + # Set quite mode + if flags.skip_err: + command.append('--quiet') # Set compress mode if flags.compress: command.append('-z') @@ -298,6 +315,9 @@ def compose_command(flags, host): command.append('-ahu --no-perms --no-owner --no-group') if flags.verbose: command.append('-vP') + # Set quite mode + if flags.skip_err: + command.append('--quiet') # Set I/O timeout if flags.timeout: command.append('--timeout={0}'.format(flags.timeout)) @@ -316,6 +336,31 @@ def compose_command(flags, host): ) utility.write_log(log_args['status'], log_args['destination'], 'INFO', 'rsync log path: {0}'.format(log_path)) + elif flags.action == 'export': + command.append('-ahu --no-perms --no-owner --no-group') + if flags.verbose: + command.append('-vP') + # Set quite mode + if flags.skip_err: + command.append('--quiet') + # Set I/O timeout + if flags.timeout: + command.append('--timeout={0}'.format(flags.timeout)) + # Set mirror mode + if flags.mirror: + command.append('--delete') + command.append('--ignore-times') + # Set dry-run mode + if flags.dry_run: + command.append('--dry-run') + utility.write_log(log_args['status'], log_args['destination'], 'INFO', 'dry-run mode activate') + if flags.log: + log_path = os.path.join(rpath, 'export.log') + command.append( + '--log-file={0}'.format(log_path) + ) + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'rsync log path: {0}'.format(log_path)) print_verbose(args.verbose, 'Command flags are: {0}'.format(' '.join(command))) return command @@ -402,7 +447,11 @@ def compose_destination(computer_name, folder): """ # Create root folder of backup first_layer = os.path.join(folder, computer_name) - second_layer = os.path.join(first_layer, utility.time_for_folder()) + # Check if backup is a Mirror or not + if args.mode != 'Mirror': + second_layer = os.path.join(first_layer, utility.time_for_folder()) + else: + second_layer = os.path.join(first_layer, 'mirror_backup') if not os.path.exists(first_layer): os.mkdir(first_layer) utility.write_log(log_args['status'], log_args['destination'], 'INFO', @@ -421,14 +470,21 @@ def get_last_full(catalog): """ Get the last full :param catalog: configparser object - :return: path (string) + :return: path (string), os (string) """ - config = read_catalog(catalog) + config = catalog if config: dates = [] for bid in config.sections(): - if config.get(bid, 'type') == 'Full' and config.get(bid, 'name') == hostname: - dates.append(utility.string_to_time(config.get(bid, 'timestamp'))) + if config.get(bid, 'type') == 'Full' \ + and config.get(bid, 'name') == hostname \ + and (not config.has_option(bid, 'cleaned') or not config.has_option(bid, 'archived')): + try: + dates.append(utility.string_to_time(config.get(bid, 'timestamp'))) + except configparser.NoOptionError: + print(utility.PrintColor.RED + + "ERROR: Corrupted catalog! No found timestamp in {0}".format(bid) + utility.PrintColor.END) + exit(2) if dates: last_full = utility.time_to_string(max(dates)) if last_full: @@ -437,7 +493,7 @@ def get_last_full(catalog): if config.get(bid, 'type') == 'Full' and \ config.get(bid, 'name') == hostname and \ config.get(bid, 'timestamp') == last_full: - return config.get(bid, 'path') + return config.get(bid, 'path'), config.get(bid, 'os') else: return False @@ -446,14 +502,20 @@ def get_last_backup(catalog): """ Get the last available backup :param catalog: configparser object - :return: path (string) + :return: path (string), os (string) """ config = catalog dates = [] if config: for bid in config.sections(): - if config.get(bid, 'name') == hostname: - dates.append(utility.string_to_time(config.get(bid, 'timestamp'))) + if config.get(bid, 'name') == hostname \ + and (not config.has_option(bid, 'cleaned') or not config.has_option(bid, 'archived')): + try: + dates.append(utility.string_to_time(config.get(bid, 'timestamp'))) + except configparser.NoOptionError: + print(utility.PrintColor.RED + + "ERROR: Corrupted catalog! No found timestamp in {0}".format(bid) + utility.PrintColor.END) + exit(2) if dates: dates.sort() last = utility.time_to_string(dates[-1]) @@ -461,6 +523,8 @@ def get_last_backup(catalog): for bid in config.sections(): if config.get(bid, 'name') == hostname and config.get(bid, 'timestamp') == last: return config.get(bid, 'path'), config.get(bid, 'os') + else: + return False def count_full(config, name): @@ -607,8 +671,8 @@ def deploy_configuration(computer, user): print_verbose(args.verbose, 'Public id_rsa is {0}'.format(id_rsa_pub_file)) if not dry_run('Copying configuration to {0}'.format(computer)): if os.path.exists(id_rsa_pub_file): - print('Copying configuration to' + utility.PrintColor.BOLD + ' {0}'.format(computer) + utility.PrintColor.END + - '; write the password:') + print('Copying configuration to' + utility.PrintColor.BOLD + ' {0}'.format(computer) + + utility.PrintColor.END + '; write the password:') return_code = subprocess.call('ssh-copy-id -i {0} {1}@{2}'.format(id_rsa_pub_file, user, computer), shell=True) print_verbose(args.verbose, 'Return code of ssh-copy-id: {0}'.format(return_code)) @@ -620,7 +684,8 @@ def deploy_configuration(computer, user): computer) + utility.PrintColor.END) else: - print(utility.PrintColor.YELLOW + "WARNING: Public key ~/.ssh/id_rsa.pub is not exist" + utility.PrintColor.END) + print(utility.PrintColor.YELLOW + "WARNING: Public key ~/.ssh/id_rsa.pub is not exist" + + utility.PrintColor.END) exit(2) @@ -640,7 +705,8 @@ def remove_configuration(): os.remove(id_rsa_file) else: print( - utility.PrintColor.YELLOW + "WARNING: Private key ~/.ssh/id_rsa is not exist" + utility.PrintColor.END) + utility.PrintColor.YELLOW + "WARNING: Private key ~/.ssh/id_rsa is not exist" + + utility.PrintColor.END) exit(2) # Remove public key file id_rsa_pub_file = os.path.join(ssh_folder, 'id_rsa.pub') @@ -696,7 +762,8 @@ def new_configuration(): id_rsa.write(private_key_str) else: print(utility.PrintColor.YELLOW + "WARNING: Private key ~/.ssh/id_rsa exists" + utility.PrintColor.END) - print('If you want to use the existing key, run "bb config --deploy name_of_machine", otherwise to remove it, ' + print('If you want to use the existing key, run "bb config --deploy name_of_machine", ' + 'otherwise to remove it, ' 'run "bb config --remove"') exit(2) # Create private key file @@ -708,7 +775,8 @@ def new_configuration(): id_rsa_pub.write(public_key_str) else: print(utility.PrintColor.YELLOW + "WARNING: Public key ~/.ssh/id_rsa.pub exists" + utility.PrintColor.END) - print('If you want to use the existing key, run "bb config --deploy name_of_machine", otherwise to remove it, ' + print('If you want to use the existing key, run "bb config --deploy name_of_machine", ' + 'otherwise to remove it, ' 'run "bb config --remove"') exit(2) print(utility.PrintColor.GREEN + "SUCCESS: New configuration successfully created!" + utility.PrintColor.END) @@ -724,13 +792,9 @@ def check_configuration(ip): try: out = check_output(["ssh-keyscan", "{0}".format(ip)]) if not out: - print(utility.PrintColor.RED + - '''ERROR: For bulk or silently backup to deploy configuration! -See bb deploy --help or specify --verbose - ''' + utility.PrintColor.END) + return False except subprocess.CalledProcessError: - print(utility.PrintColor.RED + 'ERROR: Keyscan failed! Check ip {0}'.format(ip) + utility.PrintColor.END) - exit(1) + return False def parse_arguments(): @@ -777,7 +841,7 @@ def parse_arguments(): group_backup.add_argument('--destination', '-d', help='Destination path', dest='destination', action='store', required=True) group_backup.add_argument('--mode', '-m', help='Backup mode', dest='mode', action='store', - choices=['Full', 'Incremental', 'Mirror'], default='Incremental') + choices=['Full', 'Incremental', 'Differential', 'Mirror'], default='Incremental') data_or_custom = group_backup.add_mutually_exclusive_group(required=True) data_or_custom.add_argument('--data', '-D', help='Data of which you want to backup', dest='data', action='store', choices=['User', 'Config', 'Application', 'System', 'Log'], nargs='+') @@ -795,6 +859,7 @@ def parse_arguments(): type=int, default=5) group_backup.add_argument('--timeout', '-T', help='I/O timeout in seconds', dest='timeout', action='store', type=int) + group_backup.add_argument('--skip-error', '-e', help='Skip error', dest='skip_err', action='store_true') # restore session restore = action.add_parser('restore', help='Restore options', parents=[parent_parser]) group_restore = restore.add_argument_group(title='Restore options') @@ -813,6 +878,7 @@ def parse_arguments(): group_restore.add_argument('--timeout', '-T', help='I/O timeout in seconds', dest='timeout', action='store', type=int) group_restore.add_argument('--mirror', '-m', help='Mirror mode', dest='mirror', action='store_true') + group_restore.add_argument('--skip-error', '-e', help='Skip error', dest='skip_err', action='store_true') # archive session archive = action.add_parser('archive', help='Archive options', parents=[parent_parser]) group_archive = archive.add_argument_group(title='Archive options') @@ -827,9 +893,33 @@ def parse_arguments(): group_list = list_action.add_argument_group(title='List options') group_list.add_argument('--catalog', '-C', help='Folder where is catalog file', dest='catalog', action='store', required=True) - group_list.add_argument('--backup-id', '-i', help='Backup-id of backup', dest='id', action='store') - group_list.add_argument('--archived', '-a', help='List only archived backup', dest='archived', action='store_true') - group_list.add_argument('--cleaned', '-c', help='List only cleaned backup', dest='cleaned', action='store_true') + group_list_mutually = group_list.add_mutually_exclusive_group() + group_list_mutually.add_argument('--backup-id', '-i', help='Backup-id of backup', dest='id', action='store') + group_list_mutually.add_argument('--archived', '-a', help='List only archived backup', dest='archived', + action='store_true') + group_list_mutually.add_argument('--cleaned', '-c', help='List only cleaned backup', dest='cleaned', + action='store_true') + group_list_mutually.add_argument('--computer', '-H', help='List only match hostname or ip', dest='hostname', + action='store') + group_list.add_argument('--oneline', '-o', help='One line output', dest='oneline', action='store_true') + # export session + export_action = action.add_parser('export', help='Export options', parents=[parent_parser]) + group_export = export_action.add_argument_group(title='Export options') + group_export.add_argument('--catalog', '-C', help='Folder where is catalog file', dest='catalog', action='store', + required=True) + group_export.add_argument('--backup-id', '-i', help='Backup-id of backup', dest='id', action='store', required=True) + group_export.add_argument('--destination', '-d', help='Destination path', dest='destination', action='store', + required=True) + group_export.add_argument('--mirror', '-m', help='Mirror mode', dest='mirror', action='store_true') + group_export.add_argument('--cut', '-c', help='Cut mode. Delete source', dest='cut', action='store_true') + group_export_mutually = group_export.add_mutually_exclusive_group() + group_export_mutually.add_argument('--include', '-I', help='Include pattern', dest='include', action='store', + nargs='+') + group_export_mutually.add_argument('--exclude', '-E', help='Exclude pattern', dest='exclude', action='store', + nargs='+') + group_export.add_argument('--timeout', '-T', help='I/O timeout in seconds', dest='timeout', action='store', + type=int) + group_export.add_argument('--skip-error', '-e', help='Skip error', dest='skip_err', action='store_true') # Return all args parser_object.add_argument('--version', '-V', help='Print version', dest='version', action='store_true') return parser_object @@ -887,7 +977,10 @@ def parse_arguments(): + utility.PrintColor.END) continue if not args.verbose: - check_configuration(hostname) + if check_configuration(hostname): + print(utility.PrintColor.RED + '''ERROR: For bulk or silently backup to deploy configuration! + See bb deploy --help or specify --verbose''' + utility.PrintColor.END) + continue # Log information's backup_id = '{}'.format(utility.new_id()) log_args = { @@ -983,7 +1076,10 @@ def parse_arguments(): + utility.PrintColor.END) exit(1) if not args.verbose: - check_configuration(rhost) + if not check_configuration(rhost): + print(utility.PrintColor.RED + '''ERROR: For bulk or silently backup to deploy configuration! + See bb deploy --help or specify --verbose''' + utility.PrintColor.END) + exit(1) log_args = { 'hostname': rhost, 'status': args.log, @@ -1034,39 +1130,73 @@ def parse_arguments(): list_catalog = read_catalog(os.path.join(args.catalog, '.catalog.cfg')) # Check specified argument backup-id if args.id: - utility.print_verbose(args.verbose, "Select backup-id: {0}".format(args.id)) - if not list_catalog.has_section(args.id): - print(utility.PrintColor.RED + - 'ERROR: Backup-id {0} not exist!'.format(args.id) - + utility.PrintColor.END) - exit(1) - print('Backup id: ' + utility.PrintColor.BOLD + args.id + - utility.PrintColor.END) - print('Hostname or ip: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['name'] + - utility.PrintColor.END) - print('Type: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['type'] + - utility.PrintColor.END) - print('Timestamp: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['timestamp'] + - utility.PrintColor.END) - print('Start: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['start'] + - utility.PrintColor.END) - print('Finish: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['end'] + - utility.PrintColor.END) - print('OS: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['os'] + - utility.PrintColor.END) - print('ExitCode: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['status'] + - utility.PrintColor.END) - print('Path: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['path'] + - utility.PrintColor.END) - if list_catalog.get(args.id, 'cleaned', fallback=False): - print('Cleaned: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['cleaned'] + + if not args.oneline: + utility.print_verbose(args.verbose, "Select backup-id: {0}".format(args.id)) + if not list_catalog.has_section(args.id): + print(utility.PrintColor.RED + + 'ERROR: Backup-id {0} not exist!'.format(args.id) + + utility.PrintColor.END) + exit(1) + print('Backup id: ' + utility.PrintColor.BOLD + args.id + utility.PrintColor.END) - elif list_catalog.get(args.id, 'archived', fallback=False): - print('Archived: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['archived'] + + print('Hostname or ip: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['name'] + utility.PrintColor.END) - else: - print('List: ' + utility.PrintColor.DARKCYAN + '\n'.join(os.listdir(list_catalog[args.id]['path'])) + + print('Type: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['type'] + + utility.PrintColor.END) + print('Timestamp: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['timestamp'] + + utility.PrintColor.END) + print('Start: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['start'] + + utility.PrintColor.END) + print('Finish: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['end'] + + utility.PrintColor.END) + print('OS: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['os'] + + utility.PrintColor.END) + print('ExitCode: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['status'] + + utility.PrintColor.END) + print('Path: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['path'] + utility.PrintColor.END) + if list_catalog.get(args.id, 'cleaned', fallback=False): + print('Cleaned: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['cleaned'] + + utility.PrintColor.END) + elif list_catalog.get(args.id, 'archived', fallback=False): + print('Archived: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['archived'] + + utility.PrintColor.END) + else: + print('List: ' + utility.PrintColor.DARKCYAN + '\n'.join(os.listdir(list_catalog[args.id]['path'])) + + utility.PrintColor.END) + else: + if not list_catalog.has_section(args.id): + print(utility.PrintColor.RED + + 'ERROR: Backup-id {0} not exist!'.format(args.id) + + utility.PrintColor.END) + exit(1) + print('Id: ' + utility.PrintColor.BOLD + args.id + + utility.PrintColor.END, end=' - ') + print('Name: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['name'] + + utility.PrintColor.END, end=' - ') + print('Type: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['type'] + + utility.PrintColor.END, end=' - ') + print('Timestamp: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['timestamp'] + + utility.PrintColor.END, end=' - ') + print('Start: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['start'] + + utility.PrintColor.END, end=' - ') + print('Finish: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['end'] + + utility.PrintColor.END, end=' - ') + print('OS: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['os'] + + utility.PrintColor.END, end=' - ') + print('ExitCode: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['status'] + + utility.PrintColor.END, end=' - ') + print('Path: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['path'] + + utility.PrintColor.END, end=' - ') + if list_catalog.get(args.id, 'cleaned', fallback=False): + print('Cleaned: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['cleaned'] + + utility.PrintColor.END, end=' - ') + elif list_catalog.get(args.id, 'archived', fallback=False): + print('Archived: ' + utility.PrintColor.DARKCYAN + list_catalog[args.id]['archived'] + + utility.PrintColor.END, end=' - ') + else: + print('List: ' + utility.PrintColor.DARKCYAN + ' '.join(os.listdir(list_catalog[args.id]['path'])) + + utility.PrintColor.END) elif args.archived: utility.print_verbose(args.verbose, "List all archived backup in catalog") text = 'BUTTERFLY BACKUP CATALOG (ARCHIVED)\n\n' @@ -1112,17 +1242,102 @@ def parse_arguments(): text = 'BUTTERFLY BACKUP CATALOG\n\n' utility.write_log(log_args['status'], log_args['destination'], 'INFO', 'BUTTERFLY BACKUP CATALOG') - for lid in list_catalog.sections(): - utility.write_log(log_args['status'], log_args['destination'], 'INFO', - 'Backup id: {0}'.format(lid)) - utility.write_log(log_args['status'], log_args['destination'], 'INFO', - 'Hostname or ip: {0}'.format(list_catalog[lid]['name'])) - utility.write_log(log_args['status'], log_args['destination'], 'INFO', - 'Timestamp: {0}'.format(list_catalog[lid]['timestamp'])) - text += 'Backup id: {0}'.format(lid) - text += '\n' - text += 'Hostname or ip: {0}'.format(list_catalog[lid]['name']) - text += '\n' - text += 'Timestamp: {0}'.format(list_catalog[lid]['timestamp']) - text += '\n\n' + if args.hostname: + for lid in list_catalog.sections(): + if list_catalog[lid]['name'] == args.hostname: + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Backup id: {0}'.format(lid)) + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Hostname or ip: {0}'.format(list_catalog[lid]['name'])) + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Timestamp: {0}'.format(list_catalog[lid]['timestamp'])) + text += 'Backup id: {0}'.format(lid) + text += '\n' + text += 'Hostname or ip: {0}'.format(list_catalog[lid]['name']) + text += '\n' + text += 'Timestamp: {0}'.format(list_catalog[lid]['timestamp']) + text += '\n\n' + else: + for lid in list_catalog.sections(): + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Backup id: {0}'.format(lid)) + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Hostname or ip: {0}'.format(list_catalog[lid]['name'])) + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Timestamp: {0}'.format(list_catalog[lid]['timestamp'])) + text += 'Backup id: {0}'.format(lid) + text += '\n' + text += 'Hostname or ip: {0}'.format(list_catalog[lid]['name']) + text += '\n' + text += 'Timestamp: {0}'.format(list_catalog[lid]['timestamp']) + text += '\n\n' utility.pager(text) + + # Check export session + if args.action == 'export': + cmds = list() + # Read catalog file + export_catalog = read_catalog(os.path.join(args.catalog, '.catalog.cfg')) + # Check specified argument backup-id + if not export_catalog.has_section(args.id): + print(utility.PrintColor.RED + + 'ERROR: Backup-id {0} not exist!'.format(args.id) + + utility.PrintColor.END) + exit(1) + print_verbose(args.verbose, 'Export backup with id {0}'.format(args.id)) + # Log info + log_args = { + 'hostname': export_catalog[args.id]['Name'], + 'status': args.log, + 'destination': os.path.join(export_catalog[args.id]['Path'], 'export.log') + } + if os.path.exists(export_catalog[args.id]['Path']) and os.path.exists(args.destination): + # Export + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Export {0}. Folder {1} to {2}'.format(args.id, export_catalog[args.id]['Path'], + args.destination)) + # Compose command + print_verbose(args.verbose, 'Build a rsync command') + logs = list() + logs.append(log_args) + # Set rsync binary and flags + expcmd = list() + expcmd.append('rsync') + expcmd.append('-ah') + expcmd.append('--no-links') + # Check flags + if args.verbose: + expcmd.append('-vP') + if args.mirror: + expcmd.append('--delete') + if args.cut: + expcmd.append('--remove-source-files') + if args.include: + for include in args.include: + expcmd.append('--include={0}'.format(include)) + expcmd.append('--exclude="*"') + if args.exclude: + for exclude in args.exclude: + expcmd.append('--exclude={0}'.format(exclude)) + if args.timeout: + expcmd.append('--timeout={0}'.format(args.timeout)) + if args.skip_err: + expcmd.append('--quiet') + if args.log: + exp_log_path = os.path.join(args.destination, 'export.log') + expcmd.append( + '--log-file={0}'.format(exp_log_path) + ) + # Add source + expcmd.append('{}'.format(export_catalog[args.id]['Path'])) + # Add destination + expcmd.append('{}'.format(os.path.join(args.destination, export_catalog[args.id]['Name']))) + utility.write_log(log_args['status'], log_args['destination'], 'INFO', + 'Export command {0}.'.format(" ".join(expcmd))) + # Start export + cmds.append(' '.join(expcmd)) + run_in_parallel(start_process, cmds, 1) + else: + print(utility.PrintColor.RED + + "ERROR: Source or destination path doesn't exist!" + utility.PrintColor.END) + exit(1) diff --git a/docs/Makefile b/docs/Makefile old mode 100644 new mode 100755 diff --git a/docs/build/doctrees/backup.doctree b/docs/build/doctrees/backup.doctree old mode 100644 new mode 100755 diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle old mode 100644 new mode 100755 index c3b19a43937eb765a5c72b539b5e0f329ecec093..612f6caef4a909d0d630f1fafbb7a8beefe9c343 GIT binary patch literal 16004 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 literal 8519 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 diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree old mode 100644 new mode 100755 index 24519ed5dc9ef4c977d1e4bd27a5077e9951ff69..5a0f179a4f13683da1eac05334489630692eb5f2 GIT binary patch literal 162278 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 C:\cygwin\etc\passwd + mkpasswd -cl > C:\cygwin\etc\passwd bash ssh-host-config -y cygrunsrv -S sshd @@ -287,10 +289,10 @@ There are two backup modes: single and bulk. Let's see how to go about looking a .. code-block:: bash - arthur@goldenheart$ bb backup --help + arthur@heartofgold$ bb backup --help usage: bb backup [-h] [--verbose] [--log] [--dry-run] (--computer HOSTNAME | --list LIST) --destination DESTINATION - [--mode {Full,Incremental,Mirror}] + [--mode {Full,Incremental,Differential,Mirror}] (--data {User,Config,Application,System,Log} [{User,Config,Application,System,Log} ...] | --custom-data CUSTOMDATA [CUSTOMDATA ...]) [--user USER] --type {Unix,Windows,MacOS} [--compress] [--retention RETENTION] [--parallel PARALLEL] @@ -308,7 +310,7 @@ There are two backup modes: single and bulk. Let's see how to go about looking a --list LIST, -L LIST File list of computers or ip addresses to backup --destination DESTINATION, -d DESTINATION Destination path - --mode {Full,Incremental,Mirror}, -m {Full,Incremental,Mirror} + --mode {Full,Incremental,Differential,Mirror}, -m {Full,Incremental,Differential,Mirror} Backup mode --data {User,Config,Application,System,Log} [{User,Config,Application,System,Log} ...], -D {User,Config,Application,System,Log} [{User,Config,Application,System,Log} ...] Data of which you want to backup @@ -325,6 +327,8 @@ There are two backup modes: single and bulk. Let's see how to go about looking a Number of parallel jobs --timeout TIMEOUT, -T TIMEOUT I/O timeout in seconds + --skip-error, -e Skip error + * **Backup options** @@ -340,13 +344,19 @@ There are two backup modes: single and bulk. Let's see how to go about looking a host2 ... - --destination Select the destination folder (root). + --destination, -d Select the destination folder (root). --mode, -m Select how rsync perform backup: - * Full: Complete (full) backup. - * Incremental: Incremental backup is based on the latest Full (the same files are linked with hard link). + * Full: + Complete (full) backup. + * Incremental: + Incremental backup is based on the latest backup (the same files are linked with hard link). + A Full backup is executed if this mode fails to find one. + * Differential: + Incremental backup is based on the latest Full backup (the same files are linked with hard link). A Full backup is executed if this mode fails to find one. - * Mirror: Complete mirror backup. If a file in the source no longer exists, BB deletes it from the destination. + * Mirror: + Complete mirror backup. If a file in the source no longer exists, BB deletes it from the destination. --data, -D Select the type of data to put under backup: The values change depending on the type of operating system: @@ -366,6 +376,23 @@ There are two backup modes: single and bulk. Let's see how to go about looking a --retention, -r Number of days for which you want to keep your backups. --parallel, -p Maximum number of concurrent rsync processes. By default is 5 jobs. --timeout, -T Specify number of seconds of I/O timeout. + --skip-error, -e Skip error. Quiet mode. + +Flowchart of the differences between Differential and Incremental backup:: + + +----------+ +----------+ +----------+ + | | | | | | + | Full | <-+ Inc. | <-+ Inc. | + | | | | | | + +----------+ +----------+ +----------+ + + +----------+ +----------+ +----------+ + | | | | | | + | Full | <-+ Dif. | | Dif. | + | | | | | | + +----+-----+ +----------+ +----+-----+ + ^ | + +-----------------------------+ .. _backup_computer: @@ -380,7 +407,7 @@ This is a few examples: .. code-block:: bash - arthur@goldenheart$ bb backup --computer host1 --destination /mnt/backup --data User Config --type MacOS + arthur@heartofgold$ bb backup --computer host1 --destination /mnt/backup --data User Config --type MacOS # host1 SSH-2.0-OpenSSH_7.5 # host1 SSH-2.0-OpenSSH_7.5 Start backup on host1 @@ -392,14 +419,14 @@ This is a few examples: .. code-block:: bash - arthur@goldenheart$ bb backup --computer host1 --destination /mnt/backup --mode Full --data User Config --type MacOS --user root + arthur@heartofgold$ bb backup --computer host1 --destination /mnt/backup --mode Full --data User Config --type MacOS --user root "root@host1's password:" Start backup on host1 SUCCESS: Command rsync -ah --no-links root@host1:/Users :/private/etc /mnt/backup/host1/2018_08_08__10_30 .. code-block:: bash - arthur@goldenheart$ bb backup --computer host1 --destination /mnt/backup --data User Config --type MacOS --verbose --log + arthur@heartofgold$ bb backup --computer host1 --destination /mnt/backup --data User Config --type MacOS --verbose --log INFO: Build a rsync command INFO: Last full is 2018-08-08 10:30:32 INFO: Command flags are: rsync -ahu --no-links --link-dest=/mnt/backup/host1/2018_08_08__10_28 -vP @@ -433,7 +460,7 @@ This is a few examples: .. code-block:: bash - arthur@goldenheart$ bb backup --list /home/arthur/pclist.txt --destination /mnt/backup --data User Config --type MacOS + arthur@heartofgold$ bb backup --list /home/arthur/pclist.txt --destination /mnt/backup --data User Config --type MacOS # host1 SSH-2.0-OpenSSH_7.5 # host1 SSH-2.0-OpenSSH_7.5 ERROR: The port 22 on host2 is closed! @@ -452,7 +479,7 @@ This means that maximum two backup jobs will run at the same time. When a first .. code-block:: bash - arthur@goldenheart$ bb backup --list /home/arthur/pclist.txt --destination /mnt/backup --data User Config --type MacOS --parallel 2 --log + arthur@heartofgold$ bb backup --list /home/arthur/pclist.txt --destination /mnt/backup --data User Config --type MacOS --parallel 2 --log # host1 SSH-2.0-OpenSSH_7.5 # host1 SSH-2.0-OpenSSH_7.5 ERROR: The port 22 on host2 is closed! @@ -464,7 +491,7 @@ This is the same example but specifying a retention at 3 (days). This means that .. code-block:: bash - arthur@goldenheart$ bb backup --list /home/arthur/pclist.txt --destination /mnt/backup --data User Config --type MacOS --parallel 2 --retention 3 --log --verbose + arthur@heartofgold$ bb backup --list /home/arthur/pclist.txt --destination /mnt/backup --data User Config --type MacOS --parallel 2 --retention 3 --log --verbose INFO: Build a rsync command INFO: Last full is 2018-08-08 10:30:32 INFO: Command flags are: rsync -ahu --no-links --link-dest=/mnt/backup/host1/2018_08_08__10_30 -vP @@ -504,9 +531,10 @@ To query this catalog, the list command exists. .. code-block:: bash - arthur@goldenheart$ bb list --help + arthur@heartofgold$ bb list --help usage: bb list [-h] [--verbose] [--log] [--dry-run] --catalog CATALOG - [--backup-id ID] [--archived] [--cleaned] + [--backup-id ID | --archived | --cleaned | --computer HOSTNAME] + [--oneline] optional arguments: -h, --help show this help message and exit @@ -521,18 +549,24 @@ To query this catalog, the list command exists. Backup-id of backup --archived, -a List only archived backup --cleaned, -c List only cleaned backup + --computer HOSTNAME, -H HOSTNAME + List only match hostname or ip + --oneline, -o One line output + * **List options** --catalog, -C Select the backups folder (root). --backup-id, -i Select backup id in the catalog. --archived, -a List only archived backups. --cleaned, -c List only cleaned backups. + --computer, -H List only match hostname or ip. + --oneline, -o One line and concise output. First, let's query the catalog: .. code-block:: bash - arthur@goldenheart$ bb list --catalog /mnt/backup + arthur@heartofgold$ bb list --catalog /mnt/backup BUTTERFLY BACKUP CATALOG @@ -552,7 +586,7 @@ Press ``q`` for exit. Then we select a backup-id: .. code-block:: bash - arthur@goldenheart$ bb list --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 + arthur@heartofgold$ bb list --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 Backup id: dd6de2f2-9a1e-11e8-82b0-005056a664e0 Hostname or ip: host1 Type: Incremental @@ -570,8 +604,8 @@ If you want to export the catalog list instead, include the log flag: .. code-block:: bash - arthur@goldenheart$ bb list --catalog /mnt/backup --log - arthur@goldenheart$ cat /mnt/backup/backup.list + arthur@heartofgold$ bb list --catalog /mnt/backup --log + arthur@heartofgold$ cat /mnt/backup/backup.list Now that we have identified a backup, let's proceed with the restore @@ -585,7 +619,7 @@ The restore process is the exact opposite of the backup process. It takes the fi .. code-block:: bash - arthur@goldenheart$ bb restore --help + arthur@heartofgold$ bb restore --help usage: bb restore [-h] [--verbose] [--log] [--dry-run] --catalog CATALOG (--backup-id ID | --last) [--user USER] --computer HOSTNAME [--type {Unix,Windows,MacOS}] [--timeout TIMEOUT] [--mirror] @@ -611,6 +645,7 @@ The restore process is the exact opposite of the backup process. It takes the fi --timeout TIMEOUT, -T TIMEOUT I/O timeout in seconds --mirror, -m Mirror mode + --skip-error, -e Skip error * **Restore options** --catalog, -C Select the backups folder (root). @@ -626,6 +661,8 @@ The restore process is the exact opposite of the backup process. It takes the fi --timeout, -T Specify number of seconds of I/O timeout. --mirror, -m Mirror mode. If a file or folder not exist in destination, will delete it. Overwrite files. + --skip-error, -e Skip error. Quiet mode. + This is a few examples: @@ -633,7 +670,7 @@ This command perform a restore on the same machine of the backup: .. code-block:: bash - arthur@goldenheart$ bb restore --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 --computer host1 --log + arthur@heartofgold$ bb restore --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 --computer host1 --log Want to do restore path /mnt/backup/host1/2018_08_08__10_58/etc? To continue [Y/N]? y Want to do restore path /mnt/backup/host1/2018_08_08__10_58/Users? To continue [Y/N]? y SUCCESS: Command rsync -ahu -vP --log-file=/mnt/backup/host1/2018_08_08__10_58/restore.log /mnt/backup/host1/2018_08_08__10_58/etc arthur@host1:/restore_2018_08_08__10_58 @@ -647,7 +684,7 @@ Now, select the last available backup on catalog; run this: .. code-block:: bash - arthur@goldenheart$ bb restore --catalog /mnt/backup --last --computer host1 --log + arthur@heartofgold$ bb restore --catalog /mnt/backup --last --computer host1 --log Want to do restore path /mnt/backup/host1/2018_08_08__10_58/etc? To continue [Y/N]? y Want to do restore path /mnt/backup/host1/2018_08_08__10_58/Users? To continue [Y/N]? y SUCCESS: Command rsync -ahu -vP --log-file=/mnt/backup/host1/2018_08_08__10_58/restore.log /mnt/backup/host1/2018_08_08__10_58/etc arthur@host1:/restore_2018_08_08__10_59 @@ -657,7 +694,7 @@ This example, is the same as the previous one, but restore to other machine and .. code-block:: bash - arthur@goldenheart$ bb restore --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 --computer host2 --type Unix --log --verbose + arthur@heartofgold$ bb restore --catalog /mnt/backup --backup-id dd6de2f2-9a1e-11e8-82b0-005056a664e0 --computer host2 --type Unix --log --verbose INFO: Build a rsync command INFO: Command flags are: rsync -ahu -vP --log-file=/mnt/backup/host1/2018_08_08__10_58/restore.log Want to do restore path /mnt/backup/host1/2018_08_08__10_58/etc? To continue [Y/N]? y @@ -687,7 +724,7 @@ Archive operations are used to store backups by saving disk space. Backups older .. code-block:: bash - arthur@goldenheart$ bb archive --help + arthur@heartofgold$ bb archive --help usage: bb archive [-h] [--verbose] [--log] [--dry-run] --catalog CATALOG [--days DAYS] --destination DESTINATION @@ -708,20 +745,20 @@ Archive operations are used to store backups by saving disk space. Backups older * **Archive options** --catalog, -C Select the backups folder (root). --days, -D Number of days for which you want to keep your backups. Default is 30. - --destination New destination for compress zipped backup. + --destination, -d New destination for compress zipped backup. Archive old backup of 3 days: .. code-block:: bash - arthur@goldenheart$ bb archive --catalog /mnt/backup/ --days 3 --destination /mnt/archive/ --verbose --log + arthur@heartofgold$ bb archive --catalog /mnt/backup/ --days 3 --destination /mnt/archive/ --verbose --log INFO: Check archive this backup f65e5afe-9734-11e8-b0bb-005056a664e0. Folder /mnt/backup/host2/2018_08_08__17_50 INFO: Check archive this backup 4f2b5f6e-9939-11e8-9ab6-005056a664e0. Folder /mnt/backup/host2/2018_08_04__07_26 SUCCESS: Delete /mnt/backup/host2/2018_08_04__07_26 successfully. SUCCESS: Archive /mnt/backup/host2/2018_08_04__07_26 successfully. - arthur@goldenheart$ ls /mnt/archive + arthur@heartofgold$ ls /mnt/archive host1 - arthur@goldenheart$ ls /mnt/archive/host1 + arthur@heartofgold$ ls /mnt/archive/host1 2018_08_06__07_26.zip The backup-id *f65e5afe-9734-11e8-b0bb-005056a664e0* it is not considered, because it falls within the established time. @@ -731,7 +768,7 @@ Lastly, let's look in the catalog and see that the backup was actually archived: .. code-block:: bash - arthur@goldenheart$ bb list --catalog /mnt/backup/ -i 4f2b5f6e-9939-11e8-9ab6-005056a664e0 + arthur@heartofgold$ bb list --catalog /mnt/backup/ -i 4f2b5f6e-9939-11e8-9ab6-005056a664e0 Backup id: 4f2b5f6e-9939-11e8-9ab6-005056a664e0 Hostname or ip: host2 Type: Incremental @@ -742,3 +779,76 @@ Lastly, let's look in the catalog and see that the backup was actually archived: ExitCode: 0 Path: /mnt/backup/host2/2018_08_04__07_26 Archived: True + +.. _export: + +###### +Export +###### + +The export function is used to copy a particular backup to another path. + +.. code-block:: bash + + arthur@heartofgold$ bb export -h + usage: bb export [-h] [--verbose] [--log] [--dry-run] --catalog CATALOG + --backup-id ID --destination DESTINATION [--mirror] [--cut] + [--include INCLUDE [INCLUDE ...]] + [--exclude EXCLUDE [EXCLUDE ...]] [--timeout TIMEOUT] + [--skip-error] + + optional arguments: + -h, --help show this help message and exit + --verbose, -v Enable verbosity + --log, -l Create a log + --dry-run, -N Dry run mode + + Export options: + --catalog CATALOG, -C CATALOG + Folder where is catalog file + --backup-id ID, -i ID + Backup-id of backup + --destination DESTINATION, -d DESTINATION + Destination path + --mirror, -m Mirror mode + --cut, -c Cut mode. Delete source + --include INCLUDE [INCLUDE ...], -I INCLUDE [INCLUDE ...] + Include pattern + --exclude EXCLUDE [EXCLUDE ...], -E EXCLUDE [EXCLUDE ...] + Exclude pattern + --timeout TIMEOUT, -T TIMEOUT + I/O timeout in seconds + --skip-error, -e Skip error + +* **Export options** + --catalog, -C Select the backups folder (root). + --backup-id, -i Select backup id in the catalog. + --destination, -d Destination path than export a backup. + --mirror, -m Mirror mode. + --cut, -c Cut mode. Delete source. Like a move function. + --include, -I Include pattern. Accept wildcard character. + --exclude, -E Exclude pattern. Accept wildcard character. + --timeout, -T Specify number of seconds of I/O timeout. + --skip-error, -e Skip error. Quiet mode. + +Export a backup in other directory: + +.. code-block:: bash + + arthur@heartofgold$ bb export --catalog /mnt/backup/ --backup-id f0f700e8-0435-11e9-9e78-005056a664e0 --destination /mnt/backup/export --verbose + INFO: Export backup with id f0f700e8-0435-11e9-9e78-005056a664e0 + INFO: Build a rsync command + Start export host1 + INFO: rsync command: rsync -ah --no-links -vP /mnt/backup/host1/2018_12_20__10_02 /mnt/backup/export/host1 + SUCCESS: Command rsync -ah --no-links -vP /mnt/backup/host1/2018_12_20__10_02 /mnt/backup/export/host1 + +Export a backup with exclude pdf files: + +.. code-block:: bash + + arthur@heartofgold$ bb export --catalog /mnt/backup/ --backup-id f0f700e8-0435-11e9-9e78-005056a664e0 --destination /backup/export --verbose --exclude *.pdf + INFO: Export backup with id f0f700e8-0435-11e9-9e78-005056a664e0 + INFO: Build a rsync command + Start export host1 + INFO: rsync command: rsync -ah --no-links -vP --exclude=*.pdf /mnt/backup/host1/2018_12_20__10_02 /mnt/backup/export/host1 + SUCCESS: Command rsync -ah --no-links -vP --exclude=*.pdf /mnt/backup/host1/2018_12_20__10_02 /mnt/backup/export/host1 diff --git a/docs/build/html/_static/ajax-loader.gif b/docs/build/html/_static/ajax-loader.gif old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/alabaster.css b/docs/build/html/_static/alabaster.css old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css old mode 100644 new mode 100755 index 19ced10..104f076 --- a/docs/build/html/_static/basic.css +++ b/docs/build/html/_static/basic.css @@ -81,6 +81,10 @@ div.sphinxsidebar input { font-size: 1em; } +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + div.sphinxsidebar #searchbox input[type="text"] { float: left; width: 80%; @@ -427,6 +431,13 @@ table.field-list td, table.field-list th { hyphens: manual; } +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist td { + vertical-align: top; +} + + /* -- other body styles ----------------------------------------------------- */ ol.arabic { diff --git a/docs/build/html/_static/comment-bright.png b/docs/build/html/_static/comment-bright.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/comment-close.png b/docs/build/html/_static/comment-close.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/comment.png b/docs/build/html/_static/comment.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/custom.css b/docs/build/html/_static/custom.css old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js old mode 100644 new mode 100755 index d892892..ffadbec --- a/docs/build/html/_static/doctools.js +++ b/docs/build/html/_static/doctools.js @@ -150,7 +150,9 @@ var Documentation = { this.fixFirefoxAnchorBug(); this.highlightSearchWords(); this.initIndexTable(); - + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } }, /** @@ -310,4 +312,4 @@ _ = Documentation.gettext; $(document).ready(function() { Documentation.init(); -}); \ No newline at end of file +}); diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js old mode 100644 new mode 100755 index 87ce200..b81190b --- a/docs/build/html/_static/documentation_options.js +++ b/docs/build/html/_static/documentation_options.js @@ -5,5 +5,292 @@ var DOCUMENTATION_OPTIONS = { COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt' -}; \ No newline at end of file + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SEARCH_LANGUAGE_STOP_WORDS: ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"] +}; + + + +/* Non-minified version JS is _stemmer.js if file is provided */ +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + + + + + +var splitChars = (function() { + var result = {}; + var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, + 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, + 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, + 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, + 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, + 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, + 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, + 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, + 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, + 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; + var i, j, start, end; + for (i = 0; i < singles.length; i++) { + result[singles[i]] = true; + } + var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], + [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], + [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], + [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], + [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], + [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], + [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], + [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], + [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], + [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], + [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], + [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], + [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], + [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], + [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], + [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], + [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], + [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], + [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], + [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], + [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], + [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], + [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], + [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], + [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], + [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], + [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], + [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], + [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], + [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], + [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], + [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], + [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], + [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], + [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], + [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], + [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], + [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], + [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], + [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], + [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], + [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], + [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], + [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], + [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], + [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], + [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], + [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], + [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; + for (i = 0; i < ranges.length; i++) { + start = ranges[i][0]; + end = ranges[i][1]; + for (j = start; j <= end; j++) { + result[j] = true; + } + } + return result; +})(); + +function splitQuery(query) { + var result = []; + var start = -1; + for (var i = 0; i < query.length; i++) { + if (splitChars[query.charCodeAt(i)]) { + if (start !== -1) { + result.push(query.slice(start, i)); + start = -1; + } + } else if (start === -1) { + start = i; + } + } + if (start !== -1) { + result.push(query.slice(start)); + } + return result; +} + + diff --git a/docs/build/html/_static/down-pressed.png b/docs/build/html/_static/down-pressed.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/down.png b/docs/build/html/_static/down.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/jquery-3.2.1.js b/docs/build/html/_static/jquery-3.2.1.js old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/jquery.js b/docs/build/html/_static/jquery.js old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/minus.png b/docs/build/html/_static/minus.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/plus.png b/docs/build/html/_static/plus.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/pygments.css b/docs/build/html/_static/pygments.css old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/searchtools.js b/docs/build/html/_static/searchtools.js old mode 100644 new mode 100755 index 41b8336..7473859 --- a/docs/build/html/_static/searchtools.js +++ b/docs/build/html/_static/searchtools.js @@ -1,5 +1,5 @@ /* - * searchtools.js_t + * searchtools.js * ~~~~~~~~~~~~~~~~ * * Sphinx JavaScript utilities for the full-text search. @@ -9,323 +9,44 @@ * */ - -/* Non-minified version JS is _stemmer.js if file is provided */ -/** - * Porter Stemmer - */ -var Stemmer = function() { - - var step2list = { - ational: 'ate', - tional: 'tion', - enci: 'ence', - anci: 'ance', - izer: 'ize', - bli: 'ble', - alli: 'al', - entli: 'ent', - eli: 'e', - ousli: 'ous', - ization: 'ize', - ation: 'ate', - ator: 'ate', - alism: 'al', - iveness: 'ive', - fulness: 'ful', - ousness: 'ous', - aliti: 'al', - iviti: 'ive', - biliti: 'ble', - logi: 'log' - }; - - var step3list = { - icate: 'ic', - ative: '', - alize: 'al', - iciti: 'ic', - ical: 'ic', - ful: '', - ness: '' +if (!Scorer) { + /** + * Simple result scoring code. + */ + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [filename, title, anchor, descr, score] + // and returns the new score. + /* + score: function(result) { + return result[4]; + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: {0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5}, // used to be unimportantResults + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + // query found in terms + term: 5 }; - - var c = "[^aeiou]"; // consonant - var v = "[aeiouy]"; // vowel - var C = c + "[^aeiouy]*"; // consonant sequence - var V = v + "[aeiou]*"; // vowel sequence - - var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 - var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 - var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 - var s_v = "^(" + C + ")?" + v; // vowel in stem - - this.stemWord = function (w) { - var stem; - var suffix; - var firstch; - var origword = w; - - if (w.length < 3) - return w; - - var re; - var re2; - var re3; - var re4; - - firstch = w.substr(0,1); - if (firstch == "y") - w = firstch.toUpperCase() + w.substr(1); - - // Step 1a - re = /^(.+?)(ss|i)es$/; - re2 = /^(.+?)([^s])s$/; - - if (re.test(w)) - w = w.replace(re,"$1$2"); - else if (re2.test(w)) - w = w.replace(re2,"$1$2"); - - // Step 1b - re = /^(.+?)eed$/; - re2 = /^(.+?)(ed|ing)$/; - if (re.test(w)) { - var fp = re.exec(w); - re = new RegExp(mgr0); - if (re.test(fp[1])) { - re = /.$/; - w = w.replace(re,""); - } - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1]; - re2 = new RegExp(s_v); - if (re2.test(stem)) { - w = stem; - re2 = /(at|bl|iz)$/; - re3 = new RegExp("([^aeiouylsz])\\1$"); - re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re2.test(w)) - w = w + "e"; - else if (re3.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - else if (re4.test(w)) - w = w + "e"; - } - } - - // Step 1c - re = /^(.+?)y$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(s_v); - if (re.test(stem)) - w = stem + "i"; - } - - // Step 2 - re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step2list[suffix]; - } - - // Step 3 - re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - suffix = fp[2]; - re = new RegExp(mgr0); - if (re.test(stem)) - w = stem + step3list[suffix]; - } - - // Step 4 - re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; - re2 = /^(.+?)(s|t)(ion)$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - if (re.test(stem)) - w = stem; - } - else if (re2.test(w)) { - var fp = re2.exec(w); - stem = fp[1] + fp[2]; - re2 = new RegExp(mgr1); - if (re2.test(stem)) - w = stem; - } - - // Step 5 - re = /^(.+?)e$/; - if (re.test(w)) { - var fp = re.exec(w); - stem = fp[1]; - re = new RegExp(mgr1); - re2 = new RegExp(meq1); - re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); - if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) - w = stem; - } - re = /ll$/; - re2 = new RegExp(mgr1); - if (re.test(w) && re2.test(w)) { - re = /.$/; - w = w.replace(re,""); - } - - // and turn initial Y back to y - if (firstch == "y") - w = firstch.toLowerCase() + w.substr(1); - return w; - } } - - -/** - * Simple result scoring code. - */ -var Scorer = { - // Implement the following function to further tweak the score for each result - // The function takes a result array [filename, title, anchor, descr, score] - // and returns the new score. - /* - score: function(result) { - return result[4]; - }, - */ - - // query matches the full name of an object - objNameMatch: 11, - // or matches in the last dotted part of the object name - objPartialMatch: 6, - // Additive scores depending on the priority of the object - objPrio: {0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5}, // used to be unimportantResults - // Used when the priority is not in the mapping. - objPrioDefault: 0, - - // query found in title - title: 15, - // query found in terms - term: 5 -}; - - - - - -var splitChars = (function() { - var result = {}; - var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648, - 1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702, - 2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971, - 2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345, - 3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761, - 3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823, - 4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125, - 8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695, - 11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587, - 43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141]; - var i, j, start, end; - for (i = 0; i < singles.length; i++) { - result[singles[i]] = true; - } - var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709], - [722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161], - [1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568], - [1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807], - [1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047], - [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383], - [2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450], - [2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547], - [2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673], - [2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820], - [2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946], - [2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023], - [3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173], - [3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332], - [3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481], - [3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718], - [3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791], - [3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095], - [4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205], - [4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687], - [4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968], - [4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869], - [5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102], - [6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271], - [6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592], - [6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822], - [6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167], - [7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959], - [7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143], - [8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318], - [8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483], - [8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101], - [10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567], - [11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292], - [12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444], - [12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783], - [12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311], - [19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511], - [42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774], - [42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071], - [43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263], - [43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519], - [43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647], - [43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967], - [44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295], - [57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274], - [64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007], - [65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381], - [65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]]; - for (i = 0; i < ranges.length; i++) { - start = ranges[i][0]; - end = ranges[i][1]; - for (j = start; j <= end; j++) { - result[j] = true; - } - } - return result; -})(); - -function splitQuery(query) { - var result = []; - var start = -1; - for (var i = 0; i < query.length; i++) { - if (splitChars[query.charCodeAt(i)]) { - if (start !== -1) { - result.push(query.slice(start, i)); - start = -1; - } - } else if (start === -1) { - start = i; - } - } - if (start !== -1) { - result.push(query.slice(start)); - } - return result; +if (!splitQuery) { + function splitQuery(query) { + return query.split(/\s+/); + } } - - - /** * Search Module */ @@ -417,7 +138,7 @@ var Search = { */ query : function(query) { var i; - var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"]; + var stopwords = DOCUMENTATION_OPTIONS.SEARCH_LANGUAGE_STOP_WORDS; // stem the searchterms and add them to the correct list var stemmer = new Stemmer(); @@ -758,4 +479,4 @@ var Search = { $(document).ready(function() { Search.init(); -}); \ No newline at end of file +}); diff --git a/docs/build/html/_static/underscore-1.3.1.js b/docs/build/html/_static/underscore-1.3.1.js old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/underscore.js b/docs/build/html/_static/underscore.js old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/up-pressed.png b/docs/build/html/_static/up-pressed.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/up.png b/docs/build/html/_static/up.png old mode 100644 new mode 100755 diff --git a/docs/build/html/_static/websupport.js b/docs/build/html/_static/websupport.js old mode 100644 new mode 100755 diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html old mode 100644 new mode 100755 index 7fe4e12..cdc858b --- a/docs/build/html/genindex.html +++ b/docs/build/html/genindex.html @@ -25,8 +25,7 @@ - - + @@ -158,7 +157,7 @@

Index

- © Copyright 2018, Matteo Guadrini <matteo.guadrini@hotmail.it>. + © Copyright 2018, Matteo Guadrini <matteo.guadrini@hotmail.it>

@@ -177,27 +176,17 @@

Index

- - - - + + + + + + + - - - - + - - - + + + + + + + - - - - + - - - - + + + + + + + + - - - - +