# 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.
'''
Created on June 2, 2011

'''
from OvmCommonModule import *
from OvmStoragePoolModule import OvmStoragePool
from OVSXUtility import xen_create_disk
from OvmHostModule import OvmHost
import os

logger = OvmLogger("OvmVolume")

class OvmVolumeDecoder(json.JSONDecoder):
    def decode(self, jStr):
        deDict = asciiLoads(jStr)
        vol = OvmVolume()
        setAttrFromDict(vol, 'uuid', deDict)
        setAttrFromDict(vol, 'size', deDict, long)
        setAttrFromDict(vol, 'poolUuid', deDict)
        return vol

class OvmVolumeEncoder(json.JSONEncoder):
    def default(self, obj):
        if not isinstance(obj, OvmVolume): raise Exception("%s is not instance of OvmVolume"%type(obj))
        dct = {}
        safeDictSet(obj, dct, 'name')
        safeDictSet(obj, dct, 'uuid')
        safeDictSet(obj, dct, 'poolUuid')
        safeDictSet(obj, dct, 'path')
        safeDictSet(obj, dct, 'size')
        return dct

def toOvmVolume(jStr):
    return json.loads(jStr, cls=OvmVolumeDecoder)

def fromOvmVolume(vol):
    return normalizeToGson(json.dumps(vol, cls=OvmVolumeEncoder))

class OvmVolume(OvmObject):
    name = ''
    uuid = ''
    poolUuid = ''
    path = ''
    size = 0

    @staticmethod
    def createDataDisk(poolUuid, size, isRoot):
        try:
            vol = OvmVolume()
            vol.size = long(size)
            vol.poolUuid = poolUuid
            pool = OvmStoragePool()
            sr = pool._getSrByNameLable(vol.poolUuid)
            if isRoot:
                path = join(sr.mountpoint, 'running_pool', get_uuid())
            else:
                path = join(sr.mountpoint, 'shareDisk')
            if not exists(path): os.makedirs(path)
            freeSpace = pool._getSpaceinfoOfDir(path)
            if freeSpace < vol.size:
                raise Exception("%s has not enough space (available:%s, required:%s"%(path, freeSpace, vol.size))

            vol.uuid = get_uuid()
            vol.name = vol.uuid + '.raw'
            filePath = join(path, vol.name)
            exceptionIfNoSuccess(xen_create_disk(filePath, BytesToM(vol.size)), "Create datadisk %s failed"%filePath)
            vol.path = filePath
            rs = fromOvmVolume(vol)
            logger.debug(OvmVolume.createDataDisk, rs)
            return rs
        except Exception, e:
            errmsg = fmt_err_msg(e)
            logger.error(OvmVolume.createDataDisk, errmsg)
            raise XmlRpcFault(toErrCode(OvmVolume, OvmVolume.createDataDisk, errmsg))

    @staticmethod
    def createFromTemplate(poolUuid, templateUrl):
        try:
            if not exists(templateUrl):
                raise Exception("Cannot find template:%s"%templateUrl)
            sr = OvmStoragePool()._getSrByNameLable(poolUuid)
            volDirUuid = get_uuid()
            volUuid = get_uuid()
            priStorageMountPoint = sr.mountpoint
            volDir = join(priStorageMountPoint, 'running_pool', volDirUuid)
            if exists(volDir):
                raise Exception("Volume dir %s already existed, can not override"%volDir)
            os.makedirs(volDir)
            OvmStoragePool()._checkDirSizeForImage(volDir, templateUrl)
            volName = volUuid + '.raw'
            tgt = join(volDir, volName)
            cpVolCmd = ['cp', templateUrl, tgt]
            doCmd(cpVolCmd)
            volSize = os.path.getsize(tgt)
            vol = OvmVolume()
            vol.name = volName
            vol.path = tgt
            vol.size = volSize
            vol.uuid = volUuid
            vol.poolUuid = poolUuid
            rs = fromOvmVolume(vol)
            logger.debug(OvmVolume.createFromTemplate, rs)
            return rs
        except Exception, e:
            errmsg = fmt_err_msg(e)
            logger.error(OvmVolume.createFromTemplate, errmsg)
            raise XmlRpcFault(toErrCode(OvmVolume, OvmVolume.createFromTemplate), errmsg)

    @staticmethod
    def destroy(poolUuid, path):
        try:
            OvmStoragePool()._getSrByNameLable(poolUuid)
            if not exists(path): raise Exception("Cannot find %s"%path)
            dir = dirname(path)
            if exists(join(dir, 'vm.cfg')):
                # delete root disk
                vmNamePath = join(dir, 'vmName')
                if exists(vmNamePath):
                    vmNameFd = open(vmNamePath, 'r')
                    vmName = vmNameFd.readline()
                    vmName = vmName.rstrip('\n')
                    link = join(dirname(dir), vmName)
                    doCmd(['rm', '-rf', link])
                    vmNameFd.close()
                else:
                    logger.warning(OvmVolume.destroy, "Can not find vmName file in %s"%dir)
                doCmd(['rm','-rf', dir])
            else:
                doCmd(['rm', path])
            return SUCC()
        except Exception, e:
            errmsg = fmt_err_msg(e)
            logger.error(OvmVolume.destroy, errmsg)
            raise XmlRpcFault(toErrCode(OvmVolume, OvmVolume.destroy), errmsg)



if __name__ == "__main__":
    print OvmVolume.detachOrAttachIso(sys.argv[1], '', False)
