def __init__(self, vpool):
     self.vpool = vpool
     self.mountpoint = '/mnt/{0}'.format(vpool.name)
     self.sdk = Vmware_sdk(*GeneralHypervisor.get_hypervisor_info())
class Vmware(object):
    """
    VMWare specific hypervisor class
    """
    def __init__(self, vpool):
        self.vpool = vpool
        self.mountpoint = '/mnt/{0}'.format(vpool.name)
        self.sdk = Vmware_sdk(*GeneralHypervisor.get_hypervisor_info())

    def create_vm(self, name, cpus=1, ram=1024):
        """
        Create a Virtual Machine on hypervisor and start it
        :param name: Name of the Virtual Machine
        :param cpus: Amount of CPUs
        :param ram: Amount of RAM
        :return: None
        """
        # not sure if its the proper way to get the datastore
        esxhost = self.sdk._validate_host(None)
        datastores = self.sdk._get_object(esxhost, properties=['datastore']).datastore.ManagedObjectReference
        datastore = [d for d in datastores if self.vpool.name in d.value]
        assert datastore, "Did not found datastore"
        datastore = self.sdk._get_object(datastore[0])

        os_name = General.get_os()
        os_info = General.get_os_info(os_name)
        bootdisk_path_remote = os_info['bootdisk_location']

        os.mkdir('/'.join([self.mountpoint, name]))

        disk_name = "bootdisk.vmdk"
        disk_name_flat = "bootdisk-flat.vmdk"
        bootdisk_path = '/'.join([self.mountpoint, name, disk_name])
        bootdisk_flat_path = '/'.join([self.mountpoint, name, disk_name_flat])

        template_server = General.get_template_server()
        bootdisk_url = urlparse.urljoin(template_server, bootdisk_path_remote + disk_name)
        bootdisk_flat_url = urlparse.urljoin(template_server, bootdisk_path_remote + disk_name_flat)

        GeneralHypervisor.download_to_vpool(bootdisk_url, bootdisk_path)
        GeneralHypervisor.download_to_vpool(bootdisk_flat_url, bootdisk_flat_path)
        """
        task = self.sdk.create_vm(name      = name,
                                  cpus      = cpus,
                                  memory    = ram,
                                  os        = os_info['esx_os_name'],
                                  disks     = [],
                                  nics      = [{'bridge': 'CloudFramesPublic'}],
                                  kvmport   = str(random.randint(0, 100000)),
                                  datastore = datastore.info.name,
                                  wait      = True)
        self.sdk.validate_result(task)
        """

        nics = [{'bridge': 'CloudFramesPublic'}]

        self.sdk._validate_host(None)

        # Build basic config information
        config = self.sdk._client.factory.create('ns0:VirtualMachineConfigSpec')
        config.name = name
        config.numCPUs = cpus
        config.memoryMB = ram
        config.guestId = os_info.get('esx_os_name', 'ubuntu64Guest')
        config.deviceChange = []
        config.extraConfig = []
        config.files = self.sdk._create_file_info(self.sdk._client.factory, datastore.name)

        disk_controller_key = -101
        config.deviceChange.append(
            self.sdk._create_disk_controller(self.sdk._client.factory, disk_controller_key))

        # Add network
        for nic in nics:
            unit = nics.index(nic)
            config.deviceChange.append(self.sdk._create_nic(self.sdk._client.factory,
                                                            'VirtualE1000',
                                                            'Interface %s' % unit,
                                                            '%s interface' % nic['bridge'],
                                                            nic['bridge'],
                                                            unit))

        # Change additional properties
        extra_configs = [
            ('pciBridge0.present', 'true'),
            ('pciBridge4.present', 'true'),
            ('pciBridge4.virtualDev', 'pcieRootPort'),
            ('pciBridge4.functions', '8'),
            ('pciBridge5.present', 'true'),
            ('pciBridge5.virtualDev', 'pcieRootPort'),
            ('pciBridge5.functions', '8'),
            ('pciBridge6.present', 'true'),
            ('pciBridge6.virtualDev', 'pcieRootPort'),
            ('pciBridge6.functions', '8'),
            ('pciBridge7.present', 'true'),
            ('pciBridge7.virtualDev', 'pcieRootPort'),
            ('pciBridge7.functions', '8')
        ]
        for item in extra_configs:
            config.extraConfig.append(
                self.sdk._create_option_value(self.sdk._client.factory,
                                              item[0],
                                              item[1]))

        retries = 100
        vm = None
        while retries:
            vm_objects = self._get_vms()

            vm = [vm for vm in vm_objects if vm['name'] == name]
            if vm:
                vm = vm[0]
                if getattr(vm, "config", None):
                    break
            retries -= 1
            time.sleep(1)

        assert vm, "Did not found vm after creating it"

        vm_dir_name = vm.config.files.vmPathName.split()[1].split("/")[0]
        virt_ide_controller = [dev for dev in vm.config.hardware.device if "VirtualIDEController" in str(type(dev))][0]

        sdk_client = self.sdk._client
        vm_spec = sdk_client.factory.create('ns0:VirtualMachineConfigSpec')

        unit = 0
        device_info = sdk_client.factory.create('ns0:Description')
        device_info.label = disk_name
        device_info.summary = disk_name

        backing = sdk_client.factory.create('ns0:VirtualDiskFlatVer2BackingInfo')
        backing.diskMode = 'persistent'
        backing.fileName = '[{datastore}] {fileName}'.format(datastore=datastore.info.name,
                                                             fileName='/'.join([vm_dir_name, disk_name]))

        device = sdk_client.factory.create('ns0:VirtualDisk')
        device.controllerKey = virt_ide_controller.key
        device.key = -200 - unit
        device.unitNumber = unit
        device.deviceInfo = device_info
        device.backing = backing

        disk_spec = sdk_client.factory.create('ns0:VirtualDeviceConfigSpec')
        disk_spec.operation = 'add'
        disk_spec.fileOperation = None
        disk_spec.device = device
        vm_spec.deviceChange.append(disk_spec)

        task = sdk_client.service.ReconfigVM_Task(vm.obj_identifier, vm_spec)
        self.sdk.wait_for_task(task)
        self.sdk.validate_result(task)

        self.start(name)

    def _get_vms(self):
        esxhost = self.sdk._validate_host(None)
        return self.sdk._get_object(esxhost,
                                    prop_type='VirtualMachine',
                                    traversal={'name': 'HostSystemTraversalSpec',
                                               'type': 'HostSystem',
                                               'path': 'vm'})

    def start(self, name):
        """
        Start 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, "Vm with name {0} not found".format(name)
        vm = vm[0]
        if vm.runtime.powerState == "poweredOn":
            return

        task = self.sdk._client.service.PowerOnVM_Task(vm.obj_identifier)
        self.sdk.wait_for_task(task)
        self.sdk.validate_result(task)

    def shutdown(self, name):
        """
        Shut down 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, "Vm with name {0} not found".format(name)
        vm = vm[0]
        if vm.runtime.powerState == "poweredOff":
            return
        task = self.sdk._client.service.PowerOffVM_Task(vm.obj_identifier)
        self.sdk.wait_for_task(task)
        self.sdk.validate_result(task)

    def poweroff(self, name):
        """
        Power off a Virtual Machine
        :param name: Name of the Virtual Machine
        :return: None
        """
        self.shutdown(name=name)

    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, "Vm with name {0} not found".format(name)
        vm = vm[0]
        logging.log(1, "Powering off vm: {0}:".format(vm.name))
        self.poweroff(name)
        logging.log(1, "Deleting vm: {0}:".format(vm.name))
        task = self.sdk._client.service.Destroy_Task(vm.obj_identifier)
        self.sdk.wait_for_task(task)
        self.sdk.validate_result(task)
        logging.log(1, "Deleted vm: {0}:".format(vm.name))