bbeef95744
Rework the pull status and subscription notification to remove the top level instance tags that were returned with the notification. These tags were originally introduced to identify which PTP instance a given notification was associated with. Updates to the ORAN standard have clarified that the instance identification should instead be included in the Resource Address field. This commit includes the following changes: - Update notification format to place instance identifier in Resource Address instead of a top level tag (default behaviour) - Provide a helm override to enable legacy notification format with top level instance tags for compatibility. This can be enabled by setting the override "notification_format=legacy" - Ensure GM clockClass is correctly reported for both BC and GM configs - Changes result in new images for notificationclient-base and notificationservice-base-v2 - Pull status notifications are now delivered as a list of dicts when there are multiple instances in a request. The "overall sync status" message is delivered as a dict because it only ever has a single notification - Push notifications are delivered as individual dicts for each notification, this behaviour remains the same Test plan: Pass: Verify ptp-notification builds and deploys Pass: Verify container image builds Pass: Verify ptp-notification operations (pull status, subscribe, list, delete) Pass: Verify standard and legacy format output for each notification type Partial-bug: 2089035 Signed-off-by: Cole Walker <cole.walker@windriver.com> Change-Id: Ied6674a02b41ed31079a291fc9bace74d95d467a
91 lines
3.8 KiB
Python
91 lines
3.8 KiB
Python
#
|
|
# Copyright (c) 2022-2024 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
from pecan import expose, abort
|
|
from webob.exc import HTTPException, HTTPServerError
|
|
|
|
from datetime import datetime
|
|
import logging
|
|
import oslo_messaging
|
|
|
|
from notificationclientsdk.common.helpers import constants
|
|
from notificationclientsdk.common.helpers import subscription_helper
|
|
from notificationclientsdk.services.ptp import PtpService
|
|
from notificationclientsdk.exception import client_exception
|
|
from notificationclientsdk.common.helpers import log_helper
|
|
|
|
from sidecar.repository.notification_control import notification_control
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
log_helper.config_logger(LOG)
|
|
|
|
|
|
class ResourceAddressController(object):
|
|
def __init__(self, resource_address):
|
|
self.resource_address = resource_address
|
|
|
|
@expose('json')
|
|
def CurrentState(self):
|
|
try:
|
|
# validate resource address
|
|
_, nodename, resource, optional, self.resource_address = \
|
|
subscription_helper.parse_resource_address(
|
|
self.resource_address)
|
|
if nodename == constants.WILDCARD_CURRENT_NODE:
|
|
nodename = notification_control.get_residing_nodename()
|
|
LOG.info('Nodename to query: %s' % nodename)
|
|
if not notification_control.in_service_nodenames(nodename):
|
|
LOG.warning("Node {} is not available".format(nodename))
|
|
raise client_exception.NodeNotAvailable(nodename)
|
|
if resource not in constants.VALID_SOURCE_URI:
|
|
LOG.warning("Resource {} is not valid".format(resource))
|
|
raise client_exception.ResourceNotAvailable(resource, nodename)
|
|
ptpservice = PtpService(notification_control)
|
|
ptpstatus = ptpservice.query(nodename,
|
|
self.resource_address, optional)
|
|
LOG.info('Received ptpstatus: %s', ptpstatus)
|
|
if isinstance(ptpstatus, dict):
|
|
try:
|
|
for item in ptpstatus:
|
|
ptpstatus[item]['time'] = datetime.fromtimestamp(
|
|
ptpstatus[item]['time']).strftime(
|
|
'%Y-%m-%dT%H:%M:%S%fZ')
|
|
except TypeError:
|
|
# ptpstatus does not have instance tags
|
|
ptpstatus['time'] = datetime.fromtimestamp(
|
|
ptpstatus['time']).strftime(
|
|
'%Y-%m-%dT%H:%M:%S%fZ')
|
|
elif isinstance(ptpstatus, list):
|
|
for item in ptpstatus:
|
|
item['time'] = datetime.fromtimestamp(
|
|
item['time']).strftime(
|
|
'%Y-%m-%dT%H:%M:%S%fZ')
|
|
return ptpstatus
|
|
except client_exception.NodeNotAvailable as ex:
|
|
LOG.warning("{0}".format(str(ex)))
|
|
abort(404)
|
|
except client_exception.ResourceNotAvailable as ex:
|
|
LOG.warning("{0}".format(str(ex)))
|
|
abort(404)
|
|
except oslo_messaging.exceptions.MessagingTimeout as ex:
|
|
LOG.warning("Resource is not reachable:{0}".format(str(ex)))
|
|
abort(404)
|
|
except HTTPException as ex:
|
|
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
|
# raise ex
|
|
abort(400)
|
|
except TypeError as ex:
|
|
LOG.error("Resource {0} not found on {1}, error: {2}".format(
|
|
self.resource_address, nodename, ex))
|
|
abort(404)
|
|
except HTTPServerError as ex:
|
|
LOG.error("Server side error:{0},{1}".format(type(ex), str(ex)))
|
|
# raise ex
|
|
abort(500)
|
|
except Exception as ex:
|
|
LOG.error("Exception:{0}@{1}".format(type(ex), str(ex)))
|
|
abort(500)
|