Add keystone password change callback

Adding a callback to execute the puppet class
'platform::keystone::password::runtime'

Test Plan:

PASS: Verify the command 'openstack user password set' ran in
      openstack /var/log/sysinv.log
PASS: Verify the password change trigger reaches the subcloud
      when the environment variable OS REGION NAME is changed
      to 'SystemController'
PASS: Verify the patch apply using sw-patch and sw-manager
      patch-strategy commands after changing openstack (keystone)
      password

Regression:

PASS: Verify system patch install
PASS: Verify feature logging
PASS: Verify controllers, compute nodes after a force reboot
PASS: Verify bm type ipmi, redfish and dynamic
PASS: Verify push docker image to local registry
PASS: Verify uploading charts via helm upload
PASS: Verify host operations with custom kubectl app
PASS: Verify isolated 2 peers to big pod (HT non-AIO)
PASS: Verify system core dumps and crashes
PASS: Verify system health pre session for pods, alarms, system apps
PASS: Verify horizon host inventory display
PASS: Verify lock unlock host
PASS: Verify swact controller platform
PASS: Verify pod to pod connection
PASS: Verify pod to service connection
PASS: Verify host to service connection

Story: 2009194
Task: 43249

Signed-off-by: Alexandre Horst <alexandre.horst@windriver.com>
Change-Id: I1a2d3ff0c99ca29f63db9ca0a3f0d78b59b8d819
This commit is contained in:
Alexandre Horst 2021-10-04 12:07:03 -03:00
parent d221cafce0
commit a6740ee507
4 changed files with 74 additions and 11 deletions

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2019 Intel Corporation
# Copyright (c) 2021 Wind River Systems, Inc.
#
"""
Sysinv Keystone notification listener.
@ -9,7 +10,6 @@ Sysinv Keystone notification listener.
import keyring
import oslo_messaging
from oslo_config import cfg
from oslo_log import log
@ -19,7 +19,8 @@ from sysinv.db import api as dbapi
LOG = log.getLogger(__name__)
kube_app = None
callback_func = None
context = None
class NotificationEndpoint(object):
@ -38,8 +39,15 @@ class NotificationEndpoint(object):
def info(self, ctxt, publisher_id, event_type, payload, metadata):
"""Receives notification at info level."""
global kube_app
kube_app.audit_local_registry_secrets()
global callback_func
global context
if payload['eventType'] == 'activity' and \
payload['action'] == 'updated.user' and \
payload['outcome'] == 'success' and \
payload['resource_info'] == context.user:
callback_func(context)
return oslo_messaging.NotificationResult.HANDLED
@ -57,14 +65,19 @@ def get_transport_url():
auth_password = keyring.get_password('amqp', 'rabbit')
transport_url = "rabbit://guest:%s@%s:5672" % (auth_password, address.address)
if utils.is_valid_ipv6(address.address):
address = "[%s]" % address
transport_url = "rabbit://guest:%s@%s:5672" % (auth_password, address)
return transport_url
def start_keystone_listener(app):
def start_keystone_listener(func, ctxt):
global kube_app
kube_app = app
global callback_func
global context
callback_func = func
context = ctxt
conf = cfg.ConfigOpts()
conf.transport_url = get_transport_url()

View File

@ -957,7 +957,7 @@ class AppOperator(object):
except Exception as e:
LOG.exception(e)
def audit_local_registry_secrets(self):
def audit_local_registry_secrets(self, context):
"""
local registry uses admin's username&password for authentication.
K8s stores the authentication info in secrets in order to access

View File

@ -258,7 +258,19 @@ class ConductorManager(service.PeriodicService):
# monitor keystone user update event to check whether admin password is
# changed or not. If changed, then sync it to kubernetes's secret info.
greenthread.spawn(keystone_listener.start_keystone_listener, self._app)
admin_user = self._openstack.get_keystone_admin_user()
if admin_user:
admin_context = ctx.RequestContext(user=admin_user.id, tenant='admin', is_admin=True)
# The thread for kube_app auditing local registry secrets
greenthread.spawn(keystone_listener.start_keystone_listener,
self._app.audit_local_registry_secrets, admin_context)
# The thread for updating keystone admin password in config files
greenthread.spawn(keystone_listener.start_keystone_listener,
self.update_keystone_password,
admin_context)
# Monitor ceph to become responsive
if StorageBackendConfig.has_backend_configured(
@ -1641,6 +1653,19 @@ class ConductorManager(service.PeriodicService):
return False
def update_keystone_password(self, context):
"""This method calls a puppet class
'openstack::keystone::password::runtime'
on keystone password change"""
personalities = [constants.CONTROLLER]
config_uuid = self._config_update_hosts(context, personalities)
config_dict = {
"personalities": personalities,
"classes": ["openstack::keystone::password::runtime"]
}
self._config_apply_runtime_manifest(context, config_uuid, config_dict)
def update_remotelogging_config(self, context):
"""Update the remotelogging configuration"""
@ -5823,7 +5848,7 @@ class ConductorManager(service.PeriodicService):
# Audit kubernetes local registry secrets info
LOG.debug("Sysinv Conductor running periodic audit task for k8s local registry secrets.")
if self._app:
self._app.audit_local_registry_secrets()
self._app.audit_local_registry_secrets(context)
@periodic_task.periodic_task(spacing=CONF.conductor.audit_interval)
def _conductor_audit(self, context):

View File

@ -347,6 +347,31 @@ class OpenStackOperator(object):
"snapshots before restoring volumes."))
LOG.debug("Cinder DB ready for volume Restore")
########################
# keystone user methods
########################
def _get_keystone_users(self):
"""Get a list of all users in keystone otherwise an empty list."""
user_list = []
try:
user_list = self._get_keystone_client(OPENSTACK_CONFIG).users.list()
except Exception as e:
LOG.error("Failed to get keystone user list:\n%s" % str(e))
return user_list
def get_keystone_admin_user(self):
"""Return keystone admin otherwise None."""
users = self._get_keystone_users()
try:
return [user for user in users if user.name == 'admin'][0]
except Exception as e:
LOG.error("Failed to get keystone admin user:\n%s" % str(e))
return None
#########################
# Primary Region Sysinv
# Region specific methods