Exemple #1
0
 def _set_vm_state(self, vm_name, req_state):
     try:
         self._vmutils.set_vm_state(vm_name, req_state)
         LOG.debug(
             _("Successfully changed state of VM %(vm_name)s"
               " to: %(req_state)s") % locals())
     except Exception as ex:
         LOG.exception(ex)
         msg = _("Failed to change vm state of %(vm_name)s"
                 " to %(req_state)s") % locals()
         raise vmutils.HyperVException(msg)
Exemple #2
0
    def test_soft_shutdown_failed(self, mock_sleep):
        instance = fake_instance.fake_instance_obj(self.context)

        mock_shutdown_vm = self._vmops._vmutils.soft_shutdown_vm
        mock_shutdown_vm.side_effect = vmutils.HyperVException(
            "Expected failure.")

        result = self._vmops._soft_shutdown(instance, self._FAKE_TIMEOUT)

        mock_shutdown_vm.assert_called_once_with(instance.name)
        self.assertFalse(result)
Exemple #3
0
    def _create_root_vhd(self, context, instance):
        base_vhd_path = self._imagecache.get_cached_image(context, instance)
        format_ext = base_vhd_path.split('.')[-1]
        root_vhd_path = self._pathutils.get_root_vhd_path(instance['name'],
                                                          format_ext)

        try:
            if CONF.use_cow_images:
                LOG.debug(_("Creating differencing VHD. Parent: "
                            "%(base_vhd_path)s, Target: %(root_vhd_path)s"),
                          {'base_vhd_path': base_vhd_path,
                           'root_vhd_path': root_vhd_path},
                          instance=instance)
                self._vhdutils.create_differencing_vhd(root_vhd_path,
                                                       base_vhd_path)
            else:
                LOG.debug(_("Copying VHD image %(base_vhd_path)s to target: "
                            "%(root_vhd_path)s"),
                          {'base_vhd_path': base_vhd_path,
                           'root_vhd_path': root_vhd_path},
                          instance=instance)
                self._pathutils.copyfile(base_vhd_path, root_vhd_path)

                base_vhd_info = self._vhdutils.get_vhd_info(base_vhd_path)
                base_vhd_size = base_vhd_info['MaxInternalSize']
                root_vhd_size = instance['root_gb'] * units.Gi

                root_vhd_internal_size = (
                        self._vhdutils.get_internal_vhd_size_by_file_size(
                            root_vhd_path, root_vhd_size))

                if root_vhd_internal_size < base_vhd_size:
                    error_msg = _("Cannot resize a VHD to a smaller size, the"
                                  " original size is %(base_vhd_size)s, the"
                                  " newer size is %(root_vhd_size)s"
                                  ) % {'base_vhd_size': base_vhd_size,
                                       'root_vhd_size': root_vhd_internal_size}
                    raise vmutils.HyperVException(error_msg)
                elif root_vhd_internal_size > base_vhd_size:
                    LOG.debug(_("Resizing VHD %(root_vhd_path)s to new "
                                "size %(root_vhd_size)s"),
                              {'root_vhd_size': root_vhd_internal_size,
                               'root_vhd_path': root_vhd_path},
                              instance=instance)
                    self._vhdutils.resize_vhd(root_vhd_path,
                                              root_vhd_internal_size,
                                              is_file_max_size=False)
        except Exception:
            with excutils.save_and_reraise_exception():
                if self._pathutils.exists(root_vhd_path):
                    self._pathutils.remove(root_vhd_path)

        return root_vhd_path
Exemple #4
0
 def _create_scsi_controller(self, vm_name):
     """ Create an iscsi controller ready to mount volumes """
     LOG.debug(_('Creating a scsi controller for %(vm_name)s for volume '
             'attaching') % locals())
     vms = self._conn.MSVM_ComputerSystem(ElementName=vm_name)
     vm = vms[0]
     scsicontrldefault = self._conn.query(
             "SELECT * FROM Msvm_ResourceAllocationSettingData \
             WHERE ResourceSubType = 'Microsoft Synthetic SCSI Controller'\
             AND InstanceID LIKE '%Default%'")[0]
     if scsicontrldefault is None:
         raise vmutils.HyperVException(_('Controller not found'))
     scsicontrl = self._vmutils.clone_wmi_obj(self._conn,
             'Msvm_ResourceAllocationSettingData', scsicontrldefault)
     scsicontrl.VirtualSystemIdentifiers = ['{' + str(uuid.uuid4()) + '}']
     scsiresource = self._vmutils.add_virt_resource(self._conn,
         scsicontrl, vm)
     if scsiresource is None:
         raise vmutils.HyperVException(
             _('Failed to add scsi controller to VM %s') %
             vm_name)
Exemple #5
0
    def get_external_vswitch(self, vswitch_name):
        if vswitch_name:
            vswitches = self._conn.Msvm_VirtualEthernetSwitch(
                ElementName=vswitch_name)
            if not len(vswitches):
                raise vmutils.HyperVException(
                    _('vswitch "%s" not found') % vswitch_name)
        else:
            # Find the vswitch that is connected to the first physical nic.
            ext_port = self._conn.Msvm_ExternalEthernetPort(IsBound='TRUE')[0]
            lep = ext_port.associators(wmi_result_class='Msvm_LANEndpoint')[0]
            lep1 = lep.associators(wmi_result_class='Msvm_LANEndpoint')[0]
            esw = lep1.associators(
                wmi_result_class='Msvm_EthernetSwitchPort')[0]
            vswitches = esw.associators(
                wmi_result_class='Msvm_VirtualEthernetSwitch')

            if not len(vswitches):
                raise vmutils.HyperVException(_('No external vswitch found'))

        return vswitches[0].path_()
Exemple #6
0
 def execute(self, *args, **kwargs):
     proc = subprocess.Popen(
         [args],
         stdin=subprocess.PIPE,
         stdout=subprocess.PIPE,
         stderr=subprocess.STDOUT,
     )
     stdout_value, stderr_value = proc.communicate()
     if stdout_value.find('The operation completed successfully') == -1:
         raise vmutils.HyperVException(
             _('An error has occurred when '
               'calling the iscsi initiator: %s') % stdout_value)
Exemple #7
0
 def mount_smb_share(self, smbfs_share, username=None, password=None):
     try:
         LOG.debug('Mounting share: %s', smbfs_share)
         self._smb_conn.Msft_SmbMapping.Create(RemotePath=smbfs_share,
                                               UserName=username,
                                               Password=password)
     except wmi.x_wmi as exc:
         err_msg = (_(
             'Unable to mount SMBFS share: %(smbfs_share)s '
             'WMI exception: %(wmi_exc)s'), {'smbfs_share': smbfs_share,
                                             'wmi_exc': exc})
         raise vmutils.HyperVException(err_msg)
Exemple #8
0
    def _cache_image(self,
                     fn,
                     target,
                     fname,
                     cow=False,
                     Size=None,
                     *args,
                     **kwargs):
        """Wrapper for a method that creates an image that caches the image.

        This wrapper will save the image into a common store and create a
        copy for use by the hypervisor.

        The underlying method should specify a kwarg of target representing
        where the image will be saved.

        fname is used as the filename of the base image.  The filename needs
        to be unique to a given image.

        If cow is True, it will make a CoW image instead of a copy.
        """
        @lockutils.synchronized(fname, 'nova-')
        def call_if_not_exists(path, fn, *args, **kwargs):
            if not os.path.exists(path):
                fn(target=path, *args, **kwargs)

        if not os.path.exists(target):
            LOG.debug(_("use_cow_image:%s"), cow)
            if cow:
                base = self._vmutils.get_base_vhd_path(fname)
                call_if_not_exists(base, fn, *args, **kwargs)

                image_service = self._conn.query(
                    "Select * from Msvm_ImageManagementService")[0]
                (job, ret_val) = \
                    image_service.CreateDifferencingVirtualHardDisk(
                        Path=target, ParentPath=base)
                LOG.debug(
                    "Creating difference disk: JobID=%s, Source=%s, Target=%s",
                    job, base, target)
                if ret_val == constants.WMI_JOB_STATUS_STARTED:
                    success = self._vmutils.check_job_status(job)
                else:
                    success = (ret_val == 0)

                if not success:
                    raise vmutils.HyperVException(
                        _('Failed to create Difference Disk from '
                          '%(base)s to %(target)s') % locals())

            else:
                call_if_not_exists(target, fn, *args, **kwargs)
    def _get_mounted_disk_from_lun(self, target_iqn, target_lun):
        device_number = self._volutils.get_device_number_for_target(target_iqn,
                                                                    target_lun)
        if device_number is None:
            raise vmutils.HyperVException(_('Unable to find a mounted '
                                            'disk for target_iqn: %s')
                                          % target_iqn)
        LOG.debug(_('Device number: %(device_number)s, '
                    'target lun: %(target_lun)s') % locals())
        #Finding Mounted disk drive
        for i in range(1, CONF.hyperv.volume_attach_retry_count):
            mounted_disk_path = self._vmutils.get_mounted_disk_by_drive_number(
                device_number)
            if mounted_disk_path:
                break
            time.sleep(CONF.hyperv.volume_attach_retry_interval)

        if not mounted_disk_path:
            raise vmutils.HyperVException(_('Unable to find a mounted disk '
                                            'for target_iqn: %s')
                                          % target_iqn)
        return mounted_disk_path
Exemple #10
0
    def _resize_and_cache_vhd(self, instance, vhd_path):
        vhd_info = self._vhdutils.get_vhd_info(vhd_path)
        vhd_size = vhd_info['MaxInternalSize']

        root_vhd_size_gb = self._get_root_vhd_size_gb(instance)
        root_vhd_size = root_vhd_size_gb * units.Gi

        root_vhd_internal_size = (
            self._vhdutils.get_internal_vhd_size_by_file_size(
                vhd_path, root_vhd_size))

        if root_vhd_internal_size < vhd_size:
            raise vmutils.HyperVException(
                _("Cannot resize the image to a size smaller than the VHD "
                  "max. internal size: %(vhd_size)s. Requested disk size: "
                  "%(root_vhd_size)s") % {
                      'vhd_size': vhd_size,
                      'root_vhd_size': root_vhd_size
                  })
        if root_vhd_internal_size > vhd_size:
            path_parts = os.path.splitext(vhd_path)
            resized_vhd_path = '%s_%s%s' % (path_parts[0], root_vhd_size_gb,
                                            path_parts[1])

            @utils.synchronized(resized_vhd_path)
            def copy_and_resize_vhd():
                if not self._pathutils.exists(resized_vhd_path):
                    try:
                        LOG.debug(
                            "Copying VHD %(vhd_path)s to "
                            "%(resized_vhd_path)s", {
                                'vhd_path': vhd_path,
                                'resized_vhd_path': resized_vhd_path
                            })
                        self._pathutils.copyfile(vhd_path, resized_vhd_path)
                        LOG.debug(
                            "Resizing VHD %(resized_vhd_path)s to new "
                            "size %(root_vhd_size)s", {
                                'resized_vhd_path': resized_vhd_path,
                                'root_vhd_size': root_vhd_size
                            })
                        self._vhdutils.resize_vhd(resized_vhd_path,
                                                  root_vhd_internal_size,
                                                  is_file_max_size=False)
                    except Exception:
                        with excutils.save_and_reraise_exception():
                            if self._pathutils.exists(resized_vhd_path):
                                self._pathutils.remove(resized_vhd_path)

            copy_and_resize_vhd()
            return resized_vhd_path
Exemple #11
0
 def destroy(self, instance, network_info=None, cleanup=True,
             destroy_disks=True):
     """Destroy the VM. Also destroy the associated VHD disk files."""
     LOG.debug(_("Got request to destroy vm %s"), instance['name'])
     vm = self._vmutils.lookup(self._conn, instance['name'])
     if vm is None:
         return
     vm = self._conn.Msvm_ComputerSystem(ElementName=instance['name'])[0]
     vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0]
     #Stop the VM first.
     self._set_vm_state(instance['name'], 'Disabled')
     vmsettings = vm.associators(
                      wmi_result_class='Msvm_VirtualSystemSettingData')
     rasds = vmsettings[0].associators(
                      wmi_result_class='MSVM_ResourceAllocationSettingData')
     disks = [r for r in rasds
                 if r.ResourceSubType == 'Microsoft Virtual Hard Disk']
     disk_files = []
     volumes = [r for r in rasds
                 if r.ResourceSubType == 'Microsoft Physical Disk Drive']
     volumes_drives_list = []
     #collect the volumes information before destroying the VM.
     for volume in volumes:
         hostResources = volume.HostResource
         drive_path = hostResources[0]
         #Appending the Msvm_Disk path
         volumes_drives_list.append(drive_path)
     #Collect disk file information before destroying the VM.
     for disk in disks:
         disk_files.extend([c for c in disk.Connection])
     #Nuke the VM. Does not destroy disks.
     (job, ret_val) = vs_man_svc.DestroyVirtualSystem(vm.path_())
     if ret_val == constants.WMI_JOB_STATUS_STARTED:
         success = self._vmutils.check_job_status(job)
     elif ret_val == 0:
         success = True
     if not success:
         raise vmutils.HyperVException(_('Failed to destroy vm %s') %
             instance['name'])
     if destroy_disks:
         #Disconnect volumes
         for volume_drive in volumes_drives_list:
             self._volumeops.disconnect_volume(volume_drive)
         #Delete associated vhd disk files.
         for disk in disk_files:
             vhdfile = self._conn_cimv2.query(
             "Select * from CIM_DataFile where Name = '" +
                 disk.replace("'", "''") + "'")[0]
             LOG.debug(_("Del: disk %(vhdfile)s vm %(name)s")
                 % {'vhdfile': vhdfile, 'name': instance['name']})
             vhdfile.Delete()
Exemple #12
0
    def _resize_and_cache_vhd(self, instance, vhd_path):
        vhd_info = self._vhdutils.get_vhd_info(vhd_path)
        vhd_size = vhd_info['MaxInternalSize']

        root_vhd_size_gb = self._get_root_vhd_size_gb(instance)
        root_vhd_size = root_vhd_size_gb * unit.Gi

        # NOTE(lpetrut): Checking the namespace is needed as the following
        # method is not yet implemented in the vhdutilsv2 module.
        if not isinstance(self._vhdutils, vhdutilsv2.VHDUtilsV2):
            root_vhd_internal_size = (
                self._vhdutils.get_internal_vhd_size_by_file_size(
                    vhd_path, root_vhd_size))
        else:
            root_vhd_internal_size = root_vhd_size

        if root_vhd_internal_size < vhd_size:
            raise vmutils.HyperVException(
                _("Cannot resize the image to a size smaller than the VHD "
                  "max. internal size: %(vhd_size)s. Requested disk size: "
                  "%(root_vhd_size)s") %
                {'vhd_size': vhd_size, 'root_vhd_size': root_vhd_size}
            )
        if root_vhd_internal_size > vhd_size:
            path_parts = os.path.splitext(vhd_path)
            resized_vhd_path = '%s_%s%s' % (path_parts[0],
                                            root_vhd_size_gb,
                                            path_parts[1])

            @utils.synchronized(resized_vhd_path)
            def copy_and_resize_vhd():
                if not self._pathutils.exists(resized_vhd_path):
                    try:
                        LOG.debug(_("Copying VHD %(vhd_path)s to "
                                    "%(resized_vhd_path)s"),
                                  {'vhd_path': vhd_path,
                                   'resized_vhd_path': resized_vhd_path})
                        self._pathutils.copyfile(vhd_path, resized_vhd_path)
                        LOG.debug(_("Resizing VHD %(resized_vhd_path)s to new "
                                    "size %(root_vhd_size)s"),
                                  {'resized_vhd_path': resized_vhd_path,
                                   'root_vhd_size': root_vhd_size})
                        self._vhdutils.resize_vhd(resized_vhd_path,
                                                  root_vhd_size)
                    except Exception:
                        with excutils.save_and_reraise_exception():
                            if self._pathutils.exists(resized_vhd_path):
                                self._pathutils.remove(resized_vhd_path)

            copy_and_resize_vhd()
            return resized_vhd_path
Exemple #13
0
    def finish_migration(self,
                         context,
                         migration,
                         instance,
                         disk_info,
                         network_info,
                         image_meta,
                         resize_instance=False,
                         block_device_info=None,
                         power_on=True):
        LOG.debug("finish_migration called", instance=instance)

        instance_name = instance.name

        if self._volumeops.ebs_root_in_block_devices(block_device_info):
            root_vhd_path = None
        else:
            root_vhd_path = self._pathutils.lookup_root_vhd_path(instance_name)
            if not root_vhd_path:
                raise vmutils.HyperVException(
                    _("Cannot find boot VHD "
                      "file for instance: %s") % instance_name)

            root_vhd_info = self._vhdutils.get_vhd_info(root_vhd_path)
            src_base_disk_path = root_vhd_info.get("ParentPath")
            if src_base_disk_path:
                self._check_base_disk(context, instance, root_vhd_path,
                                      src_base_disk_path)

            if resize_instance:
                new_size = instance.root_gb * units.Gi
                self._check_resize_vhd(root_vhd_path, root_vhd_info, new_size)

        eph_vhd_path = self._pathutils.lookup_ephemeral_vhd_path(instance_name)
        if resize_instance:
            new_size = instance.get('ephemeral_gb', 0) * units.Gi
            if not eph_vhd_path:
                if new_size:
                    eph_vhd_path = self._vmops.create_ephemeral_vhd(instance)
            else:
                eph_vhd_info = self._vhdutils.get_vhd_info(eph_vhd_path)
                self._check_resize_vhd(eph_vhd_path, eph_vhd_info, new_size)

        vm_gen = self._vmops.get_image_vm_generation(root_vhd_path, image_meta)
        self._vmops.create_instance(instance, network_info, block_device_info,
                                    root_vhd_path, eph_vhd_path, vm_gen)

        self._check_and_attach_config_drive(instance, vm_gen)

        if power_on:
            self._vmops.power_on(instance)
Exemple #14
0
    def get_console_output(self, instance):
        console_log_paths = (self._pathutils.get_vm_console_log_paths(
            instance['name']))

        try:
            instance_log = ''
            for console_log_path in console_log_paths:
                if os.path.exists(console_log_path):
                    with open(console_log_path, 'rb') as fp:
                        instance_log += fp.read()
            return instance_log
        except IOError as err:
            msg = _("Could not get instance console log. Error: %s") % err
            raise vmutils.HyperVException(msg, instance=instance)
Exemple #15
0
    def get_internal_vhd_size_by_file_size(self, vhd_path, new_vhd_file_size):
        """VHDX Size = Header (1 MB)
                        + Log
                        + Metadata Region
                        + BAT
                        + Payload Blocks
            Chunk size = maximum number of bytes described by a SB block
                       = 2 ** 23 * LogicalSectorSize
        """
        vhd_format = self.get_vhd_format(vhd_path)
        if vhd_format == constants.DISK_FORMAT_VHD:
            return super(VHDUtilsV2, self).get_internal_vhd_size_by_file_size(
                vhd_path, new_vhd_file_size)
        else:
            vhd_info = self.get_vhd_info(vhd_path)
            vhd_type = vhd_info['Type']
            if vhd_type == self._VHD_TYPE_DIFFERENCING:
                vhd_parent = self.get_vhd_parent_path(vhd_path)
                return self.get_internal_vhd_size_by_file_size(
                    vhd_parent, new_vhd_file_size)
            else:
                try:
                    with open(vhd_path, 'rb') as f:
                        hs = VHDX_HEADER_SECTION_SIZE
                        bes = VHDX_BAT_ENTRY_SIZE

                        lss = vhd_info['LogicalSectorSize']
                        bs = self._get_vhdx_block_size(f)
                        ls = self._get_vhdx_log_size(f)
                        ms = self._get_vhdx_metadata_size_and_offset(f)[0]

                        chunk_ratio = (1 << 23) * lss / bs
                        size = new_vhd_file_size

                        max_internal_size = (
                            bs * chunk_ratio *
                            (size - hs - ls - ms - bes - bes / chunk_ratio) /
                            (bs * chunk_ratio + bes * chunk_ratio + bes))

                        return max_internal_size - (max_internal_size % bs)

                except IOError as ex:
                    raise vmutils.HyperVException(
                        _("Unable to obtain "
                          "internal size from VHDX: "
                          "%(vhd_path)s. Exception: "
                          "%(ex)s") % {
                              "vhd_path": vhd_path,
                              "ex": ex
                          })
Exemple #16
0
    def _create_vm(self, instance):
        """Create a VM but don't start it.  """
        instance_name = instance["name"]
        vs_man_svc = self._conn.Msvm_VirtualSystemManagementService()[0]

        vs_gs_data = self._conn.Msvm_VirtualSystemGlobalSettingData.new()
        vs_gs_data.ElementName = instance_name
        (job,
         ret_val) = vs_man_svc.DefineVirtualSystem([], None,
                                                   vs_gs_data.GetText_(1))[1:]
        if ret_val == constants.WMI_JOB_STATUS_STARTED:
            success = self._vmutils.check_job_status(job)
        else:
            success = (ret_val == 0)

        if not success:
            raise vmutils.HyperVException(
                _('Failed to create VM %s') % instance_name)

        LOG.debug(_('Created VM %s...'), instance_name)
        vm = self._conn.Msvm_ComputerSystem(ElementName=instance_name)[0]

        vmsettings = vm.associators(
            wmi_result_class='Msvm_VirtualSystemSettingData')
        vmsetting = [s for s in vmsettings
                     if s.SettingType == 3][0]  # avoid snapshots
        memsetting = vmsetting.associators(
            wmi_result_class='Msvm_MemorySettingData')[0]
        #No Dynamic Memory, so reservation, limit and quantity are identical.
        mem = long(str(instance['memory_mb']))
        memsetting.VirtualQuantity = mem
        memsetting.Reservation = mem
        memsetting.Limit = mem

        (job, ret_val) = vs_man_svc.ModifyVirtualSystemResources(
            vm.path_(), [memsetting.GetText_(1)])
        LOG.debug(_('Set memory for vm %s...'), instance_name)
        procsetting = vmsetting.associators(
            wmi_result_class='Msvm_ProcessorSettingData')[0]
        vcpus = long(instance['vcpus'])
        procsetting.VirtualQuantity = vcpus
        procsetting.Reservation = vcpus
        procsetting.Limit = 100000  # static assignment to 100%

        if FLAGS.limit_cpu_features:
            procsetting.LimitProcessorFeatures = True

        (job, ret_val) = vs_man_svc.ModifyVirtualSystemResources(
            vm.path_(), [procsetting.GetText_(1)])
        LOG.debug(_('Set vcpus for vm %s...'), instance_name)
Exemple #17
0
    def login_storage_target(self,
                             target_lun,
                             target_iqn,
                             target_portal,
                             auth_username=None,
                             auth_password=None):
        """Ensure that the target is logged in."""

        self._login_target_portal(target_portal)

        retry_count = CONF.hyperv.volume_attach_retry_count

        # If the target is not connected, at least two iterations are needed:
        # one for performing the login and another one for checking if the
        # target was logged in successfully.
        if retry_count < 2:
            retry_count = 2

        for attempt in xrange(retry_count):
            target = self._conn_storage.query("SELECT * FROM MSFT_iSCSITarget "
                                              "WHERE NodeAddress='%s' " %
                                              target_iqn)

            if target and target[0].IsConnected:
                if attempt == 0:
                    # The target was already connected but an update may be
                    # required
                    target[0].Update()
                return
            try:
                target = self._conn_storage.MSFT_iSCSITarget
                auth = {}
                if auth_username and auth_password:
                    auth['AuthenticationType'] = self._CHAP_AUTH_TYPE
                    auth['ChapUsername'] = auth_username
                    auth['ChapSecret'] = auth_password
                target.Connect(NodeAddress=target_iqn,
                               IsPersistent=True,
                               **auth)
                time.sleep(CONF.hyperv.volume_attach_retry_interval)
            except wmi.x_wmi as exc:
                LOG.debug("Attempt %(attempt)d to connect to target  "
                          "%(target_iqn)s failed. Retrying. "
                          "WMI exception: %(exc)s " % {
                              'target_iqn': target_iqn,
                              'exc': exc,
                              'attempt': attempt
                          })
        raise vmutils.HyperVException(
            _('Failed to login target %s') % target_iqn)
Exemple #18
0
    def _create_config_drive(self, instance, injected_files, admin_password):
        if CONF.config_drive_format != 'iso9660':
            vmutils.HyperVException(
                _('Invalid config_drive_format "%s"') %
                CONF.config_drive_format)

        LOG.info(_('Using config drive for instance: %s'), instance=instance)

        extra_md = {}
        if admin_password and CONF.hyperv.config_drive_inject_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md)

        instance_path = self._pathutils.get_instance_dir(instance['name'])
        configdrive_path_iso = os.path.join(instance_path, 'configdrive.iso')
        LOG.info(_('Creating config drive at %(path)s'),
                 {'path': configdrive_path_iso},
                 instance=instance)

        with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
            try:
                cdb.make_drive(configdrive_path_iso)
            except processutils.ProcessExecutionError as e:
                with excutils.save_and_reraise_exception():
                    LOG.error(_('Creating config drive failed with error: %s'),
                              e,
                              instance=instance)

        if not CONF.hyperv.config_drive_cdrom:
            drive_type = constants.IDE_DISK
            configdrive_path = os.path.join(instance_path, 'configdrive.vhd')
            utils.execute(CONF.hyperv.qemu_img_cmd,
                          'convert',
                          '-f',
                          'raw',
                          '-O',
                          'vpc',
                          configdrive_path_iso,
                          configdrive_path,
                          attempts=1)
            self._pathutils.remove(configdrive_path_iso)
        else:
            drive_type = constants.IDE_DVD
            configdrive_path = configdrive_path_iso

        self._vmutils.attach_ide_drive(instance['name'], configdrive_path, 1,
                                       0, drive_type)
Exemple #19
0
    def _test_live_migration(self, test_failure=False,
                             with_volumes=False):
        dest_server = 'fake_server'

        instance_data = self._get_instance_data()
        instance_name = instance_data['name']

        fake_post_method = self._mox.CreateMockAnything()
        if not test_failure:
            fake_post_method(self._context, instance_data, dest_server,
                             False)

        fake_recover_method = self._mox.CreateMockAnything()
        if test_failure:
            fake_recover_method(self._context, instance_data, dest_server,
                                False)

        fake_ide_controller_path = 'fakeide'
        fake_scsi_controller_path = 'fakescsi'

        if with_volumes:
            fake_scsi_disk_path = 'fake_scsi_disk_path'
            fake_target_iqn = 'fake_target_iqn'
            fake_target_lun = 1
            fake_scsi_paths = {0: fake_scsi_disk_path}
        else:
            fake_scsi_paths = {}

        m = livemigrationutils.LiveMigrationUtils.live_migrate_vm(
            instance_data['name'], dest_server)
        if test_failure:
            m.AndRaise(vmutils.HyperVException('Simulated failure'))

        if with_volumes:
            m.AndReturn([(fake_target_iqn, fake_target_lun)])
            volumeutils.VolumeUtils.logout_storage_target(fake_target_iqn)
        else:
            m.AndReturn([])

        self._mox.ReplayAll()
        try:
            self._conn.live_migration(self._context, instance_data,
                                      dest_server, fake_post_method,
                                      fake_recover_method)
            exception_raised = False
        except vmutils.HyperVException:
            exception_raised = True

        self.assertTrue(not test_failure ^ exception_raised)
        self._mox.VerifyAll()
 def _get_conn_v2(self, host='localhost'):
     try:
         return wmi.WMI(moniker='//%s/root/virtualization/v2' % host)
     except wmi.x_wmi as ex:
         LOG.exception(ex)
         if ex.com_error.hresult == -2147217394:
             msg = (_('Live migration is not supported on target host "%s"')
                    % host)
         elif ex.com_error.hresult == -2147023174:
             msg = (_('Target live migration host "%s" is unreachable')
                    % host)
         else:
             msg = _('Live migration failed: %s') % ex.message
         raise vmutils.HyperVException(msg)
Exemple #21
0
 def create_vswitch_port(self, vswitch_path, port_name):
     switch_svc = self._conn.Msvm_VirtualSwitchManagementService()[0]
     #Create a port on the vswitch.
     (new_port,
      ret_val) = switch_svc.CreateSwitchPort(Name=str(uuid.uuid4()),
                                             FriendlyName=port_name,
                                             ScopeOfResidence="",
                                             VirtualSwitch=vswitch_path)
     if ret_val != 0:
         raise vmutils.HyperVException(
             _("Failed to create vswitch port "
               "%(port_name)s on switch "
               "%(vswitch_path)s") % locals())
     return new_port
Exemple #22
0
    def get_image_vm_generation(self, root_vhd_path, image_meta):
        default_vm_gen = self._hostutils.get_default_vm_generation()
        image_prop_vm = image_meta.properties.get(
            'hw_machine_type', default_vm_gen)
        if image_prop_vm not in self._hostutils.get_supported_vm_types():
            LOG.error(_LE('Requested VM Generation %s is not supported on '
                         ' this OS.'), image_prop_vm)
            raise vmutils.HyperVException(
                _('Requested VM Generation %s is not supported on this '
                  'OS.') % image_prop_vm)

        vm_gen = VM_GENERATIONS[image_prop_vm]

        if (vm_gen != constants.VM_GEN_1 and root_vhd_path and
                self._vhdutils.get_vhd_format(
                    root_vhd_path) == constants.DISK_FORMAT_VHD):
            LOG.error(_LE('Requested VM Generation %s, but provided VHD '
                          'instead of VHDX.'), vm_gen)
            raise vmutils.HyperVException(
                _('Requested VM Generation %s, but provided VHD instead of '
                  'VHDX.') % vm_gen)

        return vm_gen
Exemple #23
0
    def get_vhd_format(self, path):
        with open(path, 'rb') as f:
            # Read header
            if f.read(8) == VHDX_SIGNATURE:
                return constants.DISK_FORMAT_VHDX

            # Read footer
            f.seek(0, 2)
            file_size = f.tell()
            if file_size >= 512:
                f.seek(-512, 2)
                if f.read(8) == VHD_SIGNATURE:
                    return constants.DISK_FORMAT_VHD

        raise vmutils.HyperVException(_('Unsupported virtual disk format'))
Exemple #24
0
    def _create_root_vhd(self, context, instance):
        base_vhd_path = self._imagecache.get_cached_image(context, instance)
        format_ext = base_vhd_path.split('.')[-1]
        root_vhd_path = self._pathutils.get_root_vhd_path(
            instance['name'], format_ext)

        try:
            if CONF.use_cow_images:
                LOG.debug(
                    _("Creating differencing VHD. Parent: "
                      "%(base_vhd_path)s, Target: %(root_vhd_path)s"), {
                          'base_vhd_path': base_vhd_path,
                          'root_vhd_path': root_vhd_path
                      })
                self._vhdutils.create_differencing_vhd(root_vhd_path,
                                                       base_vhd_path)
            else:
                LOG.debug(
                    _("Copying VHD image %(base_vhd_path)s to target: "
                      "%(root_vhd_path)s"), {
                          'base_vhd_path': base_vhd_path,
                          'root_vhd_path': root_vhd_path
                      })
                self._pathutils.copyfile(base_vhd_path, root_vhd_path)

                base_vhd_info = self._vhdutils.get_vhd_info(base_vhd_path)
                base_vhd_size = base_vhd_info['MaxInternalSize']
                root_vhd_size = instance['root_gb'] * 1024**3

                if root_vhd_size < base_vhd_size:
                    raise vmutils.HyperVException(
                        _("Cannot resize a VHD to a "
                          "smaller size"))
                elif root_vhd_size > base_vhd_size:
                    LOG.debug(
                        _("Resizing VHD %(root_vhd_path)s to new "
                          "size %(root_vhd_size)s"), {
                              'base_vhd_path': base_vhd_path,
                              'root_vhd_path': root_vhd_path
                          })
                    self._vhdutils.resize_vhd(root_vhd_path, root_vhd_size)
        except Exception:
            with excutils.save_and_reraise_exception():
                if self._pathutils.exists(root_vhd_path):
                    self._pathutils.remove(root_vhd_path)

        return root_vhd_path
Exemple #25
0
    def _create_config_drive(self, instance, injected_files, admin_password):
        if CONF.config_drive_format != 'iso9660':
            vmutils.HyperVException(
                _('Invalid config_drive_format "%s"') %
                CONF.config_drive_format)

        LOG.info(_('Using config drive'), instance=instance)
        extra_md = {}
        if admin_password and CONF.config_drive_inject_password:
            extra_md['admin_pass'] = admin_password

        inst_md = instance_metadata.InstanceMetadata(instance,
                                                     content=injected_files,
                                                     extra_md=extra_md)

        instance_path = self._vmutils.get_instance_path(instance['name'])
        configdrive_path_iso = os.path.join(instance_path, 'configdrive.iso')
        LOG.info(_('Creating config drive at %(path)s'),
                 {'path': configdrive_path_iso},
                 instance=instance)

        cdb = configdrive.ConfigDriveBuilder(instance_md=inst_md)
        try:
            cdb.make_drive(configdrive_path_iso)
        finally:
            cdb.cleanup()

        if not CONF.config_drive_cdrom:
            drive_type = constants.IDE_DISK
            configdrive_path = os.path.join(instance_path, 'configdrive.vhd')
            utils.execute(CONF.qemu_img_cmd,
                          'convert',
                          '-f',
                          'raw',
                          '-O',
                          'vpc',
                          configdrive_path_iso,
                          configdrive_path,
                          attempts=1)
            os.remove(configdrive_path_iso)
        else:
            drive_type = constants.IDE_DVD
            configdrive_path = configdrive_path_iso

        self._attach_ide_drive(instance['name'], configdrive_path, 1, 0,
                               drive_type)
Exemple #26
0
 def _attach_volume_to_controller(self, controller, address, mounted_disk,
                                  instance):
     """Attach a volume to a controller """
     #Find the default disk drive object for the vm and clone it.
     diskdflt = self._conn.query(
         "SELECT * FROM Msvm_ResourceAllocationSettingData \
             WHERE ResourceSubType LIKE 'Microsoft Physical Disk Drive'\
             AND InstanceID LIKE '%Default%'")[0]
     diskdrive = self._vmutils.clone_wmi_obj(
         self._conn, 'Msvm_ResourceAllocationSettingData', diskdflt)
     diskdrive.Address = address
     diskdrive.Parent = controller[0].path_()
     diskdrive.HostResource = [mounted_disk[0].path_()]
     new_resources = self._vmutils.add_virt_resource(
         self._conn, diskdrive, instance)
     if new_resources is None:
         raise vmutils.HyperVException(
             _('Failed to add volume to VM %s') % instance)
Exemple #27
0
    def attach_volume(self, connection_info, instance_name, ebs_root=False):
        """
        Attach a volume to the SCSI controller or to the IDE controller if
        ebs_root is True
        """
        target_iqn = None
        LOG.debug(_("Attach_volume: %(connection_info)s to %(instance_name)s"),
                  {
                      'connection_info': connection_info,
                      'instance_name': instance_name
                  })
        try:
            self._login_storage_target(connection_info)

            data = connection_info['data']
            target_lun = data['target_lun']
            target_iqn = data['target_iqn']

            #Getting the mounted disk
            mounted_disk_path = self._get_mounted_disk_from_lun(
                target_iqn, target_lun)

            if ebs_root:
                #Find the IDE controller for the vm.
                ctrller_path = self._vmutils.get_vm_ide_controller(
                    instance_name, 0)
                #Attaching to the first slot
                slot = 0
            else:
                #Find the SCSI controller for the vm
                ctrller_path = self._vmutils.get_vm_scsi_controller(
                    instance_name)
                slot = self._get_free_controller_slot(ctrller_path)

            self._vmutils.attach_volume_to_controller(instance_name,
                                                      ctrller_path, slot,
                                                      mounted_disk_path)
        except Exception as exn:
            LOG.exception(_('Attach volume failed: %s'), exn)
            if target_iqn:
                self._volutils.logout_storage_target(target_iqn)
            raise vmutils.HyperVException(
                _('Unable to attach volume '
                  'to instance %s') % instance_name)
Exemple #28
0
    def _cache_image(self,
                     fn,
                     target,
                     fname,
                     cow=False,
                     size=None,
                     *args,
                     **kwargs):
        """Wrapper for a method that creates and caches an image.

        This wrapper will save the image into a common store and create a
        copy for use by the hypervisor.

        The underlying method should specify a kwarg of target representing
        where the image will be saved.

        fname is used as the filename of the base image.  The filename needs
        to be unique to a given image.

        If cow is True, it will make a CoW image instead of a copy.
        """
        @lockutils.synchronized(fname, 'nova-')
        def call_if_not_exists(path, fn, *args, **kwargs):
            if not os.path.exists(path):
                fn(target=path, *args, **kwargs)

        if not self._pathutils.vhd_exists(target):
            LOG.debug(_("Use CoW image: %s"), cow)
            if cow:
                parent_path = self._pathutils.get_base_vhd_path(fname)
                call_if_not_exists(parent_path, fn, *args, **kwargs)

                LOG.debug(
                    _("Creating differencing VHD. Parent: "
                      "%(parent_path)s, Target: %(target)s") % locals())
                try:
                    self._vhdutils.create_differencing_vhd(target, parent_path)
                except Exception as ex:
                    LOG.exception(ex)
                    raise vmutils.HyperVException(
                        _('Failed to create a differencing disk from '
                          '%(parent_path)s to %(target)s') % locals())
            else:
                call_if_not_exists(target, fn, *args, **kwargs)
Exemple #29
0
    def finish_migration(self,
                         context,
                         migration,
                         instance,
                         disk_info,
                         network_info,
                         image_meta,
                         resize_instance=False,
                         block_device_info=None,
                         power_on=True):
        LOG.debug(_("finish_migration called"), instance=instance)

        instance_name = instance['name']

        if self._volumeops.ebs_root_in_block_devices(block_device_info):
            root_vhd_path = None
        else:
            root_vhd_path = self._pathutils.get_vhd_path(instance_name)
            if not self._pathutils.exists(root_vhd_path):
                raise vmutils.HyperVException(
                    _("Cannot find boot VHD "
                      "file: %s") % root_vhd_path)

            vhd_info = self._vhdutils.get_vhd_info(root_vhd_path)
            src_base_disk_path = vhd_info.get("ParentPath")
            if src_base_disk_path:
                self._check_base_disk(context, instance, root_vhd_path,
                                      src_base_disk_path)

            if resize_instance:
                curr_size = vhd_info['MaxInternalSize']
                new_size = instance['root_gb'] * 1024**3
                if new_size < curr_size:
                    raise vmutils.VHDResizeException(
                        _("Cannot resize a VHD "
                          "to a smaller size"))
                elif new_size > curr_size:
                    self._resize_vhd(root_vhd_path, new_size)

        self._vmops.create_instance(instance, network_info, block_device_info,
                                    root_vhd_path)
        if power_on:
            self._vmops.power_on(instance)
    def login_storage_target(self,
                             target_lun,
                             target_iqn,
                             target_portal,
                             auth_username=None,
                             auth_password=None):
        """Ensure that the target is logged in."""

        self._login_target_portal(target_portal)
        # Listing targets
        self.execute('iscsicli.exe', 'ListTargets')

        retry_count = CONF.hyperv.volume_attach_retry_count

        # If the target is not connected, at least two iterations are needed:
        # one for performing the login and another one for checking if the
        # target was logged in successfully.
        if retry_count < 2:
            retry_count = 2

        for attempt in xrange(retry_count):
            try:
                session_info = self.execute('iscsicli.exe', 'SessionList')
                if session_info.find(target_iqn) == -1:
                    # Sending login
                    self.execute('iscsicli.exe', 'qlogintarget', target_iqn,
                                 auth_username, auth_password)
                else:
                    return
            except vmutils.HyperVException as exc:
                LOG.debug(
                    "Attempt %(attempt)d to connect to target  "
                    "%(target_iqn)s failed. Retrying. "
                    "Exceptipn: %(exc)s ", {
                        'target_iqn': target_iqn,
                        'exc': exc,
                        'attempt': attempt
                    })
                time.sleep(CONF.hyperv.volume_attach_retry_interval)

        raise vmutils.HyperVException(
            _('Failed to login target %s') % target_iqn)