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
« 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.
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"""
23import re
25from oslo_log import log
26from oslo_utils import netutils
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
35LOG = log.getLogger(__name__)
38class NetAppCmodeSingleSVMFileStorageLibrary(
39 lib_base.NetAppCmodeFileStorageLibrary):
41 def __init__(self, driver_name, **kwargs):
42 super(NetAppCmodeSingleSVMFileStorageLibrary, self).__init__(
43 driver_name, **kwargs)
45 self._vserver = self.configuration.netapp_vserver
47 @na_utils.trace
48 def check_for_setup_error(self):
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)
56 # Ensure vserver exists.
57 if not self._client.vserver_exists(self._vserver):
58 raise exception.VserverNotFound(vserver=self._vserver)
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)
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))
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)
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)
90 (super(NetAppCmodeSingleSVMFileStorageLibrary, self).
91 check_for_setup_error())
93 @na_utils.trace
94 def _get_vserver(self, share_server=None):
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)
101 if not self._vserver:
102 msg = _('Vserver not specified in configuration.')
103 raise exception.InvalidInput(reason=msg)
105 if not self._client.vserver_exists(self._vserver):
106 raise exception.VserverNotFound(vserver=self._vserver)
108 vserver_client = self._get_api_client(self._vserver)
109 return self._vserver, vserver_client
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 }
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()
128 if self._have_cluster_creds:
129 # Harvest soft-deleted QoS policy groups
130 vserver_client.remove_unused_qos_policy_groups()
132 (super(NetAppCmodeSingleSVMFileStorageLibrary, self).
133 _handle_housekeeping_tasks())
135 @na_utils.trace
136 def _find_matching_aggregates(self, aggregate_names=None):
137 """Find all aggregates match pattern if FlexVol pool is configured."""
139 if not self.is_flexvol_pool_configured():
140 return []
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()
146 root_aggregate_names = []
147 if self._have_cluster_creds:
148 root_aggregate_names = self._client.list_root_aggregates()
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]
155 @na_utils.trace
156 def get_network_allocations_number(self):
157 """Get number of network interfaces to be created."""
158 return 0
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
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
184 def _get_backup_vserver(self, backup, share_server=None):
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