mirror of
https://github.com/OpenNebula/one.git
synced 2024-12-22 13:33:52 +03:00
F #6333: Snapshots for incremental backup mode
- Defines a new a attribute "INCREMENT_MODE" that can be "SNAPSHOT" or "CBT" - SNAPSHOT mode: takes a disk snapshot (virsh snapshot-create-as or qemu-img). The current snapshot is saved in the backup store, and committed to the base disk image. The backup_qcow2.rb util adapt to different VM folder layout for SSH, shared, persistent, non persistent disks. - Lint vxlan.rb - Update onevm and XSD schema to reflect the new backup attribute
This commit is contained in:
parent
2ada2ec687
commit
ea1d5183ea
@ -305,6 +305,7 @@
|
||||
<xs:element name="LAST_DATASTORE_ID" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="LAST_INCREMENT_ID" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="MODE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="INCREMENT_MODE" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
@ -1343,7 +1343,7 @@ CommandParser::CmdParser.new(ARGV) do
|
||||
VIDEO = ["TYPE", "IOMMU", "ATS", "VRAM", "RESOLUTION"]
|
||||
RAW = ["DATA", "DATA_VMX", "TYPE", "VALIDATE"]
|
||||
CPU_MODEL = ["MODEL"]
|
||||
BACKUP_CONFIG = ["FS_FREEZE", "KEEP_LAST", "BACKUP_VOLATILE", "MODE"]
|
||||
BACKUP_CONFIG = ["FS_FREEZE", "KEEP_LAST", "BACKUP_VOLATILE", "MODE", "INCREMENT_MODE"]
|
||||
CONTEXT (any value, **variable substitution will be made**)
|
||||
EOT
|
||||
|
||||
|
@ -21,6 +21,7 @@ require 'open3'
|
||||
require 'rexml/document'
|
||||
require 'base64'
|
||||
require 'getoptlong'
|
||||
require 'fileutils'
|
||||
|
||||
require_relative 'kvm'
|
||||
|
||||
@ -206,22 +207,67 @@ end
|
||||
# ------------------------------------------------------------------------------
|
||||
# This class abstracts the information and several methods to operate over
|
||||
# disk images files
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# +--------+---------------+---------------------------------------------------+
|
||||
# | Driver | PType | Layout |
|
||||
# +========+===============+===================================================+
|
||||
# | NFS | persistent | disk.0 -> /var/lib/one/datastores/1/ab24b7.snap/0 |
|
||||
# | | no persistent | disk.0 -> disk.0.snap/0 |
|
||||
# +----------------------------------------------------------------------------+
|
||||
# | SSH | persistent | disk.0 |
|
||||
# | | no persistent | (no link regular file) |
|
||||
# +--------+---------------+---------------------------------------------------+
|
||||
#
|
||||
# NOTE: A persistent SSH disk may be a link to a pevious snapshot
|
||||
#
|
||||
# @name of the file supporting the disk
|
||||
# @snap path for the snapshot folder (absolute)
|
||||
# @path real path (links resolved of the file)
|
||||
# @slink path to symlink disk.i file (= @snap for persistent)
|
||||
class QemuImg
|
||||
|
||||
include Command
|
||||
|
||||
def initialize(path)
|
||||
@path = path
|
||||
attr_reader :path, :name, :snap, :slink
|
||||
|
||||
def initialize(path, opts = {})
|
||||
@_info = nil
|
||||
|
||||
@path = File.realpath(path) if File.exist?(path)
|
||||
read_paths(path, opts)
|
||||
end
|
||||
|
||||
def read_paths(path, opts = {})
|
||||
# Default locations
|
||||
@path = path
|
||||
@name = File.basename(path)
|
||||
@snap = "#{opts[:vm_dir]}/disk.#{opts[:disk_id]}.snap"
|
||||
|
||||
return if opts.empty? || !File.exist?(path)
|
||||
|
||||
@path = File.realpath(path)
|
||||
|
||||
rl = begin
|
||||
File.readlink(path)
|
||||
rescue StandardError
|
||||
nil
|
||||
end
|
||||
|
||||
return unless rl
|
||||
|
||||
@name = File.basename(rl)
|
||||
@slink = File.dirname(rl)
|
||||
|
||||
@snap = if opts[:shared] && opts[:persistent]
|
||||
@slink
|
||||
else
|
||||
File.dirname("#{opts[:vm_dir]}/#{rl}")
|
||||
end
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# qemu-img command methods
|
||||
#---------------------------------------------------------------------------
|
||||
QEMU_IMG_COMMANDS = ['convert', 'create', 'rebase', 'info', 'bitmap']
|
||||
QEMU_IMG_COMMANDS = ['convert', 'create', 'rebase', 'info', 'bitmap', 'commit']
|
||||
|
||||
QEMU_IMG_COMMANDS.each do |command|
|
||||
define_method(command.to_sym) do |args = '', opts|
|
||||
@ -403,7 +449,7 @@ class KVMDomain
|
||||
include TransferManager::KVM
|
||||
include Command
|
||||
|
||||
attr_reader :parent_id, :backup_id, :checkpoint, :tmp_dir, :bck_dir
|
||||
attr_reader :parent_id, :backup_id, :checkpoint, :tmp_dir, :bck_dir, :inc_mode
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# @param vm[REXML::Document] OpenNebula XML VM information
|
||||
@ -419,8 +465,6 @@ class KVMDomain
|
||||
@backup_id = 0
|
||||
@parent_id = -1
|
||||
|
||||
@checkpoint = false
|
||||
|
||||
mode = @vm.elements['BACKUPS/BACKUP_CONFIG/MODE']
|
||||
|
||||
if mode
|
||||
@ -429,14 +473,19 @@ class KVMDomain
|
||||
@backup_id = 0
|
||||
@parent_id = -1
|
||||
|
||||
@checkpoint = false
|
||||
@inc_mode = :none
|
||||
when 'INCREMENT'
|
||||
li = @vm.elements['BACKUPS/BACKUP_CONFIG/LAST_INCREMENT_ID'].text.to_i
|
||||
im = @vm.elements['BACKUPS/BACKUP_CONFIG/INCREMENT_MODE']
|
||||
|
||||
if im && 'snapshot'.casecmp(im.text) == 0
|
||||
@inc_mode = :snapshot
|
||||
else
|
||||
@inc_mode = :cbt
|
||||
end
|
||||
|
||||
@backup_id = li + 1
|
||||
@parent_id = li
|
||||
|
||||
@checkpoint = true
|
||||
end
|
||||
end
|
||||
|
||||
@ -595,7 +644,7 @@ class KVMDomain
|
||||
# the backup operation in case it fails
|
||||
#---------------------------------------------------------------------------
|
||||
def clean_checkpoints(disks_s, all = false)
|
||||
return unless @checkpoint
|
||||
return if @inc_mode != :cbt
|
||||
|
||||
# Get a list of dirty checkpoints
|
||||
check_ids = checkpoints
|
||||
@ -640,7 +689,7 @@ class KVMDomain
|
||||
|
||||
fsfreeze
|
||||
|
||||
start_backup(disks, @backup_id, @parent_id, @checkpoint)
|
||||
start_backup(disks, @backup_id, @parent_id, @inc_mode == :cbt)
|
||||
|
||||
fsthaw
|
||||
|
||||
@ -668,6 +717,77 @@ class KVMDomain
|
||||
stop_backup
|
||||
end
|
||||
|
||||
def backup_snapshot_live(disks_s)
|
||||
init = Time.now
|
||||
disks = disks_s.split ':'
|
||||
dspec = []
|
||||
qdisks = []
|
||||
|
||||
@vm.elements.each 'TEMPLATE/DISK' do |d|
|
||||
did = d.elements['DISK_ID'].text
|
||||
tgt = d.elements['TARGET'].text
|
||||
per = d.elements['SAVE'].text.casecmp('YES') == 0
|
||||
ssh = d.elements['TM_MAD'].text.casecmp('SSH') == 0
|
||||
|
||||
next unless disks.include? did
|
||||
|
||||
disk = QemuImg.new("#{@vm_dir}/disk.#{did}",
|
||||
:vm_dir => @vm_dir,
|
||||
:disk_id => did,
|
||||
:persistent => per,
|
||||
:shared => !ssh)
|
||||
|
||||
qdisks << { :did => did, :tgt => tgt, :disk => disk }
|
||||
|
||||
bfile = disk['full-backing-filename']
|
||||
|
||||
next_path = "#{disk.snap}/#{@backup_id.to_i + 1}"
|
||||
next_disk = QemuImg.new(next_path)
|
||||
|
||||
next_disk.create(:f => 'qcow2', :o => 'backing_fmt=qcow2', :b => bfile)
|
||||
|
||||
dspec << "#{tgt},file=#{next_path}"
|
||||
end
|
||||
|
||||
opts = {
|
||||
:disk_only => '',
|
||||
:atomic => '',
|
||||
:reuse_external => '',
|
||||
:no_metadata => '',
|
||||
:diskspec => dspec
|
||||
}
|
||||
|
||||
fsfreeze
|
||||
|
||||
cmd("#{virsh} snapshot-create-as", @dom, opts)
|
||||
|
||||
fsthaw
|
||||
|
||||
qdisks.each do |qdisk|
|
||||
did = qdisk[:did]
|
||||
tgt = qdisk[:tgt]
|
||||
disk = qdisk[:disk]
|
||||
|
||||
back_path = "#{@bck_dir}/disk.#{did}.#{@backup_id}"
|
||||
|
||||
FileUtils.cp(disk.path, back_path)
|
||||
|
||||
back_img = QemuImg.new back_path
|
||||
back_img.rebase(:U => '', :u => '', :F => 'qcow2', :q => '', :b => '""')
|
||||
|
||||
cmd("#{virsh} blockcommit", "#{@dom} #{tgt}",
|
||||
:wait => '',
|
||||
:top => disk.path,
|
||||
:base => "#{disk.snap}/0")
|
||||
|
||||
FileUtils.rm(disk.path, :force => true)
|
||||
|
||||
symlink("#{disk.slink}/#{@backup_id.to_i + 1}", "#{@vm_dir}/disk.#{did}")
|
||||
end
|
||||
|
||||
log("[BCK]: Incremental backup done in #{Time.now - init}s")
|
||||
end
|
||||
|
||||
def backup_full_live(disks_s)
|
||||
init = Time.now
|
||||
disks = disks_s.split ':'
|
||||
@ -679,18 +799,54 @@ class KVMDomain
|
||||
@vm.elements.each 'TEMPLATE/DISK' do |d|
|
||||
did = d.elements['DISK_ID'].text
|
||||
tgt = d.elements['TARGET'].text
|
||||
per = d.elements['SAVE'].text.casecmp('YES') == 0
|
||||
ssh = d.elements['TM_MAD'].text.casecmp('SSH') == 0
|
||||
|
||||
next unless disks.include? did
|
||||
|
||||
overlay = "#{@tmp_dir}/overlay_#{did}.qcow2"
|
||||
disk_path = "#{@vm_dir}/disk.#{did}"
|
||||
disk_opts = {
|
||||
:vm_dir => @vm_dir,
|
||||
:disk_id => did,
|
||||
:persistent => per,
|
||||
:shared => !ssh
|
||||
}
|
||||
|
||||
File.open(overlay, 'w') {}
|
||||
qdisk[did] = QemuImg.new(disk_path, disk_opts)
|
||||
|
||||
if @inc_mode == :snapshot
|
||||
base = "#{qdisk[did].slink}/0"
|
||||
|
||||
if snap_folder(did, true)
|
||||
qdisk[did].read_paths(disk_path, disk_opts)
|
||||
elsif qdisk[did].name != '0'
|
||||
cmd("#{virsh} blockcommit", "#{@dom} #{tgt}",
|
||||
:active => '',
|
||||
:pivot => '',
|
||||
:wait => '',
|
||||
:top => qdisk[did].path,
|
||||
:base => base)
|
||||
|
||||
FileUtils.rm(qdisk[did].path, :force => true)
|
||||
|
||||
symlink(base, "#{@vm_dir}/disk.#{did}")
|
||||
|
||||
qdisk[did].read_paths(disk_path, disk_opts)
|
||||
end
|
||||
|
||||
overlay = "#{qdisk[did].snap}/1"
|
||||
odisk = QemuImg.new(overlay)
|
||||
|
||||
odisk.create(:f => 'qcow2', :o => 'backing_fmt=qcow2', :b => base)
|
||||
else
|
||||
overlay = "#{@tmp_dir}/overlay_#{did}.qcow2"
|
||||
|
||||
File.open(overlay, 'w') {}
|
||||
end
|
||||
|
||||
dspec << "#{tgt},file=#{overlay}"
|
||||
|
||||
disk_xml << "<disk name='#{tgt}'/>"
|
||||
|
||||
qdisk[did] = QemuImg.new("#{@vm_dir}/disk.#{did}")
|
||||
end
|
||||
|
||||
disk_xml << '</disks>'
|
||||
@ -702,6 +858,8 @@ class KVMDomain
|
||||
:diskspec => dspec
|
||||
}
|
||||
|
||||
opts.merge!({ :no_metadata =>'', :reuse_external => '' }) if @inc_mode == :snapshot
|
||||
|
||||
checkpoint_xml = <<~EOS
|
||||
<domaincheckpoint>
|
||||
<name>one-#{@vid}-0</name>
|
||||
@ -717,12 +875,18 @@ class KVMDomain
|
||||
|
||||
cmd("#{virsh} snapshot-create-as", @dom, opts)
|
||||
|
||||
cmd("#{virsh} checkpoint-create", @dom, :xmlfile => cpath) if @checkpoint
|
||||
if @inc_mode == :cbt
|
||||
cmd("#{virsh} checkpoint-create", @dom, :xmlfile => cpath)
|
||||
end
|
||||
|
||||
fsthaw
|
||||
|
||||
qdisk.each do |did, disk|
|
||||
disk.convert("#{@bck_dir}/disk.#{did}.0", :m => '4', :O => 'qcow2', :U => '')
|
||||
|
||||
next unless @inc_mode == :snapshot
|
||||
|
||||
symlink("#{disk.slink}/1", "#{@vm_dir}/disk.#{did}")
|
||||
end
|
||||
|
||||
log("[BCK]: Full backup done in #{Time.now - init}s")
|
||||
@ -756,7 +920,62 @@ class KVMDomain
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Make a backup for the VM. (see make_backup_live)
|
||||
#
|
||||
# First Backup Nth Backup
|
||||
# @parent_id = -1 @parent_id = n
|
||||
# @backup_id = 0 @backup_id = n+1
|
||||
# snapshot = 1 snapshot = n+2
|
||||
#
|
||||
# ├── backup ├── backup
|
||||
# │ ├── disk.0.0 │ ├── disk.0.n+1
|
||||
# │ └── vm.xml │ └── vm.xml
|
||||
# ├── disk.0 -> disk.0.snap/1 ├── disk.0 -> disk.0.snap/n+2
|
||||
# └── disk.0.snap └── disk.0.snap
|
||||
# ├── 0 (backingfile --> image) ├── 0 (backingfile --> image)
|
||||
# ├── 1 (backingfile --> 0) ├── n+1 (commit to 0)
|
||||
# └── disk.0.snap -> . ├── n+2 (backingfile --> 0)
|
||||
# └── disk.0.snap -> .
|
||||
#---------------------------------------------------------------------------
|
||||
def backup_snapshot(disks_s)
|
||||
init = Time.now
|
||||
disks = disks_s.split ':'
|
||||
|
||||
@vm.elements.each 'TEMPLATE/DISK' do |d|
|
||||
did = d.elements['DISK_ID'].text
|
||||
per = d.elements['SAVE'].text.casecmp('YES') == 0
|
||||
ssh = d.elements['TM_MAD'].text.casecmp('SSH') == 0
|
||||
|
||||
next unless disks.include? did
|
||||
|
||||
disk_path = "#{@vm_dir}/disk.#{did}"
|
||||
disk_opts = {
|
||||
:vm_dir => @vm_dir,
|
||||
:disk_id => did,
|
||||
:persistent => per,
|
||||
:shared => !ssh
|
||||
}
|
||||
|
||||
disk = QemuImg.new(disk_path, disk_opts)
|
||||
|
||||
FileUtils.cp(disk.path, "#{@bck_dir}/disk.#{did}.#{@backup_id}")
|
||||
|
||||
back_disk = QemuImg.new("#{@bck_dir}/disk.#{did}.#{@backup_id}")
|
||||
back_disk.rebase(:U => '', :u => '', :F => 'qcow2', :q => '', :b => '""')
|
||||
|
||||
bfile = disk['full-backing-filename']
|
||||
disk.commit(:q => '')
|
||||
|
||||
next_disk = QemuImg.new("#{disk.snap}/#{@backup_id.to_i + 1}")
|
||||
next_disk.create(:f => 'qcow2', :o => 'backing_fmt=qcow2', :b => bfile)
|
||||
|
||||
FileUtils.rm(disk.path, :force => true)
|
||||
|
||||
symlink("#{disk.slink}/#{@backup_id.to_i + 1}", disk_path)
|
||||
end
|
||||
|
||||
log("[BCK]: Snapshot incremental backup done in #{Time.now - init}s")
|
||||
end
|
||||
|
||||
def backup_nbd(disks_s)
|
||||
init = Time.now
|
||||
disks = disks_s.split ':'
|
||||
@ -787,6 +1006,7 @@ class KVMDomain
|
||||
Nbd.stop_nbd
|
||||
end
|
||||
|
||||
# rubocop:disable Style/CombinableLoops
|
||||
dids.each do |d|
|
||||
idisk = QemuImg.new("#{@vm_dir}/disk.#{d}")
|
||||
|
||||
@ -797,9 +1017,10 @@ class KVMDomain
|
||||
end
|
||||
|
||||
idisk.bitmap("one-#{@vid}-#{@backup_id}", :add => '')
|
||||
end if @checkpoint
|
||||
end
|
||||
# rubocop:enable Style/CombinableLoops
|
||||
|
||||
log("[BCK]: Incremental backup done in #{Time.now - init}s")
|
||||
log("[BCK]: CBT incremental backup done in #{Time.now - init}s")
|
||||
end
|
||||
|
||||
def backup_full(disks_s)
|
||||
@ -808,20 +1029,50 @@ class KVMDomain
|
||||
|
||||
@vm.elements.each 'TEMPLATE/DISK' do |d|
|
||||
did = d.elements['DISK_ID'].text
|
||||
per = d.elements['SAVE'].text.casecmp('YES') == 0
|
||||
ssh = d.elements['TM_MAD'].text.casecmp('SSH') == 0
|
||||
|
||||
next unless disks.include? did
|
||||
|
||||
sdisk = QemuImg.new("#{@vm_dir}/disk.#{did}")
|
||||
ddisk = "#{@bck_dir}/disk.#{did}.0"
|
||||
disk_path = "#{@vm_dir}/disk.#{did}"
|
||||
disk_opts = {
|
||||
:vm_dir => @vm_dir,
|
||||
:disk_id => did,
|
||||
:persistent => per,
|
||||
:shared => !ssh
|
||||
}
|
||||
|
||||
sdisk.convert(ddisk, :m => '4', :O => 'qcow2', :U => '')
|
||||
sdisk = QemuImg.new(disk_path, disk_opts)
|
||||
|
||||
next unless @checkpoint
|
||||
sdisk.convert("#{@bck_dir}/disk.#{did}.0", :m => '4', :O => 'qcow2', :U => '')
|
||||
|
||||
bms = sdisk.bitmaps
|
||||
bms.each {|bm| sdisk.bitmap(bm['name'], :remove => '') } unless bms.nil?
|
||||
case @inc_mode
|
||||
when :cbt
|
||||
bms = sdisk.bitmaps
|
||||
bms.each {|bm| sdisk.bitmap(bm['name'], :remove => '') } unless bms.nil?
|
||||
|
||||
sdisk.bitmap("one-#{@vid}-0", :add => '')
|
||||
sdisk.bitmap("one-#{@vid}-0", :add => '')
|
||||
when :snapshot
|
||||
if snap_folder(did, false)
|
||||
sdisk.read_paths("#{@vm_dir}/disk.#{did}", disk_opts)
|
||||
|
||||
base = sdisk.path
|
||||
elsif sdisk.name != '0'
|
||||
base = sdisk['full-backing-filename']
|
||||
|
||||
sdisk.commit(:q => '')
|
||||
|
||||
FileUtils.rm(sdisk.path, :force => true)
|
||||
else
|
||||
base = sdisk.path
|
||||
end
|
||||
|
||||
ndisk = QemuImg.new("#{sdisk.snap}/1")
|
||||
|
||||
ndisk.create(:f => 'qcow2', :o => 'backing_fmt=qcow2', :b => base)
|
||||
|
||||
symlink("#{sdisk.slink}/1", "#{@vm_dir}/disk.#{did}")
|
||||
end
|
||||
end
|
||||
|
||||
log("[BCK]: Full backup done in #{Time.now - init}s")
|
||||
@ -834,6 +1085,42 @@ class KVMDomain
|
||||
"nbd+unix:///#{target}?socket=#{@socket}"
|
||||
end
|
||||
|
||||
# Symlink files (make it succeed by removing the new_path first)
|
||||
def symlink(exist_path, new_path)
|
||||
FileUtils.rm(new_path, :force => true)
|
||||
|
||||
File.symlink(exist_path, new_path)
|
||||
end
|
||||
|
||||
# Create the snap folder structure in the first backup (SSH driver)
|
||||
def snap_folder(disk_id, live)
|
||||
snap_dir = "#{@vm_dir}/disk.#{disk_id}.snap"
|
||||
disk_path = "#{@vm_dir}/disk.#{disk_id}"
|
||||
|
||||
return false if File.ftype(disk_path) == 'link'
|
||||
|
||||
FileUtils.mkdir(snap_dir)
|
||||
|
||||
if live
|
||||
opts = {
|
||||
:path => disk_path,
|
||||
:dest => "#{snap_dir}/0",
|
||||
:pivot => '',
|
||||
:format => 'qcow2'
|
||||
}
|
||||
|
||||
FileUtils.touch "#{snap_dir}/0"
|
||||
|
||||
cmd("#{virsh} blockcopy", @dom.to_s, opts)
|
||||
else
|
||||
FileUtils.mv(disk_path, "#{snap_dir}/0")
|
||||
end
|
||||
|
||||
symlink("disk.#{disk_id}.snap/0", disk_path)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Start a Backup operation on the domain (See make_backup_live)
|
||||
#---------------------------------------------------------------------------
|
||||
@ -955,7 +1242,10 @@ begin
|
||||
# changes and cleans snapshot.
|
||||
#---------------------------------------------------------------------------
|
||||
if stop
|
||||
vm.stop_backup_full_live(disk) if vm.parent_id == -1 && live
|
||||
if vm.parent_id == -1 && live && @inc_mode != :snapshot
|
||||
vm.stop_backup_full_live(disk)
|
||||
end
|
||||
|
||||
exit(0)
|
||||
end
|
||||
|
||||
@ -995,18 +1285,22 @@ begin
|
||||
vm.clean_checkpoints(disk, true)
|
||||
|
||||
vm.backup_full_live(disk)
|
||||
else
|
||||
elsif vm.inc_mode == :cbt
|
||||
vm.define_parent(disk)
|
||||
|
||||
vm.backup_nbd_live(disk)
|
||||
|
||||
vm.clean_checkpoints(disk)
|
||||
else # vm.inc_mode == :snapshot
|
||||
vm.backup_snapshot_live(disk)
|
||||
end
|
||||
else
|
||||
if vm.parent_id == -1
|
||||
vm.backup_full(disk)
|
||||
else
|
||||
elsif vm.inc_mode == :cbt
|
||||
vm.backup_nbd(disk)
|
||||
else # vm.inc_mode == :snapshot
|
||||
vm.backup_snapshot(disk)
|
||||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
|
@ -58,14 +58,18 @@ SRC_DIR="$(dirname $SRC_PATH)"
|
||||
# and delete base + base.1, snap link and snap dir (if empty)
|
||||
#-------------------------------------------------------------------------------
|
||||
CONVERT_CMD=$(cat <<EOF
|
||||
if [ -L "$SRC_PATH" ] && readlink "$SRC_PATH" | grep -q base.1; then
|
||||
if [ -L "$SRC_PATH" ]; then
|
||||
$QEMU_IMG convert -O qcow2 $SRC_PATH $SRC_PATH.full
|
||||
rm -f $SRC_PATH $SRC_PATH_SNAP/base $SRC_PATH_SNAP/base.1 $SRC_PATH_SNAP/rs_tmp
|
||||
|
||||
if [ "\$(ls $SRC_PATH_SNAP)" = "${SRC_FILE}.snap" ]; then
|
||||
rm -f $SRC_PATH_SNAP/${SRC_FILE}.snap
|
||||
rm -f $SRC_PATH
|
||||
|
||||
if [ -e $SRC_PATH_SNAP/base ]; then
|
||||
rm -f $SRC_PATH_SNAP/base $SRC_PATH_SNAP/base.1 $SRC_PATH_SNAP/rs_tmp
|
||||
rmdir $SRC_PATH_SNAP
|
||||
elif [ -d $SRC_PATH_SNAP ]; then
|
||||
rm -rf $SRC_PATH_SNAP
|
||||
fi
|
||||
|
||||
mv $SRC_PATH.full $SRC_PATH
|
||||
fi
|
||||
EOF
|
||||
|
@ -199,6 +199,8 @@ int Backups::parse(Template *tmpl, bool can_increment,
|
||||
config.replace("LAST_INCREMENT_ID", -1);
|
||||
|
||||
config.replace("MODE", mode_to_str(FULL));
|
||||
|
||||
config.erase("INCREMENT_MODE");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -216,6 +218,24 @@ int Backups::parse(Template *tmpl, bool can_increment,
|
||||
}
|
||||
|
||||
config.replace("MODE", mode_to_str(new_mode));
|
||||
|
||||
sattr = cfg->vector_value("INCREMENT_MODE");
|
||||
|
||||
one_util::toupper(sattr);
|
||||
|
||||
if ( !sattr.empty() )
|
||||
{
|
||||
if ((sattr != "CBT") && (sattr != "SNAPSHOT"))
|
||||
{
|
||||
sattr = "CBT";
|
||||
}
|
||||
|
||||
config.replace("INCREMENT_MODE", sattr);
|
||||
}
|
||||
else if (!append)
|
||||
{
|
||||
config.replace("INCREMENT_MODE", "CBT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,6 +252,7 @@ std::map<std::string,std::vector<std::string>> VirtualMachineTemplate::UPDATECON
|
||||
{ "FS_FREEZE",
|
||||
"KEEP_LAST",
|
||||
"BACKUP_VOLATILE",
|
||||
"INCREMENT_MODE",
|
||||
"MODE"}
|
||||
}
|
||||
};
|
||||
|
@ -25,7 +25,7 @@ module VXLAN
|
||||
############################################################################
|
||||
def create_vlan_dev
|
||||
vxlan_mode = conf_attribute(@nic, :vxlan_mode, 'multicast')
|
||||
group = ""
|
||||
group = ''
|
||||
|
||||
if vxlan_mode.downcase == 'evpn'
|
||||
vxlan_tep = conf_attribute(@nic, :vxlan_tep, 'dev')
|
||||
@ -37,9 +37,9 @@ module VXLAN
|
||||
end
|
||||
else
|
||||
begin
|
||||
ipaddr = IPAddr.new conf_attribute(@nic, :vxlan_mc, '239.0.0.0')
|
||||
rescue
|
||||
ipaddr = IPAddr.new '239.0.0.0'
|
||||
ipaddr = IPAddr.new conf_attribute(@nic, :vxlan_mc, '239.0.0.0')
|
||||
rescue StandardError
|
||||
ipaddr = IPAddr.new '239.0.0.0'
|
||||
end
|
||||
|
||||
mc = ipaddr.to_i + @nic[@attr_vlan_id].to_i
|
||||
@ -50,16 +50,16 @@ module VXLAN
|
||||
end
|
||||
|
||||
mtu = @nic[:mtu] ? "mtu #{@nic[:mtu]}" : "mtu #{@nic[:conf][:vxlan_mtu]}"
|
||||
ttl = @nic[:conf][:vxlan_ttl] ? "ttl #{@nic[:conf][:vxlan_ttl]}" : ""
|
||||
ttl = @nic[:conf][:vxlan_ttl] ? "ttl #{@nic[:conf][:vxlan_ttl]}" : ''
|
||||
|
||||
ip_link_conf = ""
|
||||
ip_link_conf = ''
|
||||
|
||||
@nic[:ip_link_conf].each do |option, value|
|
||||
case value
|
||||
when true
|
||||
value = "on"
|
||||
value = 'on'
|
||||
when false
|
||||
value = "off"
|
||||
value = 'off'
|
||||
end
|
||||
|
||||
ip_link_conf << "#{option} #{value} "
|
||||
|
Loading…
Reference in New Issue
Block a user