-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #196 from flyingcircusio/FC-40738-unit-scaling-com…
…ponent [FC-40738] systemd: init ScalableService component
- Loading branch information
Showing
2 changed files
with
101 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ lib, ... }: | ||
|
||
let | ||
numRunningInstances = lib.toInt "{{ component.running_instances }}"; | ||
baseName = "{{ component.base_name }}"; | ||
in { | ||
systemd.targets."${baseName}" = { | ||
wantedBy = [ "multi-user.target" ]; | ||
# If this target is reached (i.e. started), also start | ||
# {{ component.running_instances }} messenger services. | ||
wants = lib.genList (n: "${baseName}@${toString n}.service") numRunningInstances; | ||
}; | ||
|
||
systemd.services."${baseName}@" = { | ||
# If the target stops or gets restarted, also stop/restart this unit. | ||
partOf = [ "${baseName}.target" ]; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import pkg_resources | ||
from batou.component import Attribute, Component | ||
from batou.lib.file import File | ||
|
||
|
||
class ScalableService(Component): | ||
""" | ||
Configure a systemd unit that can have multiple equal instances, such | ||
as multiple consumers for a message queue. | ||
Usage:: | ||
self += ScalableService("message-consumer", running_instances=5) | ||
self.unit_identifier = self._.unit_identifier | ||
self += File("/etc/local/nixos/message-consumer-settings.nix") | ||
self += Rebuild() | ||
With a `message-consumer-settings.nix` looking like this: | ||
{ | ||
systemd.services."{{ component.unit_identifier }}" = { | ||
serviceConfig = { | ||
/* ExecStart etc. */ | ||
}; | ||
}; | ||
} | ||
This creates a systemd target called `message-consumer.target` | ||
and a template service called `[email protected]`. When | ||
the configuration gets activated, five instances of this service | ||
are started, namely `[email protected]` to | ||
`[email protected]`. When the machine gets rebooted, | ||
these five instances will be started automatically. | ||
The number of instances running by default can be changed with the | ||
`running_instances` attribute. | ||
Please note that the unit is completely empty and thus invalid. A rebuild | ||
must not happen before `message-consumer-settings.nix` in the example above | ||
is added that fully configures the service. | ||
If needed, more services from this template can be started like this: | ||
$ systemctl start message-consumer@{5..23} | ||
This starts 19 additional units. | ||
When running | ||
$ systemctl restart message-consumer.target | ||
all 24 running units will be restarted. | ||
When running | ||
$ systemctl stop message-consumer.target | ||
all 24 running units will be stopped. | ||
However, when running | ||
$ systemctl start message-consumer.target | ||
after that, only 5 units will get back up. The same applies to an | ||
additional deployment or a reboot of the VM. | ||
Hence, starting additional services is a temporary measure to quickly | ||
get more workers up. The change must be persisted in the deployment | ||
after that. | ||
""" | ||
|
||
namevar = "base_name" | ||
running_instances = Attribute(int, 4) | ||
|
||
def configure(self): | ||
self += File( | ||
f"/etc/local/nixos/scale-{self.base_name}.nix", | ||
content=pkg_resources.resource_string( | ||
"batou_ext", "resources/scalable-service.nix" | ||
), | ||
) | ||
|
||
self.unit_identifier = f"{self.base_name}@" |