Coverage for manila/share/drivers/huawei/huawei_nas.py: 98%

114 statements  

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

1# Copyright (c) 2014 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"""Huawei Nas Driver for Huawei storage arrays.""" 

17from defusedxml import ElementTree as ET 

18from oslo_config import cfg 

19from oslo_log import log 

20from oslo_utils import importutils 

21 

22from manila import exception 

23from manila.i18n import _ 

24from manila.share import driver 

25 

26 

27HUAWEI_UNIFIED_DRIVER_REGISTRY = { 

28 'V3': 'manila.share.drivers.huawei.v3.connection.V3StorageConnection', } 

29 

30 

31huawei_opts = [ 

32 cfg.StrOpt('manila_huawei_conf_file', 

33 default='/etc/manila/manila_huawei_conf.xml', 

34 help='The configuration file for the Manila Huawei driver.')] 

35 

36CONF = cfg.CONF 

37CONF.register_opts(huawei_opts) 

38LOG = log.getLogger(__name__) 

39 

40 

41class HuaweiNasDriver(driver.ShareDriver): 

42 """Huawei Share Driver. 

43 

44 Executes commands relating to Shares. 

45 Driver version history:: 

46 

47 1.0 - Initial version. 

48 1.1 - Add shrink share. 

49 Add extend share. 

50 Add manage share. 

51 Add share level(ro). 

52 Add smartx capabilities. 

53 Support multi pools in one backend. 

54 1.2 - Add share server support. 

55 Add ensure share. 

56 Add QoS support. 

57 Add create share from snapshot. 

58 1.3 - Add manage snapshot. 

59 Support reporting disk type of pool. 

60 Add replication support. 

61 """ 

62 

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

64 """Do initialization.""" 

65 LOG.debug("Enter into init function of Huawei Driver.") 

66 super(HuaweiNasDriver, self).__init__((True, False), *args, **kwargs) 

67 

68 if not self.configuration: 

69 raise exception.InvalidInput(reason=_( 

70 "Huawei driver configuration missing.")) 

71 

72 self.configuration.append_config_values(huawei_opts) 

73 kwargs.pop('configuration') 

74 self.plugin = importutils.import_object(self.get_backend_driver(), 

75 self.configuration, 

76 **kwargs) 

77 

78 def check_for_setup_error(self): 

79 """Returns an error if prerequisites aren't met.""" 

80 self.plugin.check_conf_file() 

81 self.plugin.check_service() 

82 

83 def get_backend_driver(self): 

84 filename = self.configuration.manila_huawei_conf_file 

85 

86 try: 

87 tree = ET.parse(filename) 

88 root = tree.getroot() 

89 except Exception as err: 

90 message = (_('Read Huawei config file(%(filename)s)' 

91 ' for Manila error: %(err)s') 

92 % {'filename': filename, 

93 'err': err}) 

94 LOG.error(message) 

95 raise exception.InvalidInput(reason=message) 

96 product = root.findtext('Storage/Product') 

97 backend_driver = HUAWEI_UNIFIED_DRIVER_REGISTRY.get(product) 

98 if backend_driver is None: 

99 raise exception.InvalidInput( 

100 reason=_('Product %s is not supported. Product ' 

101 'must be set to V3.') % product) 

102 

103 return backend_driver 

104 

105 def do_setup(self, context): 

106 """Any initialization the huawei nas driver does while starting.""" 

107 LOG.debug("Do setup the plugin.") 

108 self.plugin.connect() 

109 

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

111 """Create a share.""" 

112 LOG.debug("Create a share.") 

113 location = self.plugin.create_share(share, share_server) 

114 return location 

115 

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

117 LOG.debug("Extend a share.") 

118 self.plugin.extend_share(share, new_size, share_server) 

119 

120 def create_share_from_snapshot(self, context, share, snapshot, 

121 share_server=None, parent_share=None): 

122 """Create a share from snapshot.""" 

123 LOG.debug("Create a share from snapshot %s.", snapshot['snapshot_id']) 

124 location = self.plugin.create_share_from_snapshot(share, snapshot) 

125 return location 

126 

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

128 """Shrinks size of existing share.""" 

129 LOG.debug("Shrink a share.") 

130 self.plugin.shrink_share(share, new_size, share_server) 

131 

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

133 """Delete a share.""" 

134 LOG.debug("Delete a share.") 

135 self.plugin.delete_share(share, share_server) 

136 

137 def create_snapshot(self, context, snapshot, share_server=None): 

138 """Create a snapshot.""" 

139 LOG.debug("Create a snapshot.") 

140 snapshot_name = self.plugin.create_snapshot(snapshot, share_server) 

141 return {'provider_location': snapshot_name} 

142 

143 def delete_snapshot(self, context, snapshot, share_server=None): 

144 """Delete a snapshot.""" 

145 LOG.debug("Delete a snapshot.") 

146 self.plugin.delete_snapshot(snapshot, share_server) 

147 

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

149 """Ensure that share is exported.""" 

150 LOG.debug("Ensure share.") 

151 location = self.plugin.ensure_share(share, share_server) 

152 return location 

153 

154 def allow_access(self, context, share, access, share_server=None): 

155 """Allow access to the share.""" 

156 LOG.debug("Allow access.") 

157 self.plugin.allow_access(share, access, share_server) 

158 

159 def deny_access(self, context, share, access, share_server=None): 

160 """Deny access to the share.""" 

161 LOG.debug("Deny access.") 

162 self.plugin.deny_access(share, access, share_server) 

163 

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

165 delete_rules, update_rules, share_server=None): 

166 """Update access rules list.""" 

167 LOG.debug("Update access.") 

168 self.plugin.update_access(share, access_rules, add_rules, 

169 delete_rules, update_rules, share_server) 

170 

171 def get_pool(self, share): 

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

173 LOG.debug("Get pool.") 

174 return self.plugin.get_pool(share) 

175 

176 def get_network_allocations_number(self): 

177 """Get number of network interfaces to be created.""" 

178 LOG.debug("Get network allocations number.") 

179 return self.plugin.get_network_allocations_number() 

180 

181 def manage_existing(self, share, driver_options): 

182 """Manage existing share.""" 

183 LOG.debug("Manage existing share to manila.") 

184 share_size, location = self.plugin.manage_existing(share, 

185 driver_options) 

186 return {'size': share_size, 'export_locations': location} 

187 

188 def manage_existing_snapshot(self, snapshot, driver_options): 

189 """Manage existing snapshot.""" 

190 LOG.debug("Manage existing snapshot to manila.") 

191 snapshot_name = self.plugin.manage_existing_snapshot(snapshot, 

192 driver_options) 

193 return {'provider_location': snapshot_name} 

194 

195 def _update_share_stats(self): 

196 """Retrieve status info from share group.""" 

197 

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

199 data = dict( 

200 share_backend_name=backend_name or 'HUAWEI_NAS_Driver', 

201 vendor_name='Huawei', 

202 driver_version='1.3', 

203 storage_protocol='NFS_CIFS', 

204 qos=True, 

205 total_capacity_gb=0.0, 

206 free_capacity_gb=0.0, 

207 snapshot_support=self.plugin.snapshot_support, 

208 create_share_from_snapshot_support=self.plugin.snapshot_support, 

209 revert_to_snapshot_support=self.plugin.snapshot_support, 

210 ) 

211 

212 # huawei array doesn't support snapshot replication, so driver can't 

213 # create replicated snapshot, this's not fit the requirement of 

214 # replication feature. 

215 # to avoid this problem, we specify huawei driver can't support 

216 # snapshot and replication both, as a workaround. 

217 if not data['snapshot_support'] and self.plugin.replication_support: 

218 data['replication_type'] = 'dr' 

219 

220 self.plugin.update_share_stats(data) 

221 super(HuaweiNasDriver, self)._update_share_stats(data) 

222 

223 def _setup_server(self, network_info, metadata=None): 

224 """Set up share server with given network parameters.""" 

225 # NOTE(felipe_rodrigues): keep legacy network_info support as a dict. 

226 network_info = network_info[0] 

227 

228 return self.plugin.setup_server(network_info, metadata) 

229 

230 def _teardown_server(self, server_details, security_services=None): 

231 """Teardown share server.""" 

232 return self.plugin.teardown_server(server_details, security_services) 

233 

234 def create_replica(self, context, replica_list, new_replica, 

235 access_rules, replica_snapshots, share_server=None): 

236 """Replicate the active replica to a new replica on this backend.""" 

237 return self.plugin.create_replica(context, 

238 replica_list, 

239 new_replica, 

240 access_rules, 

241 replica_snapshots, 

242 share_server) 

243 

244 def update_replica_state(self, context, replica_list, replica, 

245 access_rules, replica_snapshots, 

246 share_server=None): 

247 """Update the replica_state of a replica.""" 

248 return self.plugin.update_replica_state(context, 

249 replica_list, 

250 replica, 

251 access_rules, 

252 replica_snapshots, 

253 share_server) 

254 

255 def promote_replica(self, context, replica_list, replica, access_rules, 

256 share_server=None, quiesce_wait_time=None): 

257 """Promote a replica to 'active' replica state..""" 

258 return self.plugin.promote_replica(context, 

259 replica_list, 

260 replica, 

261 access_rules, 

262 share_server) 

263 

264 def delete_replica(self, context, replica_list, replica_snapshots, 

265 replica, share_server=None): 

266 """Delete a replica.""" 

267 self.plugin.delete_replica(context, 

268 replica_list, 

269 replica_snapshots, 

270 replica, 

271 share_server) 

272 

273 def revert_to_snapshot(self, context, snapshot, share_access_rules, 

274 snapshot_access_rules, share_server=None): 

275 self.plugin.revert_to_snapshot(context, 

276 snapshot, 

277 share_access_rules, 

278 snapshot_access_rules, 

279 share_server)