generated from linux-system-roles/template
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature: The role can manage user units in addition to system units. Each item in each input list can be a string or a `dict` consisting of the item (file, template, or unit), a user name, and a state (for files and templates). The role will not create users and will give an error if a non-existent user is specified. Reason: The role should allow management of user units. Result: The role can manage user units. NOTE: User units only supported on EL8 and later. Signed-off-by: Rich Megginson <[email protected]>
- Loading branch information
Showing
14 changed files
with
830 additions
and
109 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 |
---|---|---|
|
@@ -9,7 +9,8 @@ wrapper around systemd and template Ansible Core modules. | |
|
||
## Requirements | ||
|
||
See below | ||
*NOTE:* Support for user units is not available in EL7 or earlier. This feature | ||
is only available in EL8 and later. | ||
|
||
### Collection requirements | ||
|
||
|
@@ -24,6 +25,26 @@ ansible-galaxy collection install -vv -r meta/collection-requirements.yml | |
|
||
List of variables consumed by the role follows, note that none of them is mandatory. | ||
|
||
Each of the variables can either be a list of strings, or a list of `dicts`. | ||
|
||
The list of strings form assumes that the items to be managed are system units | ||
owned by `root`, and for files, assumes that the files should be `present`. | ||
|
||
The list of `dict` form looks like this: | ||
|
||
```yaml | ||
systemd_unit_files: | ||
- item: some.service | ||
user: my_user | ||
state: [present|absent] | ||
``` | ||
Use the `dict` form to manage user units, and to remove unit files. If using | ||
user units, the role will manage lingering for those users. | ||
|
||
*NOTE:* Support for user units is not available in EL7 or earlier. This feature | ||
is only available in EL8 and later. | ||
|
||
### systemd_unit_files | ||
|
||
List of systemd unit file names that should be deployed to managed nodes. | ||
|
@@ -79,7 +100,7 @@ List of unit files that shall be unmasked via systemd. | |
|
||
This variable is used to handle reboots required by transactional updates. If a transactional update requires a reboot, the role will proceed with the reboot if systemd_transactional_update_reboot_ok is set to true. If set to false, the role will notify the user that a reboot is required, allowing for custom handling of the reboot requirement. If this variable is not set, the role will fail to ensure the reboot requirement is not overlooked. | ||
|
||
Example of setting the variables: | ||
Example of setting the variables for the simple list of strings format: | ||
|
||
```yaml | ||
systemd_unit_files: | ||
|
@@ -96,12 +117,49 @@ systemd_enabled_units: | |
- bar.service | ||
``` | ||
|
||
Example of setting the variables for the list of `dict` format: | ||
|
||
```yaml | ||
systemd_unit_files: | ||
- item: foo.service | ||
user: root | ||
state: present | ||
- item: bar.service | ||
user: my_user | ||
state: absent | ||
systemd_dropins: | ||
- item: cups.service.conf.j2 | ||
user: root | ||
state: present | ||
- item: avahi-daemon.service.conf.j2 | ||
user: my_user | ||
state: absent | ||
systemd_started_units: | ||
- item: foo.service | ||
user: root | ||
- item: bar.service | ||
user: my_user | ||
systemd_enabled_units: | ||
- item: foo.service | ||
user: root | ||
- item: bar.service | ||
user: my_user | ||
``` | ||
|
||
## Variables Exported by the Role | ||
|
||
### `systemd_units` | ||
|
||
Variable shall contain a list of dictionaries where each entry describes state of one systemd unit | ||
present on the managed host. | ||
The variable is a `dict`. Each key is the name of a systemd unit. Each value | ||
is a dict with fields that describe the state of that systemd unit present on | ||
the managed host for the system scope. | ||
|
||
### `systemd_units_user` | ||
|
||
Variable shall contain a dict. Each key is the name of a user given in one of | ||
the lists passed to the role, and `root` (even if `root` is not given). Each | ||
value is a dict of systemd units for that user, or system units for `root`, in | ||
the format of `systemd_units` above. | ||
|
||
## Example Playbook | ||
|
||
|
@@ -112,7 +170,10 @@ present on the managed host. | |
systemd_unit_file_templates: | ||
- foo.service.j2 | ||
systemd_started_units: | ||
- foo.service | ||
- item: foo.service | ||
user: root | ||
- item: bar.service | ||
user: my_user | ||
systemd_enabled_units: | ||
- foo.service | ||
roles: | ||
|
@@ -130,3 +191,4 @@ MIT | |
## Author | ||
|
||
Michal Sekletar <[email protected]> | ||
Rich Megginson <[email protected]> |
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
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
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 @@ | ||
# SPDX-License-Identifier: MIT | ||
# Inputs: | ||
# __systemd_user_info | ||
--- | ||
- name: Check if linger for users can be cancelled | ||
vars: | ||
__systemd_linger_users: "{{ __systemd_user_info | dict2items | | ||
rejectattr('key', 'match', '^root$') | list }}" | ||
when: __systemd_linger_users | length > 0 | ||
block: | ||
- name: Cancel linger for given user | ||
include_tasks: cancel_linger_for_user.yml | ||
vars: | ||
__systemd_linger_data: "{{ __systemd_linger_user_data.value }}" | ||
__systemd_linger_user: "{{ __systemd_linger_user_data.key }}" | ||
loop: "{{ __systemd_linger_users }}" | ||
loop_control: | ||
loop_var: __systemd_linger_user_data |
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,53 @@ | ||
# SPDX-License-Identifier: MIT | ||
# Inputs: | ||
# __systemd_linger_user_data | ||
--- | ||
- name: Get unit files for user | ||
find: | ||
path: "{{ __systemd_linger_data['units_dir'] }}" | ||
register: __systemd_find | ||
|
||
- name: Cancel linger if no files | ||
command: loginctl disable-linger {{ __systemd_linger_user | quote }} | ||
changed_when: true | ||
register: __systemd_cancel_linger | ||
when: __systemd_find.matched == 0 | ||
args: | ||
removes: /var/lib/systemd/linger/{{ __systemd_linger_user }} | ||
|
||
- name: Wait for user session to exit closing state # noqa no-handler | ||
command: loginctl show-user --value -p State {{ __systemd_linger_user | quote }} | ||
register: __systemd_user_state | ||
changed_when: false | ||
until: __systemd_user_state.stdout != "closing" | ||
when: __systemd_cancel_linger is changed | ||
ignore_errors: true | ||
|
||
# see https://github.com/systemd/systemd/issues/26744#issuecomment-2261509208 | ||
- name: Handle user stuck in closing state | ||
vars: | ||
__pat: "Failed to get user: User ID .* is not logged in or lingering" | ||
when: | ||
- __systemd_cancel_linger is changed | ||
- __systemd_user_state is failed | ||
- not __systemd_user_state.stderr is match(__pat) | ||
block: | ||
- name: Stop logind | ||
service: | ||
name: systemd-logind | ||
state: stopped | ||
|
||
- name: Wait for user session to exit closing state | ||
command: loginctl show-user --value -p State {{ __systemd_linger_user | quote }} | ||
changed_when: false | ||
register: __systemd_user_state | ||
until: __systemd_user_state.stderr is match(__pat) or | ||
__systemd_user_state.stdout != "closing" | ||
failed_when: | ||
- not __systemd_user_state.stderr is match(__pat) | ||
- __systemd_user_state.stdout == "closing" | ||
|
||
- name: Restart logind | ||
service: | ||
name: systemd-logind | ||
state: started |
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,15 @@ | ||
# SPDX-License-Identifier: MIT | ||
# Inputs: | ||
# __systemd_units_info | ||
# Outputs: | ||
# ansible_facts | ||
--- | ||
- name: Gather systemd units state for system and user units | ||
systemd_units: | ||
user: "{{ __systemd_units_info.key }}" | ||
user_facts: "{{ ansible_facts['systemd_units_user'] | d({}) }}" | ||
become: "{{ __systemd_units_info.key != 'root' }}" | ||
become_user: "{{ __systemd_units_info.key if __systemd_units_info.key != 'root' | ||
else omit }}" | ||
environment: | ||
XDG_RUNTIME_DIR: "{{ __systemd_units_info.value['xdg_dir'] }}" |
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,40 @@ | ||
# SPDX-License-Identifier: MIT | ||
# Inputs: | ||
# __systemd_user_name | ||
# Outputs: | ||
# __systemd_user_info updated with getent info from user | ||
--- | ||
- name: Get user information | ||
getent: | ||
database: passwd | ||
key: "{{ __systemd_user_name }}" | ||
fail_key: true | ||
when: "'getent_passwd' not in ansible_facts or | ||
__systemd_user_name not in ansible_facts['getent_passwd']" | ||
|
||
- name: Update systemd user info with new user info | ||
when: __systemd_user_name not in __systemd_user_info | ||
set_fact: | ||
__systemd_user_info: | | ||
{% set getent = ansible_facts["getent_passwd"][__systemd_user_name] %} | ||
{% set rv = __systemd_user_info | d({}) %} | ||
{% if __systemd_user_name not in rv %} | ||
{% set _ = rv.__setitem__(__systemd_user_name, {}) %} | ||
{% endif %} | ||
{% if "xdg_dir" not in rv[__systemd_user_name] %} | ||
{% set xdg_dir = "/run/user/" ~ getent[1] %} | ||
{% set _ = rv[__systemd_user_name].update({"xdg_dir": xdg_dir}) %} | ||
{% endif %} | ||
{% if "units_dir" not in rv[__systemd_user_name] %} | ||
{% if __systemd_user_name == "root" %} | ||
{% set _ = rv[__systemd_user_name].update({"units_dir": __admin_units_dir}) %} | ||
{% else %} | ||
{% set units_dir = getent[4] ~ '/' ~ __user_units_dir %} | ||
{% set _ = rv[__systemd_user_name].update({"units_dir": units_dir}) %} | ||
{% endif %} | ||
{% endif %} | ||
{% if "group" not in rv[__systemd_user_name] %} | ||
{% set group = getent[2] %} | ||
{% set _ = rv[__systemd_user_name].update({"group": group}) %} | ||
{% endif %} | ||
{{ rv }} |
Oops, something went wrong.