Remove qvm-backup tool
The tool itself should live in qubes-core-admin-client and communicate with actual backup code over Admin API.
This commit is contained in:
parent
2ace5901df
commit
7f85d81197
@ -1,183 +0,0 @@
|
||||
#
|
||||
# The Qubes OS Project, http://www.qubes-os.org
|
||||
#
|
||||
# Copyright (C) 2016 Marek Marczykowski-Górecki
|
||||
# <marmarek@invisiblethingslab.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from __future__ import print_function
|
||||
import getpass
|
||||
import locale
|
||||
import os
|
||||
|
||||
import sys
|
||||
|
||||
import qubes.backup
|
||||
import qubes.tools
|
||||
import qubes.utils
|
||||
|
||||
parser = qubes.tools.QubesArgumentParser(want_force_root=True)
|
||||
|
||||
parser.add_argument("--exclude", "-x", action="append",
|
||||
dest="exclude_list", default=[],
|
||||
help="Exclude the specified VM from the backup (may be "
|
||||
"repeated)")
|
||||
parser.add_argument("--dest-vm", "-d", action="store",
|
||||
dest="appvm", default=None,
|
||||
help="Specify the destination VM to which the backup "
|
||||
"will be sent (implies -e)")
|
||||
parser.add_argument("--encrypt", "-e", action="store_true", dest="encrypted",
|
||||
default=False,
|
||||
help="Encrypt the backup")
|
||||
parser.add_argument("--no-encrypt", action="store_true",
|
||||
dest="no_encrypt", default=False,
|
||||
help="Skip encryption even if sending the backup to a "
|
||||
"VM")
|
||||
parser.add_argument("--passphrase-file", "-p", action="store",
|
||||
dest="pass_file", default=None,
|
||||
help="Read passphrase from a file, or use '-' to read "
|
||||
"from stdin")
|
||||
parser.add_argument("--enc-algo", "-E", action="store",
|
||||
dest="crypto_algorithm", default=None,
|
||||
help="Specify a non-default encryption algorithm. For a "
|
||||
"list of supported algorithms, execute 'openssl "
|
||||
"list-cipher-algorithms' (implies -e)")
|
||||
parser.add_argument("--hmac-algo", "-H", action="store",
|
||||
dest="hmac_algorithm", default=None,
|
||||
help="Specify a non-default HMAC algorithm. For a list "
|
||||
"of supported algorithms, execute 'openssl "
|
||||
"list-message-digest-algorithms'")
|
||||
parser.add_argument("--compress", "-z", action="store_true", dest="compressed",
|
||||
default=False,
|
||||
help="Compress the backup")
|
||||
parser.add_argument("--compress-filter", "-Z", action="store",
|
||||
dest="compression_filter", default=False,
|
||||
help="Specify a non-default compression filter program "
|
||||
"(default: gzip)")
|
||||
parser.add_argument("--tmpdir", action="store", dest="tmpdir", default=None,
|
||||
help="Specify a temporary directory (if you have at least "
|
||||
"1GB free RAM in dom0, use of /tmp is advised) ("
|
||||
"default: /var/tmp)")
|
||||
|
||||
parser.add_argument("backup_location", action="store",
|
||||
help="Backup location (directory path, or command to pipe backup to)")
|
||||
|
||||
parser.add_argument("vms", nargs="*", action=qubes.tools.VmNameAction,
|
||||
help="Backup only those VMs")
|
||||
|
||||
|
||||
def main(args=None):
|
||||
args = parser.parse_args(args)
|
||||
|
||||
appvm = None
|
||||
if args.appvm:
|
||||
try:
|
||||
appvm = args.app.domains[args.appvm]
|
||||
except KeyError:
|
||||
parser.error('no such domain: {!r}'.format(args.appvm))
|
||||
args.app.log.info(("NOTE: VM {} will be excluded because it is "
|
||||
"the backup destination.").format(args.appvm))
|
||||
|
||||
if appvm:
|
||||
args.exclude_list.append(appvm.name)
|
||||
if args.appvm or args.crypto_algorithm:
|
||||
args.encrypted = True
|
||||
if args.no_encrypt:
|
||||
args.encrypted = False
|
||||
|
||||
try:
|
||||
backup = qubes.backup.Backup(args.app,
|
||||
args.domains if args.domains else None,
|
||||
exclude_list=args.exclude_list)
|
||||
except qubes.exc.QubesException as e:
|
||||
parser.error_runtime(str(e))
|
||||
# unreachable - error_runtime will raise SystemExit
|
||||
return 1
|
||||
|
||||
backup.target_dir = args.backup_location
|
||||
|
||||
if not appvm:
|
||||
if os.path.isdir(args.backup_location):
|
||||
stat = os.statvfs(args.backup_location)
|
||||
else:
|
||||
stat = os.statvfs(os.path.dirname(args.backup_location))
|
||||
backup_fs_free_sz = stat.f_bsize * stat.f_bavail
|
||||
print()
|
||||
if backup.total_backup_bytes > backup_fs_free_sz:
|
||||
parser.error_runtime("Not enough space available on the "
|
||||
"backup filesystem!")
|
||||
|
||||
args.app.log.info("Available space: {0}".format(
|
||||
qubes.utils.size_to_human(backup_fs_free_sz)))
|
||||
else:
|
||||
stat = os.statvfs('/var/tmp')
|
||||
backup_fs_free_sz = stat.f_bsize * stat.f_bavail
|
||||
print()
|
||||
if backup_fs_free_sz < 1000000000:
|
||||
parser.error_runtime("Not enough space available "
|
||||
"on the local filesystem (1GB required for temporary files)!")
|
||||
|
||||
if not appvm.is_running():
|
||||
appvm.start()
|
||||
|
||||
if not args.encrypted:
|
||||
args.app.log.info("WARNING: The backup will NOT be encrypted!")
|
||||
|
||||
if args.pass_file is not None:
|
||||
pass_f = open(args.pass_file) if args.pass_file != "-" else sys.stdin
|
||||
passphrase = pass_f.readline().rstrip()
|
||||
if pass_f is not sys.stdin:
|
||||
pass_f.close()
|
||||
|
||||
else:
|
||||
if input("Do you want to proceed? [y/N] ").upper() != "Y":
|
||||
return 0
|
||||
|
||||
prompt = ("Please enter the passphrase that will be used to {}verify "
|
||||
"the backup: ").format('encrypt and ' if args.encrypted else '')
|
||||
passphrase = getpass.getpass(prompt)
|
||||
|
||||
if getpass.getpass("Enter again for verification: ") != passphrase:
|
||||
parser.error_runtime("Passphrase mismatch!")
|
||||
|
||||
backup.encrypted = args.encrypted
|
||||
backup.compressed = args.compressed
|
||||
if args.compression_filter:
|
||||
backup.compression_filter = args.compression_filter
|
||||
|
||||
encoding = sys.stdin.encoding or locale.getpreferredencoding()
|
||||
backup.passphrase = passphrase.decode(encoding)
|
||||
|
||||
if args.hmac_algorithm:
|
||||
backup.hmac_algorithm = args.hmac_algorithm
|
||||
if args.crypto_algorithm:
|
||||
backup.crypto_algorithm = args.crypto_algorithm
|
||||
if args.tmpdir:
|
||||
backup.tmpdir = args.tmpdir
|
||||
if appvm:
|
||||
backup.target_vm = appvm
|
||||
|
||||
try:
|
||||
backup.backup_do()
|
||||
except qubes.exc.QubesException as e:
|
||||
parser.error_runtime(str(e))
|
||||
|
||||
print()
|
||||
args.app.log.info("Backup completed.")
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -277,7 +277,6 @@ fi
|
||||
%{python3_sitelib}/qubes/tools/qubes_create.py
|
||||
%{python3_sitelib}/qubes/tools/qubesd.py
|
||||
%{python3_sitelib}/qubes/tools/qubesd_query.py
|
||||
%{python3_sitelib}/qubes/tools/qvm_backup.py
|
||||
|
||||
%dir %{python3_sitelib}/qubes/ext
|
||||
%dir %{python3_sitelib}/qubes/ext/__pycache__
|
||||
|
Loading…
Reference in New Issue
Block a user