Sysinv healthy query API request failed

The healthy query API request triggers sysinv to query the alarm list.
The alarm query is attempted via a sysinv database API which is no
longer supported. This results in the REST API request failure.

This update contains the following changes to address the issue:
1.Add FM catalog info to sysinv puppet class and manifest
2.Add service catalog to the user request context
3.Add a FM client interface to communicate with FM API
4.Update the health query to retrieve the alarm list via FM client

Closes-Bug: # 1789983

Change-Id: I31b256f6de22fe70cba59b08bf927c8b0ac119ee
Signed-off-by: Tao Liu <tao.liu@windriver.com>
This commit is contained in:
Tao Liu 2018-09-12 16:44:37 -04:00
parent 63f30fba51
commit a8acc56242
8 changed files with 104 additions and 16 deletions

View File

@ -2,6 +2,7 @@ class platform::sysinv::params (
$api_port = 6385,
$region_name = undef,
$service_create = false,
$fm_catalog_info = 'faultmanagement:fm:internalURL',
) { }
class platform::sysinv
@ -45,6 +46,7 @@ class platform::sysinv
rabbit_port => $::platform::amqp::params::port,
rabbit_userid => $::platform::amqp::params::auth_user,
rabbit_password => $::platform::amqp::params::auth_password,
fm_catalog_info => $fm_catalog_info,
}
# Note: The log format strings are prefixed with "sysinv" because it is

View File

@ -1,7 +1,7 @@
#
# Files in this package are licensed under Apache; see LICENSE file.
#
# Copyright (c) 2013-2016 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -69,7 +69,8 @@ class sysinv (
$neutron_region_name = 'RegionOne',
$cinder_region_name = 'RegionOne',
$nova_region_name = 'RegionOne',
$magnum_region_name = 'RegionOne'
$magnum_region_name = 'RegionOne',
$fm_catalog_info = undef,
) {
include sysinv::params
@ -200,6 +201,11 @@ class sysinv (
'keystone_authtoken/magnum_region_name': value => $magnum_region_name;
}
sysinv_config {
'fm/catalog_info': value => $fm_catalog_info;
'fm/os_region_name': value => $region_name;
}
sysinv_api_paste_ini {
'filter:authtoken/region_name': value => $region_name;
}

View File

@ -16,13 +16,15 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2013-2014 Wind River Systems, Inc.
# Copyright (c) 2013-2018 Wind River Systems, Inc.
#
import time
import urlparse
import webob
from oslo_config import cfg
from oslo_serialization import jsonutils
from pecan import hooks
from sysinv.common import context
@ -33,6 +35,7 @@ from sysinv.openstack.common import policy
from webob import exc
from sysinv.openstack.common import log
from sysinv.openstack.common.gettextutils import _
import eventlet.semaphore
import re
@ -78,6 +81,9 @@ class ContextHook(hooks.PecanHook):
The flag is set to True, if X-Roles contains either an administrator
or admin substring. Otherwise it is set to False.
X-Service_Catalog:
Used for context.service_catalog.
"""
def __init__(self, public_api_routes):
self.public_api_routes = public_api_routes
@ -92,6 +98,14 @@ class ContextHook(hooks.PecanHook):
domain_name = state.request.headers.get('X-User-Domain-Name')
auth_token = state.request.headers.get('X-Auth-Token', None)
creds = {'roles': state.request.headers.get('X-Roles', '').split(',')}
catalog_header = state.request.headers.get('X-Service-Catalog')
service_catalog = None
if catalog_header:
try:
service_catalog = jsonutils.loads(catalog_header)
except ValueError:
raise webob.exc.HTTPInternalServerError(
_('Invalid service catalog json.'))
is_admin = policy.check('admin', state.request.headers, creds)
@ -105,7 +119,9 @@ class ContextHook(hooks.PecanHook):
domain_id=domain_id,
domain_name=domain_name,
is_admin=is_admin,
is_public_api=is_public_api)
is_public_api=is_public_api,
service_catalog=service_catalog
)
class RPCHook(hooks.PecanHook):

View File

@ -16,18 +16,23 @@ from sysinv.db import api as dbapi
from sysinv.openstack.common import context
REQUIRED_SERVICE_TYPES = ('faultmanagement',)
class RequestContext(context.RequestContext):
"""Extends security contexts from the OpenStack common library."""
def __init__(self, auth_token=None, domain_id=None, domain_name=None,
user=None, tenant=None, is_admin=False, is_public_api=False,
read_only=False, show_deleted=False, request_id=None):
read_only=False, show_deleted=False, request_id=None,
service_catalog=None):
"""Stores several additional request parameters:
:param domain_id: The ID of the domain.
:param domain_name: The name of the domain.
:param is_public_api: Specifies whether the request should be processed
without authentication.
:param service_catalog: Specifies the service_catalog
"""
self.is_public_api = is_public_api
self.domain_id = domain_id
@ -40,6 +45,13 @@ class RequestContext(context.RequestContext):
read_only=read_only,
show_deleted=show_deleted,
request_id=request_id)
if service_catalog:
# Only include required parts of service_catalog
self.service_catalog = [s for s in service_catalog
if s.get('type') in REQUIRED_SERVICE_TYPES]
else:
# if list is empty or none
self.service_catalog = []
@property
def session(self):
@ -51,7 +63,8 @@ class RequestContext(context.RequestContext):
def to_dict(self):
result = {'domain_id': self.domain_id,
'domain_name': self.domain_name,
'is_public_api': self.is_public_api}
'is_public_api': self.is_public_api,
'service_catalog': self.service_catalog}
result.update(super(RequestContext, self).to_dict())

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Wind River Systems, Inc.
# Copyright (c) 2016-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -7,13 +7,36 @@
# FM Fault Management Handling
from keystoneauth1.access import service_catalog as k_service_catalog
from oslo_config import cfg
from fm_api import constants as fm_constants
from fm_api import fm_api
import fmclient as fm_client
from sysinv.openstack.common import log
CONF = cfg.CONF
LOG = log.getLogger(__name__)
fm_group = cfg.OptGroup(
'fm',
title='FM Options',
help="Configuration options for the fault management service")
fm_opts = [
cfg.StrOpt('catalog_info',
default='faultmanagement:fm:internalURL',
help="Service catalog Look up info."),
cfg.StrOpt('os_region_name',
default='RegionOne',
help="Region name of this node. It is used for catalog lookup")
]
CONF.register_group(fm_group)
CONF.register_opts(fm_opts, group=fm_group)
class FmCustomerLog(object):
"""
Fault Management Customer Log
@ -55,3 +78,27 @@ class FmCustomerLog(object):
LOG.info("Generated customer log, fm_uuid=%s." % fm_uuid)
else:
LOG.error("Unknown event id (%s) given." % fm_event_id)
def fmclient(context, version=1, endpoint=None):
"""Constructs a fm client object for making API requests.
:param context: The request context for auth.
:param version: API endpoint version.
:param endpoint: Optional If the endpoint is not available, it will be
retrieved from context
"""
auth_token = context.auth_token
if endpoint is None:
sc = k_service_catalog.ServiceCatalogV2(context.service_catalog)
service_type, service_name, interface = \
CONF.fm.catalog_info.split(':')
service_parameters = {'service_type': service_type,
'service_name': service_name,
'interface': interface,
'region_name': CONF.fm.os_region_name}
endpoint = sc.url_for(**service_parameters)
return fm_client.Client(version=version,
endpoint=endpoint,
auth_token=auth_token)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Wind River Systems, Inc.
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -13,6 +13,7 @@ from fm_api import fm_api
from sysinv.common import ceph
from sysinv.common import constants
from sysinv.common import utils
from sysinv.common.fm import fmclient
from sysinv.common.storage_backend_conf import StorageBackendConfig
from sysinv.api.controllers.v1 import patch_api
from sysinv.api.controllers.v1 import vim_api
@ -95,9 +96,9 @@ class Health(object):
success = not not_patch_current_hosts and not hostnames
return success, not_patch_current_hosts, hostnames
def _check_alarms(self, force=False):
def _check_alarms(self, context, force=False):
"""Checks that no alarms are active"""
db_alarms = self._dbapi.ialarm_get_all(include_suppress=True)
db_alarms = fmclient(context).alarm.list(include_suppress=True)
success = True
allowed = 0
@ -210,7 +211,7 @@ class Health(object):
return True
def get_system_health(self, force=False):
def get_system_health(self, context, force=False):
"""Returns the general health of the system"""
# Checks the following:
# All hosts are provisioned
@ -277,7 +278,7 @@ class Health(object):
health_ok = health_ok and success
success, allowed, affecting = self._check_alarms(force)
success, allowed, affecting = self._check_alarms(context, force)
output += _('No alarms: [%s]\n') \
% (Health.SUCCESS_MSG if success else Health.FAIL_MSG)
if not success:
@ -288,7 +289,7 @@ class Health(object):
return health_ok, output
def get_system_health_upgrade(self, force=False):
def get_system_health_upgrade(self, context, force=False):
"""Ensures the system is in a valid state for an upgrade"""
# Does a general health check then does the following:
# A load is imported
@ -298,7 +299,7 @@ class Health(object):
system_mode = self._dbapi.isystem_get_one().system_mode
simplex = (system_mode == constants.SYSTEM_MODE_SIMPLEX)
health_ok, output = self.get_system_health(force)
health_ok, output = self.get_system_health(context, force)
loads = self._dbapi.load_get_list()
try:
imported_load = utils.get_imported_load(loads)

View File

@ -8975,9 +8975,11 @@ class ConductorManager(service.PeriodicService):
health_util = health.Health(self.dbapi)
if upgrade is True:
return health_util.get_system_health_upgrade(force=force)
return health_util.get_system_health_upgrade(context=context,
force=force)
else:
return health_util.get_system_health(force=force)
return health_util.get_system_health(context=context,
force=force)
def _get_cinder_address_name(self, network_type):
ADDRESS_FORMAT_ARGS = (constants.CONTROLLER_HOSTNAME,

View File

@ -41,6 +41,7 @@ deps = -r{toxinidir}/requirements.txt
-e{[tox]cgcsdir}/stx-update/tsconfig/tsconfig
-e{[tox]cgcsdir}/stx-config/configutilities/configutilities
-e{[tox]cgcsdir}/stx-fault/fm-api
-e{[tox]cgcsdir}/stx-fault/python-fmclient/fmclient
-e{[tox]cgcsdir}/stx-config/controllerconfig/controllerconfig
-e{[tox]cgcsdir}/stx-update/cgcs-patch/cgcs-patch
-e{[tox]cgcsdir}/stx-integ/utilities/platform-util/platform-util