mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			600 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			600 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/python
 | |
| # Licensed to the Apache Software Foundation (ASF) under one
 | |
| # or more contributor license agreements.  See the NOTICE file
 | |
| # distributed with this work for additional information
 | |
| # regarding copyright ownership.  The ASF licenses this file
 | |
| # to you under the Apache License, Version 2.0 (the
 | |
| # "License"); you may not use this file except in compliance
 | |
| # with the License.  You may obtain a copy of the License at
 | |
| # 
 | |
| #   http://www.apache.org/licenses/LICENSE-2.0
 | |
| # 
 | |
| # Unless required by applicable law or agreed to in writing,
 | |
| # software distributed under the License is distributed on an
 | |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 | |
| # KIND, either express or implied.  See the License for the
 | |
| # specific language governing permissions and limitations
 | |
| # under the License.
 | |
| 
 | |
| # Version @VERSION@
 | |
| #
 | |
| # A plugin for executing script needed by vmops cloud 
 | |
| 
 | |
| import os, sys, time
 | |
| import XenAPIPlugin
 | |
| sys.path.append("/opt/xensource/sm/")
 | |
| import SR, VDI, SRCommand, util, lvutil
 | |
| from util import CommandException
 | |
| import vhdutil
 | |
| import shutil
 | |
| import lvhdutil
 | |
| import errno
 | |
| import subprocess
 | |
| import xs_errors
 | |
| import cleanup
 | |
| import stat
 | |
| import random
 | |
| 
 | |
| VHD_UTIL = '/opt/xensource/bin/vhd-util'
 | |
| VHD_PREFIX = 'VHD-'
 | |
| CLOUD_DIR = '/var/run/cloud_mount'
 | |
| 
 | |
| def echo(fn):
 | |
|     def wrapped(*v, **k):
 | |
|         name = fn.__name__
 | |
|         util.SMlog("#### VMOPS enter  %s ####" % name )
 | |
|         res = fn(*v, **k)
 | |
|         util.SMlog("#### VMOPS exit  %s ####" % name )
 | |
|         return res
 | |
|     return wrapped
 | |
| 
 | |
| 
 | |
| @echo
 | |
| def create_secondary_storage_folder(session, args):
 | |
|     local_mount_path = None
 | |
| 
 | |
|     util.SMlog("create_secondary_storage_folder, args: " + str(args))
 | |
| 
 | |
|     try:
 | |
|         try:
 | |
|             # Mount the remote resource folder locally
 | |
|             remote_mount_path = args["remoteMountPath"]
 | |
|             local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid())
 | |
|             mount(remote_mount_path, local_mount_path)
 | |
| 
 | |
|             # Create the new folder
 | |
|             new_folder = local_mount_path + "/" + args["newFolder"]
 | |
|             if not os.path.isdir(new_folder):
 | |
|                 current_umask = os.umask(0)
 | |
|                 os.makedirs(new_folder)
 | |
|                 os.umask(current_umask)
 | |
|         except OSError, (errno, strerror):
 | |
|             errMsg = "create_secondary_storage_folder failed: errno: " + str(errno) + ", strerr: " + strerror
 | |
|             util.SMlog(errMsg)
 | |
|             raise xs_errors.XenError(errMsg)
 | |
|         except:
 | |
|             errMsg = "create_secondary_storage_folder failed."
 | |
|             util.SMlog(errMsg)
 | |
|             raise xs_errors.XenError(errMsg)
 | |
|     finally:
 | |
|         if local_mount_path != None:
 | |
|             # Unmount the local folder
 | |
|             umount(local_mount_path)
 | |
|             # Remove the local folder
 | |
|             os.system("rmdir " + local_mount_path)
 | |
|         
 | |
|     return "1"
 | |
| 
 | |
| @echo
 | |
| def delete_secondary_storage_folder(session, args):
 | |
|     local_mount_path = None
 | |
| 
 | |
|     util.SMlog("delete_secondary_storage_folder, args: " + str(args))
 | |
| 
 | |
|     try:
 | |
|         try:
 | |
|             # Mount the remote resource folder locally
 | |
|             remote_mount_path = args["remoteMountPath"]
 | |
|             local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid())
 | |
|             mount(remote_mount_path, local_mount_path)
 | |
| 
 | |
|             # Delete the specified folder
 | |
|             folder = local_mount_path + "/" + args["folder"]
 | |
|             if os.path.isdir(folder):
 | |
|                 os.system("rm -f " + folder + "/*")
 | |
|                 os.system("rmdir " + folder)
 | |
|         except OSError, (errno, strerror):
 | |
|             errMsg = "delete_secondary_storage_folder failed: errno: " + str(errno) + ", strerr: " + strerror
 | |
|             util.SMlog(errMsg)
 | |
|             raise xs_errors.XenError(errMsg)
 | |
|         except:
 | |
|             errMsg = "delete_secondary_storage_folder failed."
 | |
|             util.SMlog(errMsg)
 | |
|             raise xs_errors.XenError(errMsg)
 | |
|     finally:
 | |
|         if local_mount_path != None:
 | |
|             # Unmount the local folder
 | |
|             umount(local_mount_path)
 | |
|             # Remove the local folder
 | |
|             os.system("rmdir " + local_mount_path)
 | |
|         
 | |
|     return "1"
 | |
|      
 | |
| @echo
 | |
| def post_create_private_template(session, args):
 | |
|     local_mount_path = None
 | |
|     try:
 | |
|         try:
 | |
|             # get local template folder 
 | |
|             templatePath = args["templatePath"]
 | |
|             local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid())
 | |
|             mount(templatePath, local_mount_path)
 | |
|             # Retrieve args
 | |
|             filename = args["templateFilename"]
 | |
|             name = args["templateName"]
 | |
|             description = args["templateDescription"]
 | |
|             checksum = args["checksum"]
 | |
|             file_size = args["size"]
 | |
|             virtual_size = args["virtualSize"]
 | |
|             template_id = args["templateId"]
 | |
|            
 | |
|             # Create the template.properties file
 | |
|             template_properties_install_path = local_mount_path + "/template.properties"
 | |
|             f = open(template_properties_install_path, "w")
 | |
|             f.write("filename=" + filename + "\n")
 | |
|             f.write("vhd=true\n")
 | |
|             f.write("id=" + template_id + "\n")
 | |
|             f.write("vhd.filename=" + filename + "\n")
 | |
|             f.write("public=false\n")
 | |
|             f.write("uniquename=" + name + "\n")
 | |
|             f.write("vhd.virtualsize=" + virtual_size + "\n")
 | |
|             f.write("virtualsize=" + virtual_size + "\n")
 | |
|             f.write("checksum=" + checksum + "\n")
 | |
|             f.write("hvm=true\n")
 | |
|             f.write("description=" + description + "\n")
 | |
|             f.write("vhd.size=" + str(file_size) + "\n")
 | |
|             f.write("size=" + str(file_size) + "\n")
 | |
|             f.close()
 | |
|             util.SMlog("Created template.properties file")
 | |
|            
 | |
|             # Set permissions
 | |
|             permissions = stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH
 | |
|             os.chmod(template_properties_install_path, permissions)
 | |
|             util.SMlog("Set permissions on template and template.properties")
 | |
| 
 | |
|         except:
 | |
|             errMsg = "post_create_private_template failed."
 | |
|             util.SMlog(errMsg)
 | |
|             raise xs_errors.XenError(errMsg)
 | |
| 
 | |
|     finally:
 | |
|         if local_mount_path != None:
 | |
|             # Unmount the local folder
 | |
|             umount(local_mount_path)
 | |
|             # Remove the local folder
 | |
|             os.system("rmdir " + local_mount_path)
 | |
|     return "1" 
 | |
|   
 | |
| def isfile(path, isISCSI):
 | |
|     errMsg = ''
 | |
|     exists = True
 | |
|     if isISCSI:
 | |
|         exists = checkVolumeAvailablility(path)
 | |
|     else:
 | |
|         exists = os.path.isfile(path)
 | |
|         
 | |
|     if not exists:
 | |
|         errMsg = "File " + path + " does not exist."
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     return errMsg
 | |
| 
 | |
| def copyfile(fromFile, toFile, isISCSI):
 | |
|     util.SMlog("Starting to copy " + fromFile + " to " + toFile)
 | |
|     errMsg = ''
 | |
|     try:
 | |
|         cmd = ['dd', 'if=' + fromFile, 'of=' + toFile, 'bs=4M']
 | |
|         txt = util.pread2(cmd)
 | |
|     except:
 | |
|         try:
 | |
|             os.system("rm -f " + toFile)
 | |
|         except:
 | |
|             txt = ''
 | |
|         txt = ''
 | |
|         errMsg = "Error while copying " + fromFile + " to " + toFile + " in secondary storage"
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
| 
 | |
|     util.SMlog("Successfully copied " + fromFile + " to " + toFile)
 | |
|     return errMsg
 | |
| 
 | |
| def chdir(path):
 | |
|     try:
 | |
|         os.chdir(path)
 | |
|     except OSError, (errno, strerror):
 | |
|         errMsg = "Unable to chdir to " + path + " because of OSError with errno: " + str(errno) + " and strerr: " + strerror
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     util.SMlog("Chdired to " + path)
 | |
|     return
 | |
| 
 | |
| def scanParent(path):
 | |
|     # Do a scan for the parent for ISCSI volumes
 | |
|     # Note that the parent need not be visible on the XenServer
 | |
|     parentUUID = ''
 | |
|     try:
 | |
|         lvName = os.path.basename(path)
 | |
|         dirname = os.path.dirname(path)
 | |
|         vgName = os.path.basename(dirname) 
 | |
|         vhdInfo = vhdutil.getVHDInfoLVM(lvName, lvhdutil.extractUuid, vgName)
 | |
|         parentUUID = vhdInfo.parentUuid
 | |
|     except:
 | |
|         errMsg = "Could not get vhd parent of " + path
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     return parentUUID
 | |
| 
 | |
| def getParent(path, isISCSI):
 | |
|     parentUUID = ''
 | |
|     try :
 | |
|         if isISCSI:
 | |
|             parentUUID = vhdutil.getParent(path, lvhdutil.extractUuid)
 | |
|         else:
 | |
|             parentUUID = vhdutil.getParent(path, cleanup.FileVDI.extractUuid)
 | |
|     except:
 | |
|         errMsg = "Could not get vhd parent of " + path
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     return parentUUID
 | |
| 
 | |
| def getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI):
 | |
|     snapshotVHD    = getVHD(snapshotUuid, isISCSI)
 | |
|     snapshotPath   = os.path.join(primarySRPath, snapshotVHD)
 | |
| 
 | |
|     baseCopyUuid = ''
 | |
|     if isISCSI:
 | |
|         checkVolumeAvailablility(snapshotPath)
 | |
|         baseCopyUuid = scanParent(snapshotPath)
 | |
|     else:
 | |
|         baseCopyUuid = getParent(snapshotPath, isISCSI)
 | |
|     
 | |
|     util.SMlog("Base copy of snapshotUuid: " + snapshotUuid + " is " + baseCopyUuid)
 | |
|     return baseCopyUuid
 | |
| 
 | |
| def setParent(parent, child):
 | |
|     try:
 | |
|         cmd = [VHD_UTIL, "modify", "-p", parent, "-n", child]
 | |
|         txt = util.pread2(cmd)
 | |
|     except:
 | |
|         errMsg = "Unexpected error while trying to set parent of " + child + " to " + parent 
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     util.SMlog("Successfully set parent of " + child + " to " + parent)
 | |
|     return
 | |
| 
 | |
| def rename(originalVHD, newVHD):
 | |
|     try:
 | |
|         os.rename(originalVHD, newVHD)
 | |
|     except OSError, (errno, strerror):
 | |
|         errMsg = "OSError while renaming " + origiinalVHD + " to " + newVHD + "with errno: " + str(errno) + " and strerr: " + strerror
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     return
 | |
| 
 | |
| def makedirs(path):
 | |
|     if not os.path.isdir(path):
 | |
|         try:
 | |
|             os.makedirs(path)
 | |
|         except OSError, (errno, strerror):
 | |
|             umount(path)
 | |
|             if os.path.isdir(path):
 | |
|                 return
 | |
|             errMsg = "OSError while creating " + path + " with errno: " + str(errno) + " and strerr: " + strerror
 | |
|             util.SMlog(errMsg)
 | |
|             raise xs_errors.XenError(errMsg)
 | |
|     return
 | |
| 
 | |
| def mount(remoteDir, localDir):
 | |
|     makedirs(localDir)
 | |
|     options = "soft,tcp,timeo=133,retrans=1"
 | |
|     try: 
 | |
|         cmd = ['mount', '-o', options, remoteDir, localDir]
 | |
|         txt = util.pread2(cmd)
 | |
|     except:
 | |
|         txt = ''
 | |
|         errMsg = "Unexpected error while trying to mount " + remoteDir + " to " + localDir 
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     util.SMlog("Successfully mounted " + remoteDir + " to " + localDir)
 | |
| 
 | |
|     return
 | |
| 
 | |
| def umount(localDir):
 | |
|     try: 
 | |
|         cmd = ['umount', localDir]
 | |
|         util.pread2(cmd)
 | |
|     except CommandException:
 | |
|         errMsg = "CommandException raised while trying to umount " + localDir 
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
| 
 | |
|     util.SMlog("Successfully unmounted " + localDir)
 | |
|     return
 | |
| 
 | |
| def mountSnapshotsDir(secondaryStorageMountPath, relativeDir, dcId, accountId, instanceId, secHostId):
 | |
|     # The aim is to mount secondaryStorageMountPath on 
 | |
|     # And create <accountId>/<instanceId> dir on it, if it doesn't exist already.
 | |
|     # Assuming that secondaryStorageMountPath  exists remotely
 | |
| 
 | |
|     # Just mount secondaryStorageMountPath/<relativeDir>/SecondaryStorageHost/ everytime
 | |
|     # Never unmount.
 | |
|     snapshotsDir = os.path.join(secondaryStorageMountPath, relativeDir)
 | |
| 
 | |
|     # Mkdir local mount point dir, if it doesn't exist.
 | |
|     localMountPointPath = os.path.join(CLOUD_DIR, dcId)
 | |
|     localMountPointPath = os.path.join(localMountPointPath, relativeDir, secHostId)
 | |
| 
 | |
|     makedirs(localMountPointPath)
 | |
|     # if something is not mounted already on localMountPointPath,
 | |
|     # mount secondaryStorageMountPath on localMountPath
 | |
|     if os.path.ismount(localMountPointPath):
 | |
|         # There is more than one secondary storage per zone.
 | |
|         # And we are mounting each sec storage under a zone-specific directory
 | |
|         # So two secondary storage snapshot dirs will never get mounted on the same point on the same XenServer.
 | |
|         util.SMlog("The remote snapshots directory has already been mounted on " + localMountPointPath)
 | |
|     else:
 | |
|         mount(snapshotsDir, localMountPointPath)
 | |
| 
 | |
|     # Create accountId/instanceId dir on localMountPointPath, if it doesn't exist
 | |
|     backupsDir = os.path.join(localMountPointPath, accountId)
 | |
|     backupsDir = os.path.join(backupsDir, instanceId)
 | |
|     makedirs(backupsDir)
 | |
|     return backupsDir
 | |
| 
 | |
| def unmountAll(path):
 | |
|     try:
 | |
|         for dir in os.listdir(path):
 | |
|             if dir.isdigit():
 | |
|                 util.SMlog("Unmounting Sub-Directory: " + dir)
 | |
|                 localMountPointPath = os.path.join(path, dir)
 | |
|                 umount(localMountPointPath)
 | |
|     except:
 | |
|         util.SMlog("Ignoring the error while trying to unmount the snapshots dir")
 | |
| 
 | |
| @echo
 | |
| def unmountSnapshotsDir(session, args):
 | |
|     dcId = args['dcId']
 | |
|     localMountPointPath = os.path.join(CLOUD_DIR, dcId)
 | |
|     localMountPointPath = os.path.join(localMountPointPath, "snapshots")
 | |
|     unmountAll(localMountPointPath)
 | |
|     try:
 | |
|         umount(localMountPointPath)
 | |
|     except:
 | |
|         util.SMlog("Ignoring the error while trying to unmount the snapshots dir.")
 | |
| 
 | |
|     return "1"
 | |
| 
 | |
| def getPrimarySRPath(primaryStorageSRUuid, isISCSI):
 | |
|     if isISCSI:
 | |
|         primarySRDir = lvhdutil.VG_PREFIX + primaryStorageSRUuid
 | |
|         return os.path.join(lvhdutil.VG_LOCATION, primarySRDir)
 | |
|     else:
 | |
|         return os.path.join(SR.MOUNT_BASE, primaryStorageSRUuid)
 | |
| 
 | |
| def getBackupVHD(UUID):
 | |
|     return UUID + '.' + SR.DEFAULT_TAP
 | |
| 
 | |
| def getVHD(UUID, isISCSI):
 | |
|     if isISCSI:
 | |
|         return VHD_PREFIX + UUID
 | |
|     else:
 | |
|         return UUID + '.' + SR.DEFAULT_TAP
 | |
| 
 | |
| def getIsTrueString(stringValue):
 | |
|     booleanValue = False
 | |
|     if (stringValue and stringValue == 'true'):
 | |
|         booleanValue = True
 | |
|     return booleanValue 
 | |
| 
 | |
| def makeUnavailable(uuid, primarySRPath, isISCSI):
 | |
|     if not isISCSI:
 | |
|         return
 | |
|     VHD = getVHD(uuid, isISCSI)
 | |
|     path = os.path.join(primarySRPath, VHD)
 | |
|     manageAvailability(path, '-an')
 | |
|     return
 | |
| 
 | |
| def manageAvailability(path, value):
 | |
|     if path.__contains__("/var/run/sr-mount"):
 | |
|         return
 | |
|     util.SMlog("Setting availability of " + path + " to " + value)
 | |
|     try:
 | |
|         cmd = ['/usr/sbin/lvchange', value, path]
 | |
|         util.pread2(cmd)
 | |
|     except: #CommandException, (rc, cmdListStr, stderr):
 | |
|         #errMsg = "CommandException thrown while executing: " + cmdListStr + " with return code: " + str(rc) + " and stderr: " + stderr
 | |
|         errMsg = "Unexpected exception thrown by lvchange"
 | |
|         util.SMlog(errMsg)
 | |
|         if value == "-ay":
 | |
|             # Raise an error only if we are trying to make it available.
 | |
|             # Just warn if we are trying to make it unavailable after the 
 | |
|             # snapshot operation is done.
 | |
|             raise xs_errors.XenError(errMsg)
 | |
|     return
 | |
| 
 | |
| 
 | |
| def checkVolumeAvailablility(path):
 | |
|     try:
 | |
|         if not isVolumeAvailable(path):
 | |
|             # The VHD file is not available on XenSever. The volume is probably
 | |
|             # inactive or detached.
 | |
|             # Do lvchange -ay to make it available on XenServer
 | |
|             manageAvailability(path, '-ay')
 | |
|     except:
 | |
|         errMsg = "Could not determine status of ISCSI path: " + path
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     
 | |
|     success = False
 | |
|     i = 0
 | |
|     while i < 6:
 | |
|         i = i + 1
 | |
|         # Check if the vhd is actually visible by checking for the link
 | |
|         # set isISCSI to true
 | |
|         success = isVolumeAvailable(path)
 | |
|         if success:
 | |
|             util.SMlog("Made vhd: " + path + " available and confirmed that it is visible")
 | |
|             break
 | |
| 
 | |
|         # Sleep for 10 seconds before checking again.
 | |
|         time.sleep(10)
 | |
| 
 | |
|     # If not visible within 1 min fail
 | |
|     if not success:
 | |
|         util.SMlog("Could not make vhd: " +  path + " available despite waiting for 1 minute. Does it exist?")
 | |
| 
 | |
|     return success
 | |
| 
 | |
| def isVolumeAvailable(path):
 | |
|     # Check if iscsi volume is available on this XenServer.
 | |
|     status = "0"
 | |
|     try:
 | |
|         p = subprocess.Popen(["/bin/bash", "-c", "if [ -L " + path + " ]; then echo 1; else echo 0;fi"], stdout=subprocess.PIPE)
 | |
|         status = p.communicate()[0].strip("\n")
 | |
|     except:
 | |
|         errMsg = "Could not determine status of ISCSI path: " + path
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
| 
 | |
|     return (status == "1")  
 | |
| 
 | |
| def getVhdParent(session, args):
 | |
|     util.SMlog("getParent with " + str(args))
 | |
|     primaryStorageSRUuid      = args['primaryStorageSRUuid']
 | |
|     snapshotUuid              = args['snapshotUuid']
 | |
|     isISCSI                   = getIsTrueString(args['isISCSI']) 
 | |
| 
 | |
|     primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
 | |
|     util.SMlog("primarySRPath: " + primarySRPath)
 | |
| 
 | |
|     baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI)
 | |
| 
 | |
|     return  baseCopyUuid
 | |
| 
 | |
| 
 | |
| def backupSnapshot(session, args):
 | |
|     util.SMlog("Called backupSnapshot with " + str(args))
 | |
|     primaryStorageSRUuid      = args['primaryStorageSRUuid']
 | |
|     dcId                      = args['dcId']
 | |
|     accountId                 = args['accountId']
 | |
|     volumeId                  = args['volumeId']
 | |
|     secondaryStorageMountPath = args['secondaryStorageMountPath']
 | |
|     snapshotUuid              = args['snapshotUuid']
 | |
|     prevBackupUuid            = args['prevBackupUuid']
 | |
|     backupUuid                = args['backupUuid']
 | |
|     isISCSI                   = getIsTrueString(args['isISCSI'])
 | |
|     secHostId                 = args['secHostId']
 | |
| 
 | |
|     primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
 | |
|     util.SMlog("primarySRPath: " + primarySRPath)
 | |
| 
 | |
|     baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI)
 | |
|     baseCopyVHD  = getVHD(baseCopyUuid, isISCSI)
 | |
|     baseCopyPath = os.path.join(primarySRPath, baseCopyVHD)
 | |
|     util.SMlog("Base copy path: " + baseCopyPath)
 | |
| 
 | |
| 
 | |
|     # Mount secondary storage mount path on XenServer along the path
 | |
|     # /var/run/sr-mount/<dcId>/snapshots/ and create <accountId>/<volumeId> dir
 | |
|     # on it.
 | |
|     backupsDir = mountSnapshotsDir(secondaryStorageMountPath, "snapshots", dcId, accountId, volumeId, secHostId)
 | |
|     util.SMlog("Backups dir " + backupsDir)
 | |
| 
 | |
|     # Check existence of snapshot on primary storage
 | |
|     isfile(baseCopyPath, isISCSI)
 | |
|     if prevBackupUuid:
 | |
|         # Check existence of prevBackupFile
 | |
|         prevBackupVHD = getBackupVHD(prevBackupUuid)
 | |
|         prevBackupFile = os.path.join(backupsDir, prevBackupVHD)
 | |
|         isfile(prevBackupFile, False)
 | |
| 
 | |
|     # copy baseCopyPath to backupsDir with new uuid
 | |
|     backupVHD = getBackupVHD(backupUuid)  
 | |
|     backupFile = os.path.join(backupsDir, backupVHD)
 | |
|     util.SMlog("Back up " + baseCopyUuid + " to Secondary Storage as " + backupUuid)
 | |
|     copyfile(baseCopyPath, backupFile, isISCSI)
 | |
|     vhdutil.setHidden(backupFile, False)
 | |
| 
 | |
|     # Because the primary storage is always scanned, the parent of this base copy is always the first base copy.
 | |
|     # We don't want that, we want a chain of VHDs each of which is a delta from the previous.
 | |
|     # So set the parent of the current baseCopyVHD to prevBackupVHD 
 | |
|     if prevBackupUuid:
 | |
|         # If there was a previous snapshot
 | |
|         setParent(prevBackupFile, backupFile)
 | |
| 
 | |
|     txt = "1#" + backupUuid
 | |
|     return txt
 | |
| 
 | |
| @echo
 | |
| def deleteSnapshotBackup(session, args):
 | |
|     util.SMlog("Calling deleteSnapshotBackup with " + str(args))
 | |
|     dcId                      = args['dcId']
 | |
|     accountId                 = args['accountId']
 | |
|     volumeId                  = args['volumeId']
 | |
|     secondaryStorageMountPath = args['secondaryStorageMountPath']
 | |
|     backupUUID                = args['backupUUID']
 | |
| 
 | |
|     backupsDir = mountSnapshotsDir(secondaryStorageMountPath, "snapshots", dcId, accountId, volumeId)
 | |
|     # chdir to the backupsDir for convenience
 | |
|     chdir(backupsDir)
 | |
| 
 | |
|     backupVHD = getBackupVHD(backupUUID)
 | |
|     util.SMlog("checking existence of " + backupVHD)
 | |
| 
 | |
|     # The backupVHD is on secondary which is NFS and not ISCSI.
 | |
|     if not os.path.isfile(backupVHD):
 | |
|         util.SMlog("backupVHD " + backupVHD + "does not exist. Not trying to delete it")
 | |
|         return "1"
 | |
|     util.SMlog("backupVHD " + backupVHD + " exists.")
 | |
|         
 | |
|     # Just delete the backupVHD
 | |
|     try:
 | |
|         os.remove(backupVHD)
 | |
|     except OSError, (errno, strerror):
 | |
|         errMsg = "OSError while removing " + backupVHD + " with errno: " + str(errno) + " and strerr: " + strerror
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
| 
 | |
|     return "1"
 | |
|    
 | |
| @echo
 | |
| def revert_memory_snapshot(session, args):
 | |
|     util.SMlog("Calling revert_memory_snapshot with " + str(args))
 | |
|     vmName = args['vmName']
 | |
|     snapshotUUID = args['snapshotUUID']
 | |
|     oldVmUuid = args['oldVmUuid']
 | |
|     snapshotMemory = args['snapshotMemory']
 | |
|     hostUUID = args['hostUUID']
 | |
|     try:
 | |
|         cmd = '''xe vbd-list vm-uuid=%s | grep 'vdi-uuid' | grep -v 'not in database' | sed -e 's/vdi-uuid ( RO)://g' ''' % oldVmUuid
 | |
|         vdiUuids = os.popen(cmd).read().split()
 | |
|         cmd2 = '''xe vm-param-get param-name=power-state uuid=''' + oldVmUuid
 | |
|         if os.popen(cmd2).read().split()[0] != 'halted':
 | |
|             os.system("xe vm-shutdown force=true vm=" + vmName)
 | |
|         os.system("xe vm-destroy uuid=" + oldVmUuid)
 | |
|         os.system("xe snapshot-revert snapshot-uuid=" + snapshotUUID)
 | |
|         if snapshotMemory == 'true':
 | |
|             os.system("xe vm-resume vm=" + vmName + " on=" + hostUUID)
 | |
|         for vdiUuid in vdiUuids:
 | |
|             os.system("xe vdi-destroy uuid=" + vdiUuid)
 | |
|     except OSError, (errno, strerror):
 | |
|         errMsg = "OSError while reverting vm " + vmName + " to snapshot " + snapshotUUID + " with errno: " + str(errno) + " and strerr: " + strerror
 | |
|         util.SMlog(errMsg)
 | |
|         raise xs_errors.XenError(errMsg)
 | |
|     return "0"
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     XenAPIPlugin.dispatch({"getVhdParent":getVhdParent,  "create_secondary_storage_folder":create_secondary_storage_folder, "delete_secondary_storage_folder":delete_secondary_storage_folder, "post_create_private_template":post_create_private_template, "backupSnapshot": backupSnapshot, "deleteSnapshotBackup": deleteSnapshotBackup, "unmountSnapshotsDir": unmountSnapshotsDir, "revert_memory_snapshot":revert_memory_snapshot})
 | |
|     
 | |
| 
 |