Coverage for manila/share/drivers/netapp/dataontap/cluster_mode/lib_single_svm.py: 82%

100 statements  

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

1# Copyright (c) 2015 Clinton Knight. All rights reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); you may 

4# not use this file except in compliance with the License. You may obtain 

5# a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

12# License for the specific language governing permissions and limitations 

13# under the License. 

14""" 

15NetApp Data ONTAP cDOT single-SVM storage driver library. 

16 

17This library extends the abstract base library and completes the single-SVM 

18functionality needed by the cDOT single-SVM Manila driver. This library 

19variant uses a single Data ONTAP storage virtual machine (i.e. 'vserver') 

20as defined in manila.conf to provision shares. 

21""" 

22 

23import re 

24 

25from oslo_log import log 

26from oslo_utils import netutils 

27 

28from manila import exception 

29from manila.i18n import _ 

30from manila.share.drivers.netapp.dataontap.cluster_mode import data_motion 

31from manila.share.drivers.netapp.dataontap.cluster_mode import lib_base 

32from manila.share.drivers.netapp import utils as na_utils 

33 

34 

35LOG = log.getLogger(__name__) 

36 

37 

38class NetAppCmodeSingleSVMFileStorageLibrary( 

39 lib_base.NetAppCmodeFileStorageLibrary): 

40 

41 def __init__(self, driver_name, **kwargs): 

42 super(NetAppCmodeSingleSVMFileStorageLibrary, self).__init__( 

43 driver_name, **kwargs) 

44 

45 self._vserver = self.configuration.netapp_vserver 

46 

47 @na_utils.trace 

48 def check_for_setup_error(self): 

49 

50 # Ensure vserver is specified in configuration. 

51 if not self._vserver: 

52 msg = _('Vserver must be specified in the configuration ' 

53 'when the driver is not managing share servers.') 

54 raise exception.InvalidInput(reason=msg) 

55 

56 # Ensure vserver exists. 

57 if not self._client.vserver_exists(self._vserver): 

58 raise exception.VserverNotFound(vserver=self._vserver) 

59 

60 # If we have vserver credentials, ensure the vserver they connect 

61 # to matches the vserver specified in the configuration. 

62 if not self._have_cluster_creds: 

63 if self._vserver not in self._client.list_vservers(): 

64 msg = _('Vserver specified in the configuration does not ' 

65 'match supplied credentials.') 

66 raise exception.InvalidInput(reason=msg) 

67 

68 # Ensure FlexGroup support 

69 vserver_client = self._get_api_client(vserver=self._vserver) 

70 aggr_list = vserver_client.list_vserver_aggregates() 

71 self._initialize_flexgroup_pools(set(aggr_list)) 

72 

73 # Ensure one or more aggregates are available to the vserver. 

74 if (self.is_flexvol_pool_configured() and 

75 not self._find_matching_aggregates(aggregate_names=aggr_list)): 

76 msg = _('No aggregates are available to Vserver %s for ' 

77 'provisioning shares. Ensure that one or more aggregates ' 

78 'are assigned to the Vserver and that the configuration ' 

79 'option netapp_aggregate_name_search_pattern is set ' 

80 'correctly.') % self._vserver 

81 raise exception.NetAppException(msg) 

82 

83 msg = ('Using Vserver %(vserver)s for backend %(backend)s with ' 

84 '%(creds)s credentials.') 

85 msg_args = {'vserver': self._vserver, 'backend': self._backend_name} 

86 msg_args['creds'] = ('cluster' if self._have_cluster_creds 

87 else 'Vserver') 

88 LOG.info(msg, msg_args) 

89 

90 (super(NetAppCmodeSingleSVMFileStorageLibrary, self). 

91 check_for_setup_error()) 

92 

93 @na_utils.trace 

94 def _get_vserver(self, share_server=None): 

95 

96 if share_server is not None: 

97 msg = _('Share server must not be passed to the driver ' 

98 'when the driver is not managing share servers.') 

99 raise exception.InvalidParameterValue(err=msg) 

100 

101 if not self._vserver: 

102 msg = _('Vserver not specified in configuration.') 

103 raise exception.InvalidInput(reason=msg) 

104 

105 if not self._client.vserver_exists(self._vserver): 

106 raise exception.VserverNotFound(vserver=self._vserver) 

107 

108 vserver_client = self._get_api_client(self._vserver) 

109 return self._vserver, vserver_client 

110 

111 def _get_ems_pool_info(self): 

112 return { 

113 'pools': { 

114 'vserver': self._vserver, 

115 'aggregates': self._find_matching_aggregates(), 

116 'flexgroup_aggregates': self._flexgroup_pools, 

117 }, 

118 } 

119 

120 @na_utils.trace 

121 def _handle_housekeeping_tasks(self): 

122 """Handle various cleanup activities.""" 

123 vserver_client = self._get_api_client(vserver=self._vserver) 

124 vserver_client.prune_deleted_nfs_export_policies() 

125 vserver_client.prune_deleted_snapshots() 

126 vserver_client.prune_deleted_volumes() 

127 

128 if self._have_cluster_creds: 

129 # Harvest soft-deleted QoS policy groups 

130 vserver_client.remove_unused_qos_policy_groups() 

131 

132 (super(NetAppCmodeSingleSVMFileStorageLibrary, self). 

133 _handle_housekeeping_tasks()) 

134 

135 @na_utils.trace 

136 def _find_matching_aggregates(self, aggregate_names=None): 

137 """Find all aggregates match pattern if FlexVol pool is configured.""" 

138 

139 if not self.is_flexvol_pool_configured(): 

140 return [] 

141 

142 if not aggregate_names: 142 ↛ 146line 142 didn't jump to line 146 because the condition on line 142 was always true

143 vserver_client = self._get_api_client(vserver=self._vserver) 

144 aggregate_names = vserver_client.list_vserver_aggregates() 

145 

146 root_aggregate_names = [] 

147 if self._have_cluster_creds: 

148 root_aggregate_names = self._client.list_root_aggregates() 

149 

150 pattern = self.configuration.netapp_aggregate_name_search_pattern 

151 return [aggr_name for aggr_name in aggregate_names 

152 if re.match(pattern, aggr_name) and 

153 aggr_name not in root_aggregate_names] 

154 

155 @na_utils.trace 

156 def get_network_allocations_number(self): 

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

158 return 0 

159 

160 @na_utils.trace 

161 def get_admin_network_allocations_number(self): 

162 """Get number of network allocations for creating admin LIFs.""" 

163 return 0 

164 

165 @na_utils.trace 

166 def get_configured_ip_versions(self): 

167 ipv4 = False 

168 ipv6 = False 

169 vserver_client = self._get_api_client(vserver=self._vserver) 

170 interfaces = vserver_client.get_network_interfaces() 

171 for interface in interfaces: 

172 address = interface['address'] 

173 if netutils.is_valid_ipv6(address): 

174 ipv6 = True 

175 else: 

176 ipv4 = True 

177 versions = [] 

178 if ipv4: 

179 versions.append(4) 

180 if ipv6: 

181 versions.append(6) 

182 return versions 

183 

184 def _get_backup_vserver(self, backup, share_server=None): 

185 

186 backend_name = self._get_backend(backup) 

187 backend_config = data_motion.get_backend_configuration(backend_name) 

188 if share_server is not None: 

189 msg = _('Share server must not be passed to the driver ' 

190 'when the driver is not managing share servers.') 

191 raise exception.InvalidParameterValue(err=msg) 

192 return backend_config.netapp_vserver