Coverage for manila/share/drivers/netapp/dataontap/client/client_base.py: 100%
55 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) 2014 Alex Meade. All rights reserved.
2# Copyright (c) 2014 Clinton Knight. 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.
16from oslo_log import log
17from oslo_utils import excutils
19from manila.share.drivers.netapp.dataontap.client import api as netapp_api
20from manila.share.drivers.netapp import utils as na_utils
23LOG = log.getLogger(__name__)
26class NetAppBaseClient(object):
28 def __init__(self, **kwargs):
29 self.connection = netapp_api.NaServer(
30 host=kwargs['hostname'],
31 transport_type=kwargs['transport_type'],
32 ssl_cert_path=kwargs['ssl_cert_path'],
33 port=kwargs['port'],
34 username=kwargs['username'],
35 password=kwargs['password'],
36 trace=kwargs.get('trace', False),
37 api_trace_pattern=kwargs.get('api_trace_pattern',
38 na_utils.API_TRACE_PATTERN),
39 private_key_file=kwargs['private_key_file'],
40 certificate_file=kwargs['certificate_file'],
41 ca_certificate_file=kwargs['ca_certificate_file'],
42 certificate_host_validation=kwargs['certificate_host_validation'])
44 def get_ontapi_version(self, cached=True):
45 """Gets the supported ontapi version."""
47 if cached:
48 return self.connection.get_api_version()
50 result = self.send_request('system-get-ontapi-version',
51 enable_tunneling=False)
52 major = result.get_child_content('major-version')
53 minor = result.get_child_content('minor-version')
54 return major, minor
56 @na_utils.trace
57 def get_system_version(self, cached=True):
58 """Gets the current Data ONTAP version."""
60 if cached:
61 return self.connection.get_system_version()
63 result = self.send_request('system-get-version',
64 enable_tunneling=False)
66 version_tuple = result.get_child_by_name(
67 'version-tuple') or netapp_api.NaElement('none')
68 system_version_tuple = version_tuple.get_child_by_name(
69 'system-version-tuple') or netapp_api.NaElement('none')
71 version = {}
72 version['version'] = result.get_child_content('version')
73 version['version-tuple'] = (
74 int(system_version_tuple.get_child_content('generation')),
75 int(system_version_tuple.get_child_content('major')),
76 int(system_version_tuple.get_child_content('minor')))
78 return version
80 def _init_features(self):
81 """Set up the repository of available Data ONTAP features."""
82 self.features = Features()
84 def _strip_xml_namespace(self, string):
85 if string.startswith('{') and '}' in string:
86 return string.split('}', 1)[1]
87 return string
89 def send_request(self, api_name, api_args=None, enable_tunneling=True,
90 use_zapi=True):
91 """Sends request to Ontapi."""
92 request = netapp_api.NaElement(api_name)
93 return self.connection.invoke_successfully(
94 request, api_args=api_args, enable_tunneling=enable_tunneling,
95 use_zapi=use_zapi)
97 @na_utils.trace
98 def get_licenses(self):
99 try:
100 result = self.send_request('license-v2-list-info')
101 except netapp_api.NaApiError:
102 with excutils.save_and_reraise_exception():
103 LOG.exception("Could not get licenses list.")
105 return sorted(
106 [child.get_child_content('package').lower()
107 for child in result.get_child_by_name('licenses').get_children()])
109 def send_ems_log_message(self, message_dict):
110 """Sends a message to the Data ONTAP EMS log."""
111 raise NotImplementedError()
114class Features(object):
116 def __init__(self):
117 self.defined_features = set()
119 def add_feature(self, name, supported=True):
120 if not isinstance(supported, bool):
121 raise TypeError("Feature value must be a bool type.")
122 self.defined_features.add(name)
123 setattr(self, name, supported)
125 def __getattr__(self, name):
126 # NOTE(cknight): Needed to keep pylint happy.
127 raise AttributeError