4
Run deployer in a loop, then remove any services not
7
To experiment with this::
10
. .tox/py27/bin/activate
11
python cloudfoundry/reconciler.py \
12
--logging=debug --repo=build --port=8888
14
# then in another window you can do the follow to play
19
This should push a bundle of expected state, HUP the
20
server to force a run and then status the system.
21
Debug output should show whats happening and
25
local charm version in charm url
26
need to probe server still
28
should only trigger builds after push/reality change
29
execute should happen by queueing the callback
30
should listen directly on the websocket and schedule
32
no support for unit state currently (auto-retry/replace, etc)
33
relation removal still needs work
41
import tornado.autoreload
42
import tornado.httpserver
44
import tornado.options
45
import tornado.process
48
from tornado.options import define, options
49
from cloudfoundry import config
50
from cloudfoundry import model
51
from cloudfoundry import utils
60
# delta state real vs expected
62
# execute strategy inside lock
65
db.build_strategy(reality)
66
if db.strategy and application.config.runtime.modify:
70
def sig_reconcile(sig, frame):
71
logging.info("Forcing reconcile loop")
72
tornado.ioloop.IOLoop.instance().add_callback(reconcile)
75
def sig_restart(sig, frame):
76
logging.warning('Caught signal: %s', sig)
77
tornado.ioloop.IOLoop.instance().add_callback(shutdown)
81
logging.info('Stopping http server')
84
logging.info('Will shutdown in %s seconds ...',
85
config.MAX_WAIT_SECONDS_BEFORE_SHUTDOWN)
86
io_loop = tornado.ioloop.IOLoop.instance()
88
deadline = time.time() + config.MAX_WAIT_SECONDS_BEFORE_SHUTDOWN
92
if now < deadline and (io_loop._callbacks or io_loop._timeouts):
93
io_loop.add_timeout(now + 1, stop_loop)
96
logging.info('Shutdown')
100
class StateHandler(tornado.web.RequestHandler):
102
self.write(json.dumps(db.expected, indent=2, default=utils.serializable))
105
db.expected = json.loads(self.request.body)
106
tornado.ioloop.IOLoop.instance().add_callback(reconcile)
109
class StrategyHandler(tornado.web.RequestHandler):
111
self.write(utils.jsonify(db.strategy))
114
class ResetHandler(tornado.web.RequestHandler):
119
class ReconcilerWebApp(tornado.web.Application):
122
return self.settings['config']
126
define('config', default='/etc/juju-deployer/server.conf', type=str)
128
tornado.options.parse_command_line()
129
config = utils.parse_config(options.config, {
130
'server.address': '127.0.0.1',
132
'credentials.user': 'user-admin',
133
'server.repository': 'build',
134
'juju.environment': utils.current_env(),
135
'runtime.observe': True,
136
'runtime.modify': True
140
application = ReconcilerWebApp([
141
(r"/api/v1/", StateHandler),
142
(r"/api/v1/strategy", StrategyHandler),
143
(r"/api/v1/reset", ResetHandler),
153
if not os.path.exists(config['server.repository']):
154
os.makedirs(config['server.repository'])
156
db = model.StateDatabase(config)
157
server = tornado.httpserver.HTTPServer(application)
158
server.listen(config['server.port'], config['server.address'])
160
signal.signal(signal.SIGTERM, sig_restart)
161
signal.signal(signal.SIGINT, sig_restart)
162
signal.signal(signal.SIGHUP, sig_reconcile)
164
# config file change should reload the application
165
# its values are passed to Application init
166
tornado.autoreload.watch(options.config)
168
loop = tornado.ioloop.IOLoop.instance()
169
# tornado.ioloop.PeriodicCallback(reconcile, 500, io_loop=loop).start()
173
if __name__ == "__main__":