###############################################################################
##
##   Copyright (C) 2008 Virtual Iron Software, Inc.
##
##                          All Rights Reserved
##
##   This program is free software; you can redistribute it and/or modify
##   it under the terms of the GNU General Public License and GNU Library
##   General Public License as published by the Free Software Foundation;
##   either version 2, or (at your option) any later version.
##
##   This program is distributed in the hope that it will be useful,
##   but WITHOUT ANY WARRANTY; without even the implied warranty of
##   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
##   GNU General Public License and GNU Library General Public License
##   for more details.
##
##   You should have received a copy of the GNU General Public License
##   and GNU Library General Public License along with this program; if
##   not, write to the Free Software Foundation, 51 Franklin Street, 
##   Fifth Floor, Boston, MA 02110-1301 
##
###############################################################################
##
##  Script      : snapshotExport 
##  Description : snapshot a VS's logical disks and export snapshots
##                to ManagementServer VirtualIron/vdisks directory
##  Requirements: VI version 4.2 or greater
##                only LogicalDisks are supported
##
##  Note1: due to runner.sh(.bat) limitations, VS can't have spaces in its name
##  Note2: customer must pause VS guest apps prior to running script
##
###############################################################################
from com.virtualiron.vce.mgmt.api import VirtualizationManager
from com.virtualiron.vce.mgmt.api.physical import LogicalDisk
from com.virtualiron.vce.mgmt.api.virtual import VirtualServer
from com.virtualiron.vce.mgmt.api.util import Units
from com.virtualiron.vce.mgmt.util import VersionNumber
import java.lang
import os
import string
import sys
import traceback

def Usage():
	if os.name == 'nt':
		command = 'runner.bat'
	else:
		command = 'runner.sh'
	print 'Usage: %s --inputfile=snapshotExport.py --vs=<VirtualServer> [--bootdisk]' % (command)
	sys.exit(1)

#
#  fraction of logical disk size for snapshot disk (default: 10%)
#
snapshotPercent = 0.1

#
# parse command line arguments
#         --vs        :  tame of VirtualServer to snapshot
#
vsName   = None
bootdiskonly = 0
for arg in sys.argv[1:]:
	if string.find(arg, "--vs=") != -1:
		tokens = string.splitfields(arg, "=")
		vsName = tokens[1]
	elif string.find(arg, "--bootdisk") != -1:
		tokens = string.splitfields(arg, "=")
		bootdiskonly = 1

#
# check if required arguments were specified
#
if vsName is None:
	Usage()

#
# get connection to Database
#
configurationManager = VirtualizationManager.getConfigurationManager()

#
# find VirtualServer 
#
vs = configurationManager.findObject(VirtualServer, vsName)
if vs is None:
	print 'FAIL to find VirtualServer: %s' % (vsName)
	sys.exit(1)

#
# if bootdisk only set, only export VS bootdisk if it's a LogicalDisk
# otherwise, export all VS LogicalDisks
#
diskList = java.util.ArrayList()
if bootdiskonly:
	device = vs.getBootDevice()
	if LogicalDisk.isAssignableFrom(device.getKind()):
		diskList.add(device)
	else:
		print 'BootDisk %s is not a LogicalDisk.' % (device)
		sys.exit(1)
else:
	for device in vs.getStorageDevices():
		if LogicalDisk.isAssignableFrom(device.getKind()):
			diskList.add(device)
		else:
			print 'StorageDevice %s is not a LogicalDisk.  Ignore.' % (device)

if diskList.size() == 0:
	print 'No LogicalDisks to snapshot and export'
	sys.exit(0)


#
# snapshot logical disks.  Applications running on the VS should be shutdown 
#  and their data quiesent prior to create a clean snapshot.

print 'Step: Snapshot all Logical Disks of VS %s' % (vs.getName())

exportList = java.util.ArrayList()
for disk in diskList:

	bytes = long(disk.getSize(Units.StorageUnit.BYTE) * snapshotPercent)
#
	print ' Job: Create Snapshot of %s' % (disk)
	try:
		jobName = java.lang.Long.toString(configurationManager.getLocalTime())
		job = configurationManager.createJob(jobName)
		job.begin()

		#
	        snapdisk = disk.createSnapshot(bytes, Units.StorageUnit.BYTE)
		job.addOperationDescription("Snapshot " + disk.getName(), disk, disk, disk)

		try:
			job.commit()
			exportList.add(snapdisk)
		except java.lang.Throwable, throw:
			throw.printStackTrace()
		except:
			traceback.print_exc()

	except java.lang.Throwable, throw:
		job.abort()		# if job fails, rollback
		throw.printStackTrace()
	except:
		job.abort()		# if job fails, rollback
		traceback.print_exc()


#
# fail if all snapshots failed
#
if exportList.size() == 0:
	print 'FAIL to snapshot any disks.  Stop'
	sys.exit(1)

#
#  export all snapshots on this list
#
foundry = configurationManager.getFoundryContext()
vdimgr  = foundry.getVdiManager()
print "Step: Export Snapshots to ManagementServer", vdimgr.getVhdRepositoryPath()

for disk in exportList:
	exportName = "%s_%s" % (vs.getName(), disk.getSnapshotParent())
	print ' Job: Export Snapshot of %s to %s.vhd' % (disk.getSnapshotParent(), exportName) 
	try:
		jobName = java.lang.Long.toString(configurationManager.getLocalTime())
		job = configurationManager.createJob(jobName)
		job.begin()

        	vdi = vdimgr.findAssociatedVirtualDiskImage(exportName)
	        if vdi is None:
       	        	vdi = vdimgr.createVirtualDiskImage(exportName)
        	disk.exportVirtualDiskImage(vdi)
		job.addOperationDescription("Export " + disk + " to " + vdi.getName(), disk, disk, disk)
	
		try:
			job.commit()
		except java.lang.Throwable, throw:
			throw.printStackTrace()
		except:
			traceback.print_exc()

	except java.lang.Throwable, throw:
		job.abort()		# if job fails, rollback
		throw.printStackTrace()
	except:
		job.abort()		# if job fails, rollback
		traceback.print_exc()

#
# delete logical disk snapshots
#
print 'Step: Delete LogicalDisk Snapshots for VS %s' % (vs)
for disk in exportList:
	try:
		jobName = java.lang.Long.toString(configurationManager.getLocalTime())
		job = configurationManager.createJob(jobName)
		job.begin()

  		lvmDiskGroup = disk.getParentLvmDiskGroup()

		# LvmDiskGroup.deleteLogicalDisk(LogicalDisk) was deprecated in 4.4
		#   use new call for 4.4 and greater
		version = VersionNumber.valueOf("4.4")
		currentVersion = VersionNumber.valueOf(VirtualizationManager.getSoftwareVersion())
	        if currentVersion.equals(version) == VersionNumber.LESS:
			lvmDiskGroup.deleteLogicalDisk(disk)
		else:
			isOnline = 1
			lvmDiskGroup.deleteLogicalDisk(disk, isOnline)

		job.addOperationDescription("Delete Snapshot Disk" + disk, disk, disk, disk)
		print " Job: Delete Snapshot of %s" % (disk.getSnapshotParent())

		try:
			job.commit()
		except java.lang.Throwable, throw:
			throw.printStackTrace()
		except:
			traceback.print_exc()

	except java.lang.Throwable, throw:
		job.abort()		# if job fails, rollback
		throw.printStackTrace()
	except:
		job.abort()		# if job fails, rollback
		traceback.print_exc()

sys.exit(0)
