From c8d28ad18f87b3158bb7a3459766241ac2a4eda2 Mon Sep 17 00:00:00 2001 From: Guillemo Ramos Date: Fri, 20 Sep 2024 12:04:15 +0200 Subject: [PATCH] B #6505: Fix volatile disk backup (Ceph) (#3225) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * B #6505: follow-up fix for Ceph bk/restore (#3212) Signed-off-by: Guillermo Ramos Co-authored-by: Pavel Czerný --- src/tm_mad/ceph/prebackup | 53 ++++++++++++++-------------------- src/tm_mad/ceph/prebackup_live | 33 +++++++++------------ src/tm_mad/lib/backup.rb | 2 +- src/tm_mad/lib/ceph.rb | 34 +++++++++++++++------- src/vm/VirtualMachineDisk.cc | 1 + 5 files changed, 60 insertions(+), 63 deletions(-) diff --git a/src/tm_mad/ceph/prebackup b/src/tm_mad/ceph/prebackup index 64fa112ffd..1e6d4e26d6 100755 --- a/src/tm_mad/ceph/prebackup +++ b/src/tm_mad/ceph/prebackup @@ -54,19 +54,10 @@ $LOAD_PATH << RUBY_LIB_LOCATION require 'rexml/document' require_relative '../lib/tm_action' +require_relative '../lib/ceph' require_relative '../lib/kvm' require_relative '../lib/datastore' -#------------------------------------------------------------------------------- -# Helper functions -#------------------------------------------------------------------------------- -def rbd_append(str, disk, name, opt) - opt_val = disk.elements[name].text - "#{str} #{opt} #{opt_val}" unless opt_val.empty? -rescue StandardError - str -end - #------------------------------------------------------------------------------- # BACKUP tm_mad host:remote_dir DISK_ID:...:DISK_ID deploy_id bjid vmid dsid #------------------------------------------------------------------------------- @@ -84,11 +75,11 @@ _dsid = ARGV[5] rhost = dir[0] rdir = dir[1] -xml_doc = REXML::Document.new(vm_xml) -vm = xml_doc.root - ds = TransferManager::Datastore.from_vm_backup_ds(:vm_xml => vm_xml) +action = TransferManager::Action.new(:action_name => 'prebackup', + :vm_id => vmid) + base_path = ENV['BACKUP_BASE_PATH'] bck_dir = if base_path @@ -97,27 +88,20 @@ bck_dir = if base_path "#{rdir}/backup" end +snap_cmd = '' expo_cmd = '' conv_cmd = '' clup_cmd = '' -vm.elements.each 'TEMPLATE/DISK' do |d| - did = d.elements['DISK_ID'].text - next unless disks.include? did +ceph_disks = TransferManager::Ceph::Disk.from_vm(action.vm.template_xml) +ceph_disks.compact.each do |d| + did = d.id + next unless disks.include? did.to_s - src = d.elements['SOURCE'].text - clon = d.elements['CLONE'].text - - rbd_src = if clon == 'NO' - src - else - "#{src}-#{vmid}-#{did}" - end - - cmd = rbd_append('rbd', d, 'CEPH_USER', '--id') - cmd = rbd_append(cmd, d, 'CEPH_KEY', '--keyfile') - cmd = rbd_append(cmd, d, 'CEPH_CONF', '--conf') + rbd_src = d.rbd_image + cmd = d.rbd_cmd + # Full backup draw = "#{bck_dir}/disk.#{did}.raw" ddst = "#{bck_dir}/disk.#{did}.0" @@ -145,6 +129,11 @@ script = <<~EOS echo "#{Base64.encode64(vm_xml)}" > #{bck_dir}/vm.xml + # -------------------------------- + # Create Ceph snapshots for disks + # -------------------------------- + #{snap_cmd} + # -------------------------- # export, convert & cleanup # -------------------------- @@ -155,10 +144,10 @@ script = <<~EOS #{clup_cmd} EOS -rc = TransferManager::Action.ssh('prebackup_live', :host => rhost, - :cmds => script, - :nostdout => false, - :nostderr => false) +rc = action.ssh(:host => rhost, + :cmds => script, + :nostdout => false, + :nostderr => false) if rc.code != 0 STDERR.puts "Error preparing disk files: #{rc.stdout} #{rc.stderr}" diff --git a/src/tm_mad/ceph/prebackup_live b/src/tm_mad/ceph/prebackup_live index a5c2d881a7..d06fe19145 100755 --- a/src/tm_mad/ceph/prebackup_live +++ b/src/tm_mad/ceph/prebackup_live @@ -54,6 +54,7 @@ $LOAD_PATH << RUBY_LIB_LOCATION require 'rexml/document' require_relative '../lib/tm_action' +require_relative '../lib/ceph' require_relative '../lib/kvm' require_relative '../lib/datastore' @@ -92,6 +93,9 @@ vm = xml_doc.root ds = TransferManager::Datastore.from_vm_backup_ds(:vm_xml => vm_xml) +action = TransferManager::Action.new(:action_name => 'prebackup_live', + :vm_id => vmid) + base_path = ENV['BACKUP_BASE_PATH'] bck_dir = if base_path @@ -105,22 +109,13 @@ expo_cmd = '' conv_cmd = '' clup_cmd = '' -vm.elements.each 'TEMPLATE/DISK' do |d| - did = d.elements['DISK_ID'].text - next unless disks.include? did +ceph_disks = TransferManager::Ceph::Disk.from_vm(action.vm.template_xml) +ceph_disks.compact.each do |d| + did = d.id + next unless disks.include? did.to_s - src = d.elements['SOURCE'].text - clon = d.elements['CLONE'].text - - rbd_src = if clon == 'NO' - src - else - "#{src}-#{vmid}-#{did}" - end - - cmd = rbd_append('rbd', d, 'CEPH_USER', '--id') - cmd = rbd_append(cmd, d, 'CEPH_KEY', '--keyfile') - cmd = rbd_append(cmd, d, 'CEPH_CONF', '--conf') + rbd_src = d.rbd_image + cmd = d.rbd_cmd draw = "#{bck_dir}/disk.#{did}.raw" ddst = "#{bck_dir}/disk.#{did}.0" @@ -173,10 +168,10 @@ script = <<~EOS #{clup_cmd} EOS -rc = TransferManager::Action.ssh('prebackup_live', :host => rhost, - :cmds => script, - :nostdout => false, - :nostderr => false) +rc = action.ssh(:host => rhost, + :cmds => script, + :nostdout => false, + :nostderr => false) if rc.code != 0 STDERR.puts "Error preparing disk files: #{rc.stdout} #{rc.stderr}" diff --git a/src/tm_mad/lib/backup.rb b/src/tm_mad/lib/backup.rb index f1983f78e7..fdc65e592f 100644 --- a/src/tm_mad/lib/backup.rb +++ b/src/tm_mad/lib/backup.rb @@ -351,7 +351,7 @@ module TransferManager d.delete('SIZE') # CDROM keeps original image_id - next if type == 'CDROM' + next if ['CDROM', 'RBD_CDROM'].include?(type) d['IMAGE_ID'] = bck_disks[id][:image_id].to_s end diff --git a/src/tm_mad/lib/ceph.rb b/src/tm_mad/lib/ceph.rb index 52bd3bd894..8b07ee5974 100644 --- a/src/tm_mad/lib/ceph.rb +++ b/src/tm_mad/lib/ceph.rb @@ -35,17 +35,25 @@ module TransferManager def initialize(vmid, disk_xml) disk_xml = REXML::Document.new(disk_xml) if disk_xml.is_a?(String) - @id = disk_xml.elements['DISK_ID'].text.to_i - @vmid = vmid - @source = disk_xml.elements['SOURCE'].text - @clone = disk_xml.elements['CLONE'].text == 'YES' + @id = disk_xml.elements['DISK_ID'].text.to_i + @vmid = vmid + @type = disk_xml.elements['TYPE'].text + @pool = disk_xml.elements['POOL_NAME'].text - @rbd_image = - if @clone - "#{@source}-#{@vmid}-#{@id}" - else - @source - end + if volatile? + @source = nil + @clone = nil + @rbd_image = "#{@pool}/one-sys-#{vmid}-#{id}" + else + @source = disk_xml.elements['SOURCE'].text + @clone = disk_xml.elements['CLONE'].text == 'YES' + @rbd_image = + if @clone + "#{@source}-#{@vmid}-#{@id}" + else + @source + end + end @rbd_cmd = 'rbd' @rbd_cmd += Ceph.xml_opt(disk_xml, 'CEPH_USER', '--id') @@ -53,6 +61,10 @@ module TransferManager @rbd_cmd += Ceph.xml_opt(disk_xml, 'CEPH_CONF', '--conf') end + def volatile? + ['fs', 'swap'].include?(@type) + end + # @return [String] Shell definitions for functionality related to this disk def shdefs <<~SCRIPT @@ -85,7 +97,7 @@ module TransferManager ## CLASS METHODS # @param vm_xml [String, REXML::Document, REXML::Element] - # @return [Array(Disk)] indexed VM disks (disk id = position in array) + # @return [Array(Disk), nil] indexed VM disks (disk id = position in array) def self.from_vm(vm_xml) vm_xml = REXML::Document.new(vm_xml) if vm_xml.is_a?(String) vm = vm_xml.root diff --git a/src/vm/VirtualMachineDisk.cc b/src/vm/VirtualMachineDisk.cc index 3d61bc0487..d6f189c1b6 100644 --- a/src/vm/VirtualMachineDisk.cc +++ b/src/vm/VirtualMachineDisk.cc @@ -1629,6 +1629,7 @@ void VirtualMachineDisks::backup_disk_ids(bool do_volatile, std::vector& id if ((type == "SWAP") || (type == "CDROM") || + (type == "RBD_CDROM") || ((type == "FS") && !do_volatile)) { continue;