blob: 36c60136e6fb3afc5f490f65ed32e09e6e634cf6 [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
khenaidoocbe30832017-08-25 10:43:27 -040033from common.structlog_setup import setup_logging, update_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
Richard Jankowski8b277c22017-12-19 09:49:27 -050039from voltha.coordinator_etcd import CoordinatorEtcd
Zsolt Harasztidafefe12016-11-14 21:29:58 -080040from voltha.core.core import VolthaCore
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080041from voltha.core.config.config_backend import load_backend
Zsolt Haraszti99509d32016-12-10 16:41:45 -080042from voltha.northbound.diagnostics import Diagnostics
Zsolt Harasztieb435072016-09-23 17:10:49 -070043from voltha.northbound.grpc.grpc_server import VolthaGrpcServer
khenb95fe9a2016-10-05 11:15:25 -070044from voltha.northbound.kafka.kafka_proxy import KafkaProxy, get_kafka_proxy
Zsolt Harasztid70cd4d2016-11-03 23:23:36 -070045from voltha.northbound.rest.health_check import init_rest_service
Zsolt Haraszti66862032016-11-28 14:28:39 -080046from voltha.protos.common_pb2 import LogLevel
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -080047from voltha.registry import registry, IComponent
Zsolt Haraszti89a27302016-12-08 16:53:06 -080048from common.frameio.frameio import FrameIOManager
Jonathan Hartda93ac62018-05-01 11:25:29 -070049from packaging.version import Version
khenb95fe9a2016-10-05 11:15:25 -070050
khenaidoo032d3302017-06-09 14:50:04 -040051
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070052defs = dict(
Jonathan Hartda93ac62018-05-01 11:25:29 -070053 version_file='./VERSION',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070054 config=os.environ.get('CONFIG', './voltha.yml'),
Richard Jankowski4ea26632018-05-14 17:45:38 -040055 container_name_regex=os.environ.get('CORE_NUMBER_EXTRACTOR', '^.*\.([0-9]+)\..*$'),
Zsolt Haraszti553826c2016-09-27 10:24:27 -070056 consul=os.environ.get('CONSUL', 'localhost:8500'),
Richard Jankowski8b277c22017-12-19 09:49:27 -050057 etcd=os.environ.get('ETCD', 'localhost:2379'),
khenaidoo26a8c012017-07-07 18:25:47 -040058 inter_core_subnet=os.environ.get('INTER_CORE_SUBNET', None),
59 pon_subnet=os.environ.get('PON_SUBNET', None),
60 external_host_address=os.environ.get('EXTERNAL_HOST_ADDRESS',
61 get_my_primary_local_ipv4()),
Zsolt Haraszti553826c2016-09-27 10:24:27 -070062 grpc_port=os.environ.get('GRPC_PORT', 50055),
63 instance_id=os.environ.get('INSTANCE_ID', os.environ.get('HOSTNAME', '1')),
khenaidoo26a8c012017-07-07 18:25:47 -040064 internal_host_address=os.environ.get('INTERNAL_HOST_ADDRESS',
65 get_my_primary_local_ipv4()),
Zsolt Haraszti553826c2016-09-27 10:24:27 -070066 interface=os.environ.get('INTERFACE', get_my_primary_interface()),
Zsolt Harasztide22bbc2016-09-14 15:27:33 -070067 rest_port=os.environ.get('REST_PORT', 8880),
khenb95fe9a2016-10-05 11:15:25 -070068 kafka=os.environ.get('KAFKA', 'localhost:9092'),
Zsolt Haraszti3bfff662016-12-14 23:41:49 -080069 manhole_port=os.environ.get('MANHOLE_PORT', 12222),
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080070 backend=os.environ.get('BACKEND', 'none'),
Stephane Barbarie35595062018-02-08 08:34:39 -050071 ponsim_comm=os.environ.get('PONSIM_COMM', 'frameio')
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070072)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -070073
74
75def parse_args():
Zsolt Harasztib71c2a02016-09-12 13:12:07 -070076 parser = argparse.ArgumentParser()
77
Zsolt Haraszti109db832016-09-16 16:32:36 -070078 _help = ('Path to voltha.yml config file (default: %s). '
79 'If relative, it is relative to main.py of voltha.'
80 % defs['config'])
81 parser.add_argument('-c', '--config',
82 dest='config',
83 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070084 default=defs['config'],
Zsolt Haraszti109db832016-09-16 16:32:36 -070085 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070086
Richard Jankowski4ea26632018-05-14 17:45:38 -040087 _help = 'Regular expression for extracting core number from container name (default: %s)' % defs['container_name_regex']
88 parser.add_argument(
89 '-X', '--core-number-extractor', dest='container_name_regex', action='store',
90 default=defs['container_name_regex'],
91 help=_help)
92
Zsolt Haraszti109db832016-09-16 16:32:36 -070093 _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
94 parser.add_argument(
95 '-C', '--consul', dest='consul', action='store',
96 default=defs['consul'],
97 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -070098
Richard Jankowski8b277c22017-12-19 09:49:27 -050099 _help = '<hostname>:<port> to etcd server (default: %s)' % defs['etcd']
100 parser.add_argument(
101 '-e', '--etcd', dest='etcd', action='store',
102 default=defs['etcd'],
103 help=_help)
khenaidoo26a8c012017-07-07 18:25:47 -0400104
105 _help = ('<inter_core_subnet> is the subnet connecting all the voltha '
106 'instances in a cluster (default: %s)' % defs['inter_core_subnet'])
107 parser.add_argument('-V', '--inter-core-subnet',
108 dest='inter_core_subnet',
109 action='store',
110 default=defs['inter_core_subnet'],
111 help=_help)
112
113 _help = ('<pon subnet> is the subnet connecting the voltha instances'
114 'with the PON network (default: %s)' % defs['pon_subnet'])
115 parser.add_argument('-P', '--pon-subnet',
116 dest='pon_subnet',
117 action='store',
118 default=defs['pon_subnet'],
119 help=_help)
120
Zsolt Haraszti109db832016-09-16 16:32:36 -0700121 _help = ('<hostname> or <ip> at which Voltha is reachable from outside '
122 'the cluster (default: %s)' % defs['external_host_address'])
123 parser.add_argument('-E', '--external-host-address',
124 dest='external_host_address',
125 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700126 default=defs['external_host_address'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700127 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700128
Zsolt Haraszti553826c2016-09-27 10:24:27 -0700129 _help = ('port number of the GRPC service exposed by voltha (default: %s)'
130 % defs['grpc_port'])
131 parser.add_argument('-g', '--grpc-port',
132 dest='grpc_port',
133 action='store',
134 default=defs['grpc_port'],
135 help=_help)
Khen Nursimulu441dedd2016-10-05 14:44:26 -0700136
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700137
Zsolt Haraszti109db832016-09-16 16:32:36 -0700138 _help = ('<hostname> or <ip> at which Voltha is reachable from inside the'
139 'cluster (default: %s)' % defs['internal_host_address'])
140 parser.add_argument('-H', '--internal-host-address',
141 dest='internal_host_address',
142 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700143 default=defs['internal_host_address'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700144 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700145
Zsolt Haraszti109db832016-09-16 16:32:36 -0700146 _help = ('unique string id of this voltha instance (default: %s)'
Zsolt Haraszti86be6f12016-09-27 09:56:49 -0700147 % defs['instance_id'])
Zsolt Haraszti109db832016-09-16 16:32:36 -0700148 parser.add_argument('-i', '--instance-id',
149 dest='instance_id',
150 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700151 default=defs['instance_id'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700152 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700153
khenaidooccc42252017-07-06 23:00:49 -0400154 _help = 'ETH interface to recieve (default: %s)' % defs['interface']
Zsolt Haraszti109db832016-09-16 16:32:36 -0700155 parser.add_argument('-I', '--interface',
156 dest='interface',
157 action='store',
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700158 default=defs['interface'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700159 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700160
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800161 _help = 'open ssh manhole at given port'
162 parser.add_argument('-m', '--manhole-port',
163 dest='manhole_port',
164 action='store',
165 type=int,
166 default=None,
167 help=_help)
168
Zsolt Haraszti109db832016-09-16 16:32:36 -0700169 _help = 'omit startup banner log lines'
170 parser.add_argument('-n', '--no-banner',
171 dest='no_banner',
172 action='store_true',
173 default=False,
174 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700175
Zsolt Haraszti109db832016-09-16 16:32:36 -0700176 _help = 'do not emit periodic heartbeat log messages'
177 parser.add_argument('-N', '--no-heartbeat',
178 dest='no_heartbeat',
179 action='store_true',
180 default=False,
181 help=_help)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700182
Zsolt Haraszti109db832016-09-16 16:32:36 -0700183 _help = ('port number for the rest service (default: %d)'
184 % defs['rest_port'])
185 parser.add_argument('-R', '--rest-port',
186 dest='rest_port',
187 action='store',
188 type=int,
Zsolt Harasztide22bbc2016-09-14 15:27:33 -0700189 default=defs['rest_port'],
Zsolt Haraszti109db832016-09-16 16:32:36 -0700190 help=_help)
Zsolt Harasztide22bbc2016-09-14 15:27:33 -0700191
Zsolt Haraszti109db832016-09-16 16:32:36 -0700192 _help = "suppress debug and info logs"
193 parser.add_argument('-q', '--quiet',
194 dest='quiet',
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 = 'enable verbose logging'
199 parser.add_argument('-v', '--verbose',
200 dest='verbose',
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700201 action='count',
Zsolt Haraszti109db832016-09-16 16:32:36 -0700202 help=_help)
Zsolt Harasztiadbb88d2016-09-12 21:24:57 -0700203
Zsolt Haraszti109db832016-09-16 16:32:36 -0700204 _help = ('use docker container name as voltha instance id'
205 ' (overrides -i/--instance-id option)')
206 parser.add_argument('--instance-id-is-container-name',
207 dest='instance_id_is_container_name',
208 action='store_true',
209 default=False,
210 help=_help)
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700211
khenb95fe9a2016-10-05 11:15:25 -0700212 _help = ('<hostname>:<port> of the kafka broker (default: %s). (If not '
213 'specified (None), the address from the config file is used'
214 % defs['kafka'])
215 parser.add_argument('-K', '--kafka',
216 dest='kafka',
217 action='store',
218 default=defs['kafka'],
219 help=_help)
220
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -0800221 _help = 'backend to use for config persitence'
222 parser.add_argument('-b', '--backend',
223 default=defs['backend'],
Richard Jankowski8b277c22017-12-19 09:49:27 -0500224 choices=['none', 'consul', 'etcd'],
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -0800225 help=_help)
226
Stephane Barbarie35595062018-02-08 08:34:39 -0500227 _help = "Communication mechanism to use with PON simulator"
228 parser.add_argument('-S', '--ponsim-comm',
229 dest='ponsim_comm',
230 default=defs['ponsim_comm'],
231 choices=['frameio', 'grpc'],
232 help=_help)
233
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700234 args = parser.parse_args()
235
236 # post-processing
237
238 if args.instance_id_is_container_name:
239 args.instance_id = get_my_containers_name()
240
Jonathan Hartda93ac62018-05-01 11:25:29 -0700241 """
242 The container external, internal IP and PON interface needs to be
243 set based on the subnet data. At this time the internal IP is not used.
khenaidoo26a8c012017-07-07 18:25:47 -0400244 The external IP is used for inter-core communications. If the subnets are
245 set then they take precedence over the other relevant arguments (
246 external and internal host as well as interface
247 """
248 if args.inter_core_subnet:
249 m_ip = get_my_primary_local_ipv4(inter_core_subnet=args.inter_core_subnet)
khenaidooccc42252017-07-06 23:00:49 -0400250 args.external_host_address = m_ip
khenaidooccc42252017-07-06 23:00:49 -0400251 args.internal_host_address = m_ip
252
khenaidoo26a8c012017-07-07 18:25:47 -0400253 if args.pon_subnet:
254 args.interface = get_my_primary_interface(args.pon_subnet)
255
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700256 return args
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700257
258
Zsolt Harasztid7c7c482016-09-13 00:45:38 -0700259def load_config(args):
260 path = args.config
261 if path.startswith('.'):
262 dir = os.path.dirname(os.path.abspath(__file__))
263 path = os.path.join(dir, path)
264 path = os.path.abspath(path)
265 with open(path) as fd:
266 config = yaml.load(fd)
267 return config
268
269
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700270def print_banner(log):
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700271 log.info(' _ ______ __ ________ _____ ')
272 log.info('| | / / __ \/ / /_ __/ / / / |')
273 log.info('| | / / / / / / / / / /_/ / /| |')
274 log.info('| |/ / /_/ / /___/ / / __ / ___ |')
275 log.info('|___/\____/_____/_/ /_/ /_/_/ |_|')
Zsolt Haraszti59b7a882016-09-12 14:42:59 -0700276 log.info('(to stop: press Ctrl-C)')
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700277
278
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800279@implementer(IComponent)
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700280class Main(object):
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800281
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700282 def __init__(self):
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700283
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700284 self.args = args = parse_args()
285 self.config = load_config(args)
Zsolt Haraszti1420def2016-09-18 00:07:31 -0700286
287 verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
Zsolt Haraszti109db832016-09-16 16:32:36 -0700288 self.log = setup_logging(self.config.get('logging', {}),
289 args.instance_id,
khenaidoo50b286d2018-03-02 17:44:30 -0500290 verbosity_adjust=verbosity_adjust)
Richard Jankowski4ea26632018-05-14 17:45:38 -0400291 self.log.info('core-number-extractor', regex=args.container_name_regex)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700292
Jonathan Hartda93ac62018-05-01 11:25:29 -0700293 self.voltha_version = self.get_version()
294 self.log.info('VOLTHA version is {}'.format(self.voltha_version))
295
Rouzbahan Rashidi-Tabrizi1c3eba82016-10-27 21:47:18 -0400296 # configurable variables from voltha.yml file
297 #self.configurable_vars = self.config.get('Constants', {})
298
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700299 if not args.no_banner:
300 print_banner(self.log)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700301
Richard Jankowski4ea26632018-05-14 17:45:38 -0400302 # Create a unique instance id using the passed-in instance id and
khenaidoo032d3302017-06-09 14:50:04 -0400303 # UTC timestamp
304 current_time = arrow.utcnow().timestamp
305 self.instance_id = self.args.instance_id + '_' + str(current_time)
306
307 # Every voltha instance is given a core_storage id where the
308 # instance data is stored
309 self.core_store_id = None
310
khenb95fe9a2016-10-05 11:15:25 -0700311 self.startup_components()
312
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700313 if not args.no_heartbeat:
314 self.start_heartbeat()
khenaidoo032d3302017-06-09 14:50:04 -0400315 self.start_kafka_heartbeat(self.instance_id)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700316
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800317 self.manhole = None
318
Jonathan Hartda93ac62018-05-01 11:25:29 -0700319 def get_version(self):
320 path = defs['version_file']
321 if not path.startswith('/'):
322 dir = os.path.dirname(os.path.abspath(__file__))
323 path = os.path.join(dir, path)
324
325 path = os.path.abspath(path)
326 version_file = open(path, 'r')
327 v = version_file.read()
328
329 # Use Version to validate the version string - exception will be raised
330 # if the version is invalid
331 Version(v)
332
333 version_file.close()
334 return v
335
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700336 def start(self):
337 self.start_reactor() # will not return except Keyboard interrupt
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700338
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800339 def stop(self):
340 pass
341
342 def get_args(self):
343 """Allow access to command line args"""
344 return self.args
345
346 def get_config(self):
347 """Allow access to content of config file"""
348 return self.config
349
Zsolt Haraszti7eeb2b32016-11-06 14:04:55 -0800350 @inlineCallbacks
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700351 def startup_components(self):
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800352 try:
khenaidooccc42252017-07-06 23:00:49 -0400353 self.log.info('starting-internal-components',
354 internal_host=self.args.internal_host_address,
khenaidoo26a8c012017-07-07 18:25:47 -0400355 external_host=self.args.external_host_address,
356 interface=self.args.interface,
Richard Jankowski8b277c22017-12-19 09:49:27 -0500357 consul=self.args.consul,
358 etcd=self.args.etcd)
Zsolt Harasztidafefe12016-11-14 21:29:58 -0800359
Zsolt Harasztia17f3ec2016-12-08 14:55:49 -0800360 registry.register('main', self)
361
Richard Jankowski8b277c22017-12-19 09:49:27 -0500362 if self.args.backend == 'consul':
363 yield registry.register(
364 'coordinator',
365 Coordinator(
366 internal_host_address=self.args.internal_host_address,
367 external_host_address=self.args.external_host_address,
368 rest_port=self.args.rest_port,
369 instance_id=self.instance_id,
370 config=self.config,
Richard Jankowski4ea26632018-05-14 17:45:38 -0400371 consul=self.args.consul,
372 container_name_regex=self.args.container_name_regex)
Richard Jankowski8b277c22017-12-19 09:49:27 -0500373 ).start()
374 elif self.args.backend == 'etcd':
375 yield registry.register(
376 'coordinator',
377 CoordinatorEtcd(
378 internal_host_address=self.args.internal_host_address,
379 external_host_address=self.args.external_host_address,
380 rest_port=self.args.rest_port,
381 instance_id=self.instance_id,
382 config=self.config,
383 consul=self.args.consul,
Richard Jankowski4ea26632018-05-14 17:45:38 -0400384 etcd=self.args.etcd,
385 container_name_regex=self.args.container_name_regex)
Richard Jankowski8b277c22017-12-19 09:49:27 -0500386 ).start()
Zsolt Harasztidafefe12016-11-14 21:29:58 -0800387
khenaidoo032d3302017-06-09 14:50:04 -0400388 self.log.info('waiting-for-config-assignment')
389
390 # Wait until we get a config id before we proceed
391 self.core_store_id, store_prefix = \
392 yield registry('coordinator').get_core_store_id_and_prefix()
393
394 self.log.info('store-id', core_store_id=self.core_store_id)
Zsolt Harasztieb435072016-09-23 17:10:49 -0700395
khenaidoocbe30832017-08-25 10:43:27 -0400396 # Update the logger to output the vcore id.
397 self.log = update_logging(instance_id=self.instance_id, vcore_id=self.core_store_id)
398
Zsolt Haraszti66862032016-11-28 14:28:39 -0800399 yield registry.register(
400 'grpc_server',
401 VolthaGrpcServer(self.args.grpc_port)
402 ).start()
Zsolt Harasztieb435072016-09-23 17:10:49 -0700403
Zsolt Haraszti66862032016-11-28 14:28:39 -0800404 yield registry.register(
khenaidoo032d3302017-06-09 14:50:04 -0400405 'core',
406 VolthaCore(
407 instance_id=self.instance_id,
408 core_store_id = self.core_store_id,
khenaidoo08d48d22017-06-29 19:42:49 -0400409 grpc_port=self.args.grpc_port,
Jonathan Hartda93ac62018-05-01 11:25:29 -0700410 version=self.voltha_version,
khenaidoo032d3302017-06-09 14:50:04 -0400411 log_level=LogLevel.INFO
412 )
413 ).start(config_backend=load_backend(store_id=self.core_store_id,
414 store_prefix=store_prefix,
415 args=self.args))
416
417 init_rest_service(self.args.rest_port)
418
419 yield registry.register(
Zsolt Haraszti66862032016-11-28 14:28:39 -0800420 'kafka_proxy',
Zsolt Haraszti99509d32016-12-10 16:41:45 -0800421 KafkaProxy(
422 self.args.consul,
423 self.args.kafka,
424 config=self.config.get('kafka-proxy', {})
425 )
Zsolt Haraszti66862032016-11-28 14:28:39 -0800426 ).start()
427
428 yield registry.register(
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800429 'frameio',
430 FrameIOManager()
431 ).start()
432
433 yield registry.register(
Zsolt Haraszti66862032016-11-28 14:28:39 -0800434 'adapter_loader',
435 AdapterLoader(config=self.config.get('adapter_loader', {}))
436 ).start()
khenb95fe9a2016-10-05 11:15:25 -0700437
Zsolt Haraszti99509d32016-12-10 16:41:45 -0800438 yield registry.register(
439 'diag',
440 Diagnostics(config=self.config.get('diagnostics', {}))
441 ).start()
442
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800443 if self.args.manhole_port is not None:
444 self.start_manhole(self.args.manhole_port)
445
khenaidoo032d3302017-06-09 14:50:04 -0400446 # Now that all components are loaded, in the scenario where this
447 # voltha instance is picking up an existing set of data (from a
448 # voltha instance that dies/stopped) then we need to setup this
449 # instance from where the previous one left
450
451 yield registry('core').reconcile_data()
452
khenaidoocbe30832017-08-25 10:43:27 -0400453 # Now that the data is in memory and the reconcile process
454 # within the core has completed (the reconciliation may still be
455 # in progress with the adapters) we expose the NBI of voltha core
456 yield registry('core').register_grpc_service()
457
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800458 self.log.info('started-internal-services')
459
460 except Exception as e:
khenaidoo032d3302017-06-09 14:50:04 -0400461 self.log.exception('Failure-to-start-all-components', e=e)
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800462
Zsolt Haraszti3bfff662016-12-14 23:41:49 -0800463 def start_manhole(self, port):
464 self.manhole = Manhole(
465 port,
466 pws=dict(admin='adminpw'),
467 eventbus = EventBusClient(),
468 **registry.components
469 )
470
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700471 @inlineCallbacks
472 def shutdown_components(self):
473 """Execute before the reactor is shut down"""
474 self.log.info('exiting-on-keyboard-interrupt')
Zsolt Harasztidafefe12016-11-14 21:29:58 -0800475 for component in reversed(registry.iterate()):
476 yield component.stop()
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700477
Zsolt Haraszti3300f742017-01-09 01:14:20 -0800478 import threading
479 self.log.info('THREADS:')
480 main_thread = threading.current_thread()
481 for t in threading.enumerate():
482 if t is main_thread:
483 continue
484 if not t.isDaemon():
485 continue
486 self.log.info('joining thread {} {}'.format(
487 t.getName(), "daemon" if t.isDaemon() else "not-daemon"))
488 t.join()
489
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700490 def start_reactor(self):
491 from twisted.internet import reactor
Zsolt Haraszti109db832016-09-16 16:32:36 -0700492 reactor.callWhenRunning(
493 lambda: self.log.info('twisted-reactor-started'))
494 reactor.addSystemEventTrigger('before', 'shutdown',
495 self.shutdown_components)
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700496 reactor.run()
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700497
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700498 def start_heartbeat(self):
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700499
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700500 t0 = time.time()
501 t0s = time.ctime(t0)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700502
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700503 def heartbeat():
504 self.log.debug(status='up', since=t0s, uptime=time.time() - t0)
Zsolt Harasztif2da1d02016-09-13 23:21:35 -0700505
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700506 lc = LoopingCall(heartbeat)
507 lc.start(10)
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700508
khenb95fe9a2016-10-05 11:15:25 -0700509 # Temporary function to send a heartbeat message to the external kafka
510 # broker
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800511 def start_kafka_heartbeat(self, instance_id):
khenb95fe9a2016-10-05 11:15:25 -0700512 # For heartbeat we will send a message to a specific "voltha-heartbeat"
513 # topic. The message is a protocol buf
514 # message
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800515 message = dict(
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800516 type='heartbeat',
517 voltha_instance=instance_id,
518 ip=get_my_primary_local_ipv4()
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800519 )
520 topic = "voltha.heartbeat"
khenb95fe9a2016-10-05 11:15:25 -0700521
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800522 def send_msg():
Rouzbahan Rashidi-Tabrizi380dcb32017-03-23 18:01:02 -0400523 try:
524 kafka_proxy = get_kafka_proxy()
525 if kafka_proxy and not kafka_proxy.is_faulty():
526 self.log.debug('kafka-proxy-available')
527 message['ts'] = arrow.utcnow().timestamp
528 self.log.debug('start-kafka-heartbeat')
529 kafka_proxy.send_message(topic, dumps(message))
530 else:
531 self.log.error('kafka-proxy-unavailable')
532 except Exception, e:
533 self.log.exception('failed-sending-message-heartbeat', e=e)
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800534
Rouzbahan Rashidi-Tabrizi380dcb32017-03-23 18:01:02 -0400535 try:
Zsolt Harasztib5d72f12017-01-15 20:44:02 -0800536 lc = LoopingCall(send_msg)
Khen Nursimulu3c74d3b2016-11-08 15:14:01 -0800537 lc.start(10)
Rouzbahan Rashidi-Tabrizi380dcb32017-03-23 18:01:02 -0400538 except Exception, e:
539 self.log.exception('failed-kafka-heartbeat', e=e)
Khen Nursimulu441dedd2016-10-05 14:44:26 -0700540
Zsolt Haraszti89a27302016-12-08 16:53:06 -0800541
Zsolt Harasztib71c2a02016-09-12 13:12:07 -0700542if __name__ == '__main__':
Zsolt Harasztie060a7d2016-09-16 11:08:24 -0700543 Main().start()