diff options
| author | Robert Günzler <r@gnzler.io> | 2025-09-07 17:32:13 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2025-09-07 17:42:42 +0200 |
| commit | 38be6c13f76e893cf47636257071b440dec0c5b2 (patch) | |
| tree | f7ded3235a7e3362cbd1ed3d91523968fe0faf90 /items/svc_openrc2.py | |
initial commit
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to 'items/svc_openrc2.py')
| -rw-r--r-- | items/svc_openrc2.py | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/items/svc_openrc2.py b/items/svc_openrc2.py new file mode 100644 index 0000000..5b74f61 --- /dev/null +++ b/items/svc_openrc2.py @@ -0,0 +1,126 @@ +from shlex import quote + +from bundlewrap.exceptions import BundleError +from bundlewrap.items import Item +from bundlewrap.utils.text import mark_for_translation as _ + + +def svc_start(node, svcname): + return node.run(f"rc-service {quote(svcname)} start", may_fail=True) + + +def svc_running(node, svcname): + result = node.run(f"rc-service {quote(svcname)} status", may_fail=True) + return result.return_code == 0 and "started" in result.stdout_text + + +def svc_stop(node, svcname): + return node.run(f"rc-service {quote(svcname)} stop", may_fail=True) + + +def svc_enable(node, svcname, runlevel): + return node.run(f"rc-update add {quote(svcname)} {quote(runlevel)}", may_fail=True) + + +def svc_enabled(node, svcname, runlevel): + result = node.run( + f"rc-update show {quote(runlevel)} | grep -w {quote(svcname)}", + may_fail=True, + ) + return result.return_code == 0 and svcname in result.stdout_text + + +def svc_runlevel(node, svcname): + result = node.run( + f"rc-update show --all | grep -w {quote(svcname)} | cut -d \\| -f 2", + may_fail=True, + ) + return result.stdout_text.strip() if result.return_code == 0 else None + + +def svc_disable(node, svcname, runlevel): + return node.run(f"rc-update del {quote(svcname)} {quote(runlevel)}", may_fail=True) + + +class SvcOpenRC2(Item): + """ + A service managed by OpenRC init scripts. + """ + + BUNDLE_ATTRIBUTE_NAME = "svc_openrc2" + ITEM_ATTRIBUTES = { + "running": True, + "enabled": True, + "runlevel": "default", + } + ITEM_TYPE_NAME = "svc_openrc2" + + def __repr__(self): + return "<SvcOpenRC name:{} runlevel:{} enabled:{} running:{}>".format( + self.name, + self.attributes["runlevel"], + self.attributes["enabled"], + self.attributes["running"], + ) + + def fix(self, status): + if "enabled" in status.keys_to_fix: + if self.attributes["enabled"]: + svc_enable(self.node, self.name, self.attributes["runlevel"]) + else: + svc_disable(self.node, self.name, self.attributes["runlevel"]) + + if "running" in status.keys_to_fix: + if self.attributes["running"]: + svc_start(self.node, self.name) + else: + svc_stop(self.node, self.name) + + if "runlevel" in status.keys_to_fix: + if status.sdict["runlevel"]: + svc_disable(self.node, self.name, status.sdict["runlevel"]) + svc_enable(self.node, self.name, self.attributes["runlevel"]) + + def get_canned_actions(self): + return { + "stop": { + "command": f"rc-service {self.name} stop", + "needed_by": {self.id}, + }, + "restart": { + "command": f"rc-service {self.name} restart", + "needs": {self.id}, + }, + "reload": { + "command": f"rc-service {self.name} reload".format(self.name), + "needs": { + # make sure we don't reload and restart simultaneously + f"{self.id}:restart", + # with only the dep on restart, we might still end + # up reloading if the service itself is skipped + # because the restart action has cascade_skip False + self.id, + }, + }, + } + + def sdict(self): + return { + "enabled": svc_enabled(self.node, self.name, self.attributes["runlevel"]), + "running": svc_running(self.node, self.name), + "runlevel": svc_runlevel(self.node, self.name), + } + + @classmethod + def validate_attributes(cls, bundle, item_id, attributes): + for attribute in ("enabled", "running"): + if attributes.get(attribute, None) not in (True, False, None): + raise BundleError( + _( + "expected boolean or None for '{attribute}' on {item} in bundle '{bundle}'" + ).format( + attribute=attribute, + bundle=bundle.name, + item=item_id, + ) + ) |