blob: c5cb30077556514497e9f4efed4cc614eaa6470b [file] [log] [blame]
Zsolt Harasztib71c2a02016-09-12 13:12:07 -07001#!/usr/bin/env python
2#
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08003# Copyright 2017 the original author or authors.
Zsolt Harasztib71c2a02016-09-12 13:12:07 -07004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
Zsolt Harasztiadbb88d2016-09-12 21:24:57 -070018"""Virtual OLT Hardware Abstraction main entry point"""
Zsolt Harasztib71c2a02016-09-12 13:12:07 -070019
20import argparse
Zsolt Harasztib5d72f12017-01-15 20:44:02 -080021import arrow
Zsolt Harasztid7c7c482016-09-13 00:45:38 -070022import os
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070023import time
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070024
Zsolt Harasztid7c7c482016-09-13 00:45:38 -070025import yaml
Zsolt Haraszti89a27302016-12-08 16:53:06 -080026from simplejson import dumps
Zsolt Harasztie060a7d2016-09-16 11:08:24 -070027from twisted.internet.defer import inlineCallbacks
Zsolt Harasztib5d72f12017-01-15 20:44:02 -080028from twisted.internet.task import LoopingCall
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -080029from zope.interface import implementer
Zsolt Harasztiadbb88d2016-09-12 21:24:57 -070030
Zsolt Haraszti3bfff662016-12-14 23:41:49 -080031from common.event_bus import EventBusClient
32from common.manhole import Manhole
Zsolt Harasztid70cd4d2016-11-03 23:23:36 -070033from common.structlog_setup import setup_logging
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070034from common.utils.dockerhelpers import get_my_containers_name
35from common.utils.nethelpers import get_my_primary_interface, \
Khen Nursimulu441dedd2016-10-05 14:44:26 -070036 get_my_primary_local_ipv4
Zsolt Haraszti7eeb2b32016-11-06 14:04:55 -080037from voltha.adapters.loader import AdapterLoader
Zsolt Harasztid70cd4d2016-11-03 23:23:36 -070038from voltha.coordinator import Coordinator
Zsolt Harasztidafefe12016-11-14 21:29:58 -080039from voltha.core.core import VolthaCore
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080040from voltha.core.config.config_backend import load_backend
Zsolt Haraszti99509d32016-12-10 16:41:45 -080041from voltha.northbound.diagnostics import Diagnostics
Zsolt Harasztieb435072016-09-23 17:10:49 -070042from voltha.northbound.grpc.grpc_server import VolthaGrpcServer
khenb95fe9a2016-10-05 11:15:25 -070043from voltha.northbound.kafka.kafka_proxy import KafkaProxy, get_kafka_proxy
Zsolt Harasztid70cd4d2016-11-03 23:23:36 -070044from voltha.northbound.rest.health_check import init_rest_service
Zsolt Haraszti66862032016-11-28 14:28:39 -080045from voltha.protos.common_pb2 import LogLevel
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -080046from voltha.registry import registry, IComponent
Zsolt Haraszti89a27302016-12-08 16:53:06 -080047from common.frameio.frameio import FrameIOManager
48
Zsolt Harasztidafefe12016-11-14 21:29:58 -080049VERSION = '0.9.0'
khenb95fe9a2016-10-05 11:15:25 -070050
khenaidoo032d3302017-06-09 14:50:04 -040051
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070052defs = dict(
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070053 config=os.environ.get('CONFIG', './voltha.yml'),
Zsolt Haraszti553826c2016-09-27 10:24:27 -070054 consul=os.environ.get('CONSUL', 'localhost:8500'),
khenaidoo26a8c012017-07-07 18:25:47 -040055 inter_core_subnet=os.environ.get('INTER_CORE_SUBNET', None),
56 pon_subnet=os.environ.get('PON_SUBNET', None),
57 external_host_address=os.environ.get('EXTERNAL_HOST_ADDRESS',
58 get_my_primary_local_ipv4()),
Zsolt Harasztide22bbc2016-09-14 15:27:33 -070059 fluentd=os.environ.get('FLUENTD', None),
Zsolt Haraszti553826c2016-09-27 10:24:27 -070060 grpc_port=os.environ.get('GRPC_PORT', 50055),
61 instance_id=os.environ.get('INSTANCE_ID', os.environ.get('HOSTNAME', '1')),
khenaidoo26a8c012017-07-07 18:25:47 -040062 internal_host_address=os.environ.get('INTERNAL_HOST_ADDRESS',
63 get_my_primary_local_ipv4()),
Zsolt Haraszti553826c2016-09-27 10:24:27 -070064 interface=os.environ.get('INTERFACE', get_my_primary_interface()),
Zsolt Harasztide22bbc2016-09-14 15:27:33 -070065 rest_port=os.environ.get('REST_PORT', 8880),
khenb95fe9a2016-10-05 11:15:25 -070066 kafka=os.environ.get('KAFKA', 'localhost:9092'),
Zsolt Haraszti3bfff662016-12-14 23:41:49 -080067 manhole_port=os.environ.get('MANHOLE_PORT', 12222),
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080068 backend=os.environ.get('BACKEND', 'none'),
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070069)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -070070
71
72def parse_args():
Zsolt Harasztib71c2a02016-09-12 13:12:07 -070073 parser = argparse.ArgumentParser()
74
Zsolt Haraszti109db832016-09-16 16:32:36 -070075 _help = ('Path to voltha.yml config file (default: %s). '
76 'If relative, it is relative to main.py of voltha.'
77 % defs['config'])
78 parser.add_argument('-c', '--config',
79 dest='config',
80 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070081 default=defs['config'],
Zsolt Haraszti109db832016-09-16 16:32:36 -070082 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070083
Zsolt Haraszti109db832016-09-16 16:32:36 -070084 _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
85 parser.add_argument(
86 '-C', '--consul', dest='consul', action='store',
87 default=defs['consul'],
88 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070089
khenaidoo26a8c012017-07-07 18:25:47 -040090
91 _help = ('<inter_core_subnet> is the subnet connecting all the voltha '
92 'instances in a cluster (default: %s)' % defs['inter_core_subnet'])
93 parser.add_argument('-V', '--inter-core-subnet',
94 dest='inter_core_subnet',
95 action='store',
96 default=defs['inter_core_subnet'],
97 help=_help)
98
99 _help = ('<pon subnet> is the subnet connecting the voltha instances'
100 'with the PON network (default: %s)' % defs['pon_subnet'])
101 parser.add_argument('-P', '--pon-subnet',
102 dest='pon_subnet',
103 action='store',
104 default=defs['pon_subnet'],
105 help=_help)
106
Zsolt Haraszti109db832016-09-16 16:32:36 -0700107 _help = ('<hostname> or <ip> at which Voltha is reachable from outside '
108 'the cluster (default: %s)' % defs['external_host_address'])
109 parser.add_argument('-E', '--external-host-address',
110 dest='external_host_address',
111 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700112 default=defs['external_host_address'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700113 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700114
Zsolt Haraszti553826c2016-09-27 10:24:27 -0700115 _help = ('port number of the GRPC service exposed by voltha (default: %s)'
116 % defs['grpc_port'])
117 parser.add_argument('-g', '--grpc-port',
118 dest='grpc_port',
119 action='store',
120 default=defs['grpc_port'],
121 help=_help)
Khen Nursimulu441dedd2016-10-05 14:44:26 -0700122
Zsolt Haraszti109db832016-09-16 16:32:36 -0700123 _help = ('<hostname>:<port> to fluentd server (default: %s). (If not '
124 'specified (None), the address from the config file is used'
125 % defs['fluentd'])
126 parser.add_argument('-F', '--fluentd',
127 dest='fluentd',
128 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700129 default=defs['fluentd'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700130 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700131
Zsolt Haraszti109db832016-09-16 16:32:36 -0700132 _help = ('<hostname> or <ip> at which Voltha is reachable from inside the'
133 'cluster (default: %s)' % defs['internal_host_address'])
134 parser.add_argument('-H', '--internal-host-address',
135 dest='internal_host_address',
136 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700137 default=defs['internal_host_address'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700138 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700139
Zsolt Haraszti109db832016-09-16 16:32:36 -0700140 _help = ('unique string id of this voltha instance (default: %s)'
Zsolt Haraszti86be6f12016-09-27 09:56:49 -0700141 % defs['instance_id'])
Zsolt Haraszti109db832016-09-16 16:32:36 -0700142 parser.add_argument('-i', '--instance-id',
143 dest='instance_id',
144 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700145 default=defs['instance_id'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700146 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700147
khenaidooccc42252017-07-06 23:00:49 -0400148 _help = 'ETH interface to recieve (default: %s)' % defs['interface']
Zsolt Haraszti109db832016-09-16 16:32:36 -0700149 parser.add_argument('-I', '--interface',
150 dest='interface',
151 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700152 default=defs['interface'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700153 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700154
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800155 _help = 'open ssh manhole at given port'
156 parser.add_argument('-m', '--manhole-port',
157 dest='manhole_port',
158 action='store',
159 type=int,
160 default=None,
161 help=_help)
162
Zsolt Haraszti109db832016-09-16 16:32:36 -0700163 _help = 'omit startup banner log lines'
164 parser.add_argument('-n', '--no-banner',
165 dest='no_banner',
166 action='store_true',
167 default=False,
168 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700169
Zsolt Haraszti109db832016-09-16 16:32:36 -0700170 _help = 'do not emit periodic heartbeat log messages'
171 parser.add_argument('-N', '--no-heartbeat',
172 dest='no_heartbeat',
173 action='store_true',
174 default=False,
175 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700176
Zsolt Haraszti109db832016-09-16 16:32:36 -0700177 _help = ('port number for the rest service (default: %d)'
178 % defs['rest_port'])
179 parser.add_argument('-R', '--rest-port',
180 dest='rest_port',
181 action='store',
182 type=int,
Zsolt Harasztide22bbc2016-09-14 15:27:33 -0700183 default=defs['rest_port'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700184 help=_help)
Zsolt Harasztide22bbc2016-09-14 15:27:33 -0700185
Zsolt Haraszti109db832016-09-16 16:32:36 -0700186 _help = "suppress debug and info logs"
187 parser.add_argument('-q', '--quiet',
188 dest='quiet',
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700189 action='count',
Zsolt Haraszti109db832016-09-16 16:32:36 -0700190 help=_help)
Zsolt Harasztiadbb88d2016-09-12 21:24:57 -0700191
Zsolt Haraszti109db832016-09-16 16:32:36 -0700192 _help = 'enable verbose logging'
193 parser.add_argument('-v', '--verbose',
194 dest='verbose',
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700195 action='count',
Zsolt Haraszti109db832016-09-16 16:32:36 -0700196 help=_help)
Zsolt Harasztiadbb88d2016-09-12 21:24:57 -0700197
Zsolt Haraszti109db832016-09-16 16:32:36 -0700198 _help = ('use docker container name as voltha instance id'
199 ' (overrides -i/--instance-id option)')
200 parser.add_argument('--instance-id-is-container-name',
201 dest='instance_id_is_container_name',
202 action='store_true',
203 default=False,
204 help=_help)
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700205
khenb95fe9a2016-10-05 11:15:25 -0700206 _help = ('<hostname>:<port> of the kafka broker (default: %s). (If not '
207 'specified (None), the address from the config file is used'
208 % defs['kafka'])
209 parser.add_argument('-K', '--kafka',
210 dest='kafka',
211 action='store',
212 default=defs['kafka'],
213 help=_help)
214
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -0800215 _help = 'backend to use for config persitence'
216 parser.add_argument('-b', '--backend',
217 default=defs['backend'],
218 choices=['none', 'consul'],
219 help=_help)
220
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700221 args = parser.parse_args()
222
223 # post-processing
224
225 if args.instance_id_is_container_name:
226 args.instance_id = get_my_containers_name()
227
khenaidoo26a8c012017-07-07 18:25:47 -0400228 """
229 The container external, internal IP and PON interface needs to be
230 set based on the subnet data. At this time the internal IP is not used.
231 The external IP is used for inter-core communications. If the subnets are
232 set then they take precedence over the other relevant arguments (
233 external and internal host as well as interface
234 """
235 if args.inter_core_subnet:
236 m_ip = get_my_primary_local_ipv4(inter_core_subnet=args.inter_core_subnet)
khenaidooccc42252017-07-06 23:00:49 -0400237 args.external_host_address = m_ip
khenaidooccc42252017-07-06 23:00:49 -0400238 args.internal_host_address = m_ip
239
khenaidoo26a8c012017-07-07 18:25:47 -0400240 if args.pon_subnet:
241 args.interface = get_my_primary_interface(args.pon_subnet)
242
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700243 return args
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700244
245
Zsolt Harasztid7c7c482016-09-13 00:45:38 -0700246def load_config(args):
247 path = args.config
248 if path.startswith('.'):
249 dir = os.path.dirname(os.path.abspath(__file__))
250 path = os.path.join(dir, path)
251 path = os.path.abspath(path)
252 with open(path) as fd:
253 config = yaml.load(fd)
254 return config
255
256
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700257def print_banner(log):
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700258 log.info(' _ ______ __ ________ _____ ')
259 log.info('| | / / __ \/ / /_ __/ / / / |')
260 log.info('| | / / / / / / / / / /_/ / /| |')
261 log.info('| |/ / /_/ / /___/ / / __ / ___ |')
262 log.info('|___/\____/_____/_/ /_/ /_/_/ |_|')
Zsolt Haraszti59b7a882016-09-12 14:42:59 -0700263 log.info('(to stop: press Ctrl-C)')
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700264
265
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800266@implementer(IComponent)
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700267class Main(object):
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800268
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700269 def __init__(self):
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700270
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700271 self.args = args = parse_args()
272 self.config = load_config(args)
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700273
274 verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
Zsolt Haraszti109db832016-09-16 16:32:36 -0700275 self.log = setup_logging(self.config.get('logging', {}),
276 args.instance_id,
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700277 verbosity_adjust=verbosity_adjust,
Zsolt Haraszti109db832016-09-16 16:32:36 -0700278 fluentd=args.fluentd)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700279
Rouzbahan Rashidi-Tabrizi1c3eba82016-10-27 21:47:18 -0400280 # configurable variables from voltha.yml file
281 #self.configurable_vars = self.config.get('Constants', {})
282
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700283 if not args.no_banner:
284 print_banner(self.log)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700285
khenaidoo032d3302017-06-09 14:50:04 -0400286 # Create a unique instnce id using the passed-in instanceid and
287 # UTC timestamp
288 current_time = arrow.utcnow().timestamp
289 self.instance_id = self.args.instance_id + '_' + str(current_time)
290
291 # Every voltha instance is given a core_storage id where the
292 # instance data is stored
293 self.core_store_id = None
294
khenb95fe9a2016-10-05 11:15:25 -0700295 self.startup_components()
296
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700297 if not args.no_heartbeat:
298 self.start_heartbeat()
khenaidoo032d3302017-06-09 14:50:04 -0400299 self.start_kafka_heartbeat(self.instance_id)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700300
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800301 self.manhole = None
302
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700303 def start(self):
304 self.start_reactor() # will not return except Keyboard interrupt
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700305
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800306 def stop(self):
307 pass
308
309 def get_args(self):
310 """Allow access to command line args"""
311 return self.args
312
313 def get_config(self):
314 """Allow access to content of config file"""
315 return self.config
316
Zsolt Haraszti7eeb2b32016-11-06 14:04:55 -0800317 @inlineCallbacks
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700318 def startup_components(self):
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800319 try:
khenaidooccc42252017-07-06 23:00:49 -0400320 self.log.info('starting-internal-components',
321 internal_host=self.args.internal_host_address,
khenaidoo26a8c012017-07-07 18:25:47 -0400322 external_host=self.args.external_host_address,
323 interface=self.args.interface,
324 consul=self.args.consul)
Zsolt Harasztidafefe12016-11-14 21:29:58 -0800325
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800326 registry.register('main', self)
327
Zsolt Haraszti66862032016-11-28 14:28:39 -0800328 yield registry.register(
329 'coordinator',
330 Coordinator(
331 internal_host_address=self.args.internal_host_address,
332 external_host_address=self.args.external_host_address,
333 rest_port=self.args.rest_port,
khenaidoo032d3302017-06-09 14:50:04 -0400334 instance_id=self.instance_id,
Zsolt Haraszti66862032016-11-28 14:28:39 -0800335 config=self.config,
336 consul=self.args.consul)
337 ).start()
Zsolt Harasztidafefe12016-11-14 21:29:58 -0800338
khenaidoo032d3302017-06-09 14:50:04 -0400339 self.log.info('waiting-for-config-assignment')
340
341 # Wait until we get a config id before we proceed
342 self.core_store_id, store_prefix = \
343 yield registry('coordinator').get_core_store_id_and_prefix()
344
345 self.log.info('store-id', core_store_id=self.core_store_id)
Zsolt Harasztieb435072016-09-23 17:10:49 -0700346
Zsolt Haraszti66862032016-11-28 14:28:39 -0800347 yield registry.register(
348 'grpc_server',
349 VolthaGrpcServer(self.args.grpc_port)
350 ).start()
Zsolt Harasztieb435072016-09-23 17:10:49 -0700351
Zsolt Haraszti66862032016-11-28 14:28:39 -0800352 yield registry.register(
khenaidoo032d3302017-06-09 14:50:04 -0400353 'core',
354 VolthaCore(
355 instance_id=self.instance_id,
356 core_store_id = self.core_store_id,
khenaidoo08d48d22017-06-29 19:42:49 -0400357 grpc_port=self.args.grpc_port,
khenaidoo032d3302017-06-09 14:50:04 -0400358 version=VERSION,
359 log_level=LogLevel.INFO
360 )
361 ).start(config_backend=load_backend(store_id=self.core_store_id,
362 store_prefix=store_prefix,
363 args=self.args))
364
365 init_rest_service(self.args.rest_port)
366
367 yield registry.register(
Zsolt Haraszti66862032016-11-28 14:28:39 -0800368 'kafka_proxy',
Zsolt Haraszti99509d32016-12-10 16:41:45 -0800369 KafkaProxy(
370 self.args.consul,
371 self.args.kafka,
372 config=self.config.get('kafka-proxy', {})
373 )
Zsolt Haraszti66862032016-11-28 14:28:39 -0800374 ).start()
375
376 yield registry.register(
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800377 'frameio',
378 FrameIOManager()
379 ).start()
380
381 yield registry.register(
Zsolt Haraszti66862032016-11-28 14:28:39 -0800382 'adapter_loader',
383 AdapterLoader(config=self.config.get('adapter_loader', {}))
384 ).start()
khenb95fe9a2016-10-05 11:15:25 -0700385
Zsolt Haraszti99509d32016-12-10 16:41:45 -0800386 yield registry.register(
387 'diag',
388 Diagnostics(config=self.config.get('diagnostics', {}))
389 ).start()
390
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800391 if self.args.manhole_port is not None:
392 self.start_manhole(self.args.manhole_port)
393
khenaidoo032d3302017-06-09 14:50:04 -0400394 # Now that all components are loaded, in the scenario where this
395 # voltha instance is picking up an existing set of data (from a
396 # voltha instance that dies/stopped) then we need to setup this
397 # instance from where the previous one left
398
399 yield registry('core').reconcile_data()
400
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800401 self.log.info('started-internal-services')
402
403 except Exception as e:
khenaidoo032d3302017-06-09 14:50:04 -0400404 self.log.exception('Failure-to-start-all-components', e=e)
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800405
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800406 def start_manhole(self, port):
407 self.manhole = Manhole(
408 port,
409 pws=dict(admin='adminpw'),
410 eventbus = EventBusClient(),
411 **registry.components
412 )
413
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700414 @inlineCallbacks
415 def shutdown_components(self):
416 """Execute before the reactor is shut down"""
417 self.log.info('exiting-on-keyboard-interrupt')
Zsolt Harasztidafefe12016-11-14 21:29:58 -0800418 for component in reversed(registry.iterate()):
419 yield component.stop()
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700420
Zsolt Haraszti3300f742017-01-09 01:14:20 -0800421 import threading
422 self.log.info('THREADS:')
423 main_thread = threading.current_thread()
424 for t in threading.enumerate():
425 if t is main_thread:
426 continue
427 if not t.isDaemon():
428 continue
429 self.log.info('joining thread {} {}'.format(
430 t.getName(), "daemon" if t.isDaemon() else "not-daemon"))
431 t.join()
432
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700433 def start_reactor(self):
434 from twisted.internet import reactor
Zsolt Haraszti109db832016-09-16 16:32:36 -0700435 reactor.callWhenRunning(
436 lambda: self.log.info('twisted-reactor-started'))
437 reactor.addSystemEventTrigger('before', 'shutdown',
438 self.shutdown_components)
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700439 reactor.run()
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700440
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700441 def start_heartbeat(self):
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700442
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700443 t0 = time.time()
444 t0s = time.ctime(t0)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700445
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700446 def heartbeat():
447 self.log.debug(status='up', since=t0s, uptime=time.time() - t0)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700448
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700449 lc = LoopingCall(heartbeat)
450 lc.start(10)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700451
khenb95fe9a2016-10-05 11:15:25 -0700452 # Temporary function to send a heartbeat message to the external kafka
453 # broker
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800454 def start_kafka_heartbeat(self, instance_id):
khenb95fe9a2016-10-05 11:15:25 -0700455 # For heartbeat we will send a message to a specific "voltha-heartbeat"
456 # topic. The message is a protocol buf
457 # message
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800458 message = dict(
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800459 type='heartbeat',
460 voltha_instance=instance_id,
461 ip=get_my_primary_local_ipv4()
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800462 )
463 topic = "voltha.heartbeat"
khenb95fe9a2016-10-05 11:15:25 -0700464
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800465 def send_msg():
Rouzbahan Rashidi-Tabrizi380dcb32017-03-23 18:01:02 -0400466 try:
467 kafka_proxy = get_kafka_proxy()
468 if kafka_proxy and not kafka_proxy.is_faulty():
469 self.log.debug('kafka-proxy-available')
470 message['ts'] = arrow.utcnow().timestamp
471 self.log.debug('start-kafka-heartbeat')
472 kafka_proxy.send_message(topic, dumps(message))
473 else:
474 self.log.error('kafka-proxy-unavailable')
475 except Exception, e:
476 self.log.exception('failed-sending-message-heartbeat', e=e)
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800477
Rouzbahan Rashidi-Tabrizi380dcb32017-03-23 18:01:02 -0400478 try:
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800479 lc = LoopingCall(send_msg)
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800480 lc.start(10)
Rouzbahan Rashidi-Tabrizi380dcb32017-03-23 18:01:02 -0400481 except Exception, e:
482 self.log.exception('failed-kafka-heartbeat', e=e)
Khen Nursimulu441dedd2016-10-05 14:44:26 -0700483
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800484
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700485if __name__ == '__main__':
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700486 Main().start()