Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libvirtnbdbackup/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ def copy(args: Namespace, source: str, target: str) -> None:
if args.sshClient:
args.sshClient.copy(source, target)
else:
if hasattr(args, "restore_root") and args.restore_root is not None:
dir, _ = os.path.split(target)
os.makedirs(dir, exist_ok=True)
shutil.copyfile(source, target)
except OSError as e:
log.warning("Failed to copy [%s] to [%s]: [%s]", source, target, e)
Expand Down
13 changes: 12 additions & 1 deletion libvirtnbdbackup/restore/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,20 @@
from libvirtnbdbackup.exceptions import RestoreError


def restore(args: Namespace, vmConfig: str, virtClient: virt.client) -> None:
def restore(
args: Namespace, vmConfig: str, virtClient: virt.client, restConfig: bytes
) -> bytes:
"""Notice user if backed up vm had loader / nvram"""
config = vmconfig.read(vmConfig)
info = virtClient.getDomainInfo(config)
restored_files = {}

for setting, val in info.items():
f = lib.getLatest(args.input, f"*{os.path.basename(val)}*", -1)
if args.restore_root is not None:
_, _, val_as_relative = os.path.splitroot(val)
val = os.path.join(args.restore_root, val_as_relative)
restored_files[setting] = os.path.abspath(val)
if lib.exists(args, val):
logging.info(
"File [%s]: for boot option [%s] already exists, skipping.",
Expand All @@ -50,6 +57,10 @@ def restore(args: Namespace, vmConfig: str, virtClient: virt.client) -> None:
"Restoring configured file [%s] for boot option [%s]", val, setting
)
lib.copy(args, f[0], val)
if restConfig != b"" and args.adjust_config is True:
return vmconfig.apply_paths(restConfig, restored_files)
else:
return restConfig


def verify(args: Namespace, dataFiles: List[str]) -> bool:
Expand Down
10 changes: 10 additions & 0 deletions libvirtnbdbackup/restore/vmconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from libvirtnbdbackup.virt import xml
from libvirtnbdbackup.virt import disktype

from typing import Dict


def read(ConfigFile: str) -> str:
"""Read saved virtual machine config'"""
Expand Down Expand Up @@ -138,3 +140,11 @@ def restore(
lib.copy(args, vmConfig, targetFile)
logging.info("Copied original vm config to [%s]", targetFile)
logging.info("Note: virtual machine config must be adjusted manually.")


def apply_paths(config: bytes, restored_files: Dict[str, str]):
tree = xml.asTree(config)
os_config = tree.find("os")
for flag, val in restored_files.items():
os_config.find(flag).text = val
return xml.ElementTree.tostring(tree, encoding="utf8", method="xml")
9 changes: 8 additions & 1 deletion virtnbdrestore
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ def main() -> None:
action="store_true",
help="Preallocate restored qcow images. (default: %(default)s)",
)
opt.add_argument(
"-R",
"--restore-root",
default=None,
type=str,
help="Store restored misc VM files (loader, firmware vars, etc) under alternative root directory (default /)",
)

remopt = parser.add_argument_group("Remote Restore options")
argopt.addRemoteArgs(remopt)
Expand Down Expand Up @@ -271,7 +278,7 @@ def main() -> None:
logging.error("Disk restore failed: [%s]", errmsg)
sys.exit(1)

files.restore(args, ConfigFile, virtClient)
restConfig = files.restore(args, ConfigFile, virtClient, restConfig)
vmconfig.restore(args, ConfigFile, restConfig, args.config_file)
virtClient.refreshPool(args.output)
if args.define is True:
Expand Down