blob: 6a539dcfdc48206f7296bb11b59acafbc0e49d04 [file] [log] [blame]
alshabibd69de342016-11-23 11:27:15 -05001#
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08002# Copyright 2017 the original author or authors.
alshabibd69de342016-11-23 11:27:15 -05003#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import argparse
alshabiba820d242016-11-29 14:49:34 -080018import time
alshabibd69de342016-11-23 11:27:15 -050019from common.structlog_setup import setup_logging
20from common.utils.dockerhelpers import get_my_containers_name
21import os
22from twisted.internet import reactor
alshabib8b7e0ec2017-03-02 15:12:29 -080023from voltha.adapters.microsemi_olt.microsemi import RubyAdapter
alshabibd69de342016-11-23 11:27:15 -050024import yaml
25
26defs = dict(
27 config=os.environ.get('CONFIG', './ruby.yml'),
28 consul=os.environ.get('CONSUL', 'localhost:8500'),
29 grpc_endpoint=os.environ.get('GRPC_ENDPOINT', 'localhost:50055'),
30 fluentd=os.environ.get('FLUENTD', None),
31 instance_id=os.environ.get('INSTANCE_ID', os.environ.get('HOSTNAME', '1'))
32)
33
34def parse_args():
35
36 parser = argparse.ArgumentParser()
37
38 _help = ('Path to ruby.yml config file (default: %s). '
39 'If relative, it is relative to main.py of microsemi.'
40 % defs['config'])
41 parser.add_argument('-c', '--config',
42 dest='config',
43 action='store',
44 default=defs['config'],
45 help=_help)
46
47 _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
48 parser.add_argument(
49 '-C', '--consul', dest='consul', action='store',
50 default=defs['consul'],
51 help=_help)
52
53
54 _help = ('<hostname>:<port> to fluentd server (default: %s). (If not '
55 'specified (None), the address from the config file is used'
56 % defs['fluentd'])
57 parser.add_argument('-F', '--fluentd',
58 dest='fluentd',
59 action='store',
60 default=defs['fluentd'],
61 help=_help)
62
63 _help = ('gRPC end-point to connect to. It can either be a direct'
64 'definition in the form of <hostname>:<port>, or it can be an'
65 'indirect definition in the form of @<service-name> where'
66 '<service-name> is the name of the grpc service as registered'
67 'in consul (example: @voltha-grpc). (default: %s'
68 % defs['grpc_endpoint'])
69 parser.add_argument('-G', '--grpc-endpoint',
70 dest='grpc_endpoint',
71 action='store',
72 default=defs['grpc_endpoint'],
73 help=_help)
74
75 _help = ('unique string id of this ofagent instance (default: %s)'
76 % defs['instance_id'])
77 parser.add_argument('-i', '--instance-id',
78 dest='instance_id',
79 action='store',
80 default=defs['instance_id'],
81 help=_help)
82
83 _help = "suppress debug and info logs"
84 parser.add_argument('-q', '--quiet',
85 dest='quiet',
86 action='count',
87 help=_help)
88
89 _help = 'enable verbose logging'
90 parser.add_argument('-v', '--verbose',
91 dest='verbose',
92 action='count',
93 help=_help)
94
95 _help = ('use docker container name as ofagent instance id'
96 ' (overrides -i/--instance-id option)')
97 parser.add_argument('--instance-id-is-container-name',
98 dest='instance_id_is_container_name',
99 action='store_true',
100 default=False,
101 help=_help)
102
103 _help = 'omit startup banner log lines'
104 parser.add_argument('-n', '--no-banner',
105 dest='no_banner',
106 action='store_true',
107 default=False,
108 help=_help)
109
110
111 args = parser.parse_args()
112
113 # post-processing
114
115 if args.instance_id_is_container_name:
116 args.instance_id = get_my_containers_name()
117
118 return args
119
120
121def load_config(args):
122 path = args.config
123 if path.startswith('.'):
124 dir = os.path.dirname(os.path.abspath(__file__))
125 path = os.path.join(dir, path)
126 path = os.path.abspath(path)
127 with open(path) as fd:
128 config = yaml.load(fd)
129 return config
130
131
132banner = r'''
133 ________ ___ ___ ________ ___ ___
134|\ __ \|\ \|\ \|\ __ \ |\ \ / /|
135\ \ \|\ \ \ \\\ \ \ \|\ /_ \ \ \/ / /
136 \ \ _ _\ \ \\\ \ \ __ \ \ \ / /
137 \ \ \\ \\ \ \\\ \ \ \|\ \ \/ / /
138 \ \__\\ _\\ \_______\ \_______\__/ / /
139 \|__|\|__|\|_______|\|_______|\___/ /
140 \|___|/
141'''
142
143def print_banner(log):
144 for line in banner.strip('\n').splitlines():
145 log.info(line)
146 log.info('(to stop: press Ctrl-C)')
147
148class Main(object):
149
150 def __init__(self):
151
152 self.args = args = parse_args()
153 self.config = load_config(args)
154
155 verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
156 self.log = setup_logging(self.config.get('logging', {}),
157 args.instance_id,
158 verbosity_adjust=verbosity_adjust,
159 fluentd=args.fluentd)
160
161 # components
162 self.ruby_adapter = None
163
164 self.exiting = False
165
166 if not args.no_banner:
167 print_banner(self.log)
168
169 self.startup_components()
170
171 def start(self):
172 self.start_reactor() # will not return except Keyboard interrupt
173
174 def startup_components(self):
175 self.log.info('starting-internal-components')
176 args = self.args
177 self.ruby_adapter = RubyAdapter(args, self.config).start()
178 self.log.info('started ruby adapter')
179
180 def shutdown_components(self):
181 """Execute before the reactor is shut down"""
182 self.log.info('exiting-on-keyboard-interrupt')
183 self.exiting = True
184 if self.ruby_adapter is not None:
185 self.ruby_adapter.stop()
186
187 def start_reactor(self):
188 reactor.callWhenRunning(
189 lambda: self.log.info('twisted-reactor-started'))
190
191 reactor.addSystemEventTrigger('before', 'shutdown',
192 self.shutdown_components)
193 reactor.run()
194
195if __name__ == '__main__':
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -0800196 Main().start()