#!/usr/bin/env python
#
#   ConVirt   -  Copyright (c) 2008 Convirture Corp.
#   ======
#
# ConVirt is a Virtualization management tool with a graphical user
# interface that allows for performing the standard set of VM operations
# (start, stop, pause, kill, shutdown, reboot, snapshot, etc...). It
# also attempts to simplify various aspects of VM lifecycle management.
#
#
# This software is subject to the GNU General Public License, Version 2 (GPLv2)
# and for details, please consult it at:
#
#    http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
# 
#
# author : Jd <jd_jedi@users.sourceforge.net>
#


# KVM Domain

import sys,os,re,types


from convirt.core.utils.utils import search_tree, XMConfig, PyConfig
from convirt.core.utils.NodeProxy import Node
from convirt.core.utils.constants import *
from convirt.core.model.VM import *
from convirt.core.platforms.kvm.kvm_constants import my_platform

class KVMDomain(VM):
    
    def __init__(self, node,config=None, vm_info=None):
        """
        initialize using dom_info.
        a. can be used to create a new dom
        b. can be used to instantiate dom representation of a runnig dom.
        """
        VM.__init__(self, node, config, vm_info)
        


    def init(self):
        if self._config:
            self.name = self._config.name
            self._is_resident = False
            self.id = self.name # id is name, need to resolve this with guid
        
        elif self._vm_info:
            self.name = self._vm_info.name
            self.id = self._vm_info.id
            self._is_resident = True
            

        self.state = self.init_state()
        #print "in init self.state ", self.state, self.name, self


    def get_platform(self):
        return my_platform

        
    def init_state(self):
        """
        Translate the string in to state enum
        returns one of the following
        VM.RUNNING, VM.BLOCKED, VM.PAUSED,
        VM.SHUTDOWN, VM.CRASHED, VM.UNKNOWN.
        VM.NOT_STARTED 
        """
        if self._vm_info is None:
            return VM.NOT_STARTED
        else:
            return VM.RUNNING




    def __getitem__(self, param):
        if param == "name":
            return self.name
        else:
            if self._vm_info:
                return self._vm_info[param]
            return None

    # override the save
    def _save(self, filename):
        cfg = self.get_config()
        if cfg is None: # This can be relaxed later 
            raise Exception("Can not save snapshot without associated config.")
        self.node.get_vmm().save(self.id, filename, cfg)

    # override migrate, as we need to pass more context
    def _migrate(self, dest,live, port):
        cfg = self.get_config()
        
        if cfg is None:
            raise Exception("Can not migrate KVM. Did not find any config associated with VM.\n Use Import VM Config and import the config file for this VM.")
        #print "cfg is None", cfg is None
        import copy
        cfg_clone = copy.copy(cfg) # shallow clone : Be careful

        if cfg_clone is None:
            raise Exception("Can not migrate KVM. Could not clone config associated with VM.")
        #print "cfg_clone is None", cfg_clone is None 
        cfg_clone.set_managed_node(dest)
        cfg_clone.write()

        self.node.get_vmm().migrate(self.id, dest, live, port, cfg)
        self.state = self.NOT_STARTED

    # return the (cmd, args)
    def get_console_cmd(self):
        return None
    
    def get_vnc_port(self):
        if self._vm_info is not None:
            vnc_port_string = self._vm_info.get("vnc")
            if vnc_port_string and vnc_port_string[0] == ':':
                return int(vnc_port_string[1:])
        return None

    def is_graphical_console(self):
        return True



    ## get stats
    def get_snapshot(self):
        if self._stats == None:
            self._stats = KVMStats(self)
        return self._stats.get_snapshot()
        


class KVMConfig(VMConfig):
    """
    represnts startup config object (information in the conf file)
    """


    # DomConfig follows
    def __init__(self, node, filename = None):
        """
        read stuff from file and populate the config
        when filename is None, creates an empty config
        """
        VMConfig.__init__(self, node,filename)
        

    # kvm specific validation.
    def validate(self):
        """Attempts to validate that the settings are not going to lead to
        any errors when the dom is started, and returns a list of the
        errors as strings"""

        result = []

        if not self["name"]:
            result.append("Missing domain name.")

        if not self["disk"]:
            result.append("Missing disk specification.")

        return result

# Not used
class KVMStats(VMStats):
    """
    represents statatistics/measurements for a vm. (CPU, I/O etc)
    This is abstracted out so we can cut over to some other source for
    runtime statastics/measurements
    """

    def __init__(self, vm):
        """
        constructor, dom for which the stats are to be obtained.
        """
        VMStats.__init__(self, vm)

    def get_snapshot(self):
        # get it from /proc/pid
        # OR run top -b -p <self.vm.pid>
        # 
        #for stat in ("memory", "cpu_time"):
        #   self.stat[stat] = ...
        return self.stat
    
    
### module initialization

    







    
    

    
    
