Coverage for manila/share/drivers/huawei/v3/smartx.py: 97%
128 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2015 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.
16from oslo_utils import excutils
17from oslo_utils import strutils
19from manila import exception
20from manila.i18n import _
21from manila.share.drivers.huawei import constants
24class SmartPartition(object):
25 def __init__(self, helper):
26 self.helper = helper
28 def add(self, opts, fsid):
29 if not strutils.bool_from_string(opts['huawei_smartpartition']):
30 return
31 if not opts['partitionname']:
32 raise exception.InvalidInput(
33 reason=_('Partition name is None, please set '
34 'huawei_smartpartition:partitionname in key.'))
36 partition_id = self.helper._get_partition_id_by_name(
37 opts['partitionname'])
38 if not partition_id:
39 raise exception.InvalidInput(
40 reason=_('Can not find partition id.'))
42 self.helper._add_fs_to_partition(fsid, partition_id)
45class SmartCache(object):
46 def __init__(self, helper):
47 self.helper = helper
49 def add(self, opts, fsid):
50 if not strutils.bool_from_string(opts['huawei_smartcache']):
51 return
52 if not opts['cachename']:
53 raise exception.InvalidInput(
54 reason=_('Illegal value specified for cache.'))
56 cache_id = self.helper._get_cache_id_by_name(opts['cachename'])
57 if not cache_id:
58 raise exception.InvalidInput(
59 reason=(_('Can not find cache id by cache name %(name)s.')
60 % {'name': opts['cachename']}))
62 self.helper._add_fs_to_cache(fsid, cache_id)
65class SmartQos(object):
66 def __init__(self, helper):
67 self.helper = helper
69 def create_qos(self, qos, fs_id):
70 policy_id = None
71 try:
72 # Check QoS priority.
73 if self._check_qos_high_priority(qos):
74 self.helper.change_fs_priority_high(fs_id)
75 # Create QoS policy and activate it.
76 (qos_id, fs_list) = self.helper.find_available_qos(qos)
77 if qos_id is not None:
78 self.helper.add_share_to_qos(qos_id, fs_id, fs_list)
79 else:
80 policy_id = self.helper.create_qos_policy(qos, fs_id)
81 self.helper.activate_deactivate_qos(policy_id, True)
82 except exception.InvalidInput:
83 with excutils.save_and_reraise_exception():
84 if policy_id is not None:
85 self.helper.delete_qos_policy(policy_id)
87 def _check_qos_high_priority(self, qos):
88 """Check QoS priority."""
89 for key, value in qos.items():
90 if (key.find('MIN') == 0) or (key.find('LATENCY') == 0):
91 return True
93 return False
95 def delete_qos(self, qos_id):
96 qos_info = self.helper.get_qos_info(qos_id)
97 qos_status = qos_info['RUNNINGSTATUS']
98 if qos_status != constants.STATUS_QOS_INACTIVATED:
99 self.helper.activate_deactivate_qos(qos_id, False)
100 self.helper.delete_qos_policy(qos_id)
103class SmartX(object):
104 def __init__(self, helper):
105 self.helper = helper
107 def get_smartx_extra_specs_opts(self, opts):
108 opts = self.get_capabilities_opts(opts, 'dedupe')
109 opts = self.get_capabilities_opts(opts, 'compression')
110 opts = self.get_smartprovisioning_opts(opts)
111 opts = self.get_smartcache_opts(opts)
112 opts = self.get_smartpartition_opts(opts)
113 opts = self.get_sectorsize_opts(opts)
114 qos = self.get_qos_opts(opts)
115 return opts, qos
117 def get_capabilities_opts(self, opts, key):
118 if strutils.bool_from_string(opts[key]):
119 opts[key] = True
120 else:
121 opts[key] = False
123 return opts
125 def get_smartprovisioning_opts(self, opts):
126 thin_provision = opts.get('thin_provisioning')
127 if (thin_provision is None or
128 strutils.bool_from_string(thin_provision)):
129 opts['LUNType'] = constants.ALLOC_TYPE_THIN_FLAG
130 else:
131 opts['LUNType'] = constants.ALLOC_TYPE_THICK_FLAG
133 return opts
135 def get_smartcache_opts(self, opts):
136 if strutils.bool_from_string(opts['huawei_smartcache']):
137 if not opts['cachename']:
138 raise exception.InvalidInput(
139 reason=_('Cache name is None, please set '
140 'huawei_smartcache:cachename in key.'))
141 else:
142 opts['cachename'] = None
144 return opts
146 def get_smartpartition_opts(self, opts):
147 if strutils.bool_from_string(opts['huawei_smartpartition']):
148 if not opts['partitionname']:
149 raise exception.InvalidInput(
150 reason=_('Partition name is None, please set '
151 'huawei_smartpartition:partitionname in key.'))
152 else:
153 opts['partitionname'] = None
155 return opts
157 def get_sectorsize_opts(self, opts):
158 value = None
159 if strutils.bool_from_string(opts.get('huawei_sectorsize')):
160 value = opts.get('sectorsize')
161 if not value:
162 root = self.helper._read_xml()
163 sectorsize = root.findtext('Filesystem/SectorSize')
164 if sectorsize:
165 sectorsize = sectorsize.strip()
166 value = sectorsize
168 if value:
169 if value not in constants.VALID_SECTOR_SIZES:
170 raise exception.InvalidInput(
171 reason=(_('Illegal value(%s) specified for sectorsize: '
172 'set to either 4, 8, 16, 32 or 64.') % value))
173 else:
174 opts['sectorsize'] = int(value)
175 return opts
177 def get_qos_opts(self, opts):
178 qos = {}
179 if not strutils.bool_from_string(opts.get('qos')):
180 return
182 for key, value in opts.items():
183 if (key in constants.OPTS_QOS_VALUE) and value is not None:
184 if (key.upper() != 'IOTYPE') and (int(value) <= 0):
185 err_msg = (_('QoS config is wrong. %(key)s'
186 ' must be set greater than 0.')
187 % {'key': key})
188 raise exception.InvalidInput(reason=err_msg)
189 elif ((key.upper() == 'IOTYPE')
190 and (value not in ['0', '1', '2'])):
191 raise exception.InvalidInput(
192 reason=(_('Illegal value specified for IOTYPE: '
193 'set to either 0, 1, or 2.')))
194 else:
195 qos[key.upper()] = value
197 if len(qos) <= 1 or 'IOTYPE' not in qos:
198 msg = (_('QoS config is incomplete. Please set more. '
199 'QoS policy: %(qos_policy)s.')
200 % {'qos_policy': qos})
201 raise exception.InvalidInput(reason=msg)
203 lowerlimit = constants.QOS_LOWER_LIMIT
204 upperlimit = constants.QOS_UPPER_LIMIT
205 if (set(lowerlimit).intersection(set(qos))
206 and set(upperlimit).intersection(set(qos))):
207 msg = (_('QoS policy conflict, both protection policy and '
208 'restriction policy are set. '
209 'QoS policy: %(qos_policy)s ')
210 % {'qos_policy': qos})
211 raise exception.InvalidInput(reason=msg)
213 return qos