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
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
|||||||
api-ref/build
|
api-ref/build
|
||||||
doc/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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -7,4 +7,4 @@ apiVersion: v1
|
|||||||
appVersion: "2.0"
|
appVersion: "2.0"
|
||||||
description: A Helm chart to deploy PTP Notification Service
|
description: A Helm chart to deploy PTP Notification Service
|
||||||
name: ptp-notification
|
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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -18,124 +18,6 @@
|
|||||||
# pip3 install oslo-config
|
# pip3 install oslo-config
|
||||||
# pip3 install oslo-messaging
|
# 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
|
cat <<EOF>/root/notification_control.py
|
||||||
import os
|
import os
|
||||||
import time
|
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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -88,10 +88,27 @@ spec:
|
|||||||
value: "{{ .Values.notification.endpoint.pass }}"
|
value: "{{ .Values.notification.endpoint.pass }}"
|
||||||
- name: NOTIFICATIONSERVICE_PORT
|
- name: NOTIFICATIONSERVICE_PORT
|
||||||
value: "{{ .Values.notification.endpoint.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
|
- name: LOGGING_LEVEL
|
||||||
value: "{{ .Values.location.log_level }}"
|
value: "{{ .Values.location.log_level }}"
|
||||||
|
command: ["python3", "/opt/locationservice/locationservice_start.py"]
|
||||||
command: ["/bin/bash", "/mnt/locationservice_start.sh"]
|
{{- 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:
|
volumeMounts:
|
||||||
- name: scripts
|
- name: scripts
|
||||||
mountPath: /mnt
|
mountPath: /mnt
|
||||||
@ -136,6 +153,12 @@ spec:
|
|||||||
value: "5672"
|
value: "5672"
|
||||||
- name: REGISTRATION_HOST
|
- name: REGISTRATION_HOST
|
||||||
value: "registration.{{.Values.global.namespace}}.svc.cluster.local"
|
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
|
- name: PTP4L_SERVICE_NAME
|
||||||
value: "{{ .Values.ptptrackingv2.ptp4lServiceName }}"
|
value: "{{ .Values.ptptrackingv2.ptp4lServiceName }}"
|
||||||
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
||||||
@ -153,6 +176,18 @@ spec:
|
|||||||
- name: CONTROL_TIMEOUT
|
- name: CONTROL_TIMEOUT
|
||||||
value: "{{ .Values.ptptrackingv2.control_timeout }}"
|
value: "{{ .Values.ptptrackingv2.control_timeout }}"
|
||||||
command: ["python3", "/mnt/ptptracking_start_v2.py"]
|
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:
|
securityContext:
|
||||||
privileged: true
|
privileged: true
|
||||||
capabilities:
|
capabilities:
|
||||||
@ -225,6 +260,12 @@ spec:
|
|||||||
value: "5672"
|
value: "5672"
|
||||||
- name: REGISTRATION_HOST
|
- name: REGISTRATION_HOST
|
||||||
value: "registration.{{.Values.global.namespace}}.svc.cluster.local"
|
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
|
- name: PTP4L_SERVICE_NAME
|
||||||
value: "{{ .Values.ptptracking.ptp4lServiceName }}"
|
value: "{{ .Values.ptptracking.ptp4lServiceName }}"
|
||||||
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
- name: PTP4L_CLOCK_CLASS_LOCKED_LIST
|
||||||
@ -238,6 +279,18 @@ spec:
|
|||||||
- name: LOGGING_LEVEL
|
- name: LOGGING_LEVEL
|
||||||
value: "{{ .Values.ptptracking.logging_level }}"
|
value: "{{ .Values.ptptracking.logging_level }}"
|
||||||
command: ["python3", "/mnt/ptptracking_start.py"]
|
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:
|
securityContext:
|
||||||
privileged: true
|
privileged: true
|
||||||
capabilities:
|
capabilities:
|
||||||
|
@ -63,6 +63,9 @@ notification:
|
|||||||
|
|
||||||
location:
|
location:
|
||||||
log_level: INFO
|
log_level: INFO
|
||||||
|
endpoint:
|
||||||
|
port: 8080
|
||||||
|
liveness: False
|
||||||
image:
|
image:
|
||||||
repository: starlingx/locationservice-base
|
repository: starlingx/locationservice-base
|
||||||
tag: stx.9.0-v2.2.0
|
tag: stx.9.0-v2.2.0
|
||||||
@ -77,6 +80,9 @@ ptptracking:
|
|||||||
phc2sysServiceName: phc2sys-legacy
|
phc2sysServiceName: phc2sys-legacy
|
||||||
phc2sysComSocket: False
|
phc2sysComSocket: False
|
||||||
logging_level: INFO
|
logging_level: INFO
|
||||||
|
endpoint:
|
||||||
|
port: 8081
|
||||||
|
liveness: False
|
||||||
image:
|
image:
|
||||||
repository: starlingx/notificationservice-base
|
repository: starlingx/notificationservice-base
|
||||||
tag: stx.9.0-v2.2.0
|
tag: stx.9.0-v2.2.0
|
||||||
@ -96,6 +102,9 @@ ptptrackingv2:
|
|||||||
phc2sysToleranceThreshold: 1000
|
phc2sysToleranceThreshold: 1000
|
||||||
ts2phcServiceName: True
|
ts2phcServiceName: True
|
||||||
log_level: INFO
|
log_level: INFO
|
||||||
|
endpoint:
|
||||||
|
port: 8082
|
||||||
|
liveness: False
|
||||||
image:
|
image:
|
||||||
repository: starlingx/notificationservice-base-v2
|
repository: starlingx/notificationservice-base-v2
|
||||||
tag: stx.9.0-v2.2.0
|
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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -11,12 +11,13 @@ server = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Pecan Application Configurations
|
# Pecan Application Configurations
|
||||||
|
# Ensure debug = False as per Pecan documentation
|
||||||
app = {
|
app = {
|
||||||
'root': 'apiserver.controllers.root.RootController',
|
'root': 'apiserver.controllers.root.RootController',
|
||||||
'modules': ['apiserver'],
|
'modules': ['apiserver'],
|
||||||
'static_root': '%(confdir)s/public',
|
'static_root': '%(confdir)s/public',
|
||||||
'template_path': '%(confdir)s/apiserver/templates',
|
'template_path': '%(confdir)s/apiserver/templates',
|
||||||
'debug': True,
|
'debug': False,
|
||||||
'errors': {
|
'errors': {
|
||||||
404: '/error/404',
|
404: '/error/404',
|
||||||
'__force_dict__': True
|
'__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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import time
|
|
||||||
import oslo_messaging
|
|
||||||
from oslo_config import cfg
|
|
||||||
|
|
||||||
from locationservicesdk.client.base import BrokerClientBase
|
|
||||||
|
|
||||||
import logging
|
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__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
from locationservicesdk.common.helpers import log_helper
|
|
||||||
log_helper.config_logger(LOG)
|
log_helper.config_logger(LOG)
|
||||||
|
|
||||||
|
|
||||||
@ -30,11 +29,12 @@ class LocationProducer(BrokerClientBase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def QueryLocation(self, ctx, **rpc_kwargs):
|
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
|
return self.location_info
|
||||||
|
|
||||||
def TriggerAnnouncement(self, ctx, **rpc_kwargs):
|
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:
|
if self.handler:
|
||||||
return self.handler.handle(**rpc_kwargs)
|
return self.handler.handle(**rpc_kwargs)
|
||||||
else:
|
else:
|
||||||
@ -52,23 +52,26 @@ class LocationProducer(BrokerClientBase):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def announce_location(self, LocationInfo):
|
def announce_location(self, LocationInfo):
|
||||||
location_topic_all='LocationListener-*'
|
location_topic_all = 'LocationListener-*'
|
||||||
location_topic='LocationListener-{0}'.format(self.node_name)
|
location_topic = 'LocationListener-{0}'.format(self.node_name)
|
||||||
server = None
|
server = None
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
self.cast(location_topic_all, 'NotifyLocation', location_info=LocationInfo)
|
self.cast(location_topic_all, 'NotifyLocation',
|
||||||
LOG.debug("Broadcast location info:{0}@Topic:{1}".format(LocationInfo, location_topic))
|
location_info=LocationInfo)
|
||||||
|
LOG.debug(
|
||||||
|
"Broadcast location info:{0}@Topic:{1}".format(LocationInfo, location_topic))
|
||||||
except Exception as ex:
|
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
|
continue
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
def start_location_listener(self, location_info, handler=None):
|
def start_location_listener(self, location_info, handler=None):
|
||||||
|
|
||||||
topic='LocationQuery'
|
topic = 'LocationQuery'
|
||||||
server="LocationService-{0}".format(self.node_name)
|
server = "LocationService-{0}".format(self.node_name)
|
||||||
endpoints = [LocationProducer.ListenerEndpoint(location_info, handler)]
|
endpoints = [LocationProducer.ListenerEndpoint(location_info, handler)]
|
||||||
|
|
||||||
super(LocationProducer, self).add_listener(
|
super(LocationProducer, self).add_listener(
|
||||||
@ -76,15 +79,13 @@ class LocationProducer(BrokerClientBase):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def stop_location_listener(self):
|
def stop_location_listener(self):
|
||||||
topic='LocationQuery'
|
topic = 'LocationQuery'
|
||||||
server="LocationService-{0}".format(self.node_name)
|
server = "LocationService-{0}".format(self.node_name)
|
||||||
super(LocationProducer, self).remove_listener(
|
super(LocationProducer, self).remove_listener(
|
||||||
topic, server)
|
topic, server)
|
||||||
|
|
||||||
def is_listening(self):
|
def is_listening(self):
|
||||||
topic='LocationQuery'
|
topic = 'LocationQuery'
|
||||||
server="LocationService-{0}".format(self.node_name)
|
server = "LocationService-{0}".format(self.node_name)
|
||||||
return super(LocationProducer, self).is_listening(
|
return super(LocationProducer, self).is_listening(
|
||||||
topic, server)
|
topic, server)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,27 +1,32 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2024 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
import time
|
|
||||||
import oslo_messaging
|
|
||||||
from oslo_config import cfg
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
from locationservicesdk.common.helpers import rpc_helper
|
import oslo_messaging
|
||||||
from locationservicesdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
|
||||||
from locationservicesdk.model.dto.resourcetype import ResourceType
|
|
||||||
|
|
||||||
from locationservicesdk.client.locationproducer import LocationProducer
|
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__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
from locationservicesdk.common.helpers import log_helper
|
|
||||||
log_helper.config_logger(LOG)
|
log_helper.config_logger(LOG)
|
||||||
|
|
||||||
'''Entry point of Default Process Worker'''
|
'''Entry point of Default Process Worker'''
|
||||||
|
|
||||||
|
|
||||||
def ProcessWorkerDefault(event, sqlalchemy_conf_json, registration_endpoint, location_info_json):
|
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()
|
worker.run()
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -42,7 +47,8 @@ class LocationWatcherDefault:
|
|||||||
self.location_info = json.loads(location_info_json)
|
self.location_info = json.loads(location_info_json)
|
||||||
this_node_name = self.location_info['NodeName']
|
this_node_name = self.location_info['NodeName']
|
||||||
|
|
||||||
self.registration_endpoint = RpcEndpointInfo(registration_transport_endpoint)
|
self.registration_endpoint = RpcEndpointInfo(
|
||||||
|
registration_transport_endpoint)
|
||||||
self.LocationProducer = LocationProducer(
|
self.LocationProducer = LocationProducer(
|
||||||
this_node_name,
|
this_node_name,
|
||||||
self.registration_endpoint.TransportEndpoint)
|
self.registration_endpoint.TransportEndpoint)
|
||||||
@ -67,11 +73,13 @@ class LocationWatcherDefault:
|
|||||||
# max timeout: 1 hour
|
# max timeout: 1 hour
|
||||||
if self.event_timeout < float(3600):
|
if self.event_timeout < float(3600):
|
||||||
self.event_timeout = self.event_timeout + self.event_timeout
|
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
|
continue
|
||||||
self.__stop_listener()
|
self.__stop_listener()
|
||||||
|
|
||||||
'''Start listener to answer querying from clients'''
|
'''Start listener to answer querying from clients'''
|
||||||
|
|
||||||
def __start_listener(self):
|
def __start_listener(self):
|
||||||
LOG.debug("start listener to answer location querying")
|
LOG.debug("start listener to answer location querying")
|
||||||
|
|
||||||
@ -88,21 +96,25 @@ class LocationWatcherDefault:
|
|||||||
return
|
return
|
||||||
|
|
||||||
'''announce location'''
|
'''announce location'''
|
||||||
|
|
||||||
def __announce_location(self):
|
def __announce_location(self):
|
||||||
LOG.debug("announce location info to clients")
|
LOG.debug("announce location info to clients")
|
||||||
self.LocationProducer.announce_location(self.location_info)
|
self.LocationProducer.announce_location(self.location_info)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class DaemonControl(object):
|
class DaemonControl(object):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, sqlalchemy_conf_json, registration_transport_endpoint,
|
self, sqlalchemy_conf_json, registration_transport_endpoint,
|
||||||
location_info, process_worker = None, daemon_mode=True):
|
location_info, process_worker=None, daemon_mode=True):
|
||||||
|
|
||||||
self.daemon_mode = daemon_mode
|
self.daemon_mode = daemon_mode
|
||||||
self.event = mp.Event()
|
self.event = mp.Event()
|
||||||
self.registration_endpoint = RpcEndpointInfo(registration_transport_endpoint)
|
self.registration_endpoint = RpcEndpointInfo(
|
||||||
self.registration_transport = rpc_helper.get_transport(self.registration_endpoint)
|
registration_transport_endpoint)
|
||||||
|
self.registration_transport = rpc_helper.get_transport(
|
||||||
|
self.registration_endpoint)
|
||||||
self.location_info = location_info
|
self.location_info = location_info
|
||||||
self.sqlalchemy_conf_json = sqlalchemy_conf_json
|
self.sqlalchemy_conf_json = sqlalchemy_conf_json
|
||||||
|
|
||||||
|
@ -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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -17,12 +17,13 @@ server = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Pecan Application Configurations
|
# Pecan Application Configurations
|
||||||
|
# Ensure debug = False as per Pecan documentation
|
||||||
app = {
|
app = {
|
||||||
'root': 'sidecar.controllers.root.RootController',
|
'root': 'sidecar.controllers.root.RootController',
|
||||||
'modules': ['sidecar'],
|
'modules': ['sidecar'],
|
||||||
'static_root': '%(confdir)s/public',
|
'static_root': '%(confdir)s/public',
|
||||||
'template_path': '%(confdir)s/sidecar/templates',
|
'template_path': '%(confdir)s/sidecar/templates',
|
||||||
'debug': True,
|
'debug': False,
|
||||||
'errors': {
|
'errors': {
|
||||||
404: '/error/404',
|
404: '/error/404',
|
||||||
'__force_dict__': True
|
'__force_dict__': True
|
||||||
@ -60,11 +61,11 @@ logging = {
|
|||||||
|
|
||||||
# Bindings and options to pass to SQLAlchemy's ``create_engine``
|
# Bindings and options to pass to SQLAlchemy's ``create_engine``
|
||||||
sqlalchemy = {
|
sqlalchemy = {
|
||||||
'url' : "sqlite:////{0}/sidecar.db".format(DATASTORE_PATH),
|
'url': "sqlite:////{0}/sidecar.db".format(DATASTORE_PATH),
|
||||||
'echo' : False,
|
'echo': False,
|
||||||
'echo_pool' : False,
|
'echo_pool': False,
|
||||||
'pool_recycle' : 3600,
|
'pool_recycle': 3600,
|
||||||
'encoding' : 'utf-8'
|
'encoding': 'utf-8'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Custom Configurations must be in Python dictionary format::
|
# 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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -10,21 +10,21 @@ import multiprocessing as mp
|
|||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from oslo_utils import uuidutils
|
|
||||||
|
|
||||||
|
from oslo_utils import uuidutils
|
||||||
from trackingfunctionsdk.client.ptpeventproducer import PtpEventProducer
|
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 ptpsync as utils
|
||||||
from trackingfunctionsdk.common.helpers import log_helper
|
|
||||||
from trackingfunctionsdk.common.helpers.gnss_monitor import GnssMonitor
|
from trackingfunctionsdk.common.helpers.gnss_monitor import GnssMonitor
|
||||||
from trackingfunctionsdk.common.helpers.os_clock_monitor import OsClockMonitor
|
from trackingfunctionsdk.common.helpers.os_clock_monitor import OsClockMonitor
|
||||||
from trackingfunctionsdk.common.helpers.ptp_monitor import PtpMonitor
|
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.gnssstate import GnssState
|
||||||
from trackingfunctionsdk.model.dto.osclockstate import OsClockState
|
from trackingfunctionsdk.model.dto.osclockstate import OsClockState
|
||||||
from trackingfunctionsdk.model.dto.overallclockstate import OverallClockState
|
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.resourcetype import ResourceType
|
||||||
from trackingfunctionsdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
from trackingfunctionsdk.model.dto.rpc_endpoint import RpcEndpointInfo
|
||||||
|
from trackingfunctionsdk.services.health import HealthServer
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
log_helper.config_logger(LOG)
|
log_helper.config_logger(LOG)
|
||||||
@ -379,6 +379,10 @@ class PtpWatcherDefault:
|
|||||||
# start location listener
|
# start location listener
|
||||||
self.__start_listener()
|
self.__start_listener()
|
||||||
|
|
||||||
|
# Start the server for k8s httpGet health checks
|
||||||
|
notificationservice_health = HealthServer()
|
||||||
|
notificationservice_health.run()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# announce the location
|
# announce the location
|
||||||
forced = self.forced_publishing
|
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
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
import multiprocessing as mp
|
||||||
|
import os
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
from oslo_config import cfg
|
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.client.ptpeventproducer import PtpEventProducer
|
||||||
|
|
||||||
from trackingfunctionsdk.common.helpers import ptpsync as ptpsync
|
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__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
from trackingfunctionsdk.common.helpers import log_helper
|
from trackingfunctionsdk.common.helpers import log_helper
|
||||||
|
|
||||||
log_helper.config_logger(LOG)
|
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')
|
||||||
@ -115,6 +113,11 @@ class PtpWatcherDefault:
|
|||||||
def run(self):
|
def run(self):
|
||||||
# start location listener
|
# start location listener
|
||||||
self.__start_listener()
|
self.__start_listener()
|
||||||
|
|
||||||
|
# Start the server for k8s httpGet health checks
|
||||||
|
notificationservice_health = HealthServer()
|
||||||
|
notificationservice_health.run()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# annouce the location
|
# annouce the location
|
||||||
forced = self.forced_publishing
|
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