Implement ORAN v2 api on notificationserver
The commit added the support to publish ptp status for v2 API in the notification-service. It also renamed the previously name v0 API to v1 API. Test Plan: Pass: PTP status push notification v2 API Pass: PTP status push notification v1 API Pass: Subscribe/List/Delete subscription in v2 API Pass: Subscribe/List/Delete subscription in v1 API Story: 2010056 Task: 45809 Signed-off-by: Teresa Ho <teresa.ho@windriver.com> Change-Id: Id5a1ff955eade59d68b6bcadfea4ffe6ed1567cd
This commit is contained in:
parent
84b5114027
commit
67452b94db
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -58,12 +58,12 @@ class NotificationServiceClient(BrokerClientBase):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def query_resource_status(self, resource_type,
|
def query_resource_status(self, resource_type,
|
||||||
timeout=None, retry=None, resource_qualifier_json=None):
|
timeout=None, retry=None, resource_qualifier_json=None, resource_address=None):
|
||||||
topic = '{0}-Status'.format(resource_type)
|
topic = '{0}-Status'.format(resource_type)
|
||||||
server = '{0}-Tracking-{1}'.format(resource_type, self.target_node_name)
|
server = '{0}-Tracking-{1}'.format(resource_type, self.target_node_name)
|
||||||
return self.call(
|
return self.call(
|
||||||
topic, server, 'QueryStatus', timeout=timeout, retry=retry,
|
topic, server, 'QueryStatus', timeout=timeout, retry=retry,
|
||||||
QualifierJson=resource_qualifier_json)
|
QualifierJson=resource_qualifier_json, ResourceAddress=resource_address)
|
||||||
|
|
||||||
def add_resource_status_listener(self, resource_type, status_handler=None):
|
def add_resource_status_listener(self, resource_type, status_handler=None):
|
||||||
if not status_handler:
|
if not status_handler:
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
SPEC_VERSION = "1.0"
|
||||||
|
DATA_TYPE_NOTIFICATION = "notification"
|
||||||
|
DATA_TYPE_METRIC = "metric"
|
||||||
|
VALUE_TYPE_ENUMERATION = "enumeration"
|
||||||
|
VALUE_TYPE_METRIC = "metric"
|
||||||
|
|
||||||
|
SOURCE_SYNC_ALL = '/sync'
|
||||||
|
SOURCE_SYNC_GNSS_SYNC_STATUS = '/sync/gnss-status/gnss-sync-status'
|
||||||
|
SOURCE_SYNC_PTP_CLOCK_CLASS = '/sync/ptp-status/clock-class'
|
||||||
|
SOURCE_SYNC_PTP_LOCK_STATE = '/sync/ptp-status/lock-state'
|
||||||
|
SOURCE_SYNC_OS_CLOCK = '/sync/sync-status/os-clock-sync-state'
|
||||||
|
SOURCE_SYNC_SYNC_STATE = '/sync/sync-status/sync-state'
|
||||||
|
SOURCE_SYNCE_CLOCK_QUALITY = '/sync/synce-status/clock-quality'
|
||||||
|
SOURCE_SYNCE_LOCK_STATE_EXTENDED = '/sync/synce-status/lock-state-extended'
|
||||||
|
SOURCE_SYNCE_LOCK_STATE = '/sync/synce-status/lock-state'
|
||||||
|
|
||||||
|
VALID_SOURCE_URI = {
|
||||||
|
SOURCE_SYNC_ALL,
|
||||||
|
SOURCE_SYNC_GNSS_SYNC_STATUS,
|
||||||
|
SOURCE_SYNC_PTP_CLOCK_CLASS,
|
||||||
|
SOURCE_SYNC_PTP_LOCK_STATE,
|
||||||
|
SOURCE_SYNC_OS_CLOCK,
|
||||||
|
SOURCE_SYNC_SYNC_STATE,
|
||||||
|
SOURCE_SYNCE_CLOCK_QUALITY,
|
||||||
|
SOURCE_SYNCE_LOCK_STATE_EXTENDED,
|
||||||
|
SOURCE_SYNCE_LOCK_STATE
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
#coding=utf-8
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -59,7 +58,7 @@ def parse_resource_address(resource_address):
|
|||||||
# Assume no optional hierarchy for now
|
# Assume no optional hierarchy for now
|
||||||
clusterName = resource_address.split('/')[1]
|
clusterName = resource_address.split('/')[1]
|
||||||
nodeName = resource_address.split('/')[2]
|
nodeName = resource_address.split('/')[2]
|
||||||
resource_path = re.split('[/]', resource_address, 3)[3]
|
resource_path = '/' + re.split('[/]', resource_address, 3)[3]
|
||||||
|
|
||||||
return clusterName, nodeName, resource_path
|
return clusterName, nodeName, resource_path
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
||||||
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV2
|
||||||
from notificationclientsdk.model.dto.subscription import ResourceQualifierPtp
|
from notificationclientsdk.model.dto.subscription import ResourceQualifierPtp
|
||||||
|
|
||||||
from wsme.rest.json import tojson
|
from wsme.rest.json import tojson
|
||||||
|
|
||||||
@tojson.when_object(SubscriptionInfoV0)
|
@tojson.when_object(SubscriptionInfoV1)
|
||||||
def subscriptioninfo_tojson(datatype, value):
|
def subscriptioninfo_tojson(datatype, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return None
|
return None
|
||||||
@ -22,7 +22,7 @@ def resourcequalifierptp_tojson(datatype, value):
|
|||||||
return None
|
return None
|
||||||
return value.to_dict()
|
return value.to_dict()
|
||||||
|
|
||||||
@tojson.when_object(SubscriptionInfoV1)
|
@tojson.when_object(SubscriptionInfoV2)
|
||||||
def subscriptioninfo_tojson(datatype, value):
|
def subscriptioninfo_tojson(datatype, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return None
|
return None
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#coding=utf-8
|
#coding=utf-8
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -45,7 +45,7 @@ class ResourceQualifierPtp(ResourceQualifierBase):
|
|||||||
'''
|
'''
|
||||||
ViewModel of Subscription
|
ViewModel of Subscription
|
||||||
'''
|
'''
|
||||||
class SubscriptionInfoV0(wtypes.Base):
|
class SubscriptionInfoV1(wtypes.Base):
|
||||||
SubscriptionId = wtypes.text
|
SubscriptionId = wtypes.text
|
||||||
UriLocation = wtypes.text
|
UriLocation = wtypes.text
|
||||||
ResourceType = EnumResourceType
|
ResourceType = EnumResourceType
|
||||||
@ -99,7 +99,7 @@ class SubscriptionInfoV0(wtypes.Base):
|
|||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
|
|
||||||
class SubscriptionInfoV1(wtypes.Base):
|
class SubscriptionInfoV2(wtypes.Base):
|
||||||
SubscriptionId = wtypes.text
|
SubscriptionId = wtypes.text
|
||||||
UriLocation = wtypes.text
|
UriLocation = wtypes.text
|
||||||
EndpointUri = wtypes.text
|
EndpointUri = wtypes.text
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
||||||
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV2
|
||||||
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
||||||
from notificationclientsdk.common.helpers.nodeinfo_helper import NodeInfoHelper
|
from notificationclientsdk.common.helpers.nodeinfo_helper import NodeInfoHelper
|
||||||
from notificationclientsdk.common.helpers import subscription_helper
|
from notificationclientsdk.common.helpers import subscription_helper
|
||||||
@ -96,9 +96,8 @@ class BrokerStateManager:
|
|||||||
changed = False
|
changed = False
|
||||||
broker_name = None
|
broker_name = None
|
||||||
|
|
||||||
LOG.info("__refresh_by_subscription: subscription_orm={}".format(subscription_orm))
|
|
||||||
if getattr(subscription_orm, 'ResourceType') is not None:
|
if getattr(subscription_orm, 'ResourceType') is not None:
|
||||||
subscription = SubscriptionInfoV0(subscription_orm)
|
subscription = SubscriptionInfoV1(subscription_orm)
|
||||||
resource = subscription.ResourceType
|
resource = subscription.ResourceType
|
||||||
# assume PTP and not wildcard
|
# assume PTP and not wildcard
|
||||||
if resource == ResourceType.TypePTP:
|
if resource == ResourceType.TypePTP:
|
||||||
@ -108,22 +107,22 @@ class BrokerStateManager:
|
|||||||
LOG.debug("Ignore the subscription for: {0}".format(subscription_orm.SubscriptionId))
|
LOG.debug("Ignore the subscription for: {0}".format(subscription_orm.SubscriptionId))
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
subscription = SubscriptionInfoV1(subscription_orm)
|
subscription = SubscriptionInfoV2(subscription_orm)
|
||||||
_, nodename, resource = subscription_helper.parse_resource_address(subscription.ResourceAddress)
|
_, nodename, resource = subscription_helper.parse_resource_address(subscription.ResourceAddress)
|
||||||
broker_name = nodename
|
broker_name = nodename
|
||||||
|
|
||||||
LOG.info("subscription:{0}, Status:{1}".format(subscription.to_dict(), subscription_orm.Status))
|
LOG.debug("subscription:{0}, Status:{1}".format(subscription.to_dict(), subscription_orm.Status))
|
||||||
if subscription_orm.Status != 1:
|
if subscription_orm.Status != 1:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not broker_name:
|
if not broker_name:
|
||||||
# ignore the subscription due to unsupported type
|
# ignore the subscription due to unsupported type
|
||||||
LOG.info("Ignore the subscription for: {0}".format(subscription.SubscriptionId))
|
LOG.debug("Ignore the subscription for: {0}".format(subscription.SubscriptionId))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
enumerated_broker_names = NodeInfoHelper.enumerate_nodes(broker_name)
|
enumerated_broker_names = NodeInfoHelper.enumerate_nodes(broker_name)
|
||||||
if not enumerated_broker_names:
|
if not enumerated_broker_names:
|
||||||
LOG.info("Failed to enumerate broker names for {0}".format(broker_name))
|
LOG.debug("Failed to enumerate broker names for {0}".format(broker_name))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
for expanded_broker_name in enumerated_broker_names:
|
for expanded_broker_name in enumerated_broker_names:
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -10,9 +9,10 @@ import logging
|
|||||||
|
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
||||||
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV2
|
||||||
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
||||||
|
|
||||||
from notificationclientsdk.repository.subscription_repo import SubscriptionRepo
|
from notificationclientsdk.repository.subscription_repo import SubscriptionRepo
|
||||||
@ -48,32 +48,38 @@ class NotificationHandler(NotificationHandlerBase):
|
|||||||
self.notification_lock.acquire()
|
self.notification_lock.acquire()
|
||||||
subscription_repo = SubscriptionRepo(autocommit=True)
|
subscription_repo = SubscriptionRepo(autocommit=True)
|
||||||
resource_type = notification_info.get('ResourceType', None)
|
resource_type = notification_info.get('ResourceType', None)
|
||||||
resource_address = notification_info.get('ResourceAddress', None)
|
|
||||||
# Get nodename from resource address
|
# Get nodename from resource address
|
||||||
if resource_address:
|
if resource_type:
|
||||||
_,node_name,_ = subscription_helper.parse_resource_address(resource_address)
|
|
||||||
else:
|
|
||||||
node_name = notification_info.get('ResourceQualifier', {}).get('NodeName', None)
|
node_name = notification_info.get('ResourceQualifier', {}).get('NodeName', None)
|
||||||
if not resource_type:
|
if not resource_type:
|
||||||
raise Exception("abnormal notification@{0}".format(node_name))
|
raise Exception("abnormal notification@{0}".format(node_name))
|
||||||
|
|
||||||
if not resource_type in self.__supported_resource_types:
|
if not resource_type in self.__supported_resource_types:
|
||||||
raise Exception("notification with unsupported resource type:{0}".format(resource_type))
|
raise Exception("notification with unsupported resource type:{0}".format(resource_type))
|
||||||
|
|
||||||
this_delivery_time = notification_info['EventTimestamp']
|
this_delivery_time = notification_info['EventTimestamp']
|
||||||
|
else:
|
||||||
|
source = notification_info.get('source', None)
|
||||||
|
values = notification_info.get('data', {}).get('values', [])
|
||||||
|
resource_address = values[0].get('ResourceAddress', None)
|
||||||
|
if not resource_address:
|
||||||
|
raise Exception("No resource address in notification source".format(source))
|
||||||
|
_,node_name,_ = subscription_helper.parse_resource_address(resource_address)
|
||||||
|
this_delivery_time = notification_info['time']
|
||||||
|
# Change time from float to ascii format
|
||||||
|
notification_info['time'] = time.strftime('%Y-%m-%dT%H:%M:%SZ',
|
||||||
|
time.gmtime(this_delivery_time))
|
||||||
|
|
||||||
entries = subscription_repo.get(ResourceType=resource_type, Status=1)
|
entries = subscription_repo.get(Status=1)
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
subscriptionid = entry.SubscriptionId
|
subscriptionid = entry.SubscriptionId
|
||||||
if entry.ResourceAddress:
|
if entry.ResourceAddress:
|
||||||
_,entry_node_name,_ = subscription_helper.parse_resource_address(entry.ResourceAddress)
|
_,entry_node_name,_ = subscription_helper.parse_resource_address(entry.ResourceAddress)
|
||||||
subscription_dto2 = SubscriptionInfoV1(entry)
|
subscription_dto2 = SubscriptionInfoV2(entry)
|
||||||
else:
|
else:
|
||||||
ResourceQualifierJson = entry.ResourceQualifierJson or '{}'
|
ResourceQualifierJson = entry.ResourceQualifierJson or '{}'
|
||||||
ResourceQualifier = json.loads(ResourceQualifierJson)
|
ResourceQualifier = json.loads(ResourceQualifierJson)
|
||||||
# qualify by NodeName
|
# qualify by NodeName
|
||||||
entry_node_name = ResourceQualifier.get('NodeName', None)
|
entry_node_name = ResourceQualifier.get('NodeName', None)
|
||||||
subscription_dto2 = SubscriptionInfoV0(entry)
|
subscription_dto2 = SubscriptionInfoV1(entry)
|
||||||
node_name_matched = NodeInfoHelper.match_node_name(entry_node_name, node_name)
|
node_name_matched = NodeInfoHelper.match_node_name(entry_node_name, node_name)
|
||||||
if not node_name_matched:
|
if not node_name_matched:
|
||||||
continue
|
continue
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -20,7 +20,7 @@ from notificationclientsdk.common.helpers import rpc_helper, hostfile_helper
|
|||||||
from notificationclientsdk.common.helpers.nodeinfo_helper import NodeInfoHelper
|
from notificationclientsdk.common.helpers.nodeinfo_helper import NodeInfoHelper
|
||||||
|
|
||||||
from notificationclientsdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
from notificationclientsdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
||||||
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
||||||
from notificationclientsdk.model.dto.location import LocationInfo
|
from notificationclientsdk.model.dto.location import LocationInfo
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ class NotificationWorker:
|
|||||||
|
|
||||||
for s in subs:
|
for s in subs:
|
||||||
if s.ResourceType:
|
if s.ResourceType:
|
||||||
subinfo = SubscriptionInfoV0(s)
|
subinfo = SubscriptionInfoV1(s)
|
||||||
# assume resource type being PTP and not wildcard
|
# assume resource type being PTP and not wildcard
|
||||||
resource_type = s.ResourceType
|
resource_type = s.ResourceType
|
||||||
if resource_type == ResourceType.TypePTP:
|
if resource_type == ResourceType.TypePTP:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -9,16 +9,17 @@ import logging
|
|||||||
import json
|
import json
|
||||||
import kombu
|
import kombu
|
||||||
|
|
||||||
|
from notificationclientsdk.client.notificationservice import NotificationServiceClient
|
||||||
|
from notificationclientsdk.common.helpers import subscription_helper
|
||||||
|
from notificationclientsdk.common.helpers.nodeinfo_helper import NodeInfoHelper
|
||||||
|
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
||||||
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
||||||
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV2
|
||||||
|
from notificationclientsdk.model.orm.subscription import Subscription as SubscriptionOrm
|
||||||
from notificationclientsdk.repository.node_repo import NodeRepo
|
from notificationclientsdk.repository.node_repo import NodeRepo
|
||||||
from notificationclientsdk.repository.subscription_repo import SubscriptionRepo
|
from notificationclientsdk.repository.subscription_repo import SubscriptionRepo
|
||||||
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
|
||||||
from notificationclientsdk.common.helpers.nodeinfo_helper import NodeInfoHelper
|
|
||||||
from notificationclientsdk.model.orm.subscription import Subscription as SubscriptionOrm
|
|
||||||
from notificationclientsdk.client.notificationservice import NotificationServiceClient
|
|
||||||
from notificationclientsdk.services.daemon import DaemonControl
|
from notificationclientsdk.services.daemon import DaemonControl
|
||||||
from notificationclientsdk.common.helpers import subscription_helper
|
|
||||||
|
|
||||||
from notificationclientsdk.exception import client_exception
|
from notificationclientsdk.exception import client_exception
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ class PtpService(object):
|
|||||||
finally:
|
finally:
|
||||||
del nodeinfo_repo
|
del nodeinfo_repo
|
||||||
|
|
||||||
def query(self, broker_name):
|
def query(self, broker_name, resource_address=None):
|
||||||
default_node_name = NodeInfoHelper.default_node_name(broker_name)
|
default_node_name = NodeInfoHelper.default_node_name(broker_name)
|
||||||
broker_pod_ip, supported_resource_types = self.__get_node_info(default_node_name)
|
broker_pod_ip, supported_resource_types = self.__get_node_info(default_node_name)
|
||||||
|
|
||||||
@ -83,9 +84,9 @@ class PtpService(object):
|
|||||||
ResourceType.TypePTP, default_node_name))
|
ResourceType.TypePTP, default_node_name))
|
||||||
raise client_exception.ResourceNotAvailable(broker_name, ResourceType.TypePTP)
|
raise client_exception.ResourceNotAvailable(broker_name, ResourceType.TypePTP)
|
||||||
|
|
||||||
return self._query(default_node_name, broker_pod_ip)
|
return self._query(default_node_name, broker_pod_ip, resource_address)
|
||||||
|
|
||||||
def _query(self, broker_name, broker_pod_ip):
|
def _query(self, broker_name, broker_pod_ip, resource_address=None):
|
||||||
broker_host = "[{0}]".format(broker_pod_ip)
|
broker_host = "[{0}]".format(broker_pod_ip)
|
||||||
broker_transport_endpoint = "rabbit://{0}:{1}@{2}:{3}".format(
|
broker_transport_endpoint = "rabbit://{0}:{1}@{2}:{3}".format(
|
||||||
self.daemon_control.daemon_context['NOTIFICATION_BROKER_USER'],
|
self.daemon_control.daemon_context['NOTIFICATION_BROKER_USER'],
|
||||||
@ -97,7 +98,7 @@ class PtpService(object):
|
|||||||
notificationservice_client = NotificationServiceClient(
|
notificationservice_client = NotificationServiceClient(
|
||||||
broker_name, broker_transport_endpoint, broker_pod_ip)
|
broker_name, broker_transport_endpoint, broker_pod_ip)
|
||||||
resource_status = notificationservice_client.query_resource_status(
|
resource_status = notificationservice_client.query_resource_status(
|
||||||
ResourceType.TypePTP, timeout=5, retry=10)
|
ResourceType.TypePTP, timeout=5, retry=10, resource_address=resource_address)
|
||||||
return resource_status
|
return resource_status
|
||||||
except oslo_messaging.exceptions.MessagingTimeout as ex:
|
except oslo_messaging.exceptions.MessagingTimeout as ex:
|
||||||
LOG.warning("ptp status is not available @node {0} due to {1}".format(
|
LOG.warning("ptp status is not available @node {0} due to {1}".format(
|
||||||
@ -144,9 +145,9 @@ class PtpService(object):
|
|||||||
|
|
||||||
# Delivery the initial notification of ptp status
|
# Delivery the initial notification of ptp status
|
||||||
if hasattr(subscription_dto, 'ResourceType'):
|
if hasattr(subscription_dto, 'ResourceType'):
|
||||||
subscription_dto2 = SubscriptionInfoV0(entry)
|
|
||||||
else:
|
|
||||||
subscription_dto2 = SubscriptionInfoV1(entry)
|
subscription_dto2 = SubscriptionInfoV1(entry)
|
||||||
|
else:
|
||||||
|
subscription_dto2 = SubscriptionInfoV2(entry)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
subscription_helper.notify(subscription_dto2, ptpstatus)
|
subscription_helper.notify(subscription_dto2, ptpstatus)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#coding=utf-8
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -14,9 +13,10 @@ from wsmeext.pecan import wsexpose
|
|||||||
|
|
||||||
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
||||||
|
|
||||||
from sidecar.controllers.v1.subscriptions import SubscriptionsControllerV0
|
|
||||||
from sidecar.controllers.v1.subscriptions import SubscriptionsControllerV1
|
from sidecar.controllers.v1.subscriptions import SubscriptionsControllerV1
|
||||||
|
from sidecar.controllers.v2.subscriptions import SubscriptionsControllerV2
|
||||||
from sidecar.controllers.v1.resource.ptp import PtpController
|
from sidecar.controllers.v1.resource.ptp import PtpController
|
||||||
|
from sidecar.controllers.v2.resource_address import ResourceAddressController
|
||||||
import logging
|
import logging
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
from notificationclientsdk.common.helpers import log_helper
|
from notificationclientsdk.common.helpers import log_helper
|
||||||
@ -40,21 +40,33 @@ class V1Controller(rest.RestController):
|
|||||||
|
|
||||||
@expose("json")
|
@expose("json")
|
||||||
def _lookup(self, primary_key, *remainder):
|
def _lookup(self, primary_key, *remainder):
|
||||||
LOG.info("_lookup: primary_key={} remainder={}".format(primary_key, remainder))
|
|
||||||
payload = None
|
|
||||||
if request.is_body_readable:
|
|
||||||
payload = request.json_body
|
|
||||||
LOG.info("_lookup: payload={}".format(payload))
|
|
||||||
if primary_key:
|
if primary_key:
|
||||||
if 'ptp' == primary_key.lower():
|
if 'ptp' == primary_key.lower():
|
||||||
return PtpController(), remainder
|
return PtpController(), remainder
|
||||||
elif 'subscriptions' == primary_key.lower():
|
elif 'subscriptions' == primary_key.lower():
|
||||||
if payload and 'ResourceType' in payload:
|
|
||||||
return SubscriptionsControllerV0(), remainder
|
|
||||||
else:
|
|
||||||
return SubscriptionsControllerV1(), remainder
|
return SubscriptionsControllerV1(), remainder
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
class V2Controller(rest.RestController):
|
||||||
|
|
||||||
|
@wsexpose(wtypes.text)
|
||||||
|
def get(self):
|
||||||
|
return 'v2controller'
|
||||||
|
|
||||||
|
@expose("json")
|
||||||
|
def _lookup(self, primary_key, *remainder):
|
||||||
|
if primary_key:
|
||||||
|
if 'subscriptions' == primary_key.lower():
|
||||||
|
return SubscriptionsControllerV2(), remainder
|
||||||
|
else:
|
||||||
|
if 'currentstate' == remainder[-1].lower():
|
||||||
|
resource_address_array = remainder[:-1]
|
||||||
|
resource_address = '/' + primary_key + '/' + '/'.join(resource_address_array)
|
||||||
|
remainder = remainder[-1:]
|
||||||
|
return ResourceAddressController(resource_address), remainder
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
class ocloudDaemonController(rest.RestController):
|
class ocloudDaemonController(rest.RestController):
|
||||||
|
|
||||||
# All supported API versions
|
# All supported API versions
|
||||||
@ -73,6 +85,8 @@ class ocloudDaemonController(rest.RestController):
|
|||||||
if primary_key:
|
if primary_key:
|
||||||
if 'v1' == primary_key.lower():
|
if 'v1' == primary_key.lower():
|
||||||
return V1Controller(), remainder
|
return V1Controller(), remainder
|
||||||
|
elif 'v2' == primary_key.lower():
|
||||||
|
return V2Controller(), remainder
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
class RootController(object):
|
class RootController(object):
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#coding=utf-8
|
#coding=utf-8
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -16,7 +16,6 @@ from wsme import types as wtypes
|
|||||||
from wsmeext.pecan import wsexpose
|
from wsmeext.pecan import wsexpose
|
||||||
|
|
||||||
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
||||||
|
|
||||||
from notificationclientsdk.repository.subscription_repo import SubscriptionRepo
|
from notificationclientsdk.repository.subscription_repo import SubscriptionRepo
|
||||||
@ -33,9 +32,9 @@ log_helper.config_logger(LOG)
|
|||||||
|
|
||||||
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
||||||
|
|
||||||
class SubscriptionsControllerV0(rest.RestController):
|
class SubscriptionsControllerV1(rest.RestController):
|
||||||
|
|
||||||
@wsexpose(SubscriptionInfoV0, body=SubscriptionInfoV0, status_code=201)
|
@wsexpose(SubscriptionInfoV1, body=SubscriptionInfoV1, status_code=201)
|
||||||
def post(self, subscription):
|
def post(self, subscription):
|
||||||
# decode the request body
|
# decode the request body
|
||||||
try:
|
try:
|
||||||
@ -49,7 +48,7 @@ class SubscriptionsControllerV0(rest.RestController):
|
|||||||
subscription.ResourceType))
|
subscription.ResourceType))
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
if not self._validateV0(subscription):
|
if not self._validateV1(subscription):
|
||||||
LOG.warning(' Invalid Request data:{0}'.format(subscription.to_dict()))
|
LOG.warning(' Invalid Request data:{0}'.format(subscription.to_dict()))
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
||||||
@ -88,87 +87,6 @@ class SubscriptionsControllerV0(rest.RestController):
|
|||||||
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
||||||
abort(500)
|
abort(500)
|
||||||
|
|
||||||
@expose('json')
|
|
||||||
def get(self):
|
|
||||||
try:
|
|
||||||
repo = SubscriptionRepo(defaults['dbcontext'].get_session(), autocommit = False)
|
|
||||||
entries = repo.get(Status=1)
|
|
||||||
|
|
||||||
response.status = 200
|
|
||||||
return [SubscriptionInfoV0(x).to_dict() for x in entries if x.Status == 1]
|
|
||||||
except HTTPException as ex:
|
|
||||||
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
|
||||||
raise ex
|
|
||||||
except HTTPServerError as ex:
|
|
||||||
LOG.error("Server side error:{0},{1}".format(type(ex), str(ex)))
|
|
||||||
raise ex
|
|
||||||
except Exception as ex:
|
|
||||||
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
|
||||||
abort(500)
|
|
||||||
|
|
||||||
@expose()
|
|
||||||
def _lookup(self, subscription_id, *remainder):
|
|
||||||
return SubscriptionController(subscription_id), remainder
|
|
||||||
|
|
||||||
def _validateV0(self, subscription_request):
|
|
||||||
try:
|
|
||||||
assert subscription_request.ResourceType == 'PTP'
|
|
||||||
assert subscription_request.EndpointUri
|
|
||||||
|
|
||||||
return True
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionsControllerV1(rest.RestController):
|
|
||||||
|
|
||||||
@wsexpose(SubscriptionInfoV1, body=SubscriptionInfoV1, status_code=201)
|
|
||||||
def post(self, subscription):
|
|
||||||
# decode the request body
|
|
||||||
try:
|
|
||||||
if subscription.ResourceAddress:
|
|
||||||
LOG.info(' subscribe: ResourceAddress {0} with callback uri {1}'.format(
|
|
||||||
subscription.ResourceAddress,
|
|
||||||
subscription.EndpointUri))
|
|
||||||
|
|
||||||
if not self._validateV1(subscription):
|
|
||||||
LOG.warning(' Invalid Request data:{0}'.format(subscription.to_dict()))
|
|
||||||
abort(400)
|
|
||||||
|
|
||||||
subscription.UriLocation = "{0}://{1}:{2}/ocloudNotifications/v1/subscriptions".format(
|
|
||||||
conf.server.get('protocol','http'),
|
|
||||||
conf.server.get('host', '127.0.0.1'),
|
|
||||||
conf.server.get('port', '8080')
|
|
||||||
)
|
|
||||||
if subscription.ResourceAddress:
|
|
||||||
ptpservice = PtpService(notification_control)
|
|
||||||
entry = ptpservice.add_subscription(subscription)
|
|
||||||
del ptpservice
|
|
||||||
if not entry:
|
|
||||||
abort(404)
|
|
||||||
subscription.SubscriptionId = entry.SubscriptionId
|
|
||||||
subscription.UriLocation = entry.UriLocation
|
|
||||||
LOG.info('created subscription: {0}'.format(subscription.to_dict()))
|
|
||||||
|
|
||||||
return subscription
|
|
||||||
except client_exception.InvalidSubscription as ex:
|
|
||||||
abort(400)
|
|
||||||
except client_exception.InvalidEndpoint as ex:
|
|
||||||
abort(400)
|
|
||||||
except client_exception.NodeNotAvailable as ex:
|
|
||||||
abort(404)
|
|
||||||
except client_exception.ResourceNotAvailable as ex:
|
|
||||||
abort(404)
|
|
||||||
except HTTPException as ex:
|
|
||||||
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
|
||||||
abort(400)
|
|
||||||
except HTTPServerError as ex:
|
|
||||||
LOG.error("Server side error:{0},{1}".format(type(ex), str(ex)))
|
|
||||||
abort(500)
|
|
||||||
except Exception as ex:
|
|
||||||
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
|
||||||
abort(500)
|
|
||||||
|
|
||||||
@expose('json')
|
@expose('json')
|
||||||
def get(self):
|
def get(self):
|
||||||
try:
|
try:
|
||||||
@ -178,9 +96,7 @@ class SubscriptionsControllerV1(rest.RestController):
|
|||||||
subs = []
|
subs = []
|
||||||
for x in entries:
|
for x in entries:
|
||||||
if x.Status == 1:
|
if x.Status == 1:
|
||||||
if getattr(x, 'ResourceType', None):
|
if getattr(x, 'ResourceType', None) is not None:
|
||||||
subs.append(SubscriptionInfoV0(x).to_dict())
|
|
||||||
else:
|
|
||||||
subs.append(SubscriptionInfoV1(x).to_dict())
|
subs.append(SubscriptionInfoV1(x).to_dict())
|
||||||
return subs
|
return subs
|
||||||
except HTTPException as ex:
|
except HTTPException as ex:
|
||||||
@ -199,13 +115,14 @@ class SubscriptionsControllerV1(rest.RestController):
|
|||||||
|
|
||||||
def _validateV1(self, subscription_request):
|
def _validateV1(self, subscription_request):
|
||||||
try:
|
try:
|
||||||
assert subscription_request.ResourceAddress
|
assert subscription_request.ResourceType == 'PTP'
|
||||||
assert subscription_request.EndpointUri
|
assert subscription_request.EndpointUri
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionController(rest.RestController):
|
class SubscriptionController(rest.RestController):
|
||||||
def __init__(self, subscription_id):
|
def __init__(self, subscription_id):
|
||||||
self.subscription_id = subscription_id
|
self.subscription_id = subscription_id
|
||||||
@ -220,9 +137,6 @@ class SubscriptionController(rest.RestController):
|
|||||||
abort(404)
|
abort(404)
|
||||||
else:
|
else:
|
||||||
response.status = 200
|
response.status = 200
|
||||||
if getattr(entry, 'ResourceType', None):
|
|
||||||
return SubscriptionInfoV0(entry).to_dict()
|
|
||||||
else:
|
|
||||||
return SubscriptionInfoV1(entry).to_dict()
|
return SubscriptionInfoV1(entry).to_dict()
|
||||||
except HTTPException as ex:
|
except HTTPException as ex:
|
||||||
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
@ -0,0 +1,69 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2022 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
from pecan import expose, redirect, rest, route, response, abort
|
||||||
|
from webob.exc import HTTPException, HTTPNotFound, HTTPBadRequest, HTTPClientError, HTTPServerError
|
||||||
|
|
||||||
|
from wsme import types as wtypes
|
||||||
|
from wsmeext.pecan import wsexpose
|
||||||
|
|
||||||
|
import os
|
||||||
|
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 sidecar.repository.notification_control import notification_control
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
from notificationclientsdk.common.helpers import log_helper
|
||||||
|
log_helper.config_logger(LOG)
|
||||||
|
|
||||||
|
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
||||||
|
|
||||||
|
class ResourceAddressController(object):
|
||||||
|
def __init__(self, resource_address):
|
||||||
|
self.resource_address = resource_address
|
||||||
|
|
||||||
|
@expose('json')
|
||||||
|
def CurrentState(self):
|
||||||
|
try:
|
||||||
|
# validate resource address
|
||||||
|
_, nodename, resource = subscription_helper.parse_resource_address(self.resource_address)
|
||||||
|
if nodename != THIS_NODE_NAME and nodename != '.':
|
||||||
|
LOG.warning("Node {} is not available".format(nodename))
|
||||||
|
abort(404)
|
||||||
|
if resource not in constants.VALID_SOURCE_URI:
|
||||||
|
LOG.warning("Resource {} is not valid".format(resource))
|
||||||
|
abort(404)
|
||||||
|
ptpservice = PtpService(notification_control)
|
||||||
|
ptpstatus = ptpservice.query(THIS_NODE_NAME, self.resource_address)
|
||||||
|
return ptpstatus
|
||||||
|
except client_exception.NodeNotAvailable as ex:
|
||||||
|
LOG.warning("Node is not available:{0}".format(str(ex)))
|
||||||
|
abort(404)
|
||||||
|
except client_exception.ResourceNotAvailable as ex:
|
||||||
|
LOG.warning("Resource is not available:{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 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)
|
||||||
|
|
@ -0,0 +1,168 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
from pecan import conf
|
||||||
|
from pecan import expose, rest, response, abort
|
||||||
|
from webob.exc import HTTPException, HTTPNotFound, HTTPBadRequest, HTTPClientError, HTTPServerError
|
||||||
|
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from wsme import types as wtypes
|
||||||
|
from wsmeext.pecan import wsexpose
|
||||||
|
|
||||||
|
from notificationclientsdk.model.dto.resourcetype import ResourceType
|
||||||
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV2
|
||||||
|
|
||||||
|
from notificationclientsdk.repository.subscription_repo import SubscriptionRepo
|
||||||
|
from notificationclientsdk.services.ptp import PtpService
|
||||||
|
from notificationclientsdk.exception import client_exception
|
||||||
|
|
||||||
|
from sidecar.repository.notification_control import notification_control
|
||||||
|
from sidecar.repository.dbcontext_default import defaults
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
from notificationclientsdk.common.helpers import log_helper
|
||||||
|
log_helper.config_logger(LOG)
|
||||||
|
|
||||||
|
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
||||||
|
|
||||||
|
class SubscriptionsControllerV2(rest.RestController):
|
||||||
|
|
||||||
|
@wsexpose(SubscriptionInfoV2, body=SubscriptionInfoV2, status_code=201)
|
||||||
|
def post(self, subscription):
|
||||||
|
# decode the request body
|
||||||
|
try:
|
||||||
|
if subscription.ResourceAddress:
|
||||||
|
LOG.info(' subscribe: ResourceAddress {0} with callback uri {1}'.format(
|
||||||
|
subscription.ResourceAddress,
|
||||||
|
subscription.EndpointUri))
|
||||||
|
|
||||||
|
if not self._validateV2(subscription):
|
||||||
|
LOG.warning(' Invalid Request data:{0}'.format(subscription.to_dict()))
|
||||||
|
abort(400)
|
||||||
|
|
||||||
|
subscription.UriLocation = "{0}://{1}:{2}/ocloudNotifications/v2/subscriptions".format(
|
||||||
|
conf.server.get('protocol','http'),
|
||||||
|
conf.server.get('host', '127.0.0.1'),
|
||||||
|
conf.server.get('port', '8080')
|
||||||
|
)
|
||||||
|
if subscription.ResourceAddress:
|
||||||
|
ptpservice = PtpService(notification_control)
|
||||||
|
entry = ptpservice.add_subscription(subscription)
|
||||||
|
del ptpservice
|
||||||
|
if not entry:
|
||||||
|
abort(404)
|
||||||
|
subscription.SubscriptionId = entry.SubscriptionId
|
||||||
|
subscription.UriLocation = entry.UriLocation
|
||||||
|
LOG.info('created subscription: {0}'.format(subscription.to_dict()))
|
||||||
|
|
||||||
|
return subscription
|
||||||
|
except client_exception.InvalidSubscription as ex:
|
||||||
|
abort(400)
|
||||||
|
except client_exception.InvalidEndpoint as ex:
|
||||||
|
abort(400)
|
||||||
|
except client_exception.NodeNotAvailable as ex:
|
||||||
|
abort(404)
|
||||||
|
except client_exception.ResourceNotAvailable as ex:
|
||||||
|
abort(404)
|
||||||
|
except HTTPException as ex:
|
||||||
|
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
abort(400)
|
||||||
|
except HTTPServerError as ex:
|
||||||
|
LOG.error("Server side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
abort(500)
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
||||||
|
abort(500)
|
||||||
|
|
||||||
|
@expose('json')
|
||||||
|
def get(self):
|
||||||
|
try:
|
||||||
|
repo = SubscriptionRepo(defaults['dbcontext'].get_session(), autocommit = False)
|
||||||
|
entries = repo.get(Status=1)
|
||||||
|
response.status = 200
|
||||||
|
subs = []
|
||||||
|
for x in entries:
|
||||||
|
if x.Status == 1:
|
||||||
|
if getattr(x, 'ResourceAddress', None) is not None:
|
||||||
|
subs.append(SubscriptionInfoV2(x).to_dict())
|
||||||
|
return subs
|
||||||
|
except HTTPException as ex:
|
||||||
|
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
raise ex
|
||||||
|
except HTTPServerError as ex:
|
||||||
|
LOG.error("Server side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
raise ex
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
||||||
|
abort(500)
|
||||||
|
|
||||||
|
@expose()
|
||||||
|
def _lookup(self, subscription_id, *remainder):
|
||||||
|
return SubscriptionController(subscription_id), remainder
|
||||||
|
|
||||||
|
def _validateV2(self, subscription_request):
|
||||||
|
try:
|
||||||
|
assert subscription_request.ResourceAddress
|
||||||
|
assert subscription_request.EndpointUri
|
||||||
|
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
class SubscriptionController(rest.RestController):
|
||||||
|
def __init__(self, subscription_id):
|
||||||
|
self.subscription_id = subscription_id
|
||||||
|
|
||||||
|
@expose('json')
|
||||||
|
def get(self):
|
||||||
|
try:
|
||||||
|
repo = SubscriptionRepo(defaults['dbcontext'].get_session(), autocommit = False)
|
||||||
|
entry = repo.get_one(SubscriptionId=self.subscription_id, Status=1)
|
||||||
|
|
||||||
|
if not entry:
|
||||||
|
abort(404)
|
||||||
|
else:
|
||||||
|
response.status = 200
|
||||||
|
if getattr(entry, 'ResourceAddress', None):
|
||||||
|
return SubscriptionInfoV2(entry).to_dict()
|
||||||
|
|
||||||
|
except HTTPException as ex:
|
||||||
|
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
raise ex
|
||||||
|
except HTTPServerError as ex:
|
||||||
|
LOG.error("Server side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
raise ex
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
||||||
|
abort(500)
|
||||||
|
|
||||||
|
@wsexpose(status_code=204)
|
||||||
|
def delete(self):
|
||||||
|
try:
|
||||||
|
repo = SubscriptionRepo(defaults['dbcontext'].get_session(), autocommit = False)
|
||||||
|
entry = repo.get_one(SubscriptionId=self.subscription_id)
|
||||||
|
if entry:
|
||||||
|
if entry.SubscriptionId:
|
||||||
|
ptpservice = PtpService(notification_control)
|
||||||
|
ptpservice.remove_subscription(entry.SubscriptionId)
|
||||||
|
del ptpservice
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
repo.delete_one(SubscriptionId=self.subscription_id)
|
||||||
|
return
|
||||||
|
abort(404)
|
||||||
|
except HTTPException as ex:
|
||||||
|
LOG.warning("Client side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
raise ex
|
||||||
|
except HTTPServerError as ex:
|
||||||
|
LOG.error("Server side error:{0},{1}".format(type(ex), str(ex)))
|
||||||
|
raise ex
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.error("Exception:{0}@{1}".format(type(ex),str(ex)))
|
||||||
|
abort(500)
|
@ -4,13 +4,13 @@
|
|||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
|
|
||||||
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
|
||||||
|
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV2
|
||||||
from notificationclientsdk.model.dto.subscription import ResourceQualifierPtp
|
from notificationclientsdk.model.dto.subscription import ResourceQualifierPtp
|
||||||
|
|
||||||
from pecan.jsonify import jsonify
|
from pecan.jsonify import jsonify
|
||||||
|
|
||||||
@jsonify.register(SubscriptionInfoV0)
|
@jsonify.register(SubscriptionInfoV1)
|
||||||
def jsonify_subscriptioninfo(subscriptionInfo):
|
def jsonify_subscriptioninfo(subscriptionInfo):
|
||||||
return subscriptionInfo.to_dict()
|
return subscriptionInfo.to_dict()
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ def jsonify_subscriptioninfo(subscriptionInfo):
|
|||||||
def jsonify_resourcequalifierptp(resourceQualifierPtp):
|
def jsonify_resourcequalifierptp(resourceQualifierPtp):
|
||||||
return resourceQualifierPtp.to_dict()
|
return resourceQualifierPtp.to_dict()
|
||||||
|
|
||||||
@jsonify.register(SubscriptionInfoV1)
|
@jsonify.register(SubscriptionInfoV2)
|
||||||
def jsonify_subscriptioninfo(subscriptionInfo):
|
def jsonify_subscriptioninfo(subscriptionInfo):
|
||||||
return subscriptionInfo.to_dict()
|
return subscriptionInfo.to_dict()
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ RUN set -ex ;\
|
|||||||
-y \
|
-y \
|
||||||
gcc python3-devel python3-pip \
|
gcc python3-devel python3-pip \
|
||||||
&& pip3 install --user pecan \
|
&& pip3 install --user pecan \
|
||||||
|
&& pip3 install pygtail \
|
||||||
&& pip3 install oslo-config \
|
&& pip3 install oslo-config \
|
||||||
&& pip3 install oslo-messaging \
|
&& pip3 install oslo-messaging \
|
||||||
&& pip3 install WSME
|
&& pip3 install WSME
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -37,7 +37,7 @@ class PtpEventProducer(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def TriggerDelivery(self, ctx, **rpc_kwargs):
|
def TriggerDelivery(self, ctx, **rpc_kwargs):
|
||||||
LOG.debug ("PtpEventProducer TriggerDelivery called %s" %rpc_kwargs)
|
LOG.debug("PtpEventProducer TriggerDelivery called %s" %rpc_kwargs)
|
||||||
if self.handler:
|
if self.handler:
|
||||||
return self.handler.trigger_delivery(**rpc_kwargs)
|
return self.handler.trigger_delivery(**rpc_kwargs)
|
||||||
else:
|
else:
|
||||||
@ -71,10 +71,10 @@ class PtpEventProducer(object):
|
|||||||
result2 = self.publish_status_all(ptpstatus, retry) if self.registration_broker_client else result
|
result2 = self.publish_status_all(ptpstatus, retry) if self.registration_broker_client else result
|
||||||
return result1, result2
|
return result1, result2
|
||||||
|
|
||||||
def publish_status_local(self, ptpstatus, retry=3):
|
def publish_status_local(self, ptpstatus, source, retry=3):
|
||||||
if not self.local_broker_client:
|
if not self.local_broker_client:
|
||||||
return False
|
return False
|
||||||
topic='PTP-Event-{0}'.format(self.node_name)
|
topic='{0}-Event-{1}'.format(source, self.node_name)
|
||||||
server = None
|
server = None
|
||||||
isretrystopped = False
|
isretrystopped = False
|
||||||
while not isretrystopped:
|
while not isretrystopped:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -46,3 +46,20 @@ PHC2SYS_TOLERANCE_HIGH = 37000001000
|
|||||||
|
|
||||||
# testing values
|
# testing values
|
||||||
CGU_PATH_VALID = "/sys/kernel/debug/ice/0000:18:00.0/cgu"
|
CGU_PATH_VALID = "/sys/kernel/debug/ice/0000:18:00.0/cgu"
|
||||||
|
|
||||||
|
SPEC_VERSION = "1.0"
|
||||||
|
DATA_VERSION = "1.0"
|
||||||
|
DATA_TYPE_NOTIFICATION = "notification"
|
||||||
|
DATA_TYPE_METRIC = "metric"
|
||||||
|
VALUE_TYPE_ENUMERATION = "enumeration"
|
||||||
|
VALUE_TYPE_METRIC = "metric"
|
||||||
|
|
||||||
|
SOURCE_SYNC_ALL = '/sync'
|
||||||
|
SOURCE_SYNC_GNSS_SYNC_STATUS = '/sync/gnss-status/gnss-sync-status'
|
||||||
|
SOURCE_SYNC_PTP_CLOCK_CLASS = '/sync/ptp-status/clock-class'
|
||||||
|
SOURCE_SYNC_PTP_LOCK_STATE = '/sync/ptp-status/lock-state'
|
||||||
|
SOURCE_SYNC_OS_CLOCK = '/sync/sync-status/os-clock-sync-state'
|
||||||
|
SOURCE_SYNC_SYNC_STATE = '/sync/sync-status/sync-state'
|
||||||
|
SOURCE_SYNCE_CLOCK_QUALITY = '/sync/synce-status/clock-quality'
|
||||||
|
SOURCE_SYNCE_LOCK_STATE_EXTENDED = '/sync/synce-status/lock-state-extended'
|
||||||
|
SOURCE_SYNCE_LOCK_STATE = '/sync/synce-status/lock-state'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#! /usr/bin/python3
|
#! /usr/bin/python3
|
||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2021-2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -14,6 +14,7 @@
|
|||||||
#
|
#
|
||||||
import errno, os
|
import errno, os
|
||||||
import os.path
|
import os.path
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import datetime
|
import datetime
|
||||||
@ -196,3 +197,17 @@ def ptp_status(holdover_time, freq, sync_state, event_time):
|
|||||||
else:
|
else:
|
||||||
new_event = "false"
|
new_event = "false"
|
||||||
return new_event, sync_state, event_time
|
return new_event, sync_state, event_time
|
||||||
|
|
||||||
|
def parse_resource_address(resource_address):
|
||||||
|
# The format of resource address is:
|
||||||
|
# /{clusterName}/{siteName}(/optional/hierarchy/..)/{nodeName}/{resource}
|
||||||
|
# Assume no optional hierarchy for now
|
||||||
|
clusterName = resource_address.split('/')[1]
|
||||||
|
nodeName = resource_address.split('/')[2]
|
||||||
|
resource_path = '/' + re.split('[/]', resource_address, 3)[3]
|
||||||
|
return clusterName, nodeName, resource_path
|
||||||
|
|
||||||
|
def format_resource_address(node_name, resource):
|
||||||
|
# Return a resource_address
|
||||||
|
resource_address = '/./' + node_name + resource
|
||||||
|
return resource_address
|
||||||
|
@ -9,12 +9,15 @@ import json
|
|||||||
import time
|
import time
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
from trackingfunctionsdk.client.ptpeventproducer import PtpEventProducer
|
from trackingfunctionsdk.client.ptpeventproducer import PtpEventProducer
|
||||||
|
from trackingfunctionsdk.common.helpers import constants
|
||||||
from trackingfunctionsdk.common.helpers import ptpsync
|
from trackingfunctionsdk.common.helpers import ptpsync
|
||||||
from trackingfunctionsdk.common.helpers import log_helper
|
from trackingfunctionsdk.common.helpers import log_helper
|
||||||
from trackingfunctionsdk.common.helpers.dmesg_watcher import DmesgWatcher
|
from trackingfunctionsdk.common.helpers.dmesg_watcher import DmesgWatcher
|
||||||
@ -36,6 +39,18 @@ log_helper.config_logger(LOG)
|
|||||||
|
|
||||||
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
||||||
|
|
||||||
|
# Event source to event type mapping
|
||||||
|
source_type = {
|
||||||
|
'/sync/gnss-status/gnss-sync-status': 'event.sync.gnss-status.gnss-state-change',
|
||||||
|
'/sync/ptp-status/clock-class': 'event.sync.ptp-status.ptp-clock-class-change',
|
||||||
|
'/sync/ptp-status/lock-state': 'event.sync.ptp-status.ptp-state-change',
|
||||||
|
'/sync/sync-status/os-clock-sync-state': 'event.sync.sync-status.os-clock-sync-state-change',
|
||||||
|
'/sync/sync-status/sync-state': 'event.sync.sync-status.synchronization-state-change',
|
||||||
|
'/sync/synce-status/clock-quality': 'event.sync.synce-status.synce-clock-quality-change',
|
||||||
|
'/sync/synce-status/lock-state-extended': 'event.sync.synce-status.synce-state-change-extended',
|
||||||
|
'/sync/synce-status/lock-state': 'event.sync.synce-status.synce-state-change',
|
||||||
|
'/sync/synce-status/lock-state': 'event.sync.synce-status.synce-state-change',
|
||||||
|
}
|
||||||
|
|
||||||
'''Entry point of Default Process Worker'''
|
'''Entry point of Default Process Worker'''
|
||||||
def ProcessWorkerDefault(event, sqlalchemy_conf_json, broker_transport_endpoint):
|
def ProcessWorkerDefault(event, sqlalchemy_conf_json, broker_transport_endpoint):
|
||||||
@ -61,6 +76,28 @@ class PtpWatcherDefault:
|
|||||||
last_event_time = self.watcher.ptptracker_context.get('last_event_time', time.time())
|
last_event_time = self.watcher.ptptracker_context.get('last_event_time', time.time())
|
||||||
self.watcher.ptptracker_context_lock.release()
|
self.watcher.ptptracker_context_lock.release()
|
||||||
|
|
||||||
|
resource_address = rpc_kwargs.get('ResourceAddress', None)
|
||||||
|
if resource_address:
|
||||||
|
_, nodename, resource_path = ptpsync.parse_resource_address(resource_address)
|
||||||
|
lastStatus = {
|
||||||
|
'id': uuidutils.generate_uuid(),
|
||||||
|
'specversion': constants.SPEC_VERSION,
|
||||||
|
'source': resource_path,
|
||||||
|
'type': source_type[resource_path],
|
||||||
|
'time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(last_event_time)),
|
||||||
|
'data': {
|
||||||
|
'version': constants.DATA_VERSION,
|
||||||
|
'values': [
|
||||||
|
{
|
||||||
|
'data_type': constants.DATA_TYPE_NOTIFICATION,
|
||||||
|
'ResourceAddress': resource_address,
|
||||||
|
'value_type': constants.VALUE_TYPE_ENUMERATION,
|
||||||
|
'value': sync_state
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else:
|
||||||
lastStatus = {
|
lastStatus = {
|
||||||
'ResourceType': ResourceType.TypePTP,
|
'ResourceType': ResourceType.TypePTP,
|
||||||
'EventData': {
|
'EventData': {
|
||||||
@ -183,7 +220,7 @@ class PtpWatcherDefault:
|
|||||||
holdover_time, freq, sync_state, last_event_time)
|
holdover_time, freq, sync_state, last_event_time)
|
||||||
return new_event, sync_state, new_event_time
|
return new_event, sync_state, new_event_time
|
||||||
|
|
||||||
'''announce location'''
|
'''publish ptp status'''
|
||||||
def __publish_ptpstatus(self, forced=False):
|
def __publish_ptpstatus(self, forced=False):
|
||||||
holdover_time = float(self.ptptracker_context['holdover_seconds'])
|
holdover_time = float(self.ptptracker_context['holdover_seconds'])
|
||||||
freq = float(self.ptptracker_context['poll_freq_seconds'])
|
freq = float(self.ptptracker_context['poll_freq_seconds'])
|
||||||
@ -200,7 +237,7 @@ class PtpWatcherDefault:
|
|||||||
self.ptptracker_context['last_event_time'] = new_event_time
|
self.ptptracker_context['last_event_time'] = new_event_time
|
||||||
self.ptptracker_context_lock.release()
|
self.ptptracker_context_lock.release()
|
||||||
|
|
||||||
# publish new event
|
# publish new event in API version v1 format
|
||||||
LOG.debug("publish ptp status to clients")
|
LOG.debug("publish ptp status to clients")
|
||||||
lastStatus = {
|
lastStatus = {
|
||||||
'ResourceType': 'PTP',
|
'ResourceType': 'PTP',
|
||||||
@ -212,7 +249,31 @@ class PtpWatcherDefault:
|
|||||||
},
|
},
|
||||||
'EventTimestamp': new_event_time
|
'EventTimestamp': new_event_time
|
||||||
}
|
}
|
||||||
self.ptpeventproducer.publish_status(lastStatus)
|
self.ptpeventproducer.publish_status(lastStatus, 'PTP')
|
||||||
|
|
||||||
|
# publish new event in API version v2 format
|
||||||
|
resource_address = ptpsync.format_resource_address(
|
||||||
|
self.node_name, constants.SOURCE_SYNC_SYNC_STATE)
|
||||||
|
lastStatus = {
|
||||||
|
'id': uuidutils.generate_uuid(),
|
||||||
|
'specversion': constants.SPEC_VERSION,
|
||||||
|
'source': constants.SOURCE_SYNC_SYNC_STATE,
|
||||||
|
'type': source_type[constants.SOURCE_SYNC_SYNC_STATE],
|
||||||
|
'time': new_event_time,
|
||||||
|
'data': {
|
||||||
|
'version': constants.DATA_VERSION,
|
||||||
|
'values': [
|
||||||
|
{
|
||||||
|
'data_type': constants.DATA_TYPE_NOTIFICATION,
|
||||||
|
'ResourceAddress': resource_address,
|
||||||
|
'value_type': constants.VALUE_TYPE_ENUMERATION,
|
||||||
|
'value': sync_state
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_SYNC_STATE)
|
||||||
|
self.ptpeventproducer.publish_status(lastStatus, constants.SOURCE_SYNC_ALL)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user