spawn ===== What is spawn? --------------- ``spawn`` is a suite which provides services to the process spawner of various other daemons, e.g. `beng-proxy `__ and `Workshop `__. The Accessory Daemon -------------------- This daemon listens for seqpacket connections on abstract socket :file:`@cm4all-spawn` and allow clients to create namespaces (`protocol definition `__). The client is usually the process spawner of daemons like `beng-proxy `__ and `Lukko `__. The Reaper Daemon ----------------- This daemon watches cgroups below certain scopes; once they run empty, statistics are collected and logged and the cgroup is deleted. ``SIGHUP`` ^^^^^^^^^^ On ``systemctl reload cm4all-spawn-reaper`` (i.e. ``SIGHUP``), the daemon calls the Lua function ``reload`` if one was defined. It is up to the Lua script to define the exact meaning of this feature. Resource Accounting ^^^^^^^^^^^^^^^^^^^ .. highlight:: lua The file :file:`/etc/cm4all/spawn/reaper.lua` is a `Lua `_ script which is executed at startup. If it defines a function called ``cgroup_released``, then this function will be called every time a cgroup is reaped. The function may for example log its resource usage. Example:: function cgroup_released(cgroup) print(cgroup.memory_peak) end The following attributes of the ``cgroup`` parameter can be queried: * ``path``: the cgroup path as noted in :file:`/proc/self/cgroup`, e.g. :file:`/user.slice/user-1000.slice/session-42.scope` * ``btime``: The time the cgroup was created as `Lua timestamp `__; may be ``nil`` if the kernel does not support ``btime`` on ``cgroupfs``. * ``age``: The age of this cgroup in seconds. Only available if ``btime`` is. * ``xattr``: A table containing extended attributes of the control group. * ``parent``: Information about the parent of this cgroup; it is another object of this type (or ``nil`` if there is no parent cgroup). * ``cpu_total``, ``cpu_user``, ``cpu_system``: the total, userspace-only or kernel-only CPU usage [in seconds]. * ``memory_peak``: the peak memory usage [in bytes]. * ``memory_events_high``: The number of times processes of the cgroup are throttled and routed to perform direct memory reclaim because the high memory boundary was exceeded. * ``memory_events_max``: The number of times the cgroup's memory usage was about to go over the max boundary. * ``memory_events_oom``: The number of time the cgroup's memory usage was reached the limit and allocation was about to fail. * ``pids_peak``: the peak number of processes. * ``pids_forks``: the number of ``fork()`` system calls * ``pids_events_max``: the number of times the ``pids.max`` setting was exceeded. Addresses ^^^^^^^^^ It is recommended to create all `address` objects during startup, to avoid putting unnecessary pressure on the Lua garbage collector, and to reduce the overhead for invoking the system resolver (which blocks *Passage* execution). The function `control_resolve()` creates such an `address` object:: server1 = control_resolve('192.168.0.2') server2 = control_resolve('[::1]:4321') server3 = control_resolve('server1.local:1234') server4 = control_resolve('/run/server5.sock') server5 = control_resolve('@server4') These examples do the following: - convert a numeric IPv4 address to an `address` object (port defaults to 5478, the *beng-proxy* control standard port) - convert a numeric IPv6 address with a non-standard port to an `address` object - invoke the system resolver to resolve a host name to an IP address (which blocks passage startup; not recommended) - convert a path string to a "local" socket address - convert a name to an abstract "local" socket address (prefix '@' is converted to a null byte, making the address "abstract") socket ^^^^^^ A simple low-level networking library. Example:: tcp = socket:connect('localhost:1234') udp = socket:connect('localhost:4321', {type='dgram'}) multicast = socket:connect('[ff02::dead:beef]:2345', {type='dgram'}) unix = socket:connect('/run/test.socket') abstract = socket:connect('@test', {type='seqpacket'}) abstract:send('hello world') The ``socket`` library has the following methods: - ``connect(ADDRESS, [OPTIONS])``: Create a new socket connected to the specified address. ``OPTIONS`` may be a table with the following keys: - ``type``: the socket type, one of ``stream`` (the default), ``dgram``, ``seqpacket``. Returns a new socket object on success or ``[nil,error]`` on error. Socket objects have the following methods: - ``close()``: Close the socket. - ``send(DATA, [START], [END])``: Send data (i.e. a string) to the peer. ``START`` and ``END`` are start and end position within the string with the same semantics as in ``string.sub()``. Returns the number of bytes sent on success or ``[nil,error]`` on error. control_client ^^^^^^^^^^^^^^ A client for the `beng-proxy control protocol `__. During startup, create a ``control_client`` object:: -- IPv4 (default port) c = control_client:new('224.0.0.42') -- IPv6 on default port c = control_client:new('ff02::dead:beef') -- IPv6 on non-default port (requires square brackets) c = control_client:new('[ff02::dead:beef]:1234') -- local socket c = control_client:new('/run/cm4all/workshop/control') -- abstract socket c = control_client:new('@bp-control') The ``new()`` constructor returns ``nil,error`` on error (and thus the call can be wrapped in ``assert()`` to raise a Lua error instead). The method ``build()`` creates an object which can be used to build a control datagram with one or more commands. After that datagram has been assembled, it can be sent with the ``send()`` method. Example:: c:send(c:build():fade_children('foo'):flush_http_cache('bar')) The ``send()`` method returns ``nil,error`` on error. The builder implements the following methods: - ``cancel_job(PARTITION_NAME, JOB_ID)`` - ``discard_session(ID)`` - ``disconnect_database(ACCOUNT)`` - ``fade_children(TAG)`` - ``flush_filter_cache(TAG)`` - ``flush_http_cache(TAG)`` - ``reject_client(ADDRESS)`` - ``reset_limiter(ACCOUNT)`` - ``tarpit_client(ADDRESS)`` - ``terminate_children(TAG)`` libsodium ^^^^^^^^^ There are some `libsodium `__ bindings. `Helpers `__:: bin = sodium.hex2bin("deadbeef") -- returns "\xde\xad\xbe\ef" hex = sodium.bin2hex("A\0\xff") -- returns "4100ff" `Generating random data `__:: key = sodium.randombytes(32) `Sealed boxes `__:: pk, sk = sodium.crypto_box_keypair() ciphertext = sodium.crypto_box_seal('hello world', pk) message = sodium.crypto_box_seal_open(ciphertext, pk, sk) `Point*scalar multiplication __:: pk = sodium.crypto_scalarmult_base(sk) PostgreSQL Client ^^^^^^^^^^^^^^^^^ The Lua script can query a PostgreSQL database. First, a connection should be established during initialization:: db = pg:new('dbname=foo', 'schemaname') In the handler function, queries can be executed like this (the API is similar to `LuaSQL `__):: local result = assert(db:execute('SELECT id, name FROM bar')) local row = result:fetch({}, "a") print(row.id, row.name) Query parameters are passed to ``db:execute()`` as an array after the SQL string:: local result = assert( db:execute('SELECT name FROM bar WHERE id=$1', {42})) The functions ``pg:encode_array()`` and ``pg:decode_array()`` support PostgreSQL arrays; the former encodes a Lua array to a PostgreSQL array string, and the latter decodes a PostgreSQL array string to a Lua array. To listen for `PostgreSQL notifications `__, invoke the ``listen`` method with a callback function:: db:listen('bar', function() print("Received a PostgreSQL NOTIFY") end) Network Namespaces ------------------ The Debian package :file:`cm4all-spawn-netns` contains the systemd service template :file:`cm4all-spawn-netns@.service` which creates a new network namespace connected with the current namespace over a pair of ``veth`` devices. This requires a script in :file:`/etc/cm4all/spawn/netns/setup.d` which sets up the ``veth`` device inside the new namespace; its name is passed as command-line argument. The other ``veth`` device is expected to be set up with :file:`systemd-networkd`. Slice ----- The Debian package :file:`cm4all-slice` contains the systemd slice ``system-cm4all.slice`` where the scopes of most process spawners live. NSS-LogName ----------- The NSS module was moved to https://github.com/CM4all/nss_logname