Coverage for manila/share/drivers/infortrend/driver.py: 87%

67 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-02-18 22:19 +0000

1# Copyright (c) 2019 Infortrend Technology, Inc. 

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_config import cfg 

17from oslo_log import log 

18 

19from manila import exception 

20from manila.i18n import _ 

21from manila.share import driver 

22from manila.share.drivers.infortrend import infortrend_nas 

23 

24LOG = log.getLogger(__name__) 

25 

26infortrend_nas_opts = [ 

27 cfg.HostAddressOpt('infortrend_nas_ip', 

28 required=True, 

29 help='Infortrend NAS IP for management.'), 

30 cfg.StrOpt('infortrend_nas_user', 

31 default='manila', 

32 help='User for the Infortrend NAS server.'), 

33 cfg.StrOpt('infortrend_nas_password', 

34 secret=True, 

35 help='Password for the Infortrend NAS server. ' 

36 'This is not necessary ' 

37 'if infortrend_nas_ssh_key is set.'), 

38 cfg.StrOpt('infortrend_nas_ssh_key', 

39 help='SSH key for the Infortrend NAS server. ' 

40 'This is not necessary ' 

41 'if infortrend_nas_password is set.'), 

42 cfg.ListOpt('infortrend_share_pools', 

43 required=True, 

44 help='Comma separated list of Infortrend NAS pools.'), 

45 cfg.ListOpt('infortrend_share_channels', 

46 required=True, 

47 help='Comma separated list of Infortrend channels.'), 

48 cfg.IntOpt('infortrend_ssh_timeout', 

49 default=30, 

50 help='SSH timeout in seconds.'), 

51] 

52 

53CONF = cfg.CONF 

54CONF.register_opts(infortrend_nas_opts) 

55 

56 

57class InfortrendNASDriver(driver.ShareDriver): 

58 

59 """Infortrend Share Driver for GS/GSe Family using NASCLI. 

60 

61 Version history: 

62 1.0.0 - Initial driver 

63 """ 

64 

65 VERSION = "1.0.0" 

66 PROTOCOL = "NFS_CIFS" 

67 

68 def __init__(self, *args, **kwargs): 

69 super(InfortrendNASDriver, self).__init__(False, *args, **kwargs) 

70 self.configuration.append_config_values(infortrend_nas_opts) 

71 

72 nas_ip = self.configuration.safe_get('infortrend_nas_ip') 

73 username = self.configuration.safe_get('infortrend_nas_user') 

74 password = self.configuration.safe_get('infortrend_nas_password') 

75 ssh_key = self.configuration.safe_get('infortrend_nas_ssh_key') 

76 timeout = self.configuration.safe_get('infortrend_ssh_timeout') 

77 self.backend_name = self.configuration.safe_get('share_backend_name') 

78 

79 if not (password or ssh_key): 

80 msg = _('Either infortrend_nas_password or infortrend_nas_ssh_key ' 

81 'should be set.') 

82 raise exception.InvalidParameterValue(err=msg) 

83 

84 pool_dict = self._init_pool_dict() 

85 channel_dict = self._init_channel_dict() 

86 self.ift_nas = infortrend_nas.InfortrendNAS(nas_ip, username, password, 

87 ssh_key, timeout, 

88 pool_dict, channel_dict) 

89 

90 def _init_pool_dict(self): 

91 pools_names = self.configuration.safe_get('infortrend_share_pools') 

92 

93 return {el: {} for el in pools_names} 

94 

95 def _init_channel_dict(self): 

96 channels = self.configuration.safe_get('infortrend_share_channels') 

97 

98 return {el: '' for el in channels} 

99 

100 def do_setup(self, context): 

101 """Any initialization the share driver does while starting.""" 

102 LOG.debug('Infortrend NAS do_setup start.') 

103 self.ift_nas.do_setup() 

104 

105 def check_for_setup_error(self): 

106 """Check for setup error.""" 

107 LOG.debug('Infortrend NAS check_for_setup_error start.') 

108 self.ift_nas.check_for_setup_error() 

109 

110 def _update_share_stats(self): 

111 """Retrieve stats info from share group.""" 

112 

113 LOG.debug('Updating Infortrend backend [%s].', self.backend_name) 

114 

115 data = dict( 

116 share_backend_name=self.backend_name, 

117 vendor_name='Infortrend', 

118 driver_version=self.VERSION, 

119 storage_protocol=self.PROTOCOL, 

120 reserved_percentage=self.configuration.reserved_share_percentage, 

121 reserved_snapshot_percentage=( 

122 self.configuration.reserved_share_from_snapshot_percentage 

123 or self.configuration.reserved_share_percentage), 

124 reserved_share_extend_percentage=( 

125 self.configuration.reserved_share_extend_percentage 

126 or self.configuration.reserved_share_percentage), 

127 pools=self.ift_nas.update_pools_stats()) 

128 LOG.debug('Infortrend pools status: %s', data['pools']) 

129 

130 super(InfortrendNASDriver, self)._update_share_stats(data) 

131 

132 def update_access(self, context, share, access_rules, add_rules, 

133 delete_rules, update_rules, share_server=None): 

134 """Update access rules for given share. 

135 

136 :param context: Current context 

137 :param share: Share model with share data. 

138 :param access_rules: All access rules for given share 

139 :param add_rules: Empty List or List of access rules which should be 

140 added. access_rules already contains these rules. 

141 :param delete_rules: Empty List or List of access rules which should be 

142 removed. access_rules doesn't contain these rules. 

143 :param update_rules: Empty List or List of access rules which should be 

144 updated. access_rules already contains these rules. 

145 :param share_server: Not used by this driver. 

146 

147 :returns: None, or a dictionary of ``access_id``, ``access_key`` as 

148 key: value pairs for the rules added, where, ``access_id`` 

149 is the UUID (string) of the access rule, and ``access_key`` 

150 is the credential (string) of the entity granted access. 

151 During recovery after error, the returned dictionary must 

152 contain ``access_id``, ``access_key`` for all the rules that 

153 the driver is ordered to resync, i.e. rules in the 

154 ``access_rules`` parameter. 

155 """ 

156 

157 return self.ift_nas.update_access(share, access_rules, add_rules, 

158 delete_rules, share_server) 

159 

160 def create_share(self, context, share, share_server=None): 

161 """Create a share.""" 

162 

163 LOG.debug('Creating share: %s.', share['id']) 

164 

165 return self.ift_nas.create_share(share, share_server) 

166 

167 def delete_share(self, context, share, share_server=None): 

168 """Remove a share.""" 

169 

170 LOG.debug('Deleting share: %s.', share['id']) 

171 

172 return self.ift_nas.delete_share(share, share_server) 

173 

174 def get_pool(self, share): 

175 """Return pool name where the share resides on. 

176 

177 :param share: The share hosted by the driver. 

178 """ 

179 return self.ift_nas.get_pool(share) 

180 

181 def ensure_share(self, context, share, share_server=None): 

182 """Invoked to ensure that share is exported. 

183 

184 Driver can use this method to update the list of export locations of 

185 the share if it changes. To do that, you should return list with 

186 export locations. 

187 

188 :return None or list with export locations 

189 """ 

190 return self.ift_nas.ensure_share(share, share_server) 

191 

192 def manage_existing(self, share, driver_options): 

193 """Brings an existing share under Manila management. 

194 

195 If the provided share is not valid, then raise a 

196 ManageInvalidShare exception, specifying a reason for the failure. 

197 

198 If the provided share is not in a state that can be managed, such as 

199 being replicated on the backend, the driver *MUST* raise 

200 ManageInvalidShare exception with an appropriate message. 

201 

202 The share has a share_type, and the driver can inspect that and 

203 compare against the properties of the referenced backend share. 

204 If they are incompatible, raise a 

205 ManageExistingShareTypeMismatch, specifying a reason for the failure. 

206 

207 :param share: Share model 

208 :param driver_options: Driver-specific options provided by admin. 

209 :return: share_update dictionary with required key 'size', 

210 which should contain size of the share. 

211 """ 

212 LOG.debug( 

213 'Manage existing for share: %(share)s,', { 

214 'share': share['share_id'], 

215 }) 

216 return self.ift_nas.manage_existing(share, driver_options) 

217 

218 def unmanage(self, share): 

219 """Removes the specified share from Manila management. 

220 

221 Does not delete the underlying backend share. 

222 

223 For most drivers, this will not need to do anything. However, some 

224 drivers might use this call as an opportunity to clean up any 

225 Manila-specific configuration that they have associated with the 

226 backend share. 

227 

228 If provided share cannot be unmanaged, then raise an 

229 UnmanageInvalidShare exception, specifying a reason for the failure. 

230 

231 This method is invoked when the share is being unmanaged with 

232 a share type that has ``driver_handles_share_servers`` 

233 extra-spec set to False. 

234 """ 

235 LOG.debug( 

236 'Unmanage share: %(share)s', { 

237 'share': share['share_id'], 

238 }) 

239 return self.ift_nas.unmanage(share) 

240 

241 def extend_share(self, share, new_size, share_server=None): 

242 """Extends size of existing share. 

243 

244 :param share: Share model 

245 :param new_size: New size of share (new_size > share['size']) 

246 :param share_server: Optional -- Share server model 

247 """ 

248 return self.ift_nas.extend_share(share, new_size, share_server) 

249 

250 def shrink_share(self, share, new_size, share_server=None): 

251 """Shrinks size of existing share. 

252 

253 If consumed space on share larger than new_size driver should raise 

254 ShareShrinkingPossibleDataLoss exception: 

255 raise ShareShrinkingPossibleDataLoss(share_id=share['id']) 

256 

257 :param share: Share model 

258 :param new_size: New size of share (new_size < share['size']) 

259 :param share_server: Optional -- Share server model 

260 

261 :raises ShareShrinkingPossibleDataLoss, NotImplementedError 

262 """ 

263 return self.ift_nas.shrink_share(share, new_size, share_server)