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
|
intro
|
||||||
lorax
|
lorax
|
||||||
livemedia-creator
|
livemedia-creator
|
||||||
|
lorax-composer
|
||||||
product-images
|
product-images
|
||||||
modules
|
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")
|
yum_log = logging.getLogger("yum")
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import grp
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
from gevent import socket
|
||||||
from gevent.wsgi import WSGIServer
|
from gevent.wsgi import WSGIServer
|
||||||
|
|
||||||
from pylorax import vernum
|
from pylorax import vernum
|
||||||
@ -44,10 +46,10 @@ def get_parser():
|
|||||||
parser = argparse.ArgumentParser(description="Lorax Composer API Server",
|
parser = argparse.ArgumentParser(description="Lorax Composer API Server",
|
||||||
fromfile_prefix_chars="@")
|
fromfile_prefix_chars="@")
|
||||||
|
|
||||||
parser.add_argument("--host", default="127.0.0.1", metavar="HOST",
|
parser.add_argument("--socket", default="/run/weldr/api.socket", metavar="SOCKET",
|
||||||
help="Host or IP to bind to (127.0.0.1)")
|
help="Path to the socket file to listen on")
|
||||||
parser.add_argument("--port", default=4000, metavar="PORT",
|
parser.add_argument("--group", default="weldr", metavar="GROUP",
|
||||||
help="Port to bind to (4000)")
|
help="Group to set ownership of the socket to")
|
||||||
parser.add_argument("--log", dest="logfile", default="/var/log/lorax-composer/composer.log", metavar="LOG",
|
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)")
|
help="Path to logfile (/var/log/lorax-composer/composer.log)")
|
||||||
parser.add_argument("--mockfiles", default="/var/tmp/bdcs-mockfiles/", metavar="MOCKFILES",
|
parser.add_argument("--mockfiles", default="/var/tmp/bdcs-mockfiles/", metavar="MOCKFILES",
|
||||||
@ -129,6 +131,29 @@ if __name__ == '__main__':
|
|||||||
setup_logging(opts.logfile)
|
setup_logging(opts.logfile)
|
||||||
log.debug("opts=%s", opts)
|
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):
|
if not os.path.isdir(opts.RECIPES):
|
||||||
log.warn("Creating empty recipe directory at %s", opts.RECIPES)
|
log.warn("Creating empty recipe directory at %s", opts.RECIPES)
|
||||||
os.makedirs(opts.RECIPES)
|
os.makedirs(opts.RECIPES)
|
||||||
@ -149,8 +174,16 @@ if __name__ == '__main__':
|
|||||||
# Import example recipes
|
# Import example recipes
|
||||||
commit_recipe_directory(server.config["GITLOCK"].repo, "master", opts.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
|
# The server writes directly to a file object, so point to our log directory
|
||||||
http_server.serve_forever()
|
http_server.serve_forever()
|
||||||
|
Loading…
Reference in New Issue
Block a user