Skip to content

Commit

Permalink
Merge pull request bareos#1876
Browse files Browse the repository at this point in the history
VMware Plugin: Add option restore_allow_disks_mismatch
  • Loading branch information
BareosBot authored Jul 29, 2024
2 parents 8ac7838 + fa2fe8d commit b2b9ca2
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- consolidate: disable vfull duplicate job check [PR #1739]
- dird: disallow running always incremental virtual full jobs with empty jobid list [PR #1738]
- msgchan: fix deadlock [PR #1858]
- VMware Plugin: Add option restore_allow_disks_mismatch [PR #1876]

### Removed
- plugins: remove old deprecated postgres plugin [PR #1606]
Expand Down Expand Up @@ -228,6 +229,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[PR #1871]: https://github.com/bareos/bareos/pull/1871
[PR #1872]: https://github.com/bareos/bareos/pull/1872
[PR #1875]: https://github.com/bareos/bareos/pull/1875
[PR #1876]: https://github.com/bareos/bareos/pull/1876
[PR #1878]: https://github.com/bareos/bareos/pull/1878
[PR #1881]: https://github.com/bareos/bareos/pull/1881
[PR #1883]: https://github.com/bareos/bareos/pull/1883
Expand Down
103 changes: 82 additions & 21 deletions core/src/plugins/filed/python/vmware/bareos-fd-vmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def __init__(self, plugindef):
"vadp_dumper_sectors_per_call",
"vadp_dumper_query_allocated_blocks_chunk_size",
"fallback_to_full_cbt",
"restore_allow_disks_mismatch",
]
self.allowed_options = (
self.mandatory_options_default
Expand Down Expand Up @@ -392,6 +393,9 @@ def check_plugin_options(self, mandatory_options=None):
if self.options.get("fallback_to_full_cbt") == "no":
self.vadp.fallback_to_full_cbt = False

if self.options.get("restore_allow_disks_mismatch") == "yes":
self.vadp.restore_allow_disks_mismatch = True

for option in self.options:
bareosfd.DebugMessage(
100,
Expand Down Expand Up @@ -1247,6 +1251,7 @@ def __init__(self):
self.vm_nvram_content = None
self.restore_vm_created = False
self.fallback_to_full_cbt = True
self.restore_allow_disks_mismatch = False

def connect_vmware(self):
# this prevents from repeating on second call
Expand Down Expand Up @@ -2404,6 +2409,15 @@ def check_vm_disks_match(self):
bareosfd.M_WARNING,
"Backed up Disks: %s\n" % (StringCodec.encode(", ".join(backed_up_disks))),
)

# currently ignoring disks mismatch is only allowed for recreated VMs
if self.restore_allow_disks_mismatch and self.restore_vm_created:
bareosfd.JobMessage(
bareosfd.M_WARNING,
"Ignoring disks mismatch as restore_allow_disks_mismatch=yes was given\n",
)
return True

bareosfd.JobMessage(
bareosfd.M_FATAL,
"ERROR: VM disks not matching backed up disks\n",
Expand Down Expand Up @@ -3157,40 +3171,87 @@ def add_disk_devices_to_vm(self, device_changes):
"""
Add devices to VM
"""
retry_limit = 3
disk_index = 0
for device_spec in device_changes:
config_spec = vim.vm.ConfigSpec()
device_spec.device.controllerKey = abs(device_spec.device.controllerKey)
config_spec.deviceChange = [device_spec]
device_created = False
backing_path_changed = False
while not device_created:

# 2024-07-17 sduehr: Always create disk with datastore only in
# the backing file name.
expected_disk_backing_filename = device_spec.device.backing.fileName
device_spec.device.backing.fileName = (
"[%s] " % device_spec.device.backing.datastore.name
)
retry_count = 1

while not device_created and retry_count <= retry_limit:
reconfig_task = self.vm.ReconfigVM_Task(spec=config_spec)
bareosfd.DebugMessage(
100,
"add_disk_devices_to_vm(): Trying to add disk %s\n"
% (device_spec.device.backing.fileName),
)
try:
pyVim.task.WaitForTask(reconfig_task)
device_created = True
except vim.fault.FileAlreadyExists:
device_spec.device.backing.fileName = (
"[%s] " % device_spec.device.backing.datastore.name
except Exception as create_disk_exc:
bareosfd.JobMessage(
bareosfd.M_INFO,
"add_disk_devices_to_vm(): Failed to create disk %s: %s, retrying\n"
% (device_spec.device.backing.fileName, str(create_disk_exc)),
)
backing_path_changed = True

# When handling the FileAlreadyExists exception, we only pass the datastore name
# and the backing path to the disk will be created by the API, then mapping in self.restore_disk_paths_map
# must be corrected. This is only possible by walking the VMs devices and detect the added disks path,
# because the task result does not contain it.
if backing_path_changed:
self.restore_disk_paths_map[
list(self.restore_disk_paths_map)[disk_index]
] = [
device.backing.fileName
for device in self.vm.config.hardware.device
if type(device) == vim.vm.device.VirtualDisk
][
disk_index
]
retry_count += 1

if not device_created:
bareosfd.JobMessage(
bareosfd.M_FATAL,
"add_disk_devices_to_vm(): Failed to create disk %s: giving up.\n"
% (device_spec.device.backing.fileName),
)
return False

# When only passing the datastore name in device.backing.fileName when creating a disk,
# the complete backing path to the disk will be created by the API, and the new backing
# path could differ from the old one so that mapping in self.restore_disk_paths_map
# must be corrected. This is only possible by walking the VMs devices and detect the
# added disks path, because the task result does not contain it.
created_disk_backing_filename = [
device.backing.fileName
for device in self.vm.config.hardware.device
if type(device) == vim.vm.device.VirtualDisk
][disk_index]

if expected_disk_backing_filename != created_disk_backing_filename:
bareosfd.JobMessage(
bareosfd.M_INFO,
"Disk %s was recreated as %s\n"
% (expected_disk_backing_filename, created_disk_backing_filename),
)

bareosfd.DebugMessage(
100,
"add_disk_devices_to_vm(): Adapting restore_disk_paths_maps"
"[%s] from %s to %s\n"
% (
list(self.restore_disk_paths_map)[disk_index],
self.restore_disk_paths_map[
list(self.restore_disk_paths_map)[disk_index]
],
created_disk_backing_filename,
),
)

self.restore_disk_paths_map[
list(self.restore_disk_paths_map)[disk_index]
] = created_disk_backing_filename

disk_index += 1

return True

def adapt_vm_config(self, config_spec):
"""
Adapt VM config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -710,5 +710,15 @@ fallback_to_full_cbt (optional)

Since :sinceVersion:`23.0.3: VMware Plugin`

restore_allow_disks_mismatch (optional)
When using VSAN, restoring with recreating the VM can fail because the plugin
detects a disk mismatch, as when using VSAN obviously recreated disks get a
generated backing disk path. When passing the plugin option
``restore_allow_disks_mismatch=yes``, this disk match check will allow a
mismatch and continue the restore.
This option will only be used when recreating the VM to be restored.

Since :sinceVersion:`23.0.4: VMware Plugin`

uuid (deprecated)
The uuid option could be used instead of *dc*, *folder* and *vmname* to uniquely address a VM for backup. As the plugin since :sinceVersion:`22.0.0: VMware Plugin` is able recreate VMs in a different datacenter, folder or datastore, this option has become useless. When using uuid, restoring is only possible to the same still existing VM. It is recommended to change the configuration, as the uuid option will be dropped in the next version.

0 comments on commit b2b9ca2

Please sign in to comment.