Skip to content

Commit 3e6fd13

Browse files
committed
Remove python-neutronclient
This patch replaces the deprecated library with openstacksdk. It also deprecates the use of the [service_auth] section of the configuration for authentication with Neutron. In a future release these settings need to be part of the [neutron] configuration section. Update needed on OVN provider side: https://review.opendev.org/c/openstack/ovn-octavia-provider/+/870514 Story: 2010509 Task: 47104 Change-Id: I686cfdef78de927fa4bc1921c15e8d5853fd2ef9
1 parent 8d70a80 commit 3e6fd13

File tree

16 files changed

+1218
-1208
lines changed

16 files changed

+1218
-1208
lines changed

devstack/plugin.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,16 @@ function octavia_configure {
321321
iniset $OCTAVIA_CONF service_auth cafile $SSL_BUNDLE_FILE
322322
iniset $OCTAVIA_CONF service_auth memcached_servers $SERVICE_HOST:11211
323323

324+
# neutron
325+
iniset $OCTAVIA_CONF neutron auth_url $KEYSTONE_SERVICE_URI
326+
iniset $OCTAVIA_CONF neutron auth_type password
327+
iniset $OCTAVIA_CONF neutron username $OCTAVIA_USERNAME
328+
iniset $OCTAVIA_CONF neutron password $OCTAVIA_PASSWORD
329+
iniset $OCTAVIA_CONF neutron user_domain_name $OCTAVIA_USER_DOMAIN_NAME
330+
iniset $OCTAVIA_CONF neutron project_name $OCTAVIA_PROJECT_NAME
331+
iniset $OCTAVIA_CONF neutron project_domain_name $OCTAVIA_PROJECT_DOMAIN_NAME
332+
iniset $OCTAVIA_CONF neutron cafile $SSL_BUNDLE_FILE
333+
324334
# Setting other required default options
325335
iniset $OCTAVIA_CONF controller_worker amphora_driver ${OCTAVIA_AMPHORA_DRIVER}
326336
iniset $OCTAVIA_CONF controller_worker compute_driver ${OCTAVIA_COMPUTE_DRIVER}

octavia/common/clients.py

Lines changed: 25 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212

1313
from cinderclient import client as cinder_client
1414
from glanceclient import client as glance_client
15-
from neutronclient.neutron import client as neutron_client
15+
from keystoneauth1 import session
16+
from keystoneauth1 import token_endpoint
1617
from novaclient import api_versions
1718
from novaclient import client as nova_client
19+
import openstack
1820
from oslo_config import cfg
1921
from oslo_log import log as logging
2022
from oslo_utils import excutils
@@ -25,7 +27,6 @@
2527
CONF = cfg.CONF
2628

2729
GLANCE_VERSION = '2'
28-
NEUTRON_VERSION = '2.0'
2930
NOVA_VERSION = '2.15'
3031
CINDER_VERSION = '3'
3132

@@ -73,38 +74,20 @@ class NeutronAuth(object):
7374
neutron_client = None
7475

7576
@classmethod
76-
def get_neutron_client(cls, region, service_name=None, endpoint=None,
77-
endpoint_type='publicURL', insecure=False,
78-
ca_cert=None):
79-
"""Create neutron client object.
80-
81-
:param region: The region of the service
82-
:param service_name: The name of the neutron service in the catalog
83-
:param endpoint: The endpoint of the service
84-
:param endpoint_type: The endpoint_type of the service
85-
:param insecure: Turn off certificate validation
86-
:param ca_cert: CA Cert file path
87-
:return: a Neutron Client object.
88-
:raises Exception: if the client cannot be created
89-
"""
90-
ksession = keystone.KeystoneSession()
77+
def get_neutron_client(cls):
78+
"""Create neutron client object."""
79+
ksession = keystone.KeystoneSession('neutron')
9180
if not cls.neutron_client:
92-
kwargs = {'region_name': region,
93-
'session': ksession.get_session(),
94-
'endpoint_type': endpoint_type,
95-
'insecure': insecure}
96-
if service_name:
97-
kwargs['service_name'] = service_name
98-
if endpoint:
99-
kwargs['endpoint_override'] = endpoint
100-
if ca_cert:
101-
kwargs['ca_cert'] = ca_cert
102-
try:
103-
cls.neutron_client = neutron_client.Client(
104-
NEUTRON_VERSION, **kwargs)
105-
except Exception:
106-
with excutils.save_and_reraise_exception():
107-
LOG.exception("Error creating Neutron client.")
81+
sess = ksession.get_session()
82+
83+
kwargs = {}
84+
if CONF.neutron.endpoint_override:
85+
kwargs['network_endpoint_override'] = (
86+
CONF.neutron.endpoint_override)
87+
88+
conn = openstack.connection.Connection(
89+
session=sess, **kwargs)
90+
cls.neutron_client = conn
10891
return cls.neutron_client
10992

11093
@classmethod
@@ -113,26 +96,23 @@ def get_user_neutron_client(cls, context):
11396
11497
It's possible that the token in the context is a trust scoped
11598
which can't be used to initialize a keystone session.
116-
11799
We directly use the token and endpoint_url to initialize neutron
118100
client.
119101
"""
120-
neutron_endpoint = CONF.neutron.endpoint
121-
if not neutron_endpoint:
122-
session = keystone.KeystoneSession().get_session()
123-
endpoint_data = session.get_endpoint_data(
102+
sess = keystone.KeystoneSession('neutron').get_session()
103+
neutron_endpoint = CONF.neutron.endpoint_override
104+
if neutron_endpoint is None:
105+
endpoint_data = sess.get_endpoint_data(
124106
service_type='network', interface=CONF.neutron.endpoint_type,
125107
region_name=CONF.neutron.region_name)
126108
neutron_endpoint = endpoint_data.catalog_url
127109

128-
kwargs = {
129-
'token': context.auth_token,
130-
'endpoint_url': neutron_endpoint,
131-
'insecure': CONF.neutron.insecure,
132-
'ca_cert': CONF.neutron.ca_certificates_file
133-
}
110+
user_auth = token_endpoint.Token(neutron_endpoint, context.auth_token)
111+
user_sess = session.Session(auth=user_auth)
134112

135-
return neutron_client.Client(NEUTRON_VERSION, **kwargs)
113+
conn = openstack.connection.Connection(
114+
session=user_sess, oslo_conf=CONF)
115+
return conn.network
136116

137117

138118
class GlanceAuth(object):

octavia/common/config.py

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@
3737

3838
LOG = logging.getLogger(__name__)
3939

40-
EXTRA_LOG_LEVEL_DEFAULTS = [
41-
'neutronclient.v2_0.client=INFO',
42-
]
43-
4440
core_opts = [
4541
cfg.HostnameOpt('host', default=utils.get_hostname(),
4642
sample_default='<server-hostname.example.com>',
@@ -89,7 +85,7 @@
8985
'octavia.api.drivers entrypoint.'),
9086
default={'amphora': 'The Octavia Amphora driver.',
9187
'octavia': 'Deprecated alias of the Octavia Amphora '
92-
'driver.',
88+
'driver.',
9389
}),
9490
cfg.StrOpt('default_provider_driver', default='amphora',
9591
help=_('Default provider driver.')),
@@ -747,21 +743,27 @@
747743
]
748744

749745
neutron_opts = [
750-
cfg.StrOpt('service_name',
751-
help=_('The name of the neutron service in the '
752-
'keystone catalog')),
753746
cfg.StrOpt('endpoint', help=_('A new endpoint to override the endpoint '
754-
'in the keystone catalog.')),
755-
cfg.StrOpt('region_name',
756-
help=_('Region in Identity service catalog to use for '
757-
'communication with the OpenStack services.')),
758-
cfg.StrOpt('endpoint_type', default='publicURL',
759-
help=_('Endpoint interface in identity service to use')),
747+
'in the keystone catalog.'),
748+
deprecated_for_removal=True,
749+
deprecated_reason=_('The endpoint_override option defined by '
750+
'keystoneauth1 is the new name for this '
751+
'option.'),
752+
deprecated_since='2023.2/Bobcat'),
753+
cfg.StrOpt('endpoint_type', help=_('Endpoint interface in identity '
754+
'service to use'),
755+
deprecated_for_removal=True,
756+
deprecated_reason=_('This option was replaced by the '
757+
'valid_interfaces option defined by '
758+
'keystoneauth.'),
759+
deprecated_since='2023.2/Bobcat'),
760760
cfg.StrOpt('ca_certificates_file',
761-
help=_('CA certificates file path')),
762-
cfg.BoolOpt('insecure',
763-
default=False,
764-
help=_('Disable certificate validation on SSL connections ')),
761+
help=_('CA certificates file path'),
762+
deprecated_for_removal=True,
763+
deprecated_reason=_('The cafile option defined by '
764+
'keystoneauth1 is the new name for this '
765+
'option.'),
766+
deprecated_since='2023.2/Bobcat'),
765767
]
766768

767769
glance_opts = [
@@ -902,15 +904,48 @@
902904
db_options.set_defaults(cfg.CONF, connection=_SQL_CONNECTION_DEFAULT,
903905
max_pool_size=10, max_overflow=20, pool_timeout=10)
904906

905-
ks_loading.register_auth_conf_options(cfg.CONF, constants.SERVICE_AUTH)
906-
ks_loading.register_session_conf_options(cfg.CONF, constants.SERVICE_AUTH)
907+
908+
def register_ks_options(group):
909+
ks_loading.register_auth_conf_options(cfg.CONF, group)
910+
ks_loading.register_session_conf_options(cfg.CONF, group)
911+
ks_loading.register_adapter_conf_options(cfg.CONF, group,
912+
include_deprecated=False)
913+
914+
915+
register_ks_options(constants.SERVICE_AUTH)
916+
register_ks_options('neutron')
907917

908918

909919
def register_cli_opts():
910920
cfg.CONF.register_cli_opts(core_cli_opts)
911921
logging.register_options(cfg.CONF)
912922

913923

924+
def handle_neutron_deprecations():
925+
# Apply neutron deprecated options to their new setting if needed
926+
927+
# Basicaly: if the value of the deprecated option is not the default:
928+
# * convert it to a valid "new" value if needed
929+
# * set it as the default for the new option
930+
# Thus [neutron].<new_option> has an higher precedence than
931+
# [neutron].<deprecated_option>
932+
loc = cfg.CONF.get_location('endpoint', 'neutron')
933+
if loc and loc.location != cfg.Locations.opt_default:
934+
cfg.CONF.set_default('endpoint_override', cfg.CONF.neutron.endpoint,
935+
'neutron')
936+
937+
loc = cfg.CONF.get_location('endpoint_type', 'neutron')
938+
if loc and loc.location != cfg.Locations.opt_default:
939+
endpoint_type = cfg.CONF.neutron.endpoint_type.replace('URL', '')
940+
cfg.CONF.set_default('valid_interfaces', [endpoint_type],
941+
'neutron')
942+
943+
loc = cfg.CONF.get_location('ca_certificates_file', 'neutron')
944+
if loc and loc.location != cfg.Locations.opt_default:
945+
cfg.CONF.set_default('cafile', cfg.CONF.neutron.ca_certificates_file,
946+
'neutron')
947+
948+
914949
def init(args, **kwargs):
915950
register_cli_opts()
916951
cfg.CONF(args=args, project='octavia',
@@ -920,14 +955,20 @@ def init(args, **kwargs):
920955
setup_remote_debugger()
921956
validate.check_default_ciphers_prohibit_list_conflict()
922957

958+
# Override default auth_type for plugins with the default from service_auth
959+
auth_type = cfg.CONF.service_auth.auth_type
960+
cfg.CONF.set_default('auth_type', auth_type, 'neutron')
961+
962+
handle_neutron_deprecations()
963+
923964

924965
def setup_logging(conf):
925966
"""Sets up the logging options for a log with supplied name.
926967
927968
:param conf: a cfg.ConfOpts object
928969
"""
929-
logging.set_defaults(default_log_levels=logging.get_default_log_levels() +
930-
EXTRA_LOG_LEVEL_DEFAULTS)
970+
ll = logging.get_default_log_levels()
971+
logging.set_defaults(default_log_levels=ll)
931972
product_name = "octavia"
932973
logging.setup(conf, product_name)
933974
LOG.info("Logging enabled!")

octavia/common/keystone.py

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15+
from keystoneauth1 import exceptions as ks_exceptions
1516
from keystoneauth1 import loading as ks_loading
1617
from keystonemiddleware import auth_token
1718
from oslo_config import cfg
@@ -32,14 +33,17 @@ def __init__(self, section=constants.SERVICE_AUTH):
3233
self._auth = None
3334

3435
self.section = section
35-
ks_loading.register_auth_conf_options(cfg.CONF, self.section)
36-
ks_loading.register_session_conf_options(cfg.CONF, self.section)
3736

38-
def get_session(self):
37+
def get_session(self, auth=None):
3938
"""Initializes a Keystone session.
4039
4140
:return: a Keystone Session object
4241
"""
42+
if auth:
43+
# Do not use the singleton with custom auth params
44+
return ks_loading.load_session_from_conf_options(
45+
cfg.CONF, self.section, auth=auth)
46+
4347
if not self._session:
4448
self._session = ks_loading.load_session_from_conf_options(
4549
cfg.CONF, self.section, auth=self.get_auth())
@@ -48,8 +52,57 @@ def get_session(self):
4852

4953
def get_auth(self):
5054
if not self._auth:
51-
self._auth = ks_loading.load_auth_from_conf_options(
52-
cfg.CONF, self.section)
55+
try:
56+
self._auth = ks_loading.load_auth_from_conf_options(
57+
cfg.CONF, self.section)
58+
except ks_exceptions.auth_plugins.MissingRequiredOptions as e:
59+
if self.section == constants.SERVICE_AUTH:
60+
raise e
61+
# NOTE(gthiemonge): MissingRequiredOptions is raised: there is
62+
# one or more missing auth options in the config file. It may
63+
# be due to the migration from python-neutronclient to
64+
# openstacksdk.
65+
# With neutronclient, most of the auth settings were in
66+
# [service_auth] with a few overrides in [neutron],
67+
# but with openstacksdk, we have all the auth settings in the
68+
# [neutron] section. In order to support smooth upgrades, in
69+
# case those options are missing, we override the undefined
70+
# options with the existing settings from [service_auth].
71+
72+
# This code should be removed when all the deployment tools set
73+
# the correct options in [neutron]
74+
75+
# The config options are lazily registered/loaded by keystone,
76+
# it means that we cannot get/set them before invoking
77+
# 'load_auth_from_conf_options' on 'service_auth'.
78+
ks_loading.load_auth_from_conf_options(
79+
cfg.CONF, constants.SERVICE_AUTH)
80+
81+
config = getattr(cfg.CONF, self.section)
82+
for opt in config:
83+
# For each option in the [neutron] section, get its setting
84+
# location, if the location is 'opt_default' or
85+
# 'set_default', it means that the option is not configured
86+
# in the config file, it should be replaced with the one
87+
# from [service_auth]
88+
loc = cfg.CONF.get_location(opt, self.section)
89+
if not loc or loc.location in (cfg.Locations.opt_default,
90+
cfg.Locations.set_default):
91+
if hasattr(cfg.CONF.service_auth, opt):
92+
cur_value = getattr(config, opt)
93+
value = getattr(cfg.CONF.service_auth, opt)
94+
if value != cur_value:
95+
log_value = (value if opt != "password"
96+
else "<hidden>")
97+
LOG.debug("Overriding [%s].%s with '%s'",
98+
self.section, opt, log_value)
99+
cfg.CONF.set_override(opt, value, self.section)
100+
101+
# Now we can call load_auth_from_conf_options for this specific
102+
# service with the newly defined options.
103+
self._auth = ks_loading.load_auth_from_conf_options(
104+
cfg.CONF, self.section)
105+
53106
return self._auth
54107

55108
def get_service_user_id(self):

0 commit comments

Comments
 (0)