214 lines
7.8 KiB
Python
214 lines
7.8 KiB
Python
# Copyright (c) 2015 Huawei Technologies Co., Ltd.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
from oslo_utils import excutils
|
|
from oslo_utils import strutils
|
|
|
|
from manila import exception
|
|
from manila.i18n import _
|
|
from manila.share.drivers.huawei import constants
|
|
|
|
|
|
class SmartPartition(object):
|
|
def __init__(self, helper):
|
|
self.helper = helper
|
|
|
|
def add(self, opts, fsid):
|
|
if not strutils.bool_from_string(opts['huawei_smartpartition']):
|
|
return
|
|
if not opts['partitionname']:
|
|
raise exception.InvalidInput(
|
|
reason=_('Partition name is None, please set '
|
|
'huawei_smartpartition:partitionname in key.'))
|
|
|
|
partition_id = self.helper._get_partition_id_by_name(
|
|
opts['partitionname'])
|
|
if not partition_id:
|
|
raise exception.InvalidInput(
|
|
reason=_('Can not find partition id.'))
|
|
|
|
self.helper._add_fs_to_partition(fsid, partition_id)
|
|
|
|
|
|
class SmartCache(object):
|
|
def __init__(self, helper):
|
|
self.helper = helper
|
|
|
|
def add(self, opts, fsid):
|
|
if not strutils.bool_from_string(opts['huawei_smartcache']):
|
|
return
|
|
if not opts['cachename']:
|
|
raise exception.InvalidInput(
|
|
reason=_('Illegal value specified for cache.'))
|
|
|
|
cache_id = self.helper._get_cache_id_by_name(opts['cachename'])
|
|
if not cache_id:
|
|
raise exception.InvalidInput(
|
|
reason=(_('Can not find cache id by cache name %(name)s.')
|
|
% {'name': opts['cachename']}))
|
|
|
|
self.helper._add_fs_to_cache(fsid, cache_id)
|
|
|
|
|
|
class SmartQos(object):
|
|
def __init__(self, helper):
|
|
self.helper = helper
|
|
|
|
def create_qos(self, qos, fs_id):
|
|
policy_id = None
|
|
try:
|
|
# Check QoS priority.
|
|
if self._check_qos_high_priority(qos):
|
|
self.helper.change_fs_priority_high(fs_id)
|
|
# Create QoS policy and activate it.
|
|
(qos_id, fs_list) = self.helper.find_available_qos(qos)
|
|
if qos_id is not None:
|
|
self.helper.add_share_to_qos(qos_id, fs_id, fs_list)
|
|
else:
|
|
policy_id = self.helper.create_qos_policy(qos, fs_id)
|
|
self.helper.activate_deactivate_qos(policy_id, True)
|
|
except exception.InvalidInput:
|
|
with excutils.save_and_reraise_exception():
|
|
if policy_id is not None:
|
|
self.helper.delete_qos_policy(policy_id)
|
|
|
|
def _check_qos_high_priority(self, qos):
|
|
"""Check QoS priority."""
|
|
for key, value in qos.items():
|
|
if (key.find('MIN') == 0) or (key.find('LATENCY') == 0):
|
|
return True
|
|
|
|
return False
|
|
|
|
def delete_qos(self, qos_id):
|
|
qos_info = self.helper.get_qos_info(qos_id)
|
|
qos_status = qos_info['RUNNINGSTATUS']
|
|
if qos_status != constants.STATUS_QOS_INACTIVATED:
|
|
self.helper.activate_deactivate_qos(qos_id, False)
|
|
self.helper.delete_qos_policy(qos_id)
|
|
|
|
|
|
class SmartX(object):
|
|
def __init__(self, helper):
|
|
self.helper = helper
|
|
|
|
def get_smartx_extra_specs_opts(self, opts):
|
|
opts = self.get_capabilities_opts(opts, 'dedupe')
|
|
opts = self.get_capabilities_opts(opts, 'compression')
|
|
opts = self.get_smartprovisioning_opts(opts)
|
|
opts = self.get_smartcache_opts(opts)
|
|
opts = self.get_smartpartition_opts(opts)
|
|
opts = self.get_sectorsize_opts(opts)
|
|
qos = self.get_qos_opts(opts)
|
|
return opts, qos
|
|
|
|
def get_capabilities_opts(self, opts, key):
|
|
if strutils.bool_from_string(opts[key]):
|
|
opts[key] = True
|
|
else:
|
|
opts[key] = False
|
|
|
|
return opts
|
|
|
|
def get_smartprovisioning_opts(self, opts):
|
|
thin_provision = opts.get('thin_provisioning')
|
|
if (thin_provision is None or
|
|
strutils.bool_from_string(thin_provision)):
|
|
opts['LUNType'] = constants.ALLOC_TYPE_THIN_FLAG
|
|
else:
|
|
opts['LUNType'] = constants.ALLOC_TYPE_THICK_FLAG
|
|
|
|
return opts
|
|
|
|
def get_smartcache_opts(self, opts):
|
|
if strutils.bool_from_string(opts['huawei_smartcache']):
|
|
if not opts['cachename']:
|
|
raise exception.InvalidInput(
|
|
reason=_('Cache name is None, please set '
|
|
'huawei_smartcache:cachename in key.'))
|
|
else:
|
|
opts['cachename'] = None
|
|
|
|
return opts
|
|
|
|
def get_smartpartition_opts(self, opts):
|
|
if strutils.bool_from_string(opts['huawei_smartpartition']):
|
|
if not opts['partitionname']:
|
|
raise exception.InvalidInput(
|
|
reason=_('Partition name is None, please set '
|
|
'huawei_smartpartition:partitionname in key.'))
|
|
else:
|
|
opts['partitionname'] = None
|
|
|
|
return opts
|
|
|
|
def get_sectorsize_opts(self, opts):
|
|
value = None
|
|
if strutils.bool_from_string(opts.get('huawei_sectorsize')):
|
|
value = opts.get('sectorsize')
|
|
if not value:
|
|
root = self.helper._read_xml()
|
|
sectorsize = root.findtext('Filesystem/SectorSize')
|
|
if sectorsize:
|
|
sectorsize = sectorsize.strip()
|
|
value = sectorsize
|
|
|
|
if value:
|
|
if value not in constants.VALID_SECTOR_SIZES:
|
|
raise exception.InvalidInput(
|
|
reason=(_('Illegal value(%s) specified for sectorsize: '
|
|
'set to either 4, 8, 16, 32 or 64.') % value))
|
|
else:
|
|
opts['sectorsize'] = int(value)
|
|
return opts
|
|
|
|
def get_qos_opts(self, opts):
|
|
qos = {}
|
|
if not strutils.bool_from_string(opts.get('qos')):
|
|
return
|
|
|
|
for key, value in opts.items():
|
|
if (key in constants.OPTS_QOS_VALUE) and value is not None:
|
|
if (key.upper() != 'IOTYPE') and (int(value) <= 0):
|
|
err_msg = (_('QoS config is wrong. %(key)s'
|
|
' must be set greater than 0.')
|
|
% {'key': key})
|
|
raise exception.InvalidInput(reason=err_msg)
|
|
elif ((key.upper() == 'IOTYPE')
|
|
and (value not in ['0', '1', '2'])):
|
|
raise exception.InvalidInput(
|
|
reason=(_('Illegal value specified for IOTYPE: '
|
|
'set to either 0, 1, or 2.')))
|
|
else:
|
|
qos[key.upper()] = value
|
|
|
|
if len(qos) <= 1 or 'IOTYPE' not in qos:
|
|
msg = (_('QoS config is incomplete. Please set more. '
|
|
'QoS policy: %(qos_policy)s.')
|
|
% {'qos_policy': qos})
|
|
raise exception.InvalidInput(reason=msg)
|
|
|
|
lowerlimit = constants.QOS_LOWER_LIMIT
|
|
upperlimit = constants.QOS_UPPER_LIMIT
|
|
if (set(lowerlimit).intersection(set(qos))
|
|
and set(upperlimit).intersection(set(qos))):
|
|
msg = (_('QoS policy conflict, both protection policy and '
|
|
'restriction policy are set. '
|
|
'QoS policy: %(qos_policy)s ')
|
|
% {'qos_policy': qos})
|
|
raise exception.InvalidInput(reason=msg)
|
|
|
|
return qos
|