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

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. 

15 

16from oslo_utils import excutils 

17from oslo_utils import strutils 

18 

19from manila import exception 

20from manila.i18n import _ 

21from manila.share.drivers.huawei import constants 

22 

23 

24class SmartPartition(object): 

25 def __init__(self, helper): 

26 self.helper = helper 

27 

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.')) 

35 

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.')) 

41 

42 self.helper._add_fs_to_partition(fsid, partition_id) 

43 

44 

45class SmartCache(object): 

46 def __init__(self, helper): 

47 self.helper = helper 

48 

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.')) 

55 

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']})) 

61 

62 self.helper._add_fs_to_cache(fsid, cache_id) 

63 

64 

65class SmartQos(object): 

66 def __init__(self, helper): 

67 self.helper = helper 

68 

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) 

86 

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 

92 

93 return False 

94 

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) 

101 

102 

103class SmartX(object): 

104 def __init__(self, helper): 

105 self.helper = helper 

106 

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 

116 

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 

122 

123 return opts 

124 

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 

132 

133 return opts 

134 

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 

143 

144 return opts 

145 

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 

154 

155 return opts 

156 

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 

167 

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 

176 

177 def get_qos_opts(self, opts): 

178 qos = {} 

179 if not strutils.bool_from_string(opts.get('qos')): 

180 return 

181 

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 

196 

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) 

202 

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) 

212 

213 return qos