Switch the API to use a Unix Domain Socket
This drops support for the TCP port and switches to using a socket at /var/run/weldr/api.socket Also add the start of some docs for lorax-composer. --host and --port argument have been removed. --group sets the group name to use for access to the socket and its parent directory. Defaults to 'weldr' --socket sets the full path to the socket to create. Defaults to '/var/run/weldr/api.socket'
This commit is contained in:
parent
3c18a63f76
commit
33c5d0ce4a
@ -14,6 +14,7 @@ Contents:
|
||||
intro
|
||||
lorax
|
||||
livemedia-creator
|
||||
lorax-composer
|
||||
product-images
|
||||
modules
|
||||
|
||||
|
37
docs/lorax-composer.rst
Normal file
37
docs/lorax-composer.rst
Normal file
@ -0,0 +1,37 @@
|
||||
lorax-composer
|
||||
==============
|
||||
|
||||
:Authors:
|
||||
Brian C. Lane <bcl@redhat.com>
|
||||
|
||||
lorax-composer is an API server that is compatible with the Weldr project's
|
||||
bdcs-api REST protocol. More information on Weldr can be found [on the Weldr
|
||||
blog](https://www.weldr.io).
|
||||
|
||||
The server runs as root, and communication with it is via a unix domain socket
|
||||
(``/run/weldr/api.socket`` by default). The directory and socket are owned by
|
||||
root:weldr so that any user in the weldr group can use the API to control
|
||||
lorax-composer.
|
||||
|
||||
When starting the server it will check for the correct permissions and
|
||||
ownership of pre-existing directory, or it will create a new one if none exist.
|
||||
The socket path and group owner's name can be changed from the cmdline by
|
||||
passing it the ``--socket`` and ``--group`` arguments.
|
||||
|
||||
Logs
|
||||
----
|
||||
|
||||
Logs are stored under ``/var/log/lorax-composer/`` and includes all console
|
||||
messages as well as extra debugging info and API requests.
|
||||
|
||||
Quickstart
|
||||
----------
|
||||
|
||||
1. Create a ``weldr`` group by running ``groupadd weldr``
|
||||
2. Remove any pre-existing socket directory with ``rm -rf /run/weldr/``
|
||||
A new directory with correct permissions will be created the first time the server runs.
|
||||
3. Either start it via systemd with ``systemctl start lorax-composer`` or
|
||||
run it directly with ``lorax-composer /path/to/recipes/``
|
||||
|
||||
The ``/path/to/recipes/`` is where the recipe's git repo will be created, and all
|
||||
the recipes created with the ``/api/v0/recipes/new`` route will be stored.
|
@ -25,9 +25,11 @@ server_log = logging.getLogger("server")
|
||||
yum_log = logging.getLogger("yum")
|
||||
|
||||
import argparse
|
||||
import grp
|
||||
import os
|
||||
import sys
|
||||
from threading import Lock
|
||||
from gevent import socket
|
||||
from gevent.wsgi import WSGIServer
|
||||
|
||||
from pylorax import vernum
|
||||
@ -44,10 +46,10 @@ def get_parser():
|
||||
parser = argparse.ArgumentParser(description="Lorax Composer API Server",
|
||||
fromfile_prefix_chars="@")
|
||||
|
||||
parser.add_argument("--host", default="127.0.0.1", metavar="HOST",
|
||||
help="Host or IP to bind to (127.0.0.1)")
|
||||
parser.add_argument("--port", default=4000, metavar="PORT",
|
||||
help="Port to bind to (4000)")
|
||||
parser.add_argument("--socket", default="/run/weldr/api.socket", metavar="SOCKET",
|
||||
help="Path to the socket file to listen on")
|
||||
parser.add_argument("--group", default="weldr", metavar="GROUP",
|
||||
help="Group to set ownership of the socket to")
|
||||
parser.add_argument("--log", dest="logfile", default="/var/log/lorax-composer/composer.log", metavar="LOG",
|
||||
help="Path to logfile (/var/log/lorax-composer/composer.log)")
|
||||
parser.add_argument("--mockfiles", default="/var/tmp/bdcs-mockfiles/", metavar="MOCKFILES",
|
||||
@ -129,6 +131,29 @@ if __name__ == '__main__':
|
||||
setup_logging(opts.logfile)
|
||||
log.debug("opts=%s", opts)
|
||||
|
||||
# Check to make sure the group exists and get its gid
|
||||
try:
|
||||
gid = grp.getgrnam(opts.group).gr_gid
|
||||
except KeyError:
|
||||
log.error("Missing group '%s'", opts.group)
|
||||
sys.exit(1)
|
||||
|
||||
# Check the socket path to make sure it exists, and that ownership and permissions are correct.
|
||||
socket_dir = os.path.dirname(opts.socket)
|
||||
if not os.path.exists(socket_dir):
|
||||
# Create the directory and set permissions and ownership
|
||||
os.makedirs(socket_dir, 0o750)
|
||||
os.chown(socket_dir, 0, gid)
|
||||
|
||||
sockdir_stat = os.stat(socket_dir)
|
||||
if sockdir_stat.st_mode & 0o007 != 0:
|
||||
log.error("Incorrect permissions on %s, no 'other' permissions are allowed.")
|
||||
sys.exit(1)
|
||||
|
||||
if sockdir_stat.st_gid != gid or sockdir_stat.st_uid != 0:
|
||||
log.error("%s should be owned by root:%s", socket_dir, opts.group)
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.isdir(opts.RECIPES):
|
||||
log.warn("Creating empty recipe directory at %s", opts.RECIPES)
|
||||
os.makedirs(opts.RECIPES)
|
||||
@ -149,8 +174,16 @@ if __name__ == '__main__':
|
||||
# Import example recipes
|
||||
commit_recipe_directory(server.config["GITLOCK"].repo, "master", opts.RECIPES)
|
||||
|
||||
log.info("Starting %s on %s:%d with recipes from %s", VERSION, opts.host, opts.port, opts.RECIPES)
|
||||
# Setup the Unix Domain Socket, remove old one, set ownership and permissions
|
||||
if os.path.exists(opts.socket):
|
||||
os.unlink(opts.socket)
|
||||
listener = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
listener.bind(opts.socket)
|
||||
os.chmod(opts.socket, 0o660)
|
||||
os.chown(opts.socket, 0, gid)
|
||||
listener.listen(1)
|
||||
|
||||
http_server = WSGIServer((opts.host, opts.port), server, log=LogWrapper(server_log))
|
||||
log.info("Starting %s on %s with recipes from %s", VERSION, opts.socket, opts.RECIPES)
|
||||
http_server = WSGIServer(listener, server, log=LogWrapper(server_log))
|
||||
# The server writes directly to a file object, so point to our log directory
|
||||
http_server.serve_forever()
|
||||
|
Loading…
Reference in New Issue
Block a user