# -*- coding: utf-8 -*-
#
# This file is part of Karesansui.
#
# Copyright (C) 2009 HDE, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#

import os
import stat
import time

import web
import karesansui
from karesansui.lib.rest import Rest, auth
from karesansui.lib.const import \
     VIRT_COMMAND_TAKE_SNAPSHOT, \
     NOTE_TITLE_MIN_LENGTH, NOTE_TITLE_MAX_LENGTH,\
     VIRT_XML_CONFIG_DIR
from karesansui.lib.utils import getfilesize_str, \
     uniq_filename, is_param, get_filesize_MB
from karesansui.lib.checker import Checker, \
     CHECK_EMPTY, CHECK_VALID, CHECK_MIN, CHECK_MAX, \
     CHECK_LENGTH, CHECK_ONLYSPACE

from karesansui.db.access.machine import findbyguest1
from karesansui.db.access.notebook import new as new_notebook
from karesansui.db.access.snapshot import new as new_snapshot, \
     save as save_snapshot, findbyname
from karesansui.db.access._2pysilhouette import save_job_collaboration
from karesansui.db.access.machine2jobgroup import new as m2j_new

from karesansui.lib.virt.virt import \
     KaresansuiVirtConnection, VIRT_SNAPSHOT_DIR
from karesansui.lib.virt.config import ConfigParam

from pysilhouette.command import dict2command
from karesansui.db.model._2pysilhouette import Job, JobGroup

def validates_snapshot(obj):
    checker = Checker()
    check = True

    _ = obj._
    checker.errors = []
    
    if is_param(obj.input, 'title'):
        check = checker.check_string(
                    _('Title'),
                    obj.input.title,
                    CHECK_LENGTH | CHECK_ONLYSPACE,
                    None,
                    min = NOTE_TITLE_MIN_LENGTH,
                    max = NOTE_TITLE_MAX_LENGTH,
                ) and check

    if is_param(obj.input, 'value'):
        check = checker.check_string(
                    _('Note'),
                    obj.input.value,
                    CHECK_ONLYSPACE,
                    None,
                    None,
                    None,
                ) and check

    obj.view.alert = checker.errors
    
    return check

class GuestBy1Snapshot(Rest):

    @auth
    def _GET(self, *param, **params):
        (host_id, guest_id) = self.chk_guestby1(param)
        if guest_id is None: web.notfound()

        guest = findbyguest1(self.orm, guest_id)
        
        kvc = KaresansuiVirtConnection()
        try:
            domname = kvc.uuid_to_domname(guest.uniq_key)
            if not domname: return web.conflict(web.ctx.path)
            virt = kvc.search_kvg_guests(domname)[0]
            self.view.is_creatable = virt.is_takable_snapshot()
            snapshot_list = kvc.list_snapshot(domname)
        finally:
            kvc.close()

        param = ConfigParam(kvc.get_domain_name())
        xml_file = "%s/%s.xml" % (VIRT_XML_CONFIG_DIR, kvc.get_domain_name())
        if not os.path.exists(xml_file):
            return web.notfound()
        param.load_xml_config(xml_file)
        current_snapshot = param.get_current_snapshot()

        snapshots = []
        if snapshot_list:
            snapshot_list.sort(reverse = True)
            for snapshot in snapshot_list:
                filepath = "%s/%s/%s" % (VIRT_SNAPSHOT_DIR, domname, snapshot)
                if os.path.isfile(filepath) is False:
                    self.logger.error("The specified snapshot file does not exist. - %s/%s" % filepath)
                    return web.internalerror()

                model = findbyname(self.orm, snapshot)
                if model is None:
                    continue

                current = snapshot in current_snapshot

                snapshots.append((snapshot,
                                  model,
                                  domname,
                                  get_filesize_MB(getfilesize_str(filepath)),
                                  current
                                  ))

        self.view.snapshots = snapshots
        self.view.guest = guest
            
        return True

    @auth
    def _POST(self, *param, **params):
        (host_id, guest_id) = self.chk_guestby1(param)
        if guest_id is None: web.notfound()

        if not validates_snapshot(self): 
            return web.badrequest(self.view.alert)
        
        guest = findbyguest1(self.orm, guest_id)

        name = uniq_filename()

        notebook = new_notebook(self.input.title, self.input.value)
        snapshot = new_snapshot(guest, name, self.me, self.me, notebook)
        save_snapshot(self.orm, snapshot)
        kvc = KaresansuiVirtConnection()
        try:
            domname = kvc.uuid_to_domname(guest.uniq_key)
            if not domname: return web.conflict(web.ctx.path)
        finally:
            kvc.close()

        options = {}
        options['name'] = domname
        options['id'] = name

        _cmd = dict2command(
            "%s/%s" % (karesansui.config['application.bin.dir'], VIRT_COMMAND_TAKE_SNAPSHOT),
            options)

        cmdname = 'Take Snapshot'
        _jobgroup = JobGroup(cmdname, karesansui.sheconf['env.uniqkey'])
        _jobgroup.jobs.append(Job('%s command' % cmdname, 0, _cmd))

        _machine2jobgroup = m2j_new(machine=guest,
                                    jobgroup_id=-1,
                                    uniq_key=karesansui.sheconf['env.uniqkey'],
                                    created_user=self.me,
                                    modified_user=self.me,
                                    )
        
        
        save_job_collaboration(self.orm,
                               self.pysilhouette.orm,
                               _machine2jobgroup,
                               _jobgroup,
                               )
        return web.accepted()

urls = (
    '/host/(\d+)/guest/(\d+)/snapshot/?(\.part)?$', GuestBy1Snapshot,
    )
