#!/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
if os.path.exists("/opt/xensource/sm"):
    sys.path.extend(["/opt/xensource/sm/", "/usr/local/sbin/", "/sbin/"])
if os.path.exists("/usr/lib/xcp/sm"):
    sys.path.extend(["/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"])

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
import cloudstack_pluginlib as lib
import logging

lib.setup_logging("/var/log/cloud/cloud.log")

VHDUTIL = "vhd-util"
VHD_PREFIX = 'VHD-'
CLOUD_DIR = '/var/run/cloud_mount'

def echo(fn):
    def wrapped(*v, **k):
        name = fn.__name__
        logging.debug("#### CLOUD enter  %s ####" % name )
        res = fn(*v, **k)
        logging.debug("#### CLOUD exit  %s ####" % name )
        return res
    return wrapped


@echo
def create_secondary_storage_folder(session, args):
    local_mount_path = None

    logging.debug("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())
            nfsVersion = args["nfsVersion"]
            mount(remote_mount_path, local_mount_path, nfsVersion)

            # 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
            logging.debug(errMsg)
            raise xs_errors.XenError(errMsg)
        except:
            errMsg = "create_secondary_storage_folder failed."
            logging.debug(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

    logging.debug("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())
            nfsVersion = args["nfsVersion"]
            mount(remote_mount_path, local_mount_path, nfsVersion)

            # 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
            logging.debug(errMsg)
            raise xs_errors.XenError(errMsg)
        except:
            errMsg = "delete_secondary_storage_folder failed."
            logging.debug(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())
            nfsVersion = args["nfsVersion"]
            mount(templatePath, local_mount_path, nfsVersion)
            # 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()
            logging.debug("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)
            logging.debug("Set permissions on template and template.properties")

        except:
            errMsg = "post_create_private_template failed."
            logging.debug(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 = checkVolumeAvailability(path)
    else:
        exists = os.path.isfile(path)
        
    if not exists:
        errMsg = "File " + path + " does not exist."
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)
    return errMsg

def copyfile(fromFile, toFile, isISCSI):
    logging.debug("Starting to copy " + fromFile + " to " + toFile)
    errMsg = ''
    if isISCSI:
        bs = "4M"
    else:
        bs = "128k"

    try:
        cmd = ['dd', 'if=' + fromFile, 'iflag=direct', 'of=' + toFile, 'oflag=direct', 'bs=' + bs]
        txt = util.pread2(cmd)
    except:
        try:
            os.system("rm -f " + toFile)
        except:
            txt = ''
        txt = ''
        errMsg = "Error while copying " + fromFile + " to " + toFile + " in secondary storage"
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)

    logging.debug("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
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)
    logging.debug("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
        logging.debug(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
        logging.debug(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:
        checkVolumeAvailability(snapshotPath)
        baseCopyUuid = scanParent(snapshotPath)
    else:
        baseCopyUuid = getParent(snapshotPath, isISCSI)
    
    logging.debug("Base copy of snapshotUuid: " + snapshotUuid + " is " + baseCopyUuid)
    return baseCopyUuid

def setParent(parent, child):
    try:
        cmd = [VHDUTIL, "modify", "-p", parent, "-n", child]
        txt = util.pread2(cmd)
    except:
        errMsg = "Unexpected error while trying to set parent of " + child + " to " + parent 
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)
    logging.debug("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
        logging.debug(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
            logging.debug(errMsg)
            raise xs_errors.XenError(errMsg)
    return

def mount(remoteDir, localDir, nfsVersion=None):
    makedirs(localDir)
    options = "soft,tcp,timeo=133,retrans=1"
    if nfsVersion:
        options += ",vers=" + nfsVersion
    try: 
        cmd = ['mount', '-o', options, remoteDir, localDir]
        txt = util.pread2(cmd)
    except:
        txt = ''
        errMsg = "Unexpected error while trying to mount " + remoteDir + " to " + localDir 
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)
    logging.debug("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 
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)

    logging.debug("Successfully unmounted " + localDir)
    return

def mountSnapshotsDir(secondaryStorageMountPath, localMountPointPath, path):
    # 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.
    # path is like "snapshots/account/volumeId", we mount secondary_storage:/snapshots
    relativeDir = path.split("/")[0]
    restDir = "/".join(path.split("/")[1:])
    snapshotsDir = os.path.join(secondaryStorageMountPath, relativeDir)

    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.
        logging.debug("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, restDir)
    makedirs(backupsDir)
    return backupsDir

def unmountAll(path):
    try:
        for dir in os.listdir(path):
            if dir.isdigit():
                logging.debug("Unmounting Sub-Directory: " + dir)
                localMountPointPath = os.path.join(path, dir)
                umount(localMountPointPath)
    except:
        logging.debug("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:
        logging.debug("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
    logging.debug("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"
        logging.debug(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 checkVolumeAvailability(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
        logging.debug(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:
            logging.debug("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:
        logging.debug("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
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)

    return (status == "1")  

def getVhdParent(session, args):
    logging.debug("getParent with " + str(args))
    primaryStorageSRUuid      = args['primaryStorageSRUuid']
    snapshotUuid              = args['snapshotUuid']
    isISCSI                   = getIsTrueString(args['isISCSI']) 

    primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
    logging.debug("primarySRPath: " + primarySRPath)

    baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI)

    return  baseCopyUuid

def getSnapshotSize(session, args):
    primaryStorageSRUuid      = args['primaryStorageSRUuid']
    snapshotUuid              = args['snapshotUuid']
    isISCSI                   = getIsTrueString(args['isISCSI'])

    primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
    logging.debug("primarySRPath: " + primarySRPath)

    snapshotVHD  = getVHD(snapshotUuid, isISCSI)
    snapshotPath = os.path.join(primarySRPath, snapshotVHD)
    physicalSize = vhdutil.getSizePhys(snapshotPath)
    return str(physicalSize)

def backupSnapshot(session, args):
    logging.debug("Called backupSnapshot with " + str(args))
    primaryStorageSRUuid      = args['primaryStorageSRUuid']
    secondaryStorageMountPath = args['secondaryStorageMountPath']
    snapshotUuid              = args['snapshotUuid']
    prevBackupUuid            = args['prevBackupUuid']
    backupUuid                = args['backupUuid']
    isISCSI                   = getIsTrueString(args['isISCSI'])
    path = args['path']
    localMountPoint = args['localMountPoint']
    primarySRPath = getPrimarySRPath(primaryStorageSRUuid, isISCSI)
    logging.debug("primarySRPath: " + primarySRPath)

    baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI)
    baseCopyVHD  = getVHD(baseCopyUuid, isISCSI)
    baseCopyPath = os.path.join(primarySRPath, baseCopyVHD)
    logging.debug("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, localMountPoint, path)
    logging.debug("Backups dir " + backupsDir)
    prevBackupUuid = prevBackupUuid.split("/")[-1]
    # Check existence of snapshot on primary storage
    isfile(baseCopyPath, isISCSI)
    physicalSize = vhdutil.getSizePhys(baseCopyPath)
    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)
    logging.debug("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 + "#" + str(physicalSize)
    return txt

@echo
def deleteSnapshotBackup(session, args):
    logging.debug("Calling deleteSnapshotBackup with " + str(args))
    secondaryStorageMountPath = args['secondaryStorageMountPath']
    backupUUID                = args['backupUUID']
    path = args['path']
    localMountPoint = args['localMountPoint']

    backupsDir = mountSnapshotsDir(secondaryStorageMountPath, localMountPoint, path)
    # chdir to the backupsDir for convenience
    chdir(backupsDir)

    backupVHD = getBackupVHD(backupUUID)
    logging.debug("checking existence of " + backupVHD)

    # The backupVHD is on secondary which is NFS and not ISCSI.
    if not os.path.isfile(backupVHD):
        logging.debug("backupVHD " + backupVHD + "does not exist. Not trying to delete it")
        return "1"
    logging.debug("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
        logging.debug(errMsg)
        raise xs_errors.XenError(errMsg)

    return "1"
   
@echo
def revert_memory_snapshot(session, args):
    logging.debug("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
        logging.debug(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, "getSnapshotSize":getSnapshotSize})
    
