Saikumar Pulluri 9c26885e9b [NetApp] Certificate based authentication for NetApp drivers
The NetApp ONTAP driver now supports Certificate-Based-Authentication (CBA)
for operators that desire certificate based authentication instead of user
and password.
Note: The options for cert-auth take precedence, if all the auth options
are defined in the config (both cert and legacy), the legacy ones are
ignored.

Change-Id: Idad916a541fc1f355469912da38bd30cf366e3b0
2025-03-06 08:24:03 -05:00

142 lines
5.5 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Utilities for NetApp FAS drivers.
This module contains common utilities to be used by one or more
NetApp FAS drivers to achieve the desired functionality.
"""
import json
import socket
from oslo_config import cfg
from cinder import exception
from cinder.i18n import _
from cinder.volume import configuration
from cinder.volume import driver
from cinder.volume.drivers.netapp.dataontap.client import client_cmode
from cinder.volume.drivers.netapp.dataontap.client import client_cmode_rest
from cinder.volume.drivers.netapp import options as na_opts
from cinder.volume import volume_utils
CONF = cfg.CONF
def get_backend_configuration(backend_name):
"""Get a cDOT configuration object for a specific backend."""
config_stanzas = CONF.list_all_sections()
if backend_name not in config_stanzas:
msg = _("Could not find backend stanza %(backend_name)s in "
"configuration. Available stanzas are %(stanzas)s")
params = {
"stanzas": config_stanzas,
"backend_name": backend_name,
}
raise exception.ConfigNotFound(message=msg % params)
config = configuration.Configuration(driver.volume_opts,
config_group=backend_name)
config.append_config_values(na_opts.netapp_proxy_opts)
config.append_config_values(na_opts.netapp_connection_opts)
config.append_config_values(na_opts.netapp_transport_opts)
config.append_config_values(na_opts.netapp_basicauth_opts)
config.append_config_values(na_opts.netapp_certificateauth_opts)
config.append_config_values(na_opts.netapp_provisioning_opts)
config.append_config_values(na_opts.netapp_cluster_opts)
config.append_config_values(na_opts.netapp_san_opts)
config.append_config_values(na_opts.netapp_replication_opts)
config.append_config_values(na_opts.netapp_support_opts)
config.append_config_values(na_opts.netapp_migration_opts)
return config
def get_client_for_backend(backend_name, vserver_name=None, force_rest=False):
"""Get a cDOT API client for a specific backend."""
config = get_backend_configuration(backend_name)
if config.netapp_use_legacy_client and not force_rest:
client = client_cmode.Client(
transport_type=config.netapp_transport_type,
username=config.netapp_login,
password=config.netapp_password,
hostname=config.netapp_server_hostname,
private_key_file=config.netapp_private_key_file,
certificate_file=config.netapp_certificate_file,
ca_certificate_file=config.netapp_ca_certificate_file,
certificate_host_validation=
config.netapp_certificate_host_validation,
port=config.netapp_server_port,
vserver=vserver_name or config.netapp_vserver,
trace=volume_utils.TRACE_API,
api_trace_pattern=config.netapp_api_trace_pattern)
else:
client = client_cmode_rest.RestClient(
transport_type=config.netapp_transport_type,
ssl_cert_path=config.netapp_ssl_cert_path,
username=config.netapp_login,
password=config.netapp_password,
hostname=config.netapp_server_hostname,
private_key_file=config.netapp_private_key_file,
certificate_file=config.netapp_certificate_file,
ca_certificate_file=config.netapp_ca_certificate_file,
certificate_host_validation=
config.netapp_certificate_host_validation,
port=config.netapp_server_port,
vserver=vserver_name or config.netapp_vserver,
trace=volume_utils.TRACE_API,
api_trace_pattern=config.netapp_api_trace_pattern,
async_rest_timeout=config.netapp_async_rest_timeout)
return client
def _build_base_ems_log_message(driver_name, app_version):
ems_log = {
'computer-name': socket.gethostname() or 'Cinder_node',
'event-source': 'Cinder driver %s' % driver_name,
'app-version': app_version,
'category': 'provisioning',
'log-level': '5',
'auto-support': 'false',
}
return ems_log
def build_ems_log_message_0(driver_name, app_version):
"""Construct EMS Autosupport log message with deployment info."""
ems_log = _build_base_ems_log_message(driver_name, app_version)
ems_log['event-id'] = '0'
ems_log['event-description'] = 'OpenStack Cinder connected to cluster node'
return ems_log
def build_ems_log_message_1(driver_name, app_version, vserver,
flexvol_pools, aggregate_pools):
"""Construct EMS Autosupport log message with storage pool info."""
message = {
'pools': {
'vserver': vserver,
'aggregates': aggregate_pools,
'flexvols': flexvol_pools,
},
}
ems_log = _build_base_ems_log_message(driver_name, app_version)
ems_log['event-id'] = '1'
ems_log['event-description'] = json.dumps(message)
return ems_log