Douglas Henrique Koerich 84b5114027 Images of ptp-notification containers for Debian
This change reorganizes the source directories of the ptp-notification's
containers: locationservice; notificationservice; notificationclient, to
be reused by both CentOS and Debian Dockerfiles to build the images
having the corresponding OS-specific base, together with the new files
used to build images for Debian.

Tests:
PASS: Build images of the 3 containers for Debian
PASS: Upload and apply changed ptp-notification application to pull
      Debian images from private repository (since final tag is
      not possible yet) in a Debian AIO-SX environment

Regression:
PASS: Build images of the 3 containers for CentOS

Story: 2009831
Task: 45658
Signed-off-by: Douglas Henrique Koerich <douglashenrique.koerich@windriver.com>
Change-Id: I4aa9650dbebe5ba68cd4d104ee0995e79681cfa4
2022-07-19 15:01:27 -03:00

247 lines
11 KiB
Python

#
# Copyright (c) 2021 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import json
import logging
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV0
from notificationclientsdk.model.dto.subscription import SubscriptionInfoV1
from notificationclientsdk.model.dto.resourcetype import ResourceType
from notificationclientsdk.common.helpers.nodeinfo_helper import NodeInfoHelper
from notificationclientsdk.common.helpers import subscription_helper
from notificationclientsdk.model.dto.broker_state import BrokerState
LOG = logging.getLogger(__name__)
from notificationclientsdk.common.helpers import log_helper
log_helper.config_logger(LOG)
class BrokerStateManager:
'''
Manager to manage broker states
Note: Now it is not thread safe
'''
def __init__(self):
self.broker_state_map = {}
self.disabled_brokers = []
self.subscription_refresh_iteration = 0
def count_brokers(self):
return len(self.broker_state_map)
def add_broker(self, broker_name):
brokerstate = self.broker_state_map.get(broker_name, None)
if not brokerstate:
brokerstate = BrokerState(
BrokerName=broker_name,
ResourceTypes=[], ResourceTypesSubscribed={})
brokerstate.update_connection_state(False)
self.broker_state_map[broker_name] = brokerstate
return brokerstate
def disable_broker(self, broker_name):
if not broker_name in self.disabled_brokers:
self.disabled_brokers.append(broker_name)
def remove_broker(self, broker_name):
self.broker_state_map.pop(broker_name, None)
def refresh_by_nodeinfos(self, nodeinfos_orm):
broker_state_changed = False
for s in nodeinfos_orm or []:
broker_state_changed = self.refresh_by_nodeinfo(s) or broker_state_changed
return broker_state_changed
def refresh_by_nodeinfo(self, nodeinfo_orm):
brokerstate = self.broker_state_map.get(nodeinfo_orm.NodeName, None)
if not brokerstate:
return False
if nodeinfo_orm.Status == 1:
brokerstate.update_connection_state(True)
else:
brokerstate.update_connection_state(False)
brokerstate.update_broker_ip(nodeinfo_orm.PodIP)
brokerstate.update_resources(json.loads(nodeinfo_orm.ResourceTypes))
return brokerstate.is_broker_ip_changed() or brokerstate.is_resources_changed()
def refresh_by_subscriptions(self, subscriptions_orm):
broker_state_changed = False
# 1, refresh iteration
self.subscription_refresh_iteration = self.subscription_refresh_iteration + 1
# 2, refresh resource subscriptions by subscription record
for s in subscriptions_orm or []:
broker_state_changed = self.__refresh_by_subscription(s) or broker_state_changed
# 3, mark broker state change by checking if any obsolete resources
broker_state_changed = broker_state_changed or self.any_obsolete_broker()
return broker_state_changed
def any_obsolete_broker(self):
for broker_name, brokerstate in self.broker_state_map.items():
try:
if brokerstate.any_obsolete_subscription(
self.subscription_refresh_iteration):
return True
except Exception as ex:
LOG.warning(
"failed to check obsoleted resources@{0}:{1}".format(broker_name, str(ex)))
continue
return False
def __refresh_by_subscription(self, subscription_orm):
changed = False
broker_name = None
LOG.info("__refresh_by_subscription: subscription_orm={}".format(subscription_orm))
if getattr(subscription_orm, 'ResourceType') is not None:
subscription = SubscriptionInfoV0(subscription_orm)
resource = subscription.ResourceType
# assume PTP and not wildcard
if resource == ResourceType.TypePTP:
broker_name = subscription.ResourceQualifier.NodeName
else:
# ignore the subscription due to unsupported type
LOG.debug("Ignore the subscription for: {0}".format(subscription_orm.SubscriptionId))
return False
else:
subscription = SubscriptionInfoV1(subscription_orm)
_, nodename, resource = subscription_helper.parse_resource_address(subscription.ResourceAddress)
broker_name = nodename
LOG.info("subscription:{0}, Status:{1}".format(subscription.to_dict(), subscription_orm.Status))
if subscription_orm.Status != 1:
return False
if not broker_name:
# ignore the subscription due to unsupported type
LOG.info("Ignore the subscription for: {0}".format(subscription.SubscriptionId))
return False
enumerated_broker_names = NodeInfoHelper.enumerate_nodes(broker_name)
if not enumerated_broker_names:
LOG.info("Failed to enumerate broker names for {0}".format(broker_name))
return False
for expanded_broker_name in enumerated_broker_names:
brokerstate = self.broker_state_map.get(expanded_broker_name, None)
if not brokerstate:
brokerstate = self.add_broker(expanded_broker_name)
changed = True
changed = changed or (brokerstate.is_resource_subscribed(resource) == False)
brokerstate.try_subscribe_resource(resource, self.subscription_refresh_iteration)
return changed
def syncup_broker_watchers(self, broker_connection_manager):
'''sync up brokers state to broker connection manager'''
aggregated_result = True
interested_brokers = []
removed_brokers = []
# 1, clean all obsolete resource subscriptions
# and disable broker in case no active resource subscription
for broker_name, brokerstate in self.broker_state_map.items():
try:
brokerstate.unsubscribe_resource_obsolete(self.subscription_refresh_iteration)
if not brokerstate.any_resource_subscribed():
LOG.debug("disable broker@{0} due to no subscription".format(broker_name))
self.disable_broker(broker_name)
except Exception as ex:
LOG.warning(
"failed to clean obsolete subscribed resources@{0}:{1}".format(
broker_name, str(ex)))
continue
# 2, stop watching all disabled brokers
for broker_name in self.disabled_brokers:
try:
LOG.debug("stop watching due to disabled: {0}".format(broker_name))
result = broker_connection_manager.stop_watching_broker(
broker_name)
self.remove_broker(broker_name)
removed_brokers.append(broker_name)
aggregated_result = aggregated_result and result
except Exception as ex:
LOG.warning(
"failed to clean disabled broker@{0}: {1}".format(
broker_name, str(ex)))
aggregated_result = False
continue
self.disabled_brokers.clear()
# 3, start/restart watching remains brokers
for broker_name, brokerstate in self.broker_state_map.items():
interested_brokers.append(broker_name)
try:
result = True
is_connected = brokerstate.is_connected()
is_watching = broker_connection_manager.is_watching_broker(
broker_name)
if not is_connected:
if is_watching:
LOG.debug("Stop watching due to disconnected: {0}".format(broker_name))
result = broker_connection_manager.stop_watching_broker(
broker_name)
elif is_connected:
# note: start/restart watcher will update resources as well
if not is_watching:
LOG.debug("Start watching due to connected: {0}".format(broker_name))
result = broker_connection_manager.start_watching_broker(
brokerstate)
elif brokerstate.is_broker_ip_changed():
LOG.debug("Restart watching due to IP changed: {0}".format(broker_name))
result = broker_connection_manager.restart_watching_broker(
brokerstate)
elif brokerstate.is_connection_state_changed():
# trigger to sync up notification after (re-)connection
LOG.debug("Trigger to re-sync up data: {0}".format(broker_name))
result = brokerstate.signal_data_syncup()
elif brokerstate.is_resource_subscribed_changed() or brokerstate.is_resources_changed():
LOG.debug("Update watching due to resources changed: {0}".format(broker_name))
result = broker_connection_manager.update_watching_resources(brokerstate)
# leave the signals as it is to re-sync up in next loop in case of failure
if result:
# assumption to avoid race condition: same thread to manipulate brokerstate
brokerstate.ack_connection_state_changed()
brokerstate.ack_broker_ip_changed()
brokerstate.ack_resource_subscribed_changed()
brokerstate.ack_resources_changed()
aggregated_result = aggregated_result and result
except Exception as ex:
LOG.warning("failed to sync up broker watcher:{0},{1}".format(broker_name, str(ex)))
aggregated_result = False
continue
return aggregated_result, interested_brokers, removed_brokers
def syncup_broker_data(self, broker_connection_manager):
'''sync up to get rid of stall data'''
aggregated_result = True
synced_brokers = []
unsynced_brokers = []
for broker_name, brokerstate in self.broker_state_map.items():
try:
if brokerstate.is_connected() and brokerstate.is_data_syncup():
LOG.debug("Try to sync up broker data:{0}".format(broker_name))
result = result and broker_connection_manager.syncup_broker_data(
brokerstate)
if result:
# assumption to avoid race condition: same thread to manipulate brokerstate
brokerstate.ack_data_syncup()
synced_brokers.append(broker_name)
else:
unsynced_brokers.append(broker_name)
aggregated_result = aggregated_result and result
except Exception as ex:
unsynced_brokers.append(broker_name)
LOG.warning("failed to sync up broker data:{0}".format(str(ex)))
aggregated_result = False
continue
return aggregated_result, synced_brokers, unsynced_brokers