| =========================== | 
 |  Using Systemd in DevStack | 
 | =========================== | 
 |  | 
 | By default DevStack is run with all the services as systemd unit | 
 | files. Systemd is now the default init system for nearly every Linux | 
 | distro, and systemd encodes and solves many of the problems related to | 
 | poorly running processes. | 
 |  | 
 | Why this instead of screen? | 
 | =========================== | 
 |  | 
 | The screen model for DevStack was invented when the number of services | 
 | that a DevStack user was going to run was typically < 10. This made | 
 | screen hot keys to jump around very easy. However, the landscape has | 
 | changed (not all services are stoppable in screen as some are under | 
 | Apache, there are typically at least 20 items) | 
 |  | 
 | There is also a common developer workflow of changing code in more | 
 | than one service, and needing to restart a bunch of services for that | 
 | to take effect. | 
 |  | 
 | Unit Structure | 
 | ============== | 
 |  | 
 | .. note:: | 
 |  | 
 |    Originally we actually wanted to do this as user units, however | 
 |    there are issues with running this under non interactive | 
 |    shells. For now, we'll be running as system units. Some user unit | 
 |    code is left in place in case we can switch back later. | 
 |  | 
 | All DevStack user units are created as a part of the DevStack slice | 
 | given the name ``devstack@$servicename.service``. This makes it easy | 
 | to understand which services are part of the devstack run, and lets us | 
 | disable / stop them in a single command. | 
 |  | 
 | Manipulating Units | 
 | ================== | 
 |  | 
 | Assuming the unit ``n-cpu`` to make the examples more clear. | 
 |  | 
 | Enable a unit (allows it to be started):: | 
 |  | 
 |   sudo systemctl enable devstack@n-cpu.service | 
 |  | 
 | Disable a unit:: | 
 |  | 
 |   sudo systemctl disable devstack@n-cpu.service | 
 |  | 
 | Start a unit:: | 
 |  | 
 |   sudo systemctl start devstack@n-cpu.service | 
 |  | 
 | Stop a unit:: | 
 |  | 
 |   sudo systemctl stop devstack@n-cpu.service | 
 |  | 
 | Restart a unit:: | 
 |  | 
 |   sudo systemctl restart devstack@n-cpu.service | 
 |  | 
 | See status of a unit:: | 
 |  | 
 |   sudo systemctl status devstack@n-cpu.service | 
 |  | 
 | Operating on more than one unit at a time | 
 | ----------------------------------------- | 
 |  | 
 | Systemd supports wildcarding for unit operations. To restart every | 
 | service in devstack you can do that following:: | 
 |  | 
 |   sudo systemctl restart devstack@* | 
 |  | 
 | Or to see the status of all Nova processes you can do:: | 
 |  | 
 |   sudo systemctl status devstack@n-* | 
 |  | 
 | We'll eventually make the unit names a bit more meaningful so that | 
 | it's easier to understand what you are restarting. | 
 |  | 
 | .. _journalctl-examples: | 
 |  | 
 | Querying Logs | 
 | ============= | 
 |  | 
 | One of the other major things that comes with systemd is journald, a | 
 | consolidated way to access logs (including querying through structured | 
 | metadata). This is accessed by the user via ``journalctl`` command. | 
 |  | 
 |  | 
 | Logs can be accessed through ``journalctl``. journalctl has powerful | 
 | query facilities. We'll start with some common options. | 
 |  | 
 | Follow logs for a specific service:: | 
 |  | 
 |   sudo journalctl -f --unit devstack@n-cpu.service | 
 |  | 
 | Following logs for multiple services simultaneously:: | 
 |  | 
 |   sudo journalctl -f --unit devstack@n-cpu.service --unit devstack@n-cond.service | 
 |  | 
 | or you can even do wild cards to follow all the nova services:: | 
 |  | 
 |   sudo journalctl -f --unit devstack@n-* | 
 |  | 
 | Use higher precision time stamps:: | 
 |  | 
 |   sudo journalctl -f -o short-precise --unit devstack@n-cpu.service | 
 |  | 
 | By default, journalctl strips out "unprintable" characters, including | 
 | ASCII color codes. To keep the color codes (which can be interpreted by | 
 | an appropriate terminal/pager - e.g. ``less``, the default):: | 
 |  | 
 |   sudo journalctl -a --unit devstack@n-cpu.service | 
 |  | 
 | When outputting to the terminal using the default pager, long lines | 
 | will be truncated, but horizontal scrolling is supported via the | 
 | left/right arrow keys. You can override this by setting the | 
 | ``SYSTEMD_LESS`` environment variable to e.g. ``FRXM``. | 
 |  | 
 | You can pipe the output to another tool, such as ``grep``. For | 
 | example, to find a server instance UUID in the nova logs:: | 
 |  | 
 |   sudo journalctl -a --unit devstack@n-* | grep 58391b5c-036f-44d5-bd68-21d3c26349e6 | 
 |  | 
 | See ``man 1 journalctl`` for more. | 
 |  | 
 | Debugging | 
 | ========= | 
 |  | 
 | Using pdb | 
 | --------- | 
 |  | 
 | In order to break into a regular pdb session on a systemd-controlled | 
 | service, you need to invoke the process manually - that is, take it out | 
 | of systemd's control. | 
 |  | 
 | Discover the command systemd is using to run the service:: | 
 |  | 
 |   systemctl show devstack@n-sch.service -p ExecStart --no-pager | 
 |  | 
 | Stop the systemd service:: | 
 |  | 
 |   sudo systemctl stop devstack@n-sch.service | 
 |  | 
 | Inject your breakpoint in the source, e.g.:: | 
 |  | 
 |   import pdb; pdb.set_trace() | 
 |  | 
 | Invoke the command manually:: | 
 |  | 
 |   /usr/local/bin/nova-scheduler --config-file /etc/nova/nova.conf | 
 |  | 
 | Using remote-pdb | 
 | ---------------- | 
 |  | 
 | `remote-pdb`_ works while the process is under systemd control. | 
 |  | 
 | Make sure you have remote-pdb installed:: | 
 |  | 
 |   sudo pip install remote-pdb | 
 |  | 
 | Inject your breakpoint in the source, e.g.:: | 
 |  | 
 |   import remote_pdb; remote_pdb.set_trace() | 
 |  | 
 | Restart the relevant service:: | 
 |  | 
 |   sudo systemctl restart devstack@n-api.service | 
 |  | 
 | The remote-pdb code configures the telnet port when ``set_trace()`` is | 
 | invoked.  Do whatever it takes to hit the instrumented code path, and | 
 | inspect the logs for a message displaying the listening port:: | 
 |  | 
 |   Sep 07 16:36:12 p8-100-neo devstack@n-api.service[772]: RemotePdb session open at 127.0.0.1:46771, waiting for connection ... | 
 |  | 
 | Telnet to that port to enter the pdb session:: | 
 |  | 
 |   telnet 127.0.0.1 46771 | 
 |  | 
 | See the `remote-pdb`_ home page for more options. | 
 |  | 
 | .. _`remote-pdb`: https://pypi.python.org/pypi/remote-pdb | 
 |  | 
 | Known Issues | 
 | ============ | 
 |  | 
 | Be careful about systemd python libraries. There are 3 of them on | 
 | pypi, and they are all very different. They unfortunately all install | 
 | into the ``systemd`` namespace, which can cause some issues. | 
 |  | 
 | - ``systemd-python`` - this is the upstream maintained library, it has | 
 |   a version number like systemd itself (currently ``234``). This is | 
 |   the one you want. | 
 | - ``systemd`` - a python 3 only library, not what you want. | 
 | - ``python-systemd`` - another library you don't want. Installing it | 
 |   on a system will break ansible's ability to run. | 
 |  | 
 |  | 
 | If we were using user units, the ``[Service]`` - ``Group=`` parameter | 
 | doesn't seem to work with user units, even though the documentation | 
 | says that it should. This means that we will need to do an explicit | 
 | ``/usr/bin/sg``. This has the downside of making the SYSLOG_IDENTIFIER | 
 | be ``sg``. We can explicitly set that with ``SyslogIdentifier=``, but | 
 | it's really unfortunate that we're going to need this work | 
 | around. This is currently not a problem because we're only using | 
 | system units. | 
 |  | 
 | Future Work | 
 | =========== | 
 |  | 
 | user units | 
 | ---------- | 
 |  | 
 | It would be great if we could do services as user units, so that there | 
 | is a clear separation of code being run as not root, to ensure running | 
 | as root never accidentally gets baked in as an assumption to | 
 | services. However, user units interact poorly with devstack-gate and | 
 | the way that commands are run as users with ansible and su. | 
 |  | 
 | Maybe someday we can figure that out. | 
 |  | 
 | References | 
 | ========== | 
 |  | 
 | - Arch Linux Wiki - https://wiki.archlinux.org/index.php/Systemd/User | 
 | - Python interface to journald - | 
 |   https://www.freedesktop.org/software/systemd/python-systemd/journal.html | 
 | - Systemd documentation on service files - | 
 |   https://www.freedesktop.org/software/systemd/man/systemd.service.html | 
 | - Systemd documentation on exec (can be used to impact service runs) - | 
 |   https://www.freedesktop.org/software/systemd/man/systemd.exec.html |