Merge remote-tracking branch 'qubesos/pr/44'

* qubesos/pr/44:
  Revise help and stderr messages
  Revise help and stderr messages
This commit is contained in:
Marek Marczykowski-Górecki 2016-07-16 18:10:17 +02:00
commit b3fb8ab59b
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 109 additions and 70 deletions

View File

@ -41,39 +41,41 @@ def main():
parser.add_option ("-x", "--exclude", action="append", parser.add_option ("-x", "--exclude", action="append",
dest="exclude_list", default=[], dest="exclude_list", default=[],
help="Exclude the specified VM from backup (may be " help="Exclude the specified VM from the backup (may be "
"repeated)") "repeated)")
parser.add_option ("--force-root", action="store_true", dest="force_root", default=False, parser.add_option ("--force-root", action="store_true", dest="force_root", default=False,
help="Force to run, even with root privileges") help="Force to run with root privileges")
parser.add_option ("-d", "--dest-vm", action="store", dest="appvm", parser.add_option ("-d", "--dest-vm", action="store", dest="appvm",
help="The AppVM to send backups to (implies -e)") help="Specify the destination VM to which the backup "
"will be sent (implies -e)")
parser.add_option ("-e", "--encrypt", action="store_true", dest="encrypt", default=False, parser.add_option ("-e", "--encrypt", action="store_true", dest="encrypt", default=False,
help="Encrypts the backup") help="Encrypt the backup")
parser.add_option ("--no-encrypt", action="store_true", parser.add_option ("--no-encrypt", action="store_true",
dest="no_encrypt", default=False, dest="no_encrypt", default=False,
help="Skip encryption even if sending the backup to VM") help="Skip encryption even if sending the backup to a "
"VM")
parser.add_option ("-p", "--passphrase-file", action="store", parser.add_option ("-p", "--passphrase-file", action="store",
dest="pass_file", default=None, dest="pass_file", default=None,
help="File containing the pass phrase to use, or '-' " help="Read passphrase from a file, or use '-' to read "
"to read it from stdin") "from stdin")
parser.add_option ("-E", "--enc-algo", action="store", parser.add_option ("-E", "--enc-algo", action="store",
dest="crypto_algorithm", default=None, dest="crypto_algorithm", default=None,
help="Specify non-default encryption algorithm. For " help="Specify a non-default encryption algorithm. For a "
"list of supported algos execute 'openssl " "list of supported algorithms, execute 'openssl "
"list-cipher-algorithms' (implies -e)") "list-cipher-algorithms' (implies -e)")
parser.add_option ("-H", "--hmac-algo", action="store", parser.add_option ("-H", "--hmac-algo", action="store",
dest="hmac_algorithm", default=None, dest="hmac_algorithm", default=None,
help="Specify non-default hmac algorithm. For list of " help="Specify a non-default HMAC algorithm. For a list "
"supported algos execute 'openssl " "of supported algorithms, execute 'openssl "
"list-message-digest-algorithms'") "list-message-digest-algorithms'")
parser.add_option ("-z", "--compress", action="store_true", dest="compress", default=False, parser.add_option ("-z", "--compress", action="store_true", dest="compress", default=False,
help="Compress the backup") help="Compress the backup")
parser.add_option ("-Z", "--compress-filter", action="store", parser.add_option ("-Z", "--compress-filter", action="store",
dest="compress_filter", default=False, dest="compress_filter", default=False,
help="Compress the backup using specified filter " help="Specify a non-default compression filter program "
"program (default: gzip)") "(default: gzip)")
parser.add_option("--tmpdir", action="store", dest="tmpdir", default=None, parser.add_option("--tmpdir", action="store", dest="tmpdir", default=None,
help="Custom temporary directory (if you have at least " help="Specify a temporary directory (if you have at least "
"1GB free RAM in dom0, use of /tmp is advised) (" "1GB free RAM in dom0, use of /tmp is advised) ("
"default: /var/tmp)") "default: /var/tmp)")
parser.add_option ("--debug", action="store_true", dest="debug", parser.add_option ("--debug", action="store_true", dest="debug",
@ -82,17 +84,21 @@ def main():
(options, args) = parser.parse_args () (options, args) = parser.parse_args ()
if (len (args) < 1): if (len (args) < 1):
print >> sys.stderr, "You must specify the target backup directory (e.g. /mnt/backup)" print >> sys.stderr, "You must specify the target backup directory "\
print >> sys.stderr, "qvm-backup will create a subdirectory there for each individual backup." " (e.g. /mnt/backup)."
print >> sys.stderr, "qvm-backup will create a subdirectory there for "\
" each individual backup."
exit (0) exit (0)
base_backup_dir = args[0] base_backup_dir = args[0]
if hasattr(os, "geteuid") and os.geteuid() == 0: if hasattr(os, "geteuid") and os.geteuid() == 0:
if not options.force_root: if not options.force_root:
print >> sys.stderr, "*** Running this tool as root is strongly discouraged, this will lead you in permissions problems." print >> sys.stderr, "*** Running this tool as root is strongly "\
print >> sys.stderr, "Retry as unprivileged user." "discouraged. This will lead to permissions "\
print >> sys.stderr, "... or use --force-root to continue anyway." "problems."
print >> sys.stderr, "Retry as an unprivileged user, or use "\
"--force-root to continue anyway."
exit(1) exit(1)
# Only for locking # Only for locking
@ -136,14 +142,15 @@ def main():
backup_fs_free_sz = stat.f_bsize * stat.f_bavail backup_fs_free_sz = stat.f_bsize * stat.f_bavail
print print
if (total_backup_sz > backup_fs_free_sz): if (total_backup_sz > backup_fs_free_sz):
print >>sys.stderr, "ERROR: Not enough space available on the backup filesystem!" print >>sys.stderr, "ERROR: Not enough space available on the "\
"backup filesystem!"
exit(1) exit(1)
print "-> Available space: {0}".format(size_to_human(backup_fs_free_sz)) print "-> Available space: {0}".format(size_to_human(backup_fs_free_sz))
else: else:
appvm = qvm_collection.get_vm_by_name(options.appvm) appvm = qvm_collection.get_vm_by_name(options.appvm)
if appvm is None: if appvm is None:
print >>sys.stderr, "ERROR: VM {0} does not exist".format(options.appvm) print >>sys.stderr, "ERROR: VM {0} does not exist!".format(options.appvm)
exit(1) exit(1)
stat = os.statvfs('/var/tmp') stat = os.statvfs('/var/tmp')
@ -151,19 +158,19 @@ def main():
print print
if (backup_fs_free_sz < 1000000000): if (backup_fs_free_sz < 1000000000):
print >>sys.stderr, "ERROR: Not enough space available " \ print >>sys.stderr, "ERROR: Not enough space available " \
"on the local filesystem (needs 1GB for temporary files)!" "on the local filesystem (1GB required for temporary files)!"
exit(1) exit(1)
if not appvm.is_running(): if not appvm.is_running():
appvm.start(verbose=True) appvm.start(verbose=True)
if options.appvm: if options.appvm:
print >>sys.stderr, ("WARNING: VM {} excluded because it's used to " print >>sys.stderr, ("NOTE: VM {} will be excluded because it is "
"store the backup.").format(options.appvm) "the backup destination.").format(options.appvm)
options.exclude_list.append(options.appvm) options.exclude_list.append(options.appvm)
if not options.encrypt: if not options.encrypt:
print >>sys.stderr, "WARNING: encryption will not be used" print >>sys.stderr, "WARNING: The backup will NOT be encrypted!"
if options.pass_file is not None: if options.pass_file is not None:
f = open(options.pass_file) if options.pass_file != "-" else sys.stdin f = open(options.pass_file) if options.pass_file != "-" else sys.stdin
@ -175,12 +182,12 @@ def main():
if raw_input("Do you want to proceed? [y/N] ").upper() != "Y": if raw_input("Do you want to proceed? [y/N] ").upper() != "Y":
exit(0) exit(0)
s = ("Please enter the pass phrase that will be used to {}verify " s = ("Please enter the passphrase that will be used to {}verify "
"the backup: ").format('encrypt and ' if options.encrypt else '') "the backup: ").format('encrypt and ' if options.encrypt else '')
passphrase = getpass.getpass(s) passphrase = getpass.getpass(s)
if getpass.getpass("Enter again for verification: ") != passphrase: if getpass.getpass("Enter again for verification: ") != passphrase:
print >>sys.stderr, "ERROR: Password mismatch" print >>sys.stderr, "ERROR: Passphrase mismatch!"
exit(1) exit(1)
encoding = sys.stdin.encoding or getpreferredencoding() encoding = sys.stdin.encoding or getpreferredencoding()

View File

@ -43,27 +43,31 @@ def main():
parser.add_option ("--verify-only", action="store_true", parser.add_option ("--verify-only", action="store_true",
dest="verify_only", default=False, dest="verify_only", default=False,
help="Do not restore the data, only verify backup " help="Verify backup integrity without restoring any "
"integrify.") "data")
parser.add_option ("--skip-broken", action="store_true", dest="skip_broken", default=False, parser.add_option ("--skip-broken", action="store_true", dest="skip_broken", default=False,
help="Do not restore VMs that have missing templates or netvms") help="Do not restore VMs that have missing TemplateVMs "
"or NetVMs")
parser.add_option ("--ignore-missing", action="store_true", dest="ignore_missing", default=False, parser.add_option ("--ignore-missing", action="store_true", dest="ignore_missing", default=False,
help="Ignore missing templates or netvms, restore VMs anyway") help="Restore VMs even if their associated TemplateVMs "
"and NetVMs are missing")
parser.add_option ("--skip-conflicting", action="store_true", dest="skip_conflicting", default=False, parser.add_option ("--skip-conflicting", action="store_true", dest="skip_conflicting", default=False,
help="Do not restore VMs that are already present on the host") help="Do not restore VMs that are already present on "
"the host")
parser.add_option ("--rename-conflicting", action="store_true", parser.add_option ("--rename-conflicting", action="store_true",
dest="rename_conflicting", default=False, dest="rename_conflicting", default=False,
help="Restore VMs that are already present on the host under different name") help="Restore VMs that are already present on the host "
"under different names")
parser.add_option ("--force-root", action="store_true", dest="force_root", default=False, parser.add_option ("--force-root", action="store_true", dest="force_root", default=False,
help="Force to run, even with root privileges") help="Force to run with root privileges")
parser.add_option ("--replace-template", action="append", dest="replace_template", default=[], parser.add_option ("--replace-template", action="append", dest="replace_template", default=[],
help="Restore VMs using another template, syntax: " help="Restore VMs using another TemplateVM; syntax: "
"old-template-name:new-template-name (may be " "old-template-name:new-template-name (may be "
"repeated)") "repeated)")
@ -71,20 +75,21 @@ def main():
help="Skip restore of specified VM (may be repeated)") help="Skip restore of specified VM (may be repeated)")
parser.add_option ("--skip-dom0-home", action="store_false", dest="dom0_home", default=True, parser.add_option ("--skip-dom0-home", action="store_false", dest="dom0_home", default=True,
help="Do not restore dom0 user home dir") help="Do not restore dom0 user home directory")
parser.add_option ("--ignore-username-mismatch", action="store_true", dest="ignore_username_mismatch", default=False, parser.add_option ("--ignore-username-mismatch", action="store_true", dest="ignore_username_mismatch", default=False,
help="Ignore dom0 username mismatch while restoring homedir") help="Ignore dom0 username mismatch when restoring home "
"directory")
parser.add_option ("-d", "--dest-vm", action="store", dest="appvm", parser.add_option ("-d", "--dest-vm", action="store", dest="appvm",
help="The AppVM to send backups to") help="Specify VM containing the backup to be restored")
parser.add_option ("-e", "--encrypted", action="store_true", dest="decrypt", default=False, parser.add_option ("-e", "--encrypted", action="store_true", dest="decrypt", default=False,
help="The backup is encrypted") help="The backup is encrypted")
parser.add_option ("-p", "--passphrase-file", action="store", parser.add_option ("-p", "--passphrase-file", action="store",
dest="pass_file", default=None, dest="pass_file", default=None,
help="File containing the pass phrase to use, or '-' to read it from stdin") help="Read passphrase from file, or use '-' to read from stdin")
parser.add_option ("-z", "--compressed", action="store_true", dest="compressed", default=False, parser.add_option ("-z", "--compressed", action="store_true", dest="compressed", default=False,
help="The backup is compressed") help="The backup is compressed")
@ -95,7 +100,8 @@ def main():
(options, args) = parser.parse_args () (options, args) = parser.parse_args ()
if (len (args) < 1): if (len (args) < 1):
print >> sys.stderr, "You must specify the backup directory (e.g. /mnt/backup/qubes-2010-12-01-235959)" print >> sys.stderr, "You must specify the backup directory "\
"(e.g. /mnt/backup/qubes-2010-12-01-235959)"
exit (0) exit (0)
backup_dir = args[0] backup_dir = args[0]
@ -141,7 +147,8 @@ def main():
if f is not sys.stdin: if f is not sys.stdin:
f.close() f.close()
else: else:
passphrase = getpass.getpass("Please enter the pass phrase to decrypt/verify the backup: ") passphrase = getpass.getpass("Please enter the passphrase to verify "
"and (if encrypted) decrypt the backup: ")
encoding = sys.stdin.encoding or getpreferredencoding() encoding = sys.stdin.encoding or getpreferredencoding()
passphrase = passphrase.decode(encoding) passphrase = passphrase.decode(encoding)
@ -197,67 +204,92 @@ def main():
print print
if hasattr(os, "geteuid") and os.geteuid() == 0: if hasattr(os, "geteuid") and os.geteuid() == 0:
print >> sys.stderr, "*** Running this tool as root is strongly discouraged, this will lead you in permissions problems." print >> sys.stderr, "*** Running this tool as root is strongly "\
"discouraged. This will lead to permissions "\
"problems."
if options.force_root: if options.force_root:
print >> sys.stderr, "Continuing as commanded. You have been warned." print >> sys.stderr, "Continuing as commanded. You have been "\
"warned."
else: else:
print >> sys.stderr, "Retry as unprivileged user." print >> sys.stderr, "Retry as an unprivileged user, or use "\
print >> sys.stderr, "... or use --force-root to continue anyway." "--force-root to continue anyway."
exit(1) exit(1)
if there_are_conflicting_vms: if there_are_conflicting_vms:
print >> sys.stderr, "*** There VMs with conflicting names on the host! ***" print >> sys.stderr, "*** There are VMs with conflicting names on the "\
"host! ***"
if options.skip_conflicting: if options.skip_conflicting:
print >> sys.stderr, "Those VMs will not be restored, the host VMs will not be overwritten!" print >> sys.stderr, "Those VMs will not be restored. The host "\
"VMs will NOT be overwritten."
else: else:
print >> sys.stderr, "Remove VMs with conflicting names from the host before proceeding." print >> sys.stderr, "Remove VMs with conflicting names from the "\
print >> sys.stderr, "... or use --skip-conflicting to restore only those VMs that do not exist on the host." "host before proceeding."
print >> sys.stderr, "... or use --rename-conflicting to " \ print >> sys.stderr, "Or use --skip-conflicting to restore only "\
"restore those VMs under modified " \ "those VMs that do not exist on the host."
"name (with number at the end)" print >> sys.stderr, "Or use --rename-conflicting to restore " \
"those VMs under modified names (with "\
"numbers at the end)."
exit (1) exit (1)
print "The above VMs will be copied and added to your system." print "The above VMs will be copied and added to your system."
print "Exisiting VMs will not be removed." print "Exisiting VMs will NOT be removed."
if there_are_missing_templates: if there_are_missing_templates:
print >> sys.stderr, "*** One or more template VM is missing on the host! ***" print >> sys.stderr, "*** One or more TemplateVMs are missing on the"\
"host! ***"
if not (options.skip_broken or options.ignore_missing): if not (options.skip_broken or options.ignore_missing):
print >> sys.stderr, "Install it first, before proceeding with backup restore." print >> sys.stderr, "Install them before proceeding with the "\
print >> sys.stderr, "Or pass: --skip-broken or --ignore-missing switch." "restore."
print >> sys.stderr, "Or pass: --skip-broken or --ignore-missing."
exit (1) exit (1)
elif options.skip_broken: elif options.skip_broken:
print >> sys.stderr, "... VMs that depend on it will not be restored (--skip-broken used)" print >> sys.stderr, "Skipping broken entries: VMs that depend on "\
"missing TemplateVMs will NOT be restored."
elif options.ignore_missing: elif options.ignore_missing:
print >> sys.stderr, "... VMs that depend on it will be restored anyway (--ignore-missing used)" print >> sys.stderr, "Ignoring missing entries: VMs that depend "\
"on missing TemplateVMs will NOT be restored."
else: else:
print >> sys.stderr, "INTERNAL ERROR?!" print >> sys.stderr, "INTERNAL ERROR! Please report this to the "\
"Qubes OS team!"
exit (1) exit (1)
if there_are_missing_netvms: if there_are_missing_netvms:
print >> sys.stderr, "*** One or more network VM is missing on the host! ***" print >> sys.stderr, "*** One or more NetVMs are missing on the "\
"host! ***"
if not (options.skip_broken or options.ignore_missing): if not (options.skip_broken or options.ignore_missing):
print >> sys.stderr, "Install it first, before proceeding with backup restore." print >> sys.stderr, "Install them before proceeding with the "\
print >> sys.stderr, "Or pass: --skip_broken or --ignore_missing switch." "restore."
print >> sys.stderr, "Or pass: --skip-broken or --ignore-missing."
exit (1) exit (1)
elif options.skip_broken: elif options.skip_broken:
print >> sys.stderr, "... VMs that depend on it will not be restored (--skip-broken used)" print >> sys.stderr, "Skipping broken entries: VMs that depend on "\
"missing NetVMs will NOT be restored."
elif options.ignore_missing: elif options.ignore_missing:
print >> sys.stderr, "... VMs that depend on it be restored anyway (--ignore-missing used)" print >> sys.stderr, "Ignoring missing entries: VMs that depend "\
"on missing NetVMs will NOT be restored."
else: else:
print >> sys.stderr, "INTERNAL ERROR?!" print >> sys.stderr, "INTERNAL ERROR! Please report this to the "\
"Qubes OS team!"
exit (1) exit (1)
if 'dom0' in restore_info.keys() and options.dom0_home: if 'dom0' in restore_info.keys() and options.dom0_home:
if dom0_username_mismatch: if dom0_username_mismatch:
print >> sys.stderr, "*** Dom0 username mismatch! This can break some settings ***" print >> sys.stderr, "*** Dom0 username mismatch! This can break "\
"some settings! ***"
if not options.ignore_username_mismatch: if not options.ignore_username_mismatch:
print >> sys.stderr, "Skip dom0 home restore (--skip-dom0-home)" print >> sys.stderr, "Skip restoring the dom0 home directory "\
print >> sys.stderr, "Or pass: --ignore-username-mismatch to continue anyway" "(--skip-dom0-home), or pass "\
"--ignore-username-mismatch to continue "\
"anyway."
exit(1) exit(1)
else: else:
print >> sys.stderr, "Continuing as directed" print >> sys.stderr, "Continuing as directed."
print >> sys.stderr, "While restoring user homedir, existing files/dirs will be backed up in 'home-pre-restore-<current-time>' dir" print >> sys.stderr, "NOTE: Before restoring the dom0 home directory, "
"a new directory named "\
"'home-pre-restore-<current-time>' will be "\
"created inside the dom0 home directory, and "\
"all the other existing contents of the dom0 "\
"home directory will be moved there."
if options.pass_file is None: if options.pass_file is None:
if raw_input("Do you want to proceed? [y/N] ").upper() != "Y": if raw_input("Do you want to proceed? [y/N] ").upper() != "Y":