예제 #1
0
    def _check_pool_and_fs(self, volume, fs_label):
        """Validates pool and file system of a volume being managed.

        Checks if the file system for the volume-type chosen matches the
        one passed in the volume reference. Also, checks if the pool
        for the volume type matches the pool for the host passed.

        :param volume: Reference to the volume.
        :param fs_label: Label of the file system.
        :raises: ManageExistingVolumeTypeMismatch
        """
        pool_from_vol_type = hnas_utils.get_pool(self.config, volume)

        pool_from_host = utils.extract_host(volume.host, level='pool')
        pool = self.config['services'][pool_from_vol_type]['hdp']
        if pool != fs_label:
            msg = (_("Failed to manage existing volume because the "
                     "pool %(pool)s of the volume type chosen does not "
                     "match the file system %(fs_label)s passed in the "
                     "volume reference.") % {
                         'pool': pool,
                         'fs_label': fs_label
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        if pool_from_host != pool_from_vol_type:
            msg = (_("Failed to manage existing volume because the pool "
                     "%(pool)s of the volume type chosen does not match the "
                     "pool %(pool_host)s of the host.") % {
                         'pool': pool_from_vol_type,
                         'pool_host': pool_from_host
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
예제 #2
0
    def _check_pool_and_fs(self, volume, fs_label):
        """Validation of the pool and filesystem.

        Checks if the file system for the volume-type chosen matches the
        one passed in the volume reference. Also, checks if the pool
        for the volume type matches the pool for the host passed.

        :param volume: Reference to the volume.
        :param fs_label: Label of the file system.
        """
        pool_from_vol_type = self.get_pool(volume)

        pool_from_host = utils.extract_host(volume['host'], level='pool')

        if self.config['services'][pool_from_vol_type]['hdp'] != fs_label:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen does not match the file system "
                     "passed in the volume reference."), {
                         'File System passed':
                         fs_label,
                         'File System for volume type':
                         self.config['services'][pool_from_vol_type]['hdp']
                     })
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        if pool_from_host != pool_from_vol_type:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen does not match the pool of "
                     "the host."), {
                         'Pool of the volume type': pool_from_vol_type,
                         'Pool of the host': pool_from_host
                     })
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
예제 #3
0
    def _check_pool_and_share(self, volume, nfs_share):
        """Validates the pool and the NFS share.

        Checks if the NFS share for the volume-type chosen matches the
        one passed in the volume reference. Also, checks if the pool
        for the volume type matches the pool for the host passed.

        :param volume:    cinder volume reference
        :param nfs_share: NFS share passed to manage
        """
        pool_from_vol_type = self.get_pool(volume)

        pool_from_host = utils.extract_host(volume['host'], level='pool')

        if self.config['services'][pool_from_vol_type]['hdp'] != nfs_share:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen does not match the NFS share "
                     "passed in the volume reference."), {
                         'Share passed':
                         nfs_share,
                         'Share for volume type':
                         self.config['services'][pool_from_vol_type]['hdp']
                     })
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        if pool_from_host != pool_from_vol_type:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen does not match the pool of "
                     "the host."), {
                         'Pool of the volume type': pool_from_vol_type,
                         'Pool of the host': pool_from_host
                     })
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
예제 #4
0
파일: hnas_nfs.py 프로젝트: Jchuan/cinder
    def _check_pool_and_share(self, volume, nfs_share):
        """Validates the pool and the NFS share.

        Checks if the NFS share for the volume-type chosen matches the
        one passed in the volume reference. Also, checks if the pool
        for the volume type matches the pool for the host passed.

        :param volume: cinder volume reference
        :param nfs_share: NFS share passed to manage
        :raises: ManageExistingVolumeTypeMismatch
        """
        pool_from_vol_type = hnas_utils.get_pool(self.config, volume)

        pool_from_host = utils.extract_host(volume.host, level='pool')
        pool = self.config['services'][pool_from_vol_type]['hdp']
        if pool != nfs_share:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen (%(pool)s) does not match the "
                     "NFS share passed in the volume reference (%(share)s).") %
                   {
                       'share': nfs_share,
                       'pool': pool
                   })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        if pool_from_host != pool_from_vol_type:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen (%(pool)s) does not match the "
                     "pool of the host %(pool_host)s") % {
                         'pool': pool_from_vol_type,
                         'pool_host': pool_from_host
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
예제 #5
0
 def _check_volume_type(self, volume, share, file_name, extra_specs):
     """Matches a volume type for share file."""
     qos_policy_group = extra_specs.pop('netapp:qos_policy_group', None) \
         if extra_specs else None
     if qos_policy_group:
         raise exception.ManageExistingVolumeTypeMismatch(
             reason=(_("Setting file qos policy group is not supported"
                       " on this storage family and ontap version.")))
     volume_type = na_utils.get_volume_type_from_volume(volume)
     if volume_type and 'qos_spec_id' in volume_type:
         raise exception.ManageExistingVolumeTypeMismatch(
             reason=_("QoS specs are not supported"
                      " on this storage family and ONTAP version."))
예제 #6
0
    def _check_pool_and_share(self, volume, nfs_share):
        """Validates the pool and the NFS share.

        Checks if the NFS share for the volume-type chosen matches the
        one passed in the volume reference. Also, checks if the pool
        for the volume type matches the pool for the host passed.

        :param volume: cinder volume reference
        :param nfs_share: NFS share passed to manage
        :raises ManageExistingVolumeTypeMismatch:
        """
        pool_from_vol_type = hnas_utils.get_pool(self.config, volume)

        pool_from_host = utils.extract_host(volume.host, level='pool')

        if (pool_from_vol_type == 'default'
                and 'default' not in self.config['services']):
            msg = (_("Failed to manage existing volume %(volume)s because the "
                     "chosen volume type %(vol_type)s does not have a "
                     "service_label configured in its extra-specs and there "
                     "is no pool configured with hnas_svcX_volume_type as "
                     "'default' in cinder.conf.") % {
                         'volume': volume.id,
                         'vol_type': getattr(volume.volume_type, 'id', None)
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        pool = self.config['services'][pool_from_vol_type]['hdp']
        if pool != nfs_share:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen (%(pool)s) does not match the "
                     "NFS share passed in the volume reference (%(share)s).") %
                   {
                       'share': nfs_share,
                       'pool': pool
                   })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        if pool_from_host != pool_from_vol_type:
            msg = (_("Failed to manage existing volume because the pool of "
                     "the volume type chosen (%(pool)s) does not match the "
                     "pool of the host %(pool_host)s") % {
                         'pool': pool_from_vol_type,
                         'pool_host': pool_from_host
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
예제 #7
0
    def _check_pool_and_fs(self, volume, fs_label):
        """Validates pool and file system of a volume being managed.

        Checks if the file system for the volume-type chosen matches the
        one passed in the volume reference. Also, checks if the pool
        for the volume type matches the pool for the host passed.

        :param volume: Reference to the volume.
        :param fs_label: Label of the file system.
        :raises: ManageExistingVolumeTypeMismatch
        """
        pool_from_vol_type = hnas_utils.get_pool(self.config, volume)

        if (pool_from_vol_type == 'default'
                and 'default' not in self.config['services']):
            msg = (_("Failed to manage existing volume %(volume)s because the "
                     "chosen volume type %(vol_type)s does not have a "
                     "service_label configured in its extra-specs and there "
                     "is no pool configured with hnas_svcX_volume_type as "
                     "'default' in cinder.conf.") % {
                         'volume': volume.id,
                         'vol_type': getattr(volume.volume_type, 'id', None)
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        pool = self.config['services'][pool_from_vol_type]['hdp']
        if pool != fs_label:
            msg = (_("Failed to manage existing volume because the "
                     "pool %(pool)s of the volume type chosen does not "
                     "match the file system %(fs_label)s passed in the "
                     "volume reference.") % {
                         'pool': pool,
                         'fs_label': fs_label
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)

        pool_from_host = utils.extract_host(volume.host, level='pool')

        if pool_from_host != pool_from_vol_type:
            msg = (_("Failed to manage existing volume because the pool "
                     "%(pool)s of the volume type chosen does not match the "
                     "pool %(pool_host)s of the host.") % {
                         'pool': pool_from_vol_type,
                         'pool_host': pool_from_host
                     })
            LOG.error(msg)
            raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
예제 #8
0
    def _check_volume_type_for_lun(self, volume, lun, existing_ref,
                                   extra_specs):
        """Check if LUN satisfies volume type."""
        def scan_ssc_data():
            volumes = ssc_cmode.get_volumes_for_specs(self.ssc_vols,
                                                      extra_specs)
            for vol in volumes:
                if lun.get_metadata_property('Volume') == vol.id['name']:
                    return True
            return False

        match_read = scan_ssc_data()
        if not match_read:
            ssc_cmode.get_cluster_latest_ssc(self,
                                             self.zapi_client.get_connection(),
                                             self.vserver)
            match_read = scan_ssc_data()

        if not match_read:
            raise exception.ManageExistingVolumeTypeMismatch(
                reason=(_("LUN with given ref %(ref)s does not satisfy volume"
                          " type. Ensure LUN volume with ssc features is"
                          " present on vserver %(vs)s.") % {
                              'ref': existing_ref,
                              'vs': self.vserver
                          }))
예제 #9
0
 def _check_volume_type_for_lun(self, volume, lun, existing_ref):
     """Check if lun satisfies volume type."""
     extra_specs = na_utils.get_volume_extra_specs(volume)
     if extra_specs and extra_specs.pop('netapp:qos_policy_group', None):
         raise exception.ManageExistingVolumeTypeMismatch(
             reason=_("Setting LUN QoS policy group is not supported"
                      " on this storage family and ONTAP version."))
예제 #10
0
 def _check_volume_type_for_lun(self, volume, lun, existing_ref,
                                extra_specs):
     """Check if LUN satisfies volume type."""
     if extra_specs:
         legacy_policy = extra_specs.get('netapp:qos_policy_group')
         if legacy_policy is not None:
             raise exception.ManageExistingVolumeTypeMismatch(
                 reason=_("Setting LUN QoS policy group is not supported "
                          "on this storage family and ONTAP version."))
     volume_type = na_utils.get_volume_type_from_volume(volume)
     if volume_type is None:
         return
     spec = na_utils.get_backend_qos_spec_from_volume_type(volume_type)
     if spec is not None:
         raise exception.ManageExistingVolumeTypeMismatch(
             reason=_("Back-end QoS specs are not supported on this "
                      "storage family and ONTAP version."))
예제 #11
0
 def _check_volume_type(self, volume, share, file_name):
     """Matches a volume type for share file."""
     extra_specs = na_utils.get_volume_extra_specs(volume)
     qos_policy_group = extra_specs.pop('netapp:qos_policy_group', None) \
         if extra_specs else None
     if qos_policy_group:
         raise exception.ManageExistingVolumeTypeMismatch(
             reason=(_("Setting file qos policy group is not supported"
                       " on this storage family and ontap version.")))
예제 #12
0
 def _check_volume_type(self, volume, share, file_name):
     """Match volume type for share file."""
     extra_specs = na_utils.get_volume_extra_specs(volume)
     qos_policy_group = extra_specs.pop('netapp:qos_policy_group', None) \
         if extra_specs else None
     if not self._is_share_vol_type_match(volume, share):
         raise exception.ManageExistingVolumeTypeMismatch(
             reason=(_("Volume type does not match for share %s."), share))
     if qos_policy_group:
         try:
             vserver, flex_vol_name = self._get_vserver_and_exp_vol(
                 share=share)
             self.zapi_client.file_assign_qos(flex_vol_name,
                                              qos_policy_group, file_name)
         except na_api.NaApiError as ex:
             LOG.exception(_LE('Setting file QoS policy group failed. %s'),
                           ex)
             raise exception.NetAppDriverException(
                 reason=(_('Setting file QoS policy group failed. %s'), ex))
예제 #13
0
    def _check_volume_type_for_lun(self, volume, lun, existing_ref):
        """Check if LUN satisfies volume type."""
        extra_specs = na_utils.get_volume_extra_specs(volume)
        match_write = False

        def scan_ssc_data():
            volumes = ssc_cmode.get_volumes_for_specs(self.ssc_vols,
                                                      extra_specs)
            for vol in volumes:
                if lun.get_metadata_property('Volume') == vol.id['name']:
                    return True
            return False

        match_read = scan_ssc_data()
        if not match_read:
            ssc_cmode.get_cluster_latest_ssc(self,
                                             self.zapi_client.get_connection(),
                                             self.vserver)
            match_read = scan_ssc_data()

        qos_policy_group = extra_specs.pop('netapp:qos_policy_group', None) \
            if extra_specs else None
        if qos_policy_group:
            if match_read:
                try:
                    path = lun.get_metadata_property('Path')
                    self.zapi_client.set_lun_qos_policy_group(
                        path, qos_policy_group)
                    match_write = True
                except netapp_api.NaApiError as nae:
                    LOG.error(_LE("Failure setting QoS policy group. %s"), nae)
        else:
            match_write = True
        if not (match_read and match_write):
            raise exception.ManageExistingVolumeTypeMismatch(
                reason=(_("LUN with given ref %(ref)s does not satisfy volume"
                          " type. Ensure LUN volume with ssc features is"
                          " present on vserver %(vs)s.") % {
                              'ref': existing_ref,
                              'vs': self.vserver
                          }))
예제 #14
0
 def _check_volume_type(self, volume, share, file_name, extra_specs):
     """Match volume type for share file."""
     if not self._is_share_vol_type_match(volume, share):
         raise exception.ManageExistingVolumeTypeMismatch(
             reason=(_("Volume type does not match for share %s."),
                     share))
예제 #15
0
    def manage_existing(self, volume, existing_ref):
        """Manage an existing LeftHand volume.

        existing_ref is a dictionary of the form:
        {'source-name': <name of the virtual volume>}
        """
        # Check API Version
        self._check_api_version()

        target_vol_name = self._get_existing_volume_ref_name(existing_ref)

        # Check for the existence of the virtual volume.
        client = self._login()
        try:
            volume_info = client.getVolumeByName(target_vol_name)
        except hpexceptions.HTTPNotFound:
            err = (_("Virtual volume '%s' doesn't exist on array.") %
                   target_vol_name)
            LOG.error(err)
            raise exception.InvalidInput(reason=err)
        finally:
            self._logout(client)

        # Generate the new volume information based on the new ID.
        new_vol_name = 'volume-' + volume['id']

        volume_type = None
        if volume['volume_type_id']:
            try:
                volume_type = self._get_volume_type(volume['volume_type_id'])
            except Exception:
                reason = (_("Volume type ID '%s' is invalid.") %
                          volume['volume_type_id'])
                raise exception.ManageExistingVolumeTypeMismatch(reason=reason)

        new_vals = {"name": new_vol_name}

        client = self._login()
        try:
            # Update the existing volume with the new name.
            client.modifyVolume(volume_info['id'], new_vals)
        finally:
            self._logout(client)

        LOG.info(_LI("Virtual volume '%(ref)s' renamed to '%(new)s'."), {
            'ref': existing_ref['source-name'],
            'new': new_vol_name
        })

        display_name = None
        if volume['display_name']:
            display_name = volume['display_name']

        if volume_type:
            LOG.info(
                _LI("Virtual volume %(disp)s '%(new)s' is "
                    "being retyped."), {
                        'disp': display_name,
                        'new': new_vol_name
                    })

            try:
                self.retype(None, volume, volume_type,
                            volume_type['extra_specs'], volume['host'])
                LOG.info(
                    _LI("Virtual volume %(disp)s successfully retyped to "
                        "%(new_type)s."), {
                            'disp': display_name,
                            'new_type': volume_type.get('name')
                        })
            except Exception:
                with excutils.save_and_reraise_exception():
                    LOG.warning(
                        _LW("Failed to manage virtual volume %(disp)s "
                            "due to error during retype."),
                        {'disp': display_name})
                    # Try to undo the rename and clear the new comment.
                    client = self._login()
                    try:
                        client.modifyVolume(volume_info['id'],
                                            {'name': target_vol_name})
                    finally:
                        self._logout(client)

        updates = {'display_name': display_name}

        LOG.info(
            _LI("Virtual volume %(disp)s '%(new)s' is "
                "now being managed."), {
                    'disp': display_name,
                    'new': new_vol_name
                })

        # Return display name to update the name displayed in the GUI and
        # any model updates from retype.
        return updates