blob: 1da0b41749292cbfaae793051fd298cd24fd81c1 [file] [log] [blame]
alshabibc67ee3a2016-10-25 23:24:03 -07001#!/usr/bin/env python
2#
3# Copyright 2016 the original author or authors.
4#
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
18import argparse
19import os
Zsolt Harasztid70cd4d2016-11-03 23:23:36 -070020
alshabibc67ee3a2016-10-25 23:24:03 -070021import yaml
Zsolt Harasztid70cd4d2016-11-03 23:23:36 -070022from twisted.internet.defer import inlineCallbacks
23
24from common.structlog_setup import setup_logging
25from common.utils.nethelpers import get_my_primary_local_ipv4
26from consul_mgr import ConsulManager
alshabibc67ee3a2016-10-25 23:24:03 -070027
28defs = dict(
29 config=os.environ.get('CONFIG', './podder.yml'),
30 consul=os.environ.get('CONSUL', 'localhost:8500'),
31 external_host_address=os.environ.get('EXTERNAL_HOST_ADDRESS',
32 get_my_primary_local_ipv4()),
33 grpc_endpoint=os.environ.get('GRPC_ENDPOINT', 'localhost:50055'),
34 fluentd=os.environ.get('FLUENTD', None),
35 instance_id=os.environ.get('INSTANCE_ID', os.environ.get('HOSTNAME', '1')),
36 internal_host_address=os.environ.get('INTERNAL_HOST_ADDRESS',
37 get_my_primary_local_ipv4()),
38 work_dir=os.environ.get('WORK_DIR', '/tmp/podder')
39)
40
41def parse_args():
42
43 parser = argparse.ArgumentParser()
44
45 _help = ('Path to podder.yml config file (default: %s). '
46 'If relative, it is relative to main.py of podder.'
47 % defs['config'])
48 parser.add_argument('-c', '--config',
49 dest='config',
50 action='store',
51 default=defs['config'],
52 help=_help)
53
54 _help = '<hostname>:<port> to consul agent (default: %s)' % defs['consul']
55 parser.add_argument(
56 '-C', '--consul', dest='consul', action='store',
57 default=defs['consul'],
58 help=_help)
59
60
61 _help = ('<hostname>:<port> to fluentd server (default: %s). (If not '
62 'specified (None), the address from the config file is used'
63 % defs['fluentd'])
64 parser.add_argument('-F', '--fluentd',
65 dest='fluentd',
66 action='store',
67 default=defs['fluentd'],
68 help=_help)
69
70 _help = ('unique string id of this ofagent instance (default: %s)'
71 % defs['instance_id'])
72 parser.add_argument('-i', '--instance-id',
73 dest='instance_id',
74 action='store',
75 default=defs['instance_id'],
76 help=_help)
77
78 _help = 'omit startup banner log lines'
79 parser.add_argument('-n', '--no-banner',
80 dest='no_banner',
81 action='store_true',
82 default=False,
83 help=_help)
84
85 _help = "suppress debug and info logs"
86 parser.add_argument('-q', '--quiet',
87 dest='quiet',
88 action='count',
89 help=_help)
90
91 _help = 'enable verbose logging'
92 parser.add_argument('-v', '--verbose',
93 dest='verbose',
94 action='count',
95 help=_help)
96
97
98 args = parser.parse_args()
99
100 # post-processing
101
102 return args
103
104def load_config(args):
105 path = args.config
106 if path.startswith('.'):
107 dir = os.path.dirname(os.path.abspath(__file__))
108 path = os.path.join(dir, path)
109 path = os.path.abspath(path)
110 with open(path) as fd:
111 config = yaml.load(fd)
112 return config
113
114banner = r'''
115 _____
116| | | |
117| | | |
118|_____|_____ ____|____| ___ _
119| | | | |/ _ \ /
120| |_____|____|____|\____|
121'''
122
123def print_banner(log):
124 for line in banner.strip('\n').splitlines():
125 log.info(line)
126 log.info('(to stop: press Ctrl-C)')
127
128class Main(object):
129
130 def __init__(self):
131 self.args = args = parse_args()
132 self.config = load_config(args)
133
134 verbosity_adjust = (args.verbose or 0) - (args.quiet or 0)
135 self.log = setup_logging(self.config.get('logging', {}),
136 args.instance_id,
137 verbosity_adjust=verbosity_adjust,
138 fluentd=args.fluentd)
139
140 self.consul_manager = None
141
142 if not args.no_banner:
143 print_banner(self.log)
144
145 self.startup_components()
146
147 def start(self):
148 self.start_reactor()
149
150 @inlineCallbacks
151 def startup_components(self):
152 self.log.info('starting-internal-components')
153 args = self.args
154 self.consul_manager = yield ConsulManager(args.consul).run()
155 self.log.info('started-internal-components')
156
157 @inlineCallbacks
158 def shutdown_components(self):
159 """Execute before the reactor is shut down"""
160 self.log.info('exiting-on-keyboard-interrupt')
161 if self.consul_manager is not None:
162 yield self.consul_manager.shutdown()
163
164 def start_reactor(self):
165 from twisted.internet import reactor
166 reactor.callWhenRunning(
167 lambda: self.log.info('twisted-reactor-started'))
168
169 reactor.addSystemEventTrigger('before', 'shutdown',
170 self.shutdown_components)
171 reactor.run()
172
173
174if __name__ == '__main__':
175 Main().start()