Browse Source

Add command processor to zuul-web

Zuul uses the command processor for most components to send commands
to a running service. We should add this to zuul-web as well starting
with the stop command. In a later change we'll add commands for
starting/stopping a repl server.

Change-Id: I1d02ec30341be0890afb332dcf9f32f10a52ead5
changes/07/666307/5
Tobias Henkel 2 years ago
parent
commit
f6d842dd5f
No known key found for this signature in database GPG Key ID: 3750DEC158E5FA2
8 changed files with 62 additions and 9 deletions
  1. +5
    -2
      tests/base.py
  2. +1
    -1
      tests/unit/test_github_driver.py
  3. +1
    -1
      tests/unit/test_pagure_driver.py
  4. +3
    -3
      tests/unit/test_streaming.py
  5. +1
    -0
      tests/unit/test_web.py
  6. +1
    -1
      tests/unit/test_web_urls.py
  7. +20
    -0
      zuul/cmd/web.py
  8. +30
    -1
      zuul/web/__init__.py

+ 5
- 2
tests/base.py View File

@ -2505,7 +2505,8 @@ class WebProxyFixture(fixtures.Fixture):
class ZuulWebFixture(fixtures.Fixture):
def __init__(self, gearman_server_port, config, info=None, zk_hosts=None):
def __init__(self, gearman_server_port, config, test_root, info=None,
zk_hosts=None):
super(ZuulWebFixture, self).__init__()
self.gearman_server_port = gearman_server_port
self.connections = zuul.lib.connections.ConnectionRegistry()
@ -2519,6 +2520,7 @@ class ZuulWebFixture(fixtures.Fixture):
else:
self.info = info
self.zk_hosts = zk_hosts
self.test_root = test_root
def _setUp(self):
# Start the web server
@ -2527,7 +2529,8 @@ class ZuulWebFixture(fixtures.Fixture):
gear_server='127.0.0.1', gear_port=self.gearman_server_port,
info=self.info,
connections=self.connections,
zk_hosts=self.zk_hosts)
zk_hosts=self.zk_hosts,
command_socket=os.path.join(self.test_root, 'web.socket'))
self.web.start()
self.addCleanup(self.stop)


+ 1
- 1
tests/unit/test_github_driver.py View File

@ -1258,7 +1258,7 @@ class TestGithubWebhook(ZuulTestCase):
# Start the web server
self.web = self.useFixture(
ZuulWebFixture(self.gearman_server.port,
self.config))
self.config, self.test_root))
host = '127.0.0.1'
# Wait until web server is started


+ 1
- 1
tests/unit/test_pagure_driver.py View File

@ -839,7 +839,7 @@ class TestPagureWebhook(ZuulTestCase):
# Start the web server
self.web = self.useFixture(
ZuulWebFixture(self.gearman_server.port,
self.config))
self.config, self.test_root))
host = '127.0.0.1'
# Wait until web server is started


+ 3
- 3
tests/unit/test_streaming.py View File

@ -251,7 +251,7 @@ class TestStreaming(tests.base.AnsibleZuulTestCase):
# Start the web server
web = self.useFixture(
ZuulWebFixture(self.gearman_server.port,
self.config))
self.config, self.test_root))
# Start the finger streamer daemon
streamer = zuul.lib.log_streamer.LogStreamer(
@ -327,7 +327,7 @@ class TestStreaming(tests.base.AnsibleZuulTestCase):
# Start the web server
web = self.useFixture(
ZuulWebFixture(self.gearman_server.port,
self.config))
self.config, self.test_root))
# Start the finger streamer daemon
streamer = zuul.lib.log_streamer.LogStreamer(
@ -400,7 +400,7 @@ class TestStreaming(tests.base.AnsibleZuulTestCase):
# Start the web server
web = self.useFixture(
ZuulWebFixture(self.gearman_server.port,
self.config))
self.config, self.test_root))
# Start the finger streamer daemon
streamer = zuul.lib.log_streamer.LogStreamer(


+ 1
- 0
tests/unit/test_web.py View File

@ -52,6 +52,7 @@ class BaseTestWeb(ZuulTestCase):
ZuulWebFixture(
self.gearman_server.port,
self.config,
self.test_root,
info=zuul.model.WebInfo.fromConfig(self.zuul_ini_config),
zk_hosts=self.zk_config))


+ 1
- 1
tests/unit/test_web_urls.py View File

@ -28,7 +28,7 @@ class TestWebURLs(ZuulTestCase):
super(TestWebURLs, self).setUp()
self.web = self.useFixture(
ZuulWebFixture(self.gearman_server.port,
self.config))
self.config, self.test_root))
def _get(self, port, uri):
url = "http://localhost:{}{}".format(port, uri)


+ 20
- 0
zuul/cmd/web.py View File

@ -30,6 +30,18 @@ class WebServer(zuul.cmd.ZuulDaemonApp):
app_name = 'web'
app_description = 'A standalone Zuul web server.'
def createParser(self):
parser = super().createParser()
parser.add_argument('command',
choices=zuul.web.COMMANDS,
nargs='?')
return parser
def parseArguments(self, args=None):
super().parseArguments()
if self.args.command:
self.args.nodaemon = True
def exit_handler(self, signum, frame):
self.web.stop()
@ -55,6 +67,10 @@ class WebServer(zuul.cmd.ZuulDaemonApp):
params['ssl_cert'] = get_default(self.config, 'gearman', 'ssl_cert')
params['ssl_ca'] = get_default(self.config, 'gearman', 'ssl_ca')
params['command_socket'] = get_default(
self.config, 'web', 'command_socket',
'/var/lib/zuul/web.socket')
params['connections'] = self.connections
# Validate config here before we spin up the ZuulWeb object
for conn_name, connection in self.connections.connections.items():
@ -91,6 +107,10 @@ class WebServer(zuul.cmd.ZuulDaemonApp):
self.log.info("Zuul Web Server stopped")
def run(self):
if self.args.command in zuul.web.COMMANDS:
self.send_command(self.args.command)
sys.exit(0)
self.setup_logging('web', 'log_config')
self.log = logging.getLogger("zuul.WebServer")


+ 30
- 1
zuul/web/__init__.py View File

@ -34,10 +34,13 @@ import re2
import zuul.model
import zuul.rpcclient
import zuul.zk
from zuul.lib import commandsocket
STATIC_DIR = os.path.join(os.path.dirname(__file__), 'static')
cherrypy.tools.websocket = WebSocketTool()
COMMANDS = ['stop']
class SaveParamsTool(cherrypy.Tool):
"""
@ -726,7 +729,8 @@ class ZuulWeb(object):
connections=None,
info=None,
static_path=None,
zk_hosts=None):
zk_hosts=None,
command_socket=None):
self.start_time = time.time()
self.listen_address = listen_address
self.listen_port = listen_port
@ -745,6 +749,11 @@ class ZuulWeb(object):
self.connections = connections
self.stream_manager = StreamManager()
self.command_socket = commandsocket.CommandSocket(command_socket)
self.command_map = {
'stop': self.stop,
}
route_map = cherrypy.dispatch.RoutesDispatcher()
api = ZuulWebAPI(self)
route_map.connect('api', '/api',
@ -838,6 +847,14 @@ class ZuulWeb(object):
self.wsplugin.subscribe()
cherrypy.engine.start()
self.log.debug("Starting command processor")
self._command_running = True
self.command_socket.start()
self.command_thread = threading.Thread(target=self.runCommand,
name='command')
self.command_thread.daemon = True
self.command_thread.start()
def stop(self):
self.log.debug("ZuulWeb stopping")
self.rpc.shutdown()
@ -849,6 +866,18 @@ class ZuulWeb(object):
self.wsplugin.unsubscribe()
self.stream_manager.stop()
self.zk.disconnect()
self._command_running = False
self.command_socket.stop()
self.command_thread.join()
def runCommand(self):
while self._command_running:
try:
command = self.command_socket.get().decode('utf8')
if command != '_stop':
self.command_map[command]()
except Exception:
self.log.exception("Exception while processing command")
if __name__ == "__main__":


Loading…
Cancel
Save