Add support for httpGet liveness probes
Updates the locationservice, notificationservice and notificationclient containers to support ipv6 httpGet liveness probes. notificationservice-base and notificationservice-basev2: - Adds health.py which starts a simple http server that runs within the daemon. The k8s httpGet liveness probe can query this endpoint to verify that the service is running - Update the daemonset template and values to provide the required info for initalizing the new endpoint locationservice-base: - Remove unused portions of the locationservice_start.sh config map. The location-query-server.py and location-announce.py were never active and are not required - Add locationservice_start.py in order to start the locationservice pecan WSGI application with either an ipv4 or ipv6 socket - Use existing pecan endpoint to respond to liveness probes notificationclient-base: - Add notificationclient_start.py to start the notificationclient pecan WSGI application with either an ipv4 or ipv6 socket - Use existing pecan endpoint to respond to liveness probes Daemonset: - Add required ip and port environment variables to support liveness probes on each container - Add a conditional section for enabling liveness probes. Disabled by default but can be enabled via helm overrides by setting "liveness: True" Misc: - Re-organized python imports in affected files - Incremented helm chart version to 2.0.1 Test-plan: Pass: Verify application build and install Pass: Verify containers build correctly Pass: Deploy ptp-notification and verify basic sanity (v1 and v2 get, subscribe, delete, list) Pass: Enable httpGet liveness probes for each container and verify operation Pass: Verify application removal Story: 2011090 Task: 49851 Signed-off-by: Cole Walker <cole.walker@windriver.com> Change-Id: I4671c7f8c67c4869a6d5e3b384eae66d8c57a284
This commit is contained in:
parent
d38115c8ed
commit
37c15ea4fb
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,4 +1,6 @@
|
||||
.tox
|
||||
api-ref/build
|
||||
doc/build
|
||||
venv/
|
||||
venv/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -7,4 +7,4 @@ apiVersion: v1
|
||||
appVersion: "2.0"
|
||||
description: A Helm chart to deploy PTP Notification Service
|
||||
name: ptp-notification
|
||||
version: 2.0.0
|
||||
version: 2.0.1
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -18,124 +18,6 @@
|
||||
# pip3 install oslo-config
|
||||
# pip3 install oslo-messaging
|
||||
|
||||
cat <<EOF>/root/location-query-server.py
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import os
|
||||
import json
|
||||
import time # 引入time模块
|
||||
import oslo_messaging
|
||||
from oslo_config import cfg
|
||||
|
||||
|
||||
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-1')
|
||||
THIS_POD_IP = os.environ.get("THIS_POD_IP",'127.0.0.1')
|
||||
THIS_NAMESPACE = os.environ.get("THIS_NAMESPACE",'notification')
|
||||
|
||||
rabbituser = os.environ.get("REGISTRATION_USER",'admin')
|
||||
rabbitpasswd = os.environ.get("REGISTRATION_PASS",'admin')
|
||||
rabbitip = "registration.{0}.svc.cluster.local".format(THIS_NAMESPACE)
|
||||
rabbitport = os.environ.get("REGISTRATION_PORT",'5672')
|
||||
# 'rabbit://admin:admin@[127.0.0.1]:5672/'
|
||||
# 'rabbit://admin:admin@[::1]:5672/'
|
||||
rabbitendpoint = "rabbit://{0}:{1}@[{2}]:{3}".format(
|
||||
rabbituser, rabbitpasswd, rabbitip, rabbitport)
|
||||
|
||||
class LocationInfoEndpoint(object):
|
||||
target = oslo_messaging.Target(namespace='notification', version='1.0')
|
||||
|
||||
def __init__(self, server):
|
||||
self.server = server
|
||||
|
||||
def QueryLocation(self, ctx, rpc_kwargs):
|
||||
print ("QueryLocation called %s" %rpc_kwargs)
|
||||
LocationInfo = {
|
||||
'NodeName': THIS_NODE_NAME,
|
||||
'PodIP': THIS_POD_IP,
|
||||
'ResourceTypes': ['PTP'],
|
||||
'Timestamp': time.time()
|
||||
}
|
||||
|
||||
return LocationInfo
|
||||
|
||||
oslo_messaging.set_transport_defaults('notification_exchange')
|
||||
transport = oslo_messaging.get_rpc_transport(cfg.CONF, url=rabbitendpoint)
|
||||
target = oslo_messaging.Target(topic='LocationQuery', server="LocationService-{0}".format(THIS_NODE_NAME))
|
||||
endpoints = [LocationInfoEndpoint(None)]
|
||||
server = oslo_messaging.get_rpc_server(transport, target, endpoints,
|
||||
executor=None)
|
||||
# oslo_messaging.server.ExecutorLoadFailure:
|
||||
# Failed to load executor "blocking": Executor should be None or 'eventlet' and 'threading'
|
||||
server.start()
|
||||
print("LocationService-{0} starts".format(THIS_NODE_NAME))
|
||||
server.wait()
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
|
||||
cat <<EOF>/root/location-announce.py
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import os
|
||||
import json
|
||||
import time # 引入time模块
|
||||
import oslo_messaging
|
||||
from oslo_config import cfg
|
||||
from webob.exc import HTTPException, HTTPNotFound, HTTPBadRequest, HTTPClientError, HTTPServerError
|
||||
|
||||
|
||||
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-1')
|
||||
THIS_POD_IP = os.environ.get("THIS_POD_IP",'127.0.0.1')
|
||||
THIS_NAMESPACE = os.environ.get("THIS_NAMESPACE",'notification')
|
||||
|
||||
rabbituser = os.environ.get("REGISTRATION_USER",'admin')
|
||||
rabbitpasswd = os.environ.get("REGISTRATION_PASS",'admin')
|
||||
rabbitip = "registration.{0}.svc.cluster.local".format(THIS_NAMESPACE)
|
||||
rabbitport = os.environ.get("REGISTRATION_PORT",'5672')
|
||||
rabbitendpoint = "rabbit://{0}:{1}@[{2}]:{3}".format(
|
||||
rabbituser, rabbitpasswd, rabbitip, rabbitport)
|
||||
|
||||
oslo_messaging.set_transport_defaults('notification_exchange')
|
||||
transport = oslo_messaging.get_rpc_transport(cfg.CONF, url=rabbitendpoint)
|
||||
|
||||
location_topic='LocationListener-{0}'.format(THIS_NODE_NAME),
|
||||
target = oslo_messaging.Target(
|
||||
topic=location_topic,
|
||||
fanout=True,
|
||||
version='1.0', namespace='notification')
|
||||
|
||||
client = oslo_messaging.get_rpc_client(transport, target)
|
||||
LocationInfo = {
|
||||
'NodeName': THIS_NODE_NAME,
|
||||
'PodIP': THIS_POD_IP,
|
||||
'ResourceTypes': ['PTP'],
|
||||
'Timestamp': time.time()
|
||||
}
|
||||
|
||||
while True:
|
||||
try:
|
||||
client.cast({}, 'NotifyLocation', location_info=LocationInfo)
|
||||
print("Announce location info:{0}@Topic:{1}".format(LocationInfo, location_topic))
|
||||
except HTTPNotFound as ex:
|
||||
print("Failed to publish location due to not found: {0}".format(str(ex)))
|
||||
continue
|
||||
except Exception as ex:
|
||||
print("Failed to publish location due to: {0}".format(str(ex)))
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
EOF
|
||||
|
||||
echo "done"
|
||||
|
||||
# python3 /root/location-query-server.py &
|
||||
|
||||
# python3 /root/location-announce.py
|
||||
|
||||
cat <<EOF>/root/notification_control.py
|
||||
import os
|
||||
import time
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -88,10 +88,27 @@ spec:
|
||||
value: "{{ .Values.notification.endpoint.pass }}"
|
||||
- name: NOTIFICATIONSERVICE_PORT
|
||||
value: "{{ .Values.notification.endpoint.port }}"
|
||||
- name: LOCATION_SERVICE_HOST
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
- name: LOCATION_SERVICE_PORT
|
||||
value: "{{ .Values.location.endpoint.port }}"
|
||||
- name: LOGGING_LEVEL
|
||||
value: "{{ .Values.location.log_level }}"
|
||||
|
||||
command: ["/bin/bash", "/mnt/locationservice_start.sh"]
|
||||
command: ["python3", "/opt/locationservice/locationservice_start.py"]
|
||||
{{- if .Values.location.endpoint.liveness }}
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /health
|
||||
port: {{ .Values.location.endpoint.port }}
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 3
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 3
|
||||
{{ end }}
|
||||
volumeMounts:
|
||||
- name: scripts
|
||||
mountPath: /mnt
|
||||
@ -136,6 +153,12 @@ spec:
|
||||
value: "5672"
|
||||
- name: REGISTRATION_HOST
|
||||
value: "registration.{{.Values.global.namespace}}.svc.cluster.local"
|
||||
- name: HEALTH_API_HOST
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
- name: HEALTH_API_PORT
|
||||
value: "{{ .Values.ptptrackingv2.endpoint.port }}"
|
||||
- name: PTP4L_SERVICE_NAME
|
||||
value: "{{ .Values.ptptrackingv2.ptp4lServiceName }}"
|
||||
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
||||
@ -153,6 +176,18 @@ spec:
|
||||
- name: CONTROL_TIMEOUT
|
||||
value: "{{ .Values.ptptrackingv2.control_timeout }}"
|
||||
command: ["python3", "/mnt/ptptracking_start_v2.py"]
|
||||
{{- if .Values.ptptrackingv2.endpoint.liveness }}
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /health
|
||||
port: {{ .Values.ptptrackingv2.endpoint.port }}
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 3
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 3
|
||||
{{ end }}
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
@ -225,6 +260,12 @@ spec:
|
||||
value: "5672"
|
||||
- name: REGISTRATION_HOST
|
||||
value: "registration.{{.Values.global.namespace}}.svc.cluster.local"
|
||||
- name: HEALTH_API_HOST
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
- name: HEALTH_API_PORT
|
||||
value: "{{ .Values.ptptracking.endpoint.port }}"
|
||||
- name: PTP4L_SERVICE_NAME
|
||||
value: "{{ .Values.ptptracking.ptp4lServiceName }}"
|
||||
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
||||
@ -238,6 +279,18 @@ spec:
|
||||
- name: LOGGING_LEVEL
|
||||
value: "{{ .Values.ptptracking.logging_level }}"
|
||||
command: ["python3", "/mnt/ptptracking_start.py"]
|
||||
{{- if .Values.ptptracking.endpoint.liveness }}
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /health
|
||||
port: {{ .Values.ptptracking.endpoint.port }}
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 60
|
||||
periodSeconds: 3
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 3
|
||||
{{ end }}
|
||||
securityContext:
|
||||
privileged: true
|
||||
capabilities:
|
||||
|
@ -63,6 +63,9 @@ notification:
|
||||
|
||||
location:
|
||||
log_level: INFO
|
||||
endpoint:
|
||||
port: 8080
|
||||
liveness: False
|
||||
image:
|
||||
repository: starlingx/locationservice-base
|
||||
tag: stx.9.0-v2.2.0
|
||||
@ -77,6 +80,9 @@ ptptracking:
|
||||
phc2sysServiceName: phc2sys-legacy
|
||||
phc2sysComSocket: False
|
||||
logging_level: INFO
|
||||
endpoint:
|
||||
port: 8081
|
||||
liveness: False
|
||||
image:
|
||||
repository: starlingx/notificationservice-base
|
||||
tag: stx.9.0-v2.2.0
|
||||
@ -96,6 +102,9 @@ ptptrackingv2:
|
||||
phc2sysToleranceThreshold: 1000
|
||||
ts2phcServiceName: True
|
||||
log_level: INFO
|
||||
endpoint:
|
||||
port: 8082
|
||||
liveness: False
|
||||
image:
|
||||
repository: starlingx/notificationservice-base-v2
|
||||
tag: stx.9.0-v2.2.0
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -11,12 +11,13 @@ server = {
|
||||
}
|
||||
|
||||
# Pecan Application Configurations
|
||||
# Ensure debug = False as per Pecan documentation
|
||||
app = {
|
||||
'root': 'apiserver.controllers.root.RootController',
|
||||
'modules': ['apiserver'],
|
||||
'static_root': '%(confdir)s/public',
|
||||
'template_path': '%(confdir)s/apiserver/templates',
|
||||
'debug': True,
|
||||
'debug': False,
|
||||
'errors': {
|
||||
404: '/error/404',
|
||||
'__force_dict__': True
|
||||
|
@ -0,0 +1,49 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
from wsgiref import simple_server
|
||||
|
||||
from locationservicesdk.common.helpers import log_helper
|
||||
from netaddr import IPAddress
|
||||
from pecan.deploy import deploy
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
LOCATION_SERVICE_HOST = os.environ.get(
|
||||
"LOCATION_SERVICE_HOST", '127.0.0.1')
|
||||
LOCATION_SERVICE_PORT = int(
|
||||
os.environ.get("LOCATION_SERVICE_PORT", '8080'))
|
||||
|
||||
|
||||
def get_address_family(ip_string):
|
||||
"""
|
||||
Get the family for the given ip address string.
|
||||
"""
|
||||
ip_address = IPAddress(ip_string)
|
||||
if ip_address.version == 6:
|
||||
return socket.AF_INET6
|
||||
else:
|
||||
return socket.AF_INET
|
||||
|
||||
|
||||
def main():
|
||||
simple_server.WSGIServer.address_family = get_address_family(
|
||||
LOCATION_SERVICE_HOST)
|
||||
application = deploy('/opt/locationservice/config.py')
|
||||
|
||||
with simple_server.make_server(LOCATION_SERVICE_HOST,
|
||||
LOCATION_SERVICE_PORT,
|
||||
application) as httpd:
|
||||
LOG.info("locationservice_start.py: Starting locationservice")
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,22 +1,21 @@
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
import oslo_messaging
|
||||
from oslo_config import cfg
|
||||
|
||||
from locationservicesdk.client.base import BrokerClientBase
|
||||
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
|
||||
import oslo_messaging
|
||||
from locationservicesdk.client.base import BrokerClientBase
|
||||
from locationservicesdk.common.helpers import log_helper
|
||||
from oslo_config import cfg
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
from locationservicesdk.common.helpers import log_helper
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
|
||||
@ -30,11 +29,12 @@ class LocationProducer(BrokerClientBase):
|
||||
pass
|
||||
|
||||
def QueryLocation(self, ctx, **rpc_kwargs):
|
||||
LOG.debug ("LocationProducer QueryLocation called %s" %rpc_kwargs)
|
||||
LOG.debug("LocationProducer QueryLocation called %s" % rpc_kwargs)
|
||||
return self.location_info
|
||||
|
||||
def TriggerAnnouncement(self, ctx, **rpc_kwargs):
|
||||
LOG.debug ("LocationProducer TriggerAnnouncement called %s" %rpc_kwargs)
|
||||
LOG.debug("LocationProducer TriggerAnnouncement called %s" %
|
||||
rpc_kwargs)
|
||||
if self.handler:
|
||||
return self.handler.handle(**rpc_kwargs)
|
||||
else:
|
||||
@ -52,23 +52,26 @@ class LocationProducer(BrokerClientBase):
|
||||
return
|
||||
|
||||
def announce_location(self, LocationInfo):
|
||||
location_topic_all='LocationListener-*'
|
||||
location_topic='LocationListener-{0}'.format(self.node_name)
|
||||
location_topic_all = 'LocationListener-*'
|
||||
location_topic = 'LocationListener-{0}'.format(self.node_name)
|
||||
server = None
|
||||
while True:
|
||||
try:
|
||||
self.cast(location_topic_all, 'NotifyLocation', location_info=LocationInfo)
|
||||
LOG.debug("Broadcast location info:{0}@Topic:{1}".format(LocationInfo, location_topic))
|
||||
self.cast(location_topic_all, 'NotifyLocation',
|
||||
location_info=LocationInfo)
|
||||
LOG.debug(
|
||||
"Broadcast location info:{0}@Topic:{1}".format(LocationInfo, location_topic))
|
||||
except Exception as ex:
|
||||
LOG.debug("Failed to publish location due to: {0}".format(str(ex)))
|
||||
LOG.debug(
|
||||
"Failed to publish location due to: {0}".format(str(ex)))
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
def start_location_listener(self, location_info, handler=None):
|
||||
|
||||
topic='LocationQuery'
|
||||
server="LocationService-{0}".format(self.node_name)
|
||||
topic = 'LocationQuery'
|
||||
server = "LocationService-{0}".format(self.node_name)
|
||||
endpoints = [LocationProducer.ListenerEndpoint(location_info, handler)]
|
||||
|
||||
super(LocationProducer, self).add_listener(
|
||||
@ -76,15 +79,13 @@ class LocationProducer(BrokerClientBase):
|
||||
return True
|
||||
|
||||
def stop_location_listener(self):
|
||||
topic='LocationQuery'
|
||||
server="LocationService-{0}".format(self.node_name)
|
||||
topic = 'LocationQuery'
|
||||
server = "LocationService-{0}".format(self.node_name)
|
||||
super(LocationProducer, self).remove_listener(
|
||||
topic, server)
|
||||
|
||||
def is_listening(self):
|
||||
topic='LocationQuery'
|
||||
server="LocationService-{0}".format(self.node_name)
|
||||
topic = 'LocationQuery'
|
||||
server = "LocationService-{0}".format(self.node_name)
|
||||
return super(LocationProducer, self).is_listening(
|
||||
topic, server)
|
||||
|
||||
|
||||
|
@ -1,27 +1,32 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
import oslo_messaging
|
||||
from oslo_config import cfg
|
||||
import logging
|
||||
|
||||
import multiprocessing as mp
|
||||
import os
|
||||
import time
|
||||
|
||||
from locationservicesdk.common.helpers import rpc_helper
|
||||
from locationservicesdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
||||
from locationservicesdk.model.dto.resourcetype import ResourceType
|
||||
|
||||
import oslo_messaging
|
||||
from locationservicesdk.client.locationproducer import LocationProducer
|
||||
from locationservicesdk.common.helpers import log_helper, rpc_helper
|
||||
from locationservicesdk.model.dto.resourcetype import ResourceType
|
||||
from locationservicesdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
||||
from oslo_config import cfg
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
from locationservicesdk.common.helpers import log_helper
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
'''Entry point of Default Process Worker'''
|
||||
|
||||
|
||||
def ProcessWorkerDefault(event, sqlalchemy_conf_json, registration_endpoint, location_info_json):
|
||||
worker = LocationWatcherDefault(event, sqlalchemy_conf_json, registration_endpoint, location_info_json)
|
||||
worker = LocationWatcherDefault(
|
||||
event, sqlalchemy_conf_json, registration_endpoint, location_info_json)
|
||||
worker.run()
|
||||
return
|
||||
|
||||
@ -42,7 +47,8 @@ class LocationWatcherDefault:
|
||||
self.location_info = json.loads(location_info_json)
|
||||
this_node_name = self.location_info['NodeName']
|
||||
|
||||
self.registration_endpoint = RpcEndpointInfo(registration_transport_endpoint)
|
||||
self.registration_endpoint = RpcEndpointInfo(
|
||||
registration_transport_endpoint)
|
||||
self.LocationProducer = LocationProducer(
|
||||
this_node_name,
|
||||
self.registration_endpoint.TransportEndpoint)
|
||||
@ -67,18 +73,20 @@ class LocationWatcherDefault:
|
||||
# max timeout: 1 hour
|
||||
if self.event_timeout < float(3600):
|
||||
self.event_timeout = self.event_timeout + self.event_timeout
|
||||
LOG.debug("daemon control event is timeout")
|
||||
LOG.debug("daemon control event is timeout: %s" %
|
||||
self.event_timeout)
|
||||
continue
|
||||
self.__stop_listener()
|
||||
|
||||
'''Start listener to answer querying from clients'''
|
||||
|
||||
def __start_listener(self):
|
||||
LOG.debug("start listener to answer location querying")
|
||||
|
||||
self.LocationProducer.start_location_listener(
|
||||
self.location_info,
|
||||
LocationWatcherDefault.LocationRequestHandlerDefault(self)
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
def __stop_listener(self):
|
||||
@ -88,21 +96,25 @@ class LocationWatcherDefault:
|
||||
return
|
||||
|
||||
'''announce location'''
|
||||
|
||||
def __announce_location(self):
|
||||
LOG.debug("announce location info to clients")
|
||||
self.LocationProducer.announce_location(self.location_info)
|
||||
return
|
||||
|
||||
|
||||
class DaemonControl(object):
|
||||
|
||||
def __init__(
|
||||
self, sqlalchemy_conf_json, registration_transport_endpoint,
|
||||
location_info, process_worker = None, daemon_mode=True):
|
||||
self, sqlalchemy_conf_json, registration_transport_endpoint,
|
||||
location_info, process_worker=None, daemon_mode=True):
|
||||
|
||||
self.daemon_mode = daemon_mode
|
||||
self.event = mp.Event()
|
||||
self.registration_endpoint = RpcEndpointInfo(registration_transport_endpoint)
|
||||
self.registration_transport = rpc_helper.get_transport(self.registration_endpoint)
|
||||
self.registration_endpoint = RpcEndpointInfo(
|
||||
registration_transport_endpoint)
|
||||
self.registration_transport = rpc_helper.get_transport(
|
||||
self.registration_endpoint)
|
||||
self.location_info = location_info
|
||||
self.sqlalchemy_conf_json = sqlalchemy_conf_json
|
||||
|
||||
@ -116,8 +128,8 @@ class DaemonControl(object):
|
||||
self.mpinstance = mp.Process(
|
||||
target=process_worker,
|
||||
args=(self.event, self.sqlalchemy_conf_json,
|
||||
self.registration_endpoint.TransportEndpoint,
|
||||
self.location_info))
|
||||
self.registration_endpoint.TransportEndpoint,
|
||||
self.location_info))
|
||||
self.mpinstance.start()
|
||||
|
||||
pass
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -17,12 +17,13 @@ server = {
|
||||
}
|
||||
|
||||
# Pecan Application Configurations
|
||||
# Ensure debug = False as per Pecan documentation
|
||||
app = {
|
||||
'root': 'sidecar.controllers.root.RootController',
|
||||
'modules': ['sidecar'],
|
||||
'static_root': '%(confdir)s/public',
|
||||
'template_path': '%(confdir)s/sidecar/templates',
|
||||
'debug': True,
|
||||
'debug': False,
|
||||
'errors': {
|
||||
404: '/error/404',
|
||||
'__force_dict__': True
|
||||
@ -53,18 +54,18 @@ logging = {
|
||||
'()': 'pecan.log.ColorFormatter',
|
||||
'format': ('%(asctime)s [%(padded_color_levelname)s] [%(name)s]'
|
||||
'[%(threadName)s] %(message)s'),
|
||||
'__force_dict__': True
|
||||
'__force_dict__': True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Bindings and options to pass to SQLAlchemy's ``create_engine``
|
||||
sqlalchemy = {
|
||||
'url' : "sqlite:////{0}/sidecar.db".format(DATASTORE_PATH),
|
||||
'echo' : False,
|
||||
'echo_pool' : False,
|
||||
'pool_recycle' : 3600,
|
||||
'encoding' : 'utf-8'
|
||||
'url': "sqlite:////{0}/sidecar.db".format(DATASTORE_PATH),
|
||||
'echo': False,
|
||||
'echo_pool': False,
|
||||
'pool_recycle': 3600,
|
||||
'encoding': 'utf-8'
|
||||
}
|
||||
|
||||
# Custom Configurations must be in Python dictionary format::
|
||||
|
@ -0,0 +1,49 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
from wsgiref import simple_server
|
||||
|
||||
from netaddr import IPAddress
|
||||
from notificationclientsdk.common.helpers import log_helper
|
||||
from pecan.deploy import deploy
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
SIDECAR_API_HOST = os.environ.get(
|
||||
"SIDECAR_API_HOST", '127.0.0.1')
|
||||
SIDECAR_API_PORT = int(
|
||||
os.environ.get("SIDECAR_API_PORT", '8080'))
|
||||
|
||||
|
||||
def get_address_family(ip_string):
|
||||
"""
|
||||
Get the family for the given ip address string.
|
||||
"""
|
||||
ip_address = IPAddress(ip_string)
|
||||
if ip_address.version == 6:
|
||||
return socket.AF_INET6
|
||||
else:
|
||||
return socket.AF_INET
|
||||
|
||||
|
||||
def main():
|
||||
simple_server.WSGIServer.address_family = get_address_family(
|
||||
SIDECAR_API_HOST)
|
||||
application = deploy('/opt/notificationclient/config.py')
|
||||
|
||||
with simple_server.make_server(SIDECAR_API_HOST,
|
||||
SIDECAR_API_PORT,
|
||||
application) as httpd:
|
||||
LOG.info("notificationclient_start.py: Starting notificationclient")
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
@ -10,21 +10,21 @@ import multiprocessing as mp
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
from trackingfunctionsdk.client.ptpeventproducer import PtpEventProducer
|
||||
from trackingfunctionsdk.common.helpers import constants
|
||||
from trackingfunctionsdk.common.helpers import constants, log_helper
|
||||
from trackingfunctionsdk.common.helpers import ptpsync as utils
|
||||
from trackingfunctionsdk.common.helpers import log_helper
|
||||
from trackingfunctionsdk.common.helpers.gnss_monitor import GnssMonitor
|
||||
from trackingfunctionsdk.common.helpers.os_clock_monitor import OsClockMonitor
|
||||
from trackingfunctionsdk.common.helpers.ptp_monitor import PtpMonitor
|
||||
from trackingfunctionsdk.model.dto.ptpstate import PtpState
|
||||
from trackingfunctionsdk.model.dto.gnssstate import GnssState
|
||||
from trackingfunctionsdk.model.dto.osclockstate import OsClockState
|
||||
from trackingfunctionsdk.model.dto.overallclockstate import OverallClockState
|
||||
from trackingfunctionsdk.model.dto.ptpstate import PtpState
|
||||
from trackingfunctionsdk.model.dto.resourcetype import ResourceType
|
||||
from trackingfunctionsdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
||||
from trackingfunctionsdk.services.health import HealthServer
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
log_helper.config_logger(LOG)
|
||||
@ -379,6 +379,10 @@ class PtpWatcherDefault:
|
||||
# start location listener
|
||||
self.__start_listener()
|
||||
|
||||
# Start the server for k8s httpGet health checks
|
||||
notificationservice_health = HealthServer()
|
||||
notificationservice_health.run()
|
||||
|
||||
while True:
|
||||
# announce the location
|
||||
forced = self.forced_publishing
|
||||
|
@ -0,0 +1,79 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
from netaddr import IPAddress
|
||||
from pecan.deploy import deploy
|
||||
from trackingfunctionsdk.common.helpers import log_helper
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
HEALTH_API_HOST = os.environ.get(
|
||||
"HEALTH_API_HOST", '127.0.0.1')
|
||||
HEALTH_API_PORT = int(
|
||||
os.environ.get("HEALTH_API_PORT", '8082'))
|
||||
|
||||
|
||||
def get_address_family(ip_string):
|
||||
"""
|
||||
Get the family for the given ip address string.
|
||||
"""
|
||||
ip_address = IPAddress(ip_string)
|
||||
if ip_address.version == 6:
|
||||
return socket.AF_INET6
|
||||
else:
|
||||
return socket.AF_INET
|
||||
|
||||
|
||||
class HealthRequestHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def do_GET(self):
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(self.get_response().encode("utf-8"))
|
||||
|
||||
def do_POST(self):
|
||||
self.do_GET()
|
||||
|
||||
def get_response(self):
|
||||
"""
|
||||
Return a simple confirmation if the process is running.
|
||||
Can be extended to check broader health aspects of notification service as needed
|
||||
"""
|
||||
return json.dumps(
|
||||
{'health': True}
|
||||
)
|
||||
|
||||
|
||||
class HealthServer:
|
||||
def __init__(self):
|
||||
HTTPServer.address_family = get_address_family(HEALTH_API_HOST)
|
||||
self.health_server = HTTPServer(
|
||||
(HEALTH_API_HOST, HEALTH_API_PORT), HealthRequestHandler)
|
||||
self.thread = threading.Thread(target=self.health_server.serve_forever)
|
||||
self.thread.daemon = True
|
||||
|
||||
def run(self):
|
||||
self.thread.start()
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
my_health = HealthServer()
|
||||
my_health.run()
|
||||
print(
|
||||
f"Health server running on {HEALTH_API_HOST}:{str(HEALTH_API_PORT)}")
|
||||
while True:
|
||||
# run indefinitely
|
||||
pass
|
@ -1,31 +1,29 @@
|
||||
#
|
||||
# Copyright (c) 2021-2023 Wind River Systems, Inc.
|
||||
# Copyright (c) 2021-2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import multiprocessing as mp
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
|
||||
import oslo_messaging
|
||||
from oslo_config import cfg
|
||||
import logging
|
||||
|
||||
import multiprocessing as mp
|
||||
import threading
|
||||
|
||||
from trackingfunctionsdk.common.helpers import rpc_helper
|
||||
from trackingfunctionsdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
||||
from trackingfunctionsdk.model.dto.resourcetype import ResourceType
|
||||
from trackingfunctionsdk.model.dto.ptpstate import PtpState
|
||||
|
||||
from trackingfunctionsdk.client.ptpeventproducer import PtpEventProducer
|
||||
|
||||
from trackingfunctionsdk.common.helpers import ptpsync as ptpsync
|
||||
from trackingfunctionsdk.model.dto.ptpstate import PtpState
|
||||
from trackingfunctionsdk.model.dto.resourcetype import ResourceType
|
||||
from trackingfunctionsdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
||||
from trackingfunctionsdk.services.health import HealthServer
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
from trackingfunctionsdk.common.helpers import log_helper
|
||||
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
THIS_NODE_NAME = os.environ.get("THIS_NODE_NAME",'controller-0')
|
||||
@ -115,6 +113,11 @@ class PtpWatcherDefault:
|
||||
def run(self):
|
||||
# start location listener
|
||||
self.__start_listener()
|
||||
|
||||
# Start the server for k8s httpGet health checks
|
||||
notificationservice_health = HealthServer()
|
||||
notificationservice_health.run()
|
||||
|
||||
while True:
|
||||
# annouce the location
|
||||
forced = self.forced_publishing
|
||||
|
@ -0,0 +1,79 @@
|
||||
#
|
||||
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
from netaddr import IPAddress
|
||||
from pecan.deploy import deploy
|
||||
from trackingfunctionsdk.common.helpers import log_helper
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
log_helper.config_logger(LOG)
|
||||
|
||||
HEALTH_API_HOST = os.environ.get(
|
||||
"HEALTH_API_HOST", '127.0.0.1')
|
||||
HEALTH_SERVICE_API_PORT = int(
|
||||
os.environ.get("HEALTH_API_PORT", '8081'))
|
||||
|
||||
|
||||
def get_address_family(ip_string):
|
||||
"""
|
||||
Get the family for the given ip address string.
|
||||
"""
|
||||
ip_address = IPAddress(ip_string)
|
||||
if ip_address.version == 6:
|
||||
return socket.AF_INET6
|
||||
else:
|
||||
return socket.AF_INET
|
||||
|
||||
|
||||
class HealthRequestHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def do_GET(self):
|
||||
self.send_response(200)
|
||||
self.send_header('Content-Type', 'application/json')
|
||||
self.end_headers()
|
||||
self.wfile.write(self.get_response().encode("utf-8"))
|
||||
|
||||
def do_POST(self):
|
||||
self.do_GET()
|
||||
|
||||
def get_response(self):
|
||||
"""
|
||||
Return a simple confirmation if the process is running.
|
||||
Can be extended to check broader health aspects of notification service as needed
|
||||
"""
|
||||
return json.dumps(
|
||||
{'health': True}
|
||||
)
|
||||
|
||||
|
||||
class HealthServer:
|
||||
def __init__(self):
|
||||
HTTPServer.address_family = get_address_family(HEALTH_API_HOST)
|
||||
self.health_server = HTTPServer(
|
||||
(HEALTH_API_HOST, HEALTH_SERVICE_API_PORT), HealthRequestHandler)
|
||||
self.thread = threading.Thread(target=self.health_server.serve_forever)
|
||||
self.thread.daemon = True
|
||||
|
||||
def run(self):
|
||||
self.thread.start()
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
my_health = HealthServer()
|
||||
my_health.run()
|
||||
print(
|
||||
f"Health server running on {HEALTH_API_HOST}:{str(HEALTH_SERVICE_API_PORT)}")
|
||||
while True:
|
||||
# run indefinitely
|
||||
pass
|
Loading…
Reference in New Issue
Block a user