"Fossies" - the Fresh Open Source Software Archive

Member "cinder-13.0.7/cinder/volume/drivers/huawei/smartx.py" (4 Oct 2019, 8993 Bytes) of package /linux/misc/openstack/cinder-13.0.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "smartx.py" see the Fossies "Dox" file reference documentation.

    1 # Copyright (c) 2016 Huawei Technologies Co., Ltd.
    2 # All Rights Reserved.
    3 #
    4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
    5 #    not use this file except in compliance with the License. You may obtain
    6 #    a copy of the License at
    7 #
    8 #         http://www.apache.org/licenses/LICENSE-2.0
    9 #
   10 #    Unless required by applicable law or agreed to in writing, software
   11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   13 #    License for the specific language governing permissions and limitations
   14 #    under the License.
   15 
   16 from oslo_log import log as logging
   17 from oslo_utils import excutils
   18 
   19 from cinder import context
   20 from cinder import exception
   21 from cinder.i18n import _
   22 from cinder import utils
   23 from cinder.volume.drivers.huawei import constants
   24 from cinder.volume import qos_specs
   25 
   26 LOG = logging.getLogger(__name__)
   27 
   28 
   29 class SmartQos(object):
   30     def __init__(self, client):
   31         self.client = client
   32 
   33     @staticmethod
   34     def get_qos_by_volume_type(volume_type):
   35         # We prefer the qos_specs association
   36         # and override any existing extra-specs settings
   37         # if present.
   38         if not volume_type:
   39             return {}
   40 
   41         qos_specs_id = volume_type.get('qos_specs_id')
   42         if not qos_specs_id:
   43             return {}
   44 
   45         qos = {}
   46         io_type_flag = None
   47         ctxt = context.get_admin_context()
   48         consumer = qos_specs.get_qos_specs(ctxt, qos_specs_id)['consumer']
   49         if consumer == 'front-end':
   50             return {}
   51 
   52         kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs']
   53         LOG.info('The QoS sepcs is: %s.', kvs)
   54         for k, v in kvs.items():
   55             if k not in constants.HUAWEI_VALID_KEYS:
   56                 continue
   57             if k != 'IOType' and int(v) <= 0:
   58                 msg = _('QoS config is wrong. %s must > 0.') % k
   59                 LOG.error(msg)
   60                 raise exception.InvalidInput(reason=msg)
   61             if k == 'IOType':
   62                 if v not in ['0', '1', '2']:
   63                     msg = _('Illegal value specified for IOTYPE: 0, 1, or 2.')
   64                     LOG.error(msg)
   65                     raise exception.InvalidInput(reason=msg)
   66                 io_type_flag = 1
   67                 qos[k.upper()] = v
   68             else:
   69                 qos[k.upper()] = v
   70 
   71         if not io_type_flag:
   72             msg = (_('QoS policy must specify for IOTYPE: 0, 1, or 2, '
   73                      'QoS policy: %(qos_policy)s ') % {'qos_policy': qos})
   74             LOG.error(msg)
   75             raise exception.InvalidInput(reason=msg)
   76 
   77         # QoS policy must specify for IOTYPE and another qos_specs.
   78         if len(qos) < 2:
   79             msg = (_('QoS policy must specify for IOTYPE and another '
   80                      'qos_specs, QoS policy: %(qos_policy)s.')
   81                    % {'qos_policy': qos})
   82             LOG.error(msg)
   83             raise exception.InvalidInput(reason=msg)
   84 
   85         for upper_limit in constants.UPPER_LIMIT_KEYS:
   86             for lower_limit in constants.LOWER_LIMIT_KEYS:
   87                 if upper_limit in qos and lower_limit in qos:
   88                     msg = (_('QoS policy upper_limit and lower_limit '
   89                              'conflict, QoS policy: %(qos_policy)s.')
   90                            % {'qos_policy': qos})
   91                     LOG.error(msg)
   92                     raise exception.InvalidInput(reason=msg)
   93 
   94         return qos
   95 
   96     def _is_high_priority(self, qos):
   97         """Check QoS priority."""
   98         for key, value in qos.items():
   99             if (key.find('MIN') == 0) or (key.find('LATENCY') == 0):
  100                 return True
  101 
  102         return False
  103 
  104     @utils.synchronized('huawei_qos', external=True)
  105     def add(self, qos, lun_id):
  106         policy_id = None
  107         try:
  108             # Check QoS priority.
  109             if self._is_high_priority(qos):
  110                 self.client.change_lun_priority(lun_id)
  111             # Create QoS policy and activate it.
  112             version = self.client.find_array_version()
  113             if version >= constants.ARRAY_VERSION:
  114                 (qos_id, lun_list) = self.client.find_available_qos(qos)
  115                 if qos_id:
  116                     self.client.add_lun_to_qos(qos_id, lun_id, lun_list)
  117                 else:
  118                     policy_id = self.client.create_qos_policy(qos, lun_id)
  119                     self.client.activate_deactivate_qos(policy_id, True)
  120             else:
  121                 policy_id = self.client.create_qos_policy(qos, lun_id)
  122                 self.client.activate_deactivate_qos(policy_id, True)
  123         except exception.VolumeBackendAPIException:
  124             with excutils.save_and_reraise_exception():
  125                 if policy_id is not None:
  126                     self.client.delete_qos_policy(policy_id)
  127 
  128     @utils.synchronized('huawei_qos', external=True)
  129     def remove(self, qos_id, lun_id):
  130         qos_info = self.client.get_qos_info(qos_id)
  131         lun_list = self.client.get_lun_list_in_qos(qos_id, qos_info)
  132         if len(lun_list) <= 1:
  133             qos_status = qos_info['RUNNINGSTATUS']
  134             # 2: Active status.
  135             if qos_status != constants.STATUS_QOS_INACTIVE:
  136                 self.client.activate_deactivate_qos(qos_id, False)
  137             self.client.delete_qos_policy(qos_id)
  138         else:
  139             self.client.remove_lun_from_qos(lun_id, lun_list, qos_id)
  140 
  141 
  142 class SmartPartition(object):
  143     def __init__(self, client):
  144         self.client = client
  145 
  146     def add(self, opts, lun_id):
  147         if opts['smartpartition'] != 'true':
  148             return
  149         if not opts['partitionname']:
  150             raise exception.InvalidInput(
  151                 reason=_('Partition name is None, please set '
  152                          'smartpartition:partitionname in key.'))
  153 
  154         partition_id = self.client.get_partition_id_by_name(
  155             opts['partitionname'])
  156         if not partition_id:
  157             raise exception.InvalidInput(
  158                 reason=(_('Can not find partition id by name %(name)s.')
  159                         % {'name': opts['partitionname']}))
  160 
  161         self.client.add_lun_to_partition(lun_id, partition_id)
  162 
  163 
  164 class SmartCache(object):
  165     def __init__(self, client):
  166         self.client = client
  167 
  168     def add(self, opts, lun_id):
  169         if opts['smartcache'] != 'true':
  170             return
  171         if not opts['cachename']:
  172             raise exception.InvalidInput(
  173                 reason=_('Cache name is None, please set '
  174                          'smartcache:cachename in key.'))
  175 
  176         cache_id = self.client.get_cache_id_by_name(opts['cachename'])
  177         if not cache_id:
  178             raise exception.InvalidInput(
  179                 reason=(_('Can not find cache id by cache name %(name)s.')
  180                         % {'name': opts['cachename']}))
  181 
  182         self.client.add_lun_to_cache(lun_id, cache_id)
  183 
  184 
  185 class SmartX(object):
  186     def get_smartx_specs_opts(self, opts):
  187         # Check that smarttier is 0/1/2/3
  188         opts = self.get_smarttier_opts(opts)
  189         opts = self.get_smartthin_opts(opts)
  190         opts = self.get_smartcache_opts(opts)
  191         opts = self.get_smartpartition_opts(opts)
  192         return opts
  193 
  194     def get_smarttier_opts(self, opts):
  195         if opts['smarttier'] == 'true':
  196             if not opts['policy']:
  197                 opts['policy'] = '1'
  198             elif opts['policy'] not in ['0', '1', '2', '3']:
  199                 raise exception.InvalidInput(
  200                     reason=(_('Illegal value specified for smarttier: '
  201                               'set to either 0, 1, 2, or 3.')))
  202         else:
  203             opts['policy'] = '0'
  204 
  205         return opts
  206 
  207     def get_smartthin_opts(self, opts):
  208         if opts['thin_provisioning_support'] == 'true':
  209             if opts['thick_provisioning_support'] == 'true':
  210                 raise exception.InvalidInput(
  211                     reason=(_('Illegal value specified for thin: '
  212                               'Can not set thin and thick at the same time.')))
  213             else:
  214                 opts['LUNType'] = constants.THIN_LUNTYPE
  215         if opts['thick_provisioning_support'] == 'true':
  216             opts['LUNType'] = constants.THICK_LUNTYPE
  217 
  218         return opts
  219 
  220     def get_smartcache_opts(self, opts):
  221         if opts['smartcache'] == 'true':
  222             if not opts['cachename']:
  223                 raise exception.InvalidInput(
  224                     reason=_('Cache name is None, please set '
  225                              'smartcache:cachename in key.'))
  226         else:
  227             opts['cachename'] = None
  228 
  229         return opts
  230 
  231     def get_smartpartition_opts(self, opts):
  232         if opts['smartpartition'] == 'true':
  233             if not opts['partitionname']:
  234                 raise exception.InvalidInput(
  235                     reason=_('Partition name is None, please set '
  236                              'smartpartition:partitionname in key.'))
  237         else:
  238             opts['partitionname'] = None
  239 
  240         return opts