def __init__(self, vpool):
     self.vpool = vpool
     self.mountpoint = list(vpool.storagedrivers)[0].mountpoint
     self.sdk = Kvm_sdk()
class Kvm(object):
    """
    KVM specific hypervisor class
    """
    def __init__(self, vpool):
        self.vpool = vpool
        self.mountpoint = list(vpool.storagedrivers)[0].mountpoint
        self.sdk = Kvm_sdk()

    def _get_vms(self):
        return self.sdk.get_vms()

    def create_vm(self, name, ram=1024, small=False):
        """
        Create a Virtual Machine
        :param name: Name of the Virtual Machine
        :param ram: Amount of RAM
        :param small: Small
        :return: None
        """
        os_name = General.get_os()
        bootdisk_path_remote = General.get_os_info(os_name + '_small' if small else os_name)['bootdisk_location']

        vm_path = '/'.join([self.mountpoint, name])
        if not os.path.exists(vm_path):
            os.mkdir(vm_path)

        if small:
            bootdisk_path = '/'.join([self.mountpoint, name, "bootdiskfast.raw"])
        else:
            bootdisk_path = '/'.join([self.mountpoint, name, "bootdisk.raw"])
        if not os.path.exists(bootdisk_path):
            template_server = General.get_template_server()
            bootdisk_url = urlparse.urljoin(template_server, bootdisk_path_remote)
            logging.log(1, 'Template url: {0}'.format(bootdisk_url))
            logging.log(1, 'Bootdisk path: {0}'.format(bootdisk_path))

            GeneralHypervisor.download_to_vpool(bootdisk_url, bootdisk_path)

            # When running with devstack need to set kvm group
            if GeneralOpenStack.is_openstack_present():
                General.execute_command("chgrp kvm {0}".format(bootdisk_path))

            cmd = "virt-install --connect qemu:///system -n {name} -r {ram} --disk {bootdisk_path},device=disk,format=raw,bus=virtio --import --graphics vnc,listen=0.0.0.0 --vcpus=1 --network network=default,mac=RANDOM,model=e1000 --boot hd"
            cmd = cmd.format(name=name,
                             bootdisk_path=bootdisk_path,
                             ram=ram)
            out, error, _ = General.execute_command(cmd)
            logging.log(1, 'cmd: ---')
            logging.log(1, cmd)
            logging.log(1, 'stdout: ---')
            logging.log(1, 'stdout: ---')
            logging.log(1, out)
            logging.log(1, 'stderr: ---')
            logging.log(1, error)
            # assert error == '', "Exception occurred while running {0}:\n{1}\n{2}".format(cmd, out, error)

    def _wait_for_state(self, name, state):
        retries = 240

        while retries:
            if self.sdk.get_power_state(name) == state:
                return
            retries -= 1
            time.sleep(1)

        actual_state = self.sdk.get_power_state(name)
        assert actual_state == state, "Vm did not go into state {0}, actual {1}".format(state, actual_state)

    def shutdown(self, name):
        """
        Shut down a Virtual Machine
        :param name: Name of the Virtual Machine
        :return: None
        """
        if self.sdk.get_power_state(name) == 'TURNEDOFF':
            return
        self.sdk.shutdown(name)
        self._wait_for_state(name, 'TURNEDOFF')

    def poweroff(self, name):
        """
        Power off a Virtual Machine
        :param name: Name of the Virtual Machine
        :return: None
        """
        if self.sdk.get_power_state(name) == 'TURNEDOFF':
            return
        vm_obj = self.sdk.get_vm_object(name)
        vm_obj.destroy()

    def start(self, name):
        """
        Start a Virtual Machine
        :param name: Name of the Virtual Machine
        :return: None
        """
        if self.sdk.get_power_state(name) == 'RUNNING':
            print "Vm {} already running".format(name)
            return
        self.sdk.power_on(name)
        self._wait_for_state(name, 'RUNNING')

    def get_mac_address(self, name):
        """
        Retrieve a MAC address of a Virtual Machine
        :param name: Name of the Virtual Machine
        :return:
        """
        vmo = self.sdk.get_vm_object(name)
        dom = minidom.parseString(vmo.XMLDesc()).childNodes[0]
        devices = [e for e in dom.childNodes if e.localName == 'devices'][0]
        nic = [e for e in devices.childNodes if e.localName == 'interface'][0]
        mac = [e for e in nic.childNodes if e.localName == 'mac'][0]
        return mac.attributes['address'].value

    def delete_clones(self, vm):
        """
        Delete all clones for Virtual Machine with name
        :param vm: Virtual Machine DAL object
        :return: None
        """
        clones = set()
        for vd in vm.vdisks:
            for child_vd in vd.child_vdisks:
                if child_vd.vmachine:
                    clones.add(child_vd.vmachine)
        for clone in clones:
            self.delete(clone.name)

    def delete(self, name):
        """
        Delete a Virtual Machine
        :param name: Name of the Virtual Machine
        :return: None
        """
        vms = self._get_vms()
        vm = [v for v in vms if v.name == name]

        assert vm, "Couldn't find Virtual Machine with name {0}".format(name)
        assert len(vm) == 1, "More than 1 result when looking up vmachine with name: {0}".format(name)

        logging.log(1, "Powering off vm: {0}".format(vm.name))
        self.poweroff(name)
        logging.log(1, "Deleting off vm: {0}".format(vm.name))
        self.sdk.delete_vm(name, vm.devicename, None)
        logging.log(1, "Deleted vm: {0}".format(vm.name))