import os.path
import traceback

from kvmagent import kvmagent
from zstacklib.utils import jsonobject
from zstacklib.utils import linux
from zstacklib.utils import log
from zstacklib.utils import shell
from zstacklib.utils import http

logger = log.get_logger(__name__)

class ImageStoreClient(object):

    ZSTORE_PROTOSTR = "zstore://"
    ZSTORE_CLI_PATH = "/usr/local/zstack/imagestore/bin/zstcli -rootca /var/lib/zstack/imagestorebackupstorage/package/certs/ca.pem"
    ZSTORE_DEF_PORT = 8000

    UPLOAD_BIT_PATH = "/imagestore/upload"
    DOWNLOAD_BIT_PATH = "/imagestore/download"
    COMMIT_BIT_PATH = "/imagestore/commit"

    def _get_image_json_file(self, primaryInstallPath):
        idx = primaryInstallPath.rfind('.')
        if idx == -1:
            return primaryInstallPath + ".imf2"
        return primaryInstallPath[:idx] + ".imf2"

    def _get_image_reference(self, primaryStorageInstallPath):
        try:
            with open(self._get_image_json_file(primaryStorageInstallPath)) as f:
                imf = jsonobject.loads(f.read())
                return imf.name, imf.id
        except IOError, e:
            errmsg = '_get_image_reference {0} failed: {1}'.format(primaryStorageInstallPath, e)
            raise kvmagent.KvmError(errmsg)

    def _parse_image_reference(self, backupStorageInstallPath):
        if not backupStorageInstallPath.startswith(self.ZSTORE_PROTOSTR):
            raise kvmagent.KvmError('unexpected backup storage install path %s' % backupStorageInstallPath)

        xs = backupStorageInstallPath[len(self.ZSTORE_PROTOSTR):].split('/')
        if len(xs) != 2:
            raise kvmagent.KvmError('unexpected backup storage install path %s' % backupStorageInstallPath)

        return xs[0], xs[1]

    def _build_install_path(self, name, imgid):
        return "{0}{1}/{2}".format(self.ZSTORE_PROTOSTR, name, imgid)

    def upload_to_imagestore(self, cmd, req):
        imf = self._get_image_json_file(cmd.primaryStorageInstallPath)
        if not os.path.isfile(imf):
            self.commit_to_imagestore(cmd, req)

        cmdstr = '%s -url %s:%s -callbackurl %s -taskid %s push %s' % (
        self.ZSTORE_CLI_PATH, cmd.hostname, self.ZSTORE_DEF_PORT, req[http.REQUEST_HEADER].get(http.CALLBACK_URI),
                req[http.REQUEST_HEADER].get(http.TASK_UUID), cmd.primaryStorageInstallPath)
        logger.debug(cmdstr)
        logger.debug('pushing %s to image store' % cmd.primaryStorageInstallPath)
        shell.call(cmdstr)
        logger.debug('%s pushed to image store' % cmd.primaryStorageInstallPath)

        rsp = kvmagent.AgentResponse()
        name, imageid = self._get_image_reference(cmd.primaryStorageInstallPath)
        rsp.backupStorageInstallPath = self._build_install_path(name, imageid)
        return jsonobject.dumps(rsp)


    def commit_to_imagestore(self, cmd, req):
        fpath = cmd.primaryStorageInstallPath

        # Synchronize cached writes for 'fpath'
        shell.call('/bin/sync ' + fpath)

        # Add the image to registry
        cmdstr = '%s -json  -callbackurl %s -taskid %s add -file %s' % (self.ZSTORE_CLI_PATH, req[http.REQUEST_HEADER].get(http.CALLBACK_URI),
                req[http.REQUEST_HEADER].get(http.TASK_UUID), fpath)

        logger.debug('adding %s to local image store' % fpath)
        shell.call(cmdstr)
        logger.debug('%s added to local image store' % fpath)

        name, imageid = self._get_image_reference(fpath)

        rsp = kvmagent.AgentResponse()
        rsp.backupStorageInstallPath = self._build_install_path(name, imageid)
        rsp.size = linux.qcow2_size_and_actual_size(cmd.primaryStorageInstallPath)[0]

        # we need to sum all the disk size within the chain ...
        chain = linux.qcow2_get_file_chain(cmd.primaryStorageInstallPath)
        rsp.actualSize = sum([ linux.qcow2_size_and_actual_size(f)[1] for f in chain ])

        return jsonobject.dumps(rsp)

    def download_from_imagestore(self, cachedir, host, backupStorageInstallPath, primaryStorageInstallPath):
        name, imageid = self._parse_image_reference(backupStorageInstallPath)
        cmdstr = '%s -url %s:%s -cachedir %s pull -installpath %s %s:%s' % (self.ZSTORE_CLI_PATH, host, self.ZSTORE_DEF_PORT, cachedir, primaryStorageInstallPath, name, imageid)
        logger.debug('pulling %s:%s from image store' % (name, imageid))
        shell.call(cmdstr)
        logger.debug('%s:%s pulled to local cache' % (name, imageid))
        return

@@ -2130,16 +2130,30 @@
 skid %25s 
+-imageUuid %25s 
 push %25s'
@@ -2333,16 +2333,31 @@
 K_UUID),
+ cmd.imageUuid,
  cmd.pri
@@ -3112,16 +3112,30 @@
 skid %25s 
+-imageUuid %25s 
 add -fil
@@ -3275,16 +3275,31 @@
 K_UUID),
+ cmd.imageUuid,
  fpath)%0A

use real imageUuid while createRootVolumeTempleteFromRootVolume