EOF & whitespace

This commit is contained in:
2024-11-29 00:54:09 +01:00
parent e7e98d0b47
commit 7fcc5afc64
60 changed files with 4173 additions and 4192 deletions
-1
View File
@@ -15,4 +15,3 @@
# along with TISBackup. If not, see <http://www.gnu.org/licenses/>.
#
# -----------------------------------------------------------------------
+3 -4
View File
@@ -25,10 +25,10 @@ from .common import *
class backup_null(backup_generic):
"""Null backup to register servers which don't need any backups
"""Null backup to register servers which don't need any backups
but we still want to know they are taken in account"""
type = 'null'
required_params = ['type','server_name','backup_name']
optional_params = []
@@ -44,9 +44,8 @@ class backup_null(backup_generic):
return {}
def checknagios(self,maxage_hours=30):
return (nagiosStateOk,"No backups needs to be performed")
register_driver(backup_null)
if __name__=='__main__':
pass
+9 -9
View File
@@ -38,7 +38,7 @@ from libtisbackup.common import *
class backup_oracle(backup_generic):
"""Backup a oracle database as zipped file through ssh"""
type = 'oracle+ssh'
type = 'oracle+ssh'
required_params = backup_generic.required_params + ['db_name','private_key', 'userid']
optional_params = ['username', 'remote_backup_dir', 'ignore_error_oracle_code']
db_name=''
@@ -47,7 +47,7 @@ class backup_oracle(backup_generic):
ignore_error_oracle_code = [ ]
def do_backup(self,stats):
self.logger.debug('[%s] Connecting to %s with user %s and key %s',self.backup_name,self.server_name,self.username,self.private_key)
try:
mykey = paramiko.RSAKey.from_private_key_file(self.private_key)
@@ -57,8 +57,8 @@ class backup_oracle(backup_generic):
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect(self.server_name,username=self.username,pkey = mykey,port=self.ssh_port)
self.ssh.connect(self.server_name,username=self.username,pkey = mykey,port=self.ssh_port)
t = datetime.datetime.now()
self.backup_start_date = t.strftime('%Y%m%d-%Hh%Mm%S')
dumpfile= self.remote_backup_dir + '/' + self.db_name + '_' + self.backup_start_date+'.dmp'
@@ -71,10 +71,10 @@ class backup_oracle(backup_generic):
else:
print(('mkdir "%s"' % self.dest_dir))
else:
raise Exception('backup destination directory already exists : %s' % self.dest_dir)
raise Exception('backup destination directory already exists : %s' % self.dest_dir)
# dump db
stats['status']='Dumping'
cmd = "exp '%s' file='%s' grants=y log='%s'"% (self.userid,dumpfile, dumplog)
cmd = "exp '%s' file='%s' grants=y log='%s'"% (self.userid,dumpfile, dumplog)
self.logger.debug('[%s] Dump DB : %s',self.backup_name,cmd)
if not self.dry_run:
(error_code,output) = ssh_exec(cmd,ssh=self.ssh)
@@ -97,7 +97,7 @@ class backup_oracle(backup_generic):
# zip the file
stats['status']='Zipping'
cmd = 'gzip %s' % dumpfile
cmd = 'gzip %s' % dumpfile
self.logger.debug('[%s] Compress backup : %s',self.backup_name,cmd)
if not self.dry_run:
(error_code,output) = ssh_exec(cmd,ssh=self.ssh)
@@ -120,7 +120,7 @@ class backup_oracle(backup_generic):
stats['total_files_count']=1
stats['written_files_count']=1
stats['total_bytes']=os.stat(localpath).st_size
stats['written_bytes']=os.stat(localpath).st_size
stats['written_bytes']=os.stat(localpath).st_size
stats['log']='gzip dump of DB %s:%s (%d bytes) to %s' % (self.server_name,self.db_name, stats['written_bytes'], localpath)
stats['backup_location'] = self.dest_dir
stats['status']='RMTemp'
@@ -134,7 +134,7 @@ class backup_oracle(backup_generic):
filelist = os.listdir(self.backup_dir)
filelist.sort()
p = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
p = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
for item in filelist:
if p.match(item):
dir_name = os.path.join(self.backup_dir,item)
+9 -10
View File
@@ -30,7 +30,7 @@ from libtisbackup.common import *
class backup_rsync(backup_generic):
"""Backup a directory on remote server with rsync and rsync protocol (requires running remote rsync daemon)"""
type = 'rsync'
type = 'rsync'
required_params = backup_generic.required_params + ['remote_user','remote_dir','rsync_module','password_file']
optional_params = backup_generic.optional_params + ['compressionlevel','compression','bwlimit','exclude_list','protect_args','overload_args']
@@ -46,7 +46,7 @@ class backup_rsync(backup_generic):
overload_args = None
compressionlevel = 0
def read_config(self,iniconf):
assert(isinstance(iniconf,ConfigParser))
@@ -54,7 +54,7 @@ class backup_rsync(backup_generic):
if not self.bwlimit and iniconf.has_option('global','bw_limit'):
self.bwlimit = iniconf.getint('global','bw_limit')
if not self.compressionlevel and iniconf.has_option('global','compression_level'):
self.compressionlevel = iniconf.getint('global','compression_level')
self.compressionlevel = iniconf.getint('global','compression_level')
def do_backup(self,stats):
if not self.set_lock():
@@ -216,7 +216,7 @@ class backup_rsync(backup_generic):
raise
finally:
finally:
self.remove_lock()
def get_latest_backup(self,current):
@@ -225,8 +225,8 @@ class backup_rsync(backup_generic):
filelist.sort()
filelist.reverse()
full = ''
r_full = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
r_partial = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}.rsync$')
r_full = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
r_partial = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}.rsync$')
# we take all latest partials younger than the latest full and the latest full
for item in filelist:
if r_partial.match(item) and item<current:
@@ -245,7 +245,7 @@ class backup_rsync(backup_generic):
filelist = os.listdir(self.backup_dir)
filelist.sort()
p = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
p = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
for item in filelist:
if p.match(item):
dir_name = os.path.join(self.backup_dir,item)
@@ -288,7 +288,7 @@ class backup_rsync(backup_generic):
return False
else:
self.logger.info("[" + self.backup_name + "] incorrrect lock file : no pid line")
return False
return False
def set_lock(self):
@@ -317,7 +317,7 @@ class backup_rsync(backup_generic):
class backup_rsync_ssh(backup_rsync):
"""Backup a directory on remote server with rsync and ssh protocol (requires rsync software on remote host)"""
type = 'rsync+ssh'
type = 'rsync+ssh'
required_params = backup_generic.required_params + ['remote_user','remote_dir','private_key']
optional_params = backup_generic.optional_params + ['compression','bwlimit','ssh_port','exclude_list','protect_args','overload_args', 'cipher_spec']
cipher_spec = ''
@@ -341,4 +341,3 @@ if __name__=='__main__':
b.read_config(cp)
b.process_backup()
print((b.checknagios()))
+10 -11
View File
@@ -30,7 +30,7 @@ from .common import *
class backup_rsync_btrfs(backup_generic):
"""Backup a directory on remote server with rsync and btrfs protocol (requires running remote rsync daemon)"""
type = 'rsync+btrfs'
type = 'rsync+btrfs'
required_params = backup_generic.required_params + ['remote_user','remote_dir','rsync_module','password_file']
optional_params = backup_generic.optional_params + ['compressionlevel','compression','bwlimit','exclude_list','protect_args','overload_args']
@@ -46,7 +46,7 @@ class backup_rsync_btrfs(backup_generic):
overload_args = None
compressionlevel = 0
def read_config(self,iniconf):
assert(isinstance(iniconf,ConfigParser))
@@ -54,7 +54,7 @@ class backup_rsync_btrfs(backup_generic):
if not self.bwlimit and iniconf.has_option('global','bw_limit'):
self.bwlimit = iniconf.getint('global','bw_limit')
if not self.compressionlevel and iniconf.has_option('global','compression_level'):
self.compressionlevel = iniconf.getint('global','compression_level')
self.compressionlevel = iniconf.getint('global','compression_level')
def do_backup(self,stats):
if not self.set_lock():
@@ -73,7 +73,7 @@ class backup_rsync_btrfs(backup_generic):
returncode = process.returncode
if (returncode != 0):
self.logger.error("[" + self.backup_name + "] shell program exited with error code: %s"%log)
raise Exception("[" + self.backup_name + "] shell program exited with error code " + str(returncode), cmd)
raise Exception("[" + self.backup_name + "] shell program exited with error code " + str(returncode), cmd)
else:
self.logger.info("[" + self.backup_name + "] create btrs volume: %s"%dest_dir)
else:
@@ -234,7 +234,7 @@ class backup_rsync_btrfs(backup_generic):
raise
finally:
finally:
self.remove_lock()
def get_latest_backup(self,current):
@@ -243,8 +243,8 @@ class backup_rsync_btrfs(backup_generic):
filelist.sort()
filelist.reverse()
full = ''
r_full = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
r_partial = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}.rsync$')
r_full = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
r_partial = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}.rsync$')
# we take all latest partials younger than the latest full and the latest full
for item in filelist:
if r_partial.match(item) and item<current:
@@ -262,7 +262,7 @@ class backup_rsync_btrfs(backup_generic):
filelist = os.listdir(self.backup_dir)
filelist.sort()
p = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
p = re.compile('^\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}$')
for item in filelist:
if p.match(item):
dir_name = os.path.join(self.backup_dir,item)
@@ -305,7 +305,7 @@ class backup_rsync_btrfs(backup_generic):
return False
else:
self.logger.info("[" + self.backup_name + "] incorrrect lock file : no pid line")
return False
return False
def set_lock(self):
@@ -334,7 +334,7 @@ class backup_rsync_btrfs(backup_generic):
class backup_rsync__btrfs_ssh(backup_rsync_btrfs):
"""Backup a directory on remote server with rsync,ssh and btrfs protocol (requires rsync software on remote host)"""
type = 'rsync+btrfs+ssh'
type = 'rsync+btrfs+ssh'
required_params = backup_generic.required_params + ['remote_user','remote_dir','private_key']
optional_params = backup_generic.optional_params + ['compression','bwlimit','ssh_port','exclude_list','protect_args','overload_args','cipher_spec']
cipher_spec = ''
@@ -358,4 +358,3 @@ if __name__=='__main__':
b.read_config(cp)
b.process_backup()
print((b.checknagios()))
+1 -1
View File
@@ -165,4 +165,4 @@ class backup_samba4(backup_generic):
self.logger.info('Skipping %s, already registered',dir_name)
register_driver(backup_samba4)
register_driver(backup_samba4)
+1 -2
View File
@@ -152,7 +152,7 @@ class backup_switch(backup_generic):
else:
child.sendline(self.switch_user)
child.expect(".*#")
child.sendline( "terminal datadump")
child.expect("#")
child.sendline( "show startup-config")
@@ -262,4 +262,3 @@ if __name__=='__main__':
cp.read('/opt/tisbackup/configtest.ini')
b = backup_xva()
b.read_config(cp)
+34 -35
View File
@@ -59,15 +59,15 @@ class backup_vmdk(backup_generic):
cookie_text = " " + cookie_value + "; $" + cookie_path
# Make a cookie
cookie = dict()
cookie[cookie_name] = cookie_text
cookie[cookie_name] = cookie_text
return cookie
def download_file(self,url, local_filename, cookie, headers):
r = requests.get(url, stream=True, headers=headers,cookies=cookie,verify=False)
with open(local_filename, 'wb') as f:
for chunk in r.iter_content(chunk_size=1024*1024*64):
if chunk:
for chunk in r.iter_content(chunk_size=1024*1024*64):
if chunk:
f.write(chunk)
f.flush()
return local_filename
@@ -78,7 +78,7 @@ class backup_vmdk(backup_generic):
try:
infos = HttpNfcLease.info
device_urls = infos.deviceUrl
vmdks = []
vmdks = []
for device_url in device_urls:
deviceId = device_url.key
deviceUrlStr = device_url.url
@@ -89,7 +89,7 @@ class backup_vmdk(backup_generic):
cookie = self.make_compatible_cookie(si._stub.cookie)
headers = {'Content-Type': 'application/octet-stream'}
self.logger.debug("[%s] exporting disk: %s" %(self.server_name,diskFileName))
self.download_file(diskUrlStr, diskFileName, cookie, headers)
vmdks.append({"filename":diskFileName,"id":deviceId})
finally:
@@ -99,8 +99,8 @@ class backup_vmdk(backup_generic):
def create_ovf(self,vm,vmdks):
ovfDescParams = vim.OvfManager.CreateDescriptorParams()
ovf = si.content.ovfManager.CreateDescriptor(vm, ovfDescParams)
root = ET.fromstring(ovf.ovfDescriptor)
ovf = si.content.ovfManager.CreateDescriptor(vm, ovfDescParams)
root = ET.fromstring(ovf.ovfDescriptor)
new_id = list(root[0][1].attrib.values())[0][1:3]
ovfFiles = []
for vmdk in vmdks:
@@ -109,14 +109,14 @@ class backup_vmdk(backup_generic):
ovfFiles.append(vim.OvfManager.OvfFile(size=os.path.getsize(vmdk['filename']), path=vmdk['filename'], deviceId=id))
ovfDescParams = vim.OvfManager.CreateDescriptorParams()
ovfDescParams.ovfFiles = ovfFiles;
ovfDescParams.ovfFiles = ovfFiles;
ovf = si.content.ovfManager.CreateDescriptor(vm, ovfDescParams)
ovf = si.content.ovfManager.CreateDescriptor(vm, ovfDescParams)
ovf_filename = vm.name+".ovf"
self.logger.debug("[%s] creating ovf file: %s" %(self.server_name,ovf_filename))
with open(ovf_filename, "w") as f:
f.write(ovf.ovfDescriptor)
with open(ovf_filename, "w") as f:
f.write(ovf.ovfDescriptor)
return ovf_filename
def create_ova(self,vm, vmdks, ovf_filename):
@@ -131,9 +131,9 @@ class backup_vmdk(backup_generic):
def clone_vm(self,vm):
task = self.wait_task(vm.CreateSnapshot_Task(name="backup",description="Automatic backup "+datetime.now().strftime("%Y-%m-%d %H:%M:%s"),memory=False,quiesce=True))
snapshot=task.info.result
snapshot=task.info.result
prefix_vmclone = self.prefix_clone
clone_name = prefix_vmclone + vm.name
clone_name = prefix_vmclone + vm.name
datastore = '[%s]' % vm.datastore[0].name
@@ -146,16 +146,16 @@ class backup_vmdk(backup_generic):
config = vim.vm.ConfigSpec(name=clone_name, memoryMB=vm.summary.config.memorySizeMB, numCPUs=vm.summary.config.numCpu, files=vmx_file)
hosts = datacenter.hostFolder.childEntity
resource_pool = hosts[0].resourcePool
resource_pool = hosts[0].resourcePool
self.wait_task(vmFolder.CreateVM_Task(config=config,pool=resource_pool))
self.wait_task(vmFolder.CreateVM_Task(config=config,pool=resource_pool))
new_vm = [x for x in vmFolder.childEntity if x.name == clone_name][0]
controller = vim.vm.device.VirtualDeviceSpec()
controller.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
controller.device = vim.vm.device.VirtualLsiLogicController(busNumber=0,sharedBus='noSharing')
controller.device.key = 0
controller.device = vim.vm.device.VirtualLsiLogicController(busNumber=0,sharedBus='noSharing')
controller.device.key = 0
i=0
vm_devices = []
@@ -189,7 +189,7 @@ class backup_vmdk(backup_generic):
vm_devices.append(controller)
vm_devices.append(controller)
config.deviceChange=vm_devices
self.wait_task(new_vm.ReconfigVM_Task(config))
@@ -198,7 +198,7 @@ class backup_vmdk(backup_generic):
def wait_task(self,task):
while task.info.state in ["queued", "running"]:
time.sleep(2)
self.logger.debug("[%s] %s",self.server_name,task.info.descriptionId)
self.logger.debug("[%s] %s",self.server_name,task.info.descriptionId)
return task
@@ -213,7 +213,7 @@ class backup_vmdk(backup_generic):
else:
print('mkdir "%s"' % dest_dir)
else:
raise Exception('backup destination directory already exists : %s' % dest_dir)
raise Exception('backup destination directory already exists : %s' % dest_dir)
os.chdir(dest_dir)
user_esx, password_esx, null = open(self.password_file).read().split('\n')
@@ -237,27 +237,27 @@ class backup_vmdk(backup_generic):
if vm.name == self.server_name:
vm_is_off = vm.summary.runtime.powerState == "poweredOff"
if str2bool(self.halt_vm):
vm.ShutdownGuest()
vm.ShutdownGuest()
vm_is_off = True
if vm_is_off:
vmdks = self.export_vmdks(vm)
ovf_filename = self.create_ovf(vm, vmdks)
ovf_filename = self.create_ovf(vm, vmdks)
else:
new_vm = self.clone_vm(vm)
vmdks = self.export_vmdks(new_vm)
ovf_filename = self.create_ovf(vm, vmdks)
self.wait_task(new_vm.Destroy_Task())
self.wait_task(new_vm.Destroy_Task())
if str2bool(self.create_ovafile):
ova_filename = self.create_ova(vm, vmdks, ovf_filename)
ova_filename = self.create_ova(vm, vmdks, ovf_filename)
if str2bool(self.halt_vm):
vm.PowerOnVM()
vm.PowerOnVM()
if os.path.exists(dest_dir):
for file in os.listdir(dest_dir):
for file in os.listdir(dest_dir):
stats['written_bytes'] += os.stat(file)[ST_SIZE]
stats['total_files_count'] += 1
stats['written_files_count'] += 1
@@ -266,10 +266,10 @@ class backup_vmdk(backup_generic):
stats['written_bytes'] = 0
stats['backup_location'] = dest_dir
stats['log']='XVA backup from %s OK, %d bytes written' % (self.server_name,stats['written_bytes'])
stats['status']='OK'
stats['status']='OK'
except BaseException as e:
stats['status']='ERROR'
@@ -279,4 +279,3 @@ class backup_vmdk(backup_generic):
register_driver(backup_vmdk)
+4 -4
View File
@@ -27,7 +27,7 @@ from .common import *
class backup_xcp_metadata(backup_generic):
"""Backup metatdata of a xcp pool using xe pool-dump-database"""
type = 'xcp-dump-metadata'
type = 'xcp-dump-metadata'
required_params = ['type','server_name','private_key','backup_name']
def do_backup(self,stats):
@@ -60,7 +60,7 @@ class backup_xcp_metadata(backup_generic):
stats['total_files_count']=1
stats['written_files_count']=1
stats['total_bytes']=os.stat(localpath).st_size
stats['written_bytes']=os.stat(localpath).st_size
stats['written_bytes']=os.stat(localpath).st_size
stats['log']='gzip dump of DB %s:%s (%d bytes) to %s' % (self.server_name,'xcp metadata dump', stats['written_bytes'], localpath)
stats['backup_location'] = localpath
stats['status']='OK'
@@ -74,7 +74,7 @@ class backup_xcp_metadata(backup_generic):
filelist = os.listdir(self.backup_dir)
filelist.sort()
p = re.compile('^%s-(?P<date>\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}).dump.gz$' % self.server_name)
p = re.compile('^%s-(?P<date>\d{8,8}-\d{2,2}h\d{2,2}m\d{2,2}).dump.gz$' % self.server_name)
for item in filelist:
sr = p.match(item)
if sr:
@@ -84,7 +84,7 @@ class backup_xcp_metadata(backup_generic):
self.logger.info('Registering %s from %s',file_name,fileisodate(file_name))
size_bytes = int(os.popen('du -sb "%s"' % file_name).read().split('\t')[0])
self.logger.debug(' Size in bytes : %i',size_bytes)
if not self.dry_run:
if not self.dry_run:
self.dbstat.add(self.backup_name,self.server_name,'',\
backup_start=start,backup_end=fileisodate(file_name),status='OK',total_bytes=size_bytes,backup_location=file_name)
else:
+57 -57
View File
@@ -36,7 +36,7 @@ from stat import *
from . import XenAPI
from .common import *
if hasattr(ssl, '_create_unverified_context'):
if hasattr(ssl, '_create_unverified_context'):
ssl._create_default_https_context = ssl._create_unverified_context
@@ -46,23 +46,23 @@ class copy_vm_xcp(backup_generic):
required_params = backup_generic.required_params + ['server_name','storage_name','password_file','vm_name','network_name']
optional_params = backup_generic.optional_params + ['start_vm','max_copies', 'delete_snapshot', 'halt_vm']
start_vm = "no"
max_copies = 1
halt_vm = "no"
halt_vm = "no"
delete_snapshot = "yes"
def read_config(self,iniconf):
assert(isinstance(iniconf,ConfigParser))
backup_generic.read_config(self,iniconf)
backup_generic.read_config(self,iniconf)
if self.start_vm in 'no' and iniconf.has_option('global','start_vm'):
self.start_vm = iniconf.get('global','start_vm')
self.start_vm = iniconf.get('global','start_vm')
if self.max_copies == 1 and iniconf.has_option('global','max_copies'):
self.max_copies = iniconf.getint('global','max_copies')
self.max_copies = iniconf.getint('global','max_copies')
if self.delete_snapshot == "yes" and iniconf.has_option('global','delete_snapshot'):
self.delete_snapshot = iniconf.get('global','delete_snapshot')
def copy_vm_to_sr(self, vm_name, storage_name, dry_run, delete_snapshot="yes"):
user_xen, password_xen, null = open(self.password_file).read().split('\n')
session = XenAPI.Session('https://'+self.server_name)
@@ -70,25 +70,25 @@ class copy_vm_xcp(backup_generic):
session.login_with_password(user_xen,password_xen)
except XenAPI.Failure as error:
msg,ip = error.details
if msg == 'HOST_IS_SLAVE':
server_name = ip
session = XenAPI.Session('https://'+server_name)
session.login_with_password(user_xen,password_xen)
session.login_with_password(user_xen,password_xen)
self.logger.debug("[%s] VM (%s) to backup in storage: %s",self.backup_name,vm_name,storage_name)
now = datetime.datetime.now()
#get storage opaqueRef
try:
storage = session.xenapi.SR.get_by_name_label(storage_name)[0]
except IndexError as error:
result = (1,"error get SR opaqueref %s"%(error))
return result
#get vm to copy opaqueRef
#get vm to copy opaqueRef
try:
vm = session.xenapi.VM.get_by_name_label(vm_name)[0]
except IndexError as error:
@@ -101,96 +101,96 @@ class copy_vm_xcp(backup_generic):
except IndexError as error:
result = (1, "error get VM network opaqueref %s" % (error))
return result
if str2bool(self.halt_vm):
status_vm = session.xenapi.VM.get_power_state(vm)
status_vm = session.xenapi.VM.get_power_state(vm)
self.logger.debug("[%s] Status of VM: %s",self.backup_name,status_vm)
if status_vm == "Running":
self.logger.debug("[%s] Shutdown in progress",self.backup_name)
if dry_run:
print("session.xenapi.VM.clean_shutdown(vm)")
print("session.xenapi.VM.clean_shutdown(vm)")
else:
session.xenapi.VM.clean_shutdown(vm)
session.xenapi.VM.clean_shutdown(vm)
snapshot = vm
else:
#do the snapshot
#do the snapshot
self.logger.debug("[%s] Snapshot in progress",self.backup_name)
try:
snapshot = session.xenapi.VM.snapshot(vm,"tisbackup-%s"%(vm_name))
except XenAPI.Failure as error:
result = (1,"error when snapshot %s"%(error))
return result
#get snapshot opaqueRef
#get snapshot opaqueRef
snapshot = session.xenapi.VM.get_by_name_label("tisbackup-%s"%(vm_name))[0]
session.xenapi.VM.set_name_description(snapshot,"snapshot created by tisbackup on : %s"%(now.strftime("%Y-%m-%d %H:%M")))
vm_backup_name = "zzz-%s-"%(vm_name)
#Check if old backup exit
list_backups = []
for vm_ref in session.xenapi.VM.get_all():
name_lablel = session.xenapi.VM.get_name_label(vm_ref)
if vm_backup_name in name_lablel:
list_backups.append(name_lablel)
list_backups.sort()
if len(list_backups) >= 1:
# Shutting last backup if started
last_backup_vm = session.xenapi.VM.get_by_name_label(list_backups[-1])[0]
if not "Halted" in session.xenapi.VM.get_power_state(last_backup_vm):
self.logger.debug("[%s] Shutting down last backup vm : %s", self.backup_name, list_backups[-1] )
session.xenapi.VM.hard_shutdown(last_backup_vm)
# Delete oldest backup if exist
if len(list_backups) >= int(self.max_copies):
for i in range(len(list_backups)-int(self.max_copies)+1):
oldest_backup_vm = session.xenapi.VM.get_by_name_label(list_backups[i])[0]
if not "Halted" in session.xenapi.VM.get_power_state(oldest_backup_vm):
self.logger.debug("[%s] Shutting down old vm : %s", self.backup_name, list_backups[i] )
self.logger.debug("[%s] Shutting down old vm : %s", self.backup_name, list_backups[i] )
session.xenapi.VM.hard_shutdown(oldest_backup_vm)
try:
self.logger.debug("[%s] Deleting old vm : %s", self.backup_name, list_backups[i])
for vbd in session.xenapi.VM.get_VBDs(oldest_backup_vm):
if session.xenapi.VBD.get_type(vbd) == 'CD'and session.xenapi.VBD.get_record(vbd)['empty'] == False:
session.xenapi.VBD.eject(vbd)
session.xenapi.VBD.eject(vbd)
else:
vdi = session.xenapi.VBD.get_VDI(vbd)
if not 'NULL' in vdi:
session.xenapi.VDI.destroy(vdi)
session.xenapi.VM.destroy(oldest_backup_vm)
session.xenapi.VM.destroy(oldest_backup_vm)
except XenAPI.Failure as error:
result = (1,"error when destroy old backup vm %s"%(error))
return result
self.logger.debug("[%s] Copy %s in progress on %s",self.backup_name,vm_name,storage_name)
try:
backup_vm = session.xenapi.VM.copy(snapshot,vm_backup_name+now.strftime("%Y-%m-%d %H:%M"),storage)
except XenAPI.Failure as error:
result = (1,"error when copy %s"%(error))
return result
# define VM as a template
session.xenapi.VM.set_is_a_template(backup_vm,False)
#change the network of the new VM
try:
vifDestroy = session.xenapi.VM.get_VIFs(backup_vm)
except IndexError as error:
result = (1,"error get VIF opaqueref %s"%(error))
return result
for i in vifDestroy:
vifRecord = session.xenapi.VIF.get_record(i)
session.xenapi.VIF.destroy(i)
@@ -218,13 +218,13 @@ class copy_vm_xcp(backup_generic):
except Exception as error:
result = (1,error)
return result
if self.start_vm in ['true', '1', 't', 'y', 'yes', 'oui']:
session.xenapi.VM.start(backup_vm,False,True)
session.xenapi.VM.set_name_description(backup_vm,"snapshot created by tisbackup on : %s"%(now.strftime("%Y-%m-%d %H:%M")))
size_backup = 0
for vbd in session.xenapi.VM.get_VBDs(backup_vm):
if session.xenapi.VBD.get_type(vbd) == 'CD' and session.xenapi.VBD.get_record(vbd)['empty'] == False:
@@ -233,11 +233,11 @@ class copy_vm_xcp(backup_generic):
vdi = session.xenapi.VBD.get_VDI(vbd)
if not 'NULL' in vdi:
size_backup = size_backup + int(session.xenapi.VDI.get_record(vdi)['physical_utilisation'])
result = (0,size_backup)
if self.delete_snapshot == 'no':
return result
#Disable automatic boot
if 'auto_poweron' in session.xenapi.VM.get_other_config(backup_vm):
session.xenapi.VM.remove_from_other_config(backup_vm, "auto_poweron")
@@ -260,25 +260,25 @@ class copy_vm_xcp(backup_generic):
if status_vm == "Running":
self.logger.debug("[%s] Starting in progress",self.backup_name)
if dry_run:
print("session.xenapi.VM.start(vm,False,True)")
print("session.xenapi.VM.start(vm,False,True)")
else:
session.xenapi.VM.start(vm,False,True)
return result
def do_backup(self,stats):
try:
timestamp = int(time.time())
cmd = self.copy_vm_to_sr(self.vm_name, self.storage_name, self.dry_run, delete_snapshot=self.delete_snapshot)
if cmd[0] == 0:
timeExec = int(time.time()) - timestamp
stats['log']='copy of %s to an other storage OK' % (self.backup_name)
stats['status']='OK'
stats['total_files_count'] = 1
stats['total_bytes'] = cmd[1]
stats['backup_location'] = self.storage_name
else:
stats['status']='ERROR'