dom0/qvm-backup/restore: backup and restore also dom0 home dir (#362)

To keep desktop environment settings (like theme, wallpaper, screensaver etc).
This commit is contained in:
Marek Marczykowski 2011-10-11 01:42:05 +02:00
parent 20522d04ec
commit 65bc4f6e95
2 changed files with 96 additions and 0 deletions

View File

@ -29,6 +29,8 @@ import os
import time
import subprocess
import sys
import re
import grp,pwd
def size_to_human (size):
if size < 1024:
@ -40,6 +42,18 @@ def size_to_human (size):
else:
return str(round(size/(1024.0*1024*1024),1)) + ' GiB'
def get_disk_usage(file_or_dir):
if not os.path.exists(file_or_dir):
return 0
p = subprocess.Popen (["du", "-s", "--block-size=1", file_or_dir],
stdout=subprocess.PIPE)
result = p.communicate()
m = re.match(r"^(\d+)\s.*", result[0])
sz = int(m.group(1)) if m is not None else 0
return sz
def file_to_backup (file_path, sz = None):
if sz is None:
sz = os.path.getsize (qubes_store_filename)
@ -186,6 +200,24 @@ def main():
print s
# Dom0 user home
local_user = grp.getgrnam('qubes').gr_mem[0]
home_dir = pwd.getpwnam(local_user).pw_dir
home_sz = get_disk_usage(home_dir)
home_to_backup = [ { "path" : home_dir, "size": home_sz, "subdir": 'dom0-home'} ]
files_to_backup += home_to_backup
s = ""
fmt="{{0:>{0}}} |".format(fields_to_display[0]["width"] + 1)
s += fmt.format('Dom0')
fmt="{{0:>{0}}} |".format(fields_to_display[1]["width"] + 1)
s += fmt.format("User home")
fmt="{{0:>{0}}} |".format(fields_to_display[2]["width"] + 1)
s += fmt.format(size_to_human(home_sz))
print s
total_backup_sz = 0

View File

@ -34,6 +34,7 @@ import time
import subprocess
import sys
import re
import pwd,grp
def size_to_human (size):
if size < 1024:
@ -135,6 +136,12 @@ def main():
parser.add_option ("--replace-template", action="append", dest="replace_template", default=[],
help="Restore VMs using another template, syntax: old-template-name:new-template-name (might be repeated)")
parser.add_option ("--skip-dom0-home", action="store_false", dest="dom0_home", default=True,
help="Do not restore dom0 user home dir")
parser.add_option ("--ignore-username-mismatch", action="store_true", dest="ignore_username_mismatch", default=False,
help="Ignore dom0 username mismatch while restoring homedir")
(options, args) = parser.parse_args ()
if (len (args) != 1):
@ -158,6 +165,7 @@ def main():
backup_vms_list = [vm for vm in backup_collection.values()]
host_vms_list = [vm for vm in host_collection.values()]
vms_to_restore = []
backup_dom0_home_dir = None
fields_to_display = ["name", "type", "template", "updbl", "netvm", "label" ]
@ -195,6 +203,8 @@ def main():
there_are_conflicting_vms = False
there_are_missing_templates = False
there_are_missing_netvms = False
dom0_username_mismatch = False
restore_home = False
# ... and the actual data
for vm in backup_vms_list:
if is_vm_included_in_backup (backup_dir, vm):
@ -242,6 +252,34 @@ def main():
if good_to_go:
vms_to_restore.append (vm)
# ...and dom0 home
if options.dom0_home and os.path.exists(backup_dir + '/dom0-home'):
local_user = grp.getgrnam('qubes').gr_mem[0]
s = ""
for f in fields_to_display:
fmt="{{0:>{0}}} |".format(fields[f]["max_width"] + 1)
if f == "name":
s += fmt.format("Dom0")
elif f == "type":
s += fmt.format("Home")
else:
s += fmt.format("")
dom0_homes = os.listdir(backup_dir + '/dom0-home')
if len(dom0_homes) > 1:
print >> sys.stderr, "ERROR: more than one dom0 homedir in backup!"
exit(1)
if dom0_homes[0] != local_user:
s += " <-- username in backup and dom0 mismatch"
dom0_username_mismatch = True
backup_dom0_home_dir = backup_dir + '/dom0-home/' + dom0_homes[0]
print s
restore_home = True
restore_home_backupdir = "home-pre-restore-{0}".format (time.strftime("%Y-%m-%d-%H%M%S"))
print
if os.geteuid() == 0:
@ -293,6 +331,17 @@ def main():
print >> sys.stderr, "INTERNAL ERROR?!"
exit (1)
if restore_home:
if dom0_username_mismatch:
print >> sys.stderr, "*** Dom0 username mismatch! This can break some settings ***"
if not options.ignore_username_mismatch:
print >> sys.stderr, "Skip dom0 home restore (--skip-dom0-home)"
print >> sys.stderr, "Or pass: --ignore-username-mismatch to continue anyway"
exit(1)
else:
print >> sys.stderr, "Continuing as directed"
print >> sys.stderr, "While restoring user homedir, existing files/dirs will be backed up in '{0}' dir".format(restore_home_backupdir)
prompt = raw_input ("Do you want to proceed? [y/N] ")
if not (prompt == "y" or prompt == "Y"):
exit (0)
@ -445,5 +494,20 @@ def main():
backup_collection.unlock_db()
host_collection.save()
host_collection.unlock_db()
# ... and dom0 home as last step
if restore_home:
home_dir = pwd.getpwnam(local_user).pw_dir
print "-> Restoring home of user '{0}'...".format(local_user)
os.mkdir(home_dir + '/' +restore_home_backupdir)
for f in os.listdir(backup_dom0_home_dir):
home_file = home_dir + '/' + f
if os.path.exists(home_file):
os.rename(home_file, home_dir + '/' + restore_home_backupdir + '/' + f)
retcode = subprocess.call (["cp", "-nrp", backup_dom0_home_dir + '/' + f, home_file])
if retcode != 0:
print >> sys.stderr, "*** Error while copying file {0} to {1}".format(backup_dom0_home_dir + '/' + f, home_file)
exit (1)
print "-> Done."
main()