golden hour
/usr/lib/python3.9/site-packages/ansible/modules
⬆️ Go Up
Upload
File/Folder
Size
Actions
__init__.py
0 B
Del
OK
__pycache__
-
Del
OK
_include.py
3.06 KB
Del
OK
add_host.py
3.82 KB
Del
OK
apt.py
57.4 KB
Del
OK
apt_key.py
17.45 KB
Del
OK
apt_repository.py
28.39 KB
Del
OK
assemble.py
8.76 KB
Del
OK
assert.py
2.75 KB
Del
OK
async_status.py
4.29 KB
Del
OK
async_wrapper.py
11.43 KB
Del
OK
blockinfile.py
13.29 KB
Del
OK
command.py
12.64 KB
Del
OK
copy.py
34.75 KB
Del
OK
cron.py
25.57 KB
Del
OK
debconf.py
7.55 KB
Del
OK
debug.py
2.89 KB
Del
OK
dnf.py
58.16 KB
Del
OK
dpkg_selections.py
2.35 KB
Del
OK
expect.py
8.33 KB
Del
OK
fail.py
1.67 KB
Del
OK
fetch.py
4.17 KB
Del
OK
file.py
39.93 KB
Del
OK
find.py
18.73 KB
Del
OK
gather_facts.py
2.5 KB
Del
OK
get_url.py
26.22 KB
Del
OK
getent.py
5.56 KB
Del
OK
git.py
55.22 KB
Del
OK
group.py
19.57 KB
Del
OK
group_by.py
2.41 KB
Del
OK
hostname.py
28.12 KB
Del
OK
import_playbook.py
2.06 KB
Del
OK
import_role.py
3.27 KB
Del
OK
import_tasks.py
2.14 KB
Del
OK
include_role.py
4.15 KB
Del
OK
include_tasks.py
2.64 KB
Del
OK
include_vars.py
6.45 KB
Del
OK
iptables.py
32.27 KB
Del
OK
known_hosts.py
13.5 KB
Del
OK
lineinfile.py
23.39 KB
Del
OK
meta.py
5.84 KB
Del
OK
package.py
3.33 KB
Del
OK
package_facts.py
17.71 KB
Del
OK
pause.py
3.44 KB
Del
OK
ping.py
2.32 KB
Del
OK
pip.py
30 KB
Del
OK
raw.py
3.57 KB
Del
OK
reboot.py
4.64 KB
Del
OK
replace.py
11.19 KB
Del
OK
rpm_key.py
8.48 KB
Del
OK
script.py
4.03 KB
Del
OK
service.py
63.85 KB
Del
OK
service_facts.py
16.73 KB
Del
OK
set_fact.py
5.62 KB
Del
OK
set_stats.py
2.6 KB
Del
OK
setup.py
10.79 KB
Del
OK
shell.py
6.57 KB
Del
OK
slurp.py
3.19 KB
Del
OK
stat.py
19.62 KB
Del
OK
subversion.py
13.22 KB
Del
OK
systemd.py
22.82 KB
Del
OK
systemd_service.py
22.82 KB
Del
OK
sysvinit.py
13.47 KB
Del
OK
tempfile.py
3.42 KB
Del
OK
template.py
3.1 KB
Del
OK
unarchive.py
42.79 KB
Del
OK
uri.py
27.78 KB
Del
OK
user.py
114.18 KB
Del
OK
validate_argument_spec.py
2.99 KB
Del
OK
wait_for.py
25.91 KB
Del
OK
wait_for_connection.py
3.38 KB
Del
OK
yum.py
72.05 KB
Del
OK
yum_repository.py
24.82 KB
Del
OK
Edit: systemd_service.py
# -*- coding: utf-8 -*- # Copyright: (c) 2016, Brian Coca <bcoca@ansible.com> # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = ''' module: systemd_service author: - Ansible Core Team version_added: "2.2" short_description: Manage systemd units description: - Controls systemd units (services, timers, and so on) on remote hosts. options: name: description: - Name of the unit. This parameter takes the name of exactly one unit to work with. - When no extension is given, it is implied to a C(.service) as systemd. - When using in a chroot environment you always need to specify the name of the unit with the extension. For example, C(crond.service). type: str aliases: [ service, unit ] state: description: - C(started)/C(stopped) are idempotent actions that will not run commands unless necessary. C(restarted) will always bounce the unit. C(reloaded) will always reload. type: str choices: [ reloaded, restarted, started, stopped ] enabled: description: - Whether the unit should start on boot. B(At least one of state and enabled are required.) type: bool force: description: - Whether to override existing symlinks. type: bool version_added: 2.6 masked: description: - Whether the unit should be masked or not, a masked unit is impossible to start. type: bool daemon_reload: description: - Run daemon-reload before doing any other operations, to make sure systemd has read any changes. - When set to C(true), runs daemon-reload even if the module does not start or stop anything. type: bool default: no aliases: [ daemon-reload ] daemon_reexec: description: - Run daemon_reexec command before doing any other operations, the systemd manager will serialize the manager state. type: bool default: no aliases: [ daemon-reexec ] version_added: "2.8" scope: description: - Run systemctl within a given service manager scope, either as the default system scope C(system), the current user's scope C(user), or the scope of all users C(global). - "For systemd to work with 'user', the executing user must have its own instance of dbus started and accessible (systemd requirement)." - "The user dbus process is normally started during normal login, but not during the run of Ansible tasks. Otherwise you will probably get a 'Failed to connect to bus: no such file or directory' error." - The user must have access, normally given via setting the C(XDG_RUNTIME_DIR) variable, see example below. type: str choices: [ system, user, global ] default: system version_added: "2.7" no_block: description: - Do not synchronously wait for the requested operation to finish. Enqueued job will continue without Ansible blocking on its completion. type: bool default: no version_added: "2.3" extends_documentation_fragment: action_common_attributes attributes: check_mode: support: full diff_mode: support: none platform: platforms: posix notes: - Since 2.4, one of the following options is required C(state), C(enabled), C(masked), C(daemon_reload), (C(daemon_reexec) since 2.8), and all except C(daemon_reload) and (C(daemon_reexec) since 2.8) also require C(name). - Before 2.4 you always required C(name). - Globs are not supported in name, i.e C(postgres*.service). - The service names might vary by specific OS/distribution requirements: - A system managed by systemd. ''' EXAMPLES = ''' - name: Make sure a service unit is running ansible.builtin.systemd: state: started name: httpd - name: Stop service cron on debian, if running ansible.builtin.systemd: name: cron state: stopped - name: Restart service cron on centos, in all cases, also issue daemon-reload to pick up config changes ansible.builtin.systemd: state: restarted daemon_reload: true name: crond - name: Reload service httpd, in all cases ansible.builtin.systemd: name: httpd.service state: reloaded - name: Enable service httpd and ensure it is not masked ansible.builtin.systemd: name: httpd enabled: true masked: no - name: Enable a timer unit for dnf-automatic ansible.builtin.systemd: name: dnf-automatic.timer state: started enabled: true - name: Just force systemd to reread configs (2.4 and above) ansible.builtin.systemd: daemon_reload: true - name: Just force systemd to re-execute itself (2.8 and above) ansible.builtin.systemd: daemon_reexec: true - name: Run a user service when XDG_RUNTIME_DIR is not set on remote login ansible.builtin.systemd: name: myservice state: started scope: user environment: XDG_RUNTIME_DIR: "/run/user/{{ myuid }}" ''' RETURN = ''' status: description: A dictionary with the key=value pairs returned from C(systemctl show). returned: success type: complex sample: { "ActiveEnterTimestamp": "Sun 2016-05-15 18:28:49 EDT", "ActiveEnterTimestampMonotonic": "8135942", "ActiveExitTimestampMonotonic": "0", "ActiveState": "active", "After": "auditd.service systemd-user-sessions.service time-sync.target systemd-journald.socket basic.target system.slice", "AllowIsolate": "no", "Before": "shutdown.target multi-user.target", "BlockIOAccounting": "no", "BlockIOWeight": "1000", "CPUAccounting": "no", "CPUSchedulingPolicy": "0", "CPUSchedulingPriority": "0", "CPUSchedulingResetOnFork": "no", "CPUShares": "1024", "CanIsolate": "no", "CanReload": "yes", "CanStart": "yes", "CanStop": "yes", "CapabilityBoundingSet": "18446744073709551615", "ConditionResult": "yes", "ConditionTimestamp": "Sun 2016-05-15 18:28:49 EDT", "ConditionTimestampMonotonic": "7902742", "Conflicts": "shutdown.target", "ControlGroup": "/system.slice/crond.service", "ControlPID": "0", "DefaultDependencies": "yes", "Delegate": "no", "Description": "Command Scheduler", "DevicePolicy": "auto", "EnvironmentFile": "/etc/sysconfig/crond (ignore_errors=no)", "ExecMainCode": "0", "ExecMainExitTimestampMonotonic": "0", "ExecMainPID": "595", "ExecMainStartTimestamp": "Sun 2016-05-15 18:28:49 EDT", "ExecMainStartTimestampMonotonic": "8134990", "ExecMainStatus": "0", "ExecReload": "{ path=/bin/kill ; argv[]=/bin/kill -HUP $MAINPID ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", "ExecStart": "{ path=/usr/sbin/crond ; argv[]=/usr/sbin/crond -n $CRONDARGS ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", "FragmentPath": "/usr/lib/systemd/system/crond.service", "GuessMainPID": "yes", "IOScheduling": "0", "Id": "crond.service", "IgnoreOnIsolate": "no", "IgnoreOnSnapshot": "no", "IgnoreSIGPIPE": "yes", "InactiveEnterTimestampMonotonic": "0", "InactiveExitTimestamp": "Sun 2016-05-15 18:28:49 EDT", "InactiveExitTimestampMonotonic": "8135942", "JobTimeoutUSec": "0", "KillMode": "process", "KillSignal": "15", "LimitAS": "18446744073709551615", "LimitCORE": "18446744073709551615", "LimitCPU": "18446744073709551615", "LimitDATA": "18446744073709551615", "LimitFSIZE": "18446744073709551615", "LimitLOCKS": "18446744073709551615", "LimitMEMLOCK": "65536", "LimitMSGQUEUE": "819200", "LimitNICE": "0", "LimitNOFILE": "4096", "LimitNPROC": "3902", "LimitRSS": "18446744073709551615", "LimitRTPRIO": "0", "LimitRTTIME": "18446744073709551615", "LimitSIGPENDING": "3902", "LimitSTACK": "18446744073709551615", "LoadState": "loaded", "MainPID": "595", "MemoryAccounting": "no", "MemoryLimit": "18446744073709551615", "MountFlags": "0", "Names": "crond.service", "NeedDaemonReload": "no", "Nice": "0", "NoNewPrivileges": "no", "NonBlocking": "no", "NotifyAccess": "none", "OOMScoreAdjust": "0", "OnFailureIsolate": "no", "PermissionsStartOnly": "no", "PrivateNetwork": "no", "PrivateTmp": "no", "RefuseManualStart": "no", "RefuseManualStop": "no", "RemainAfterExit": "no", "Requires": "basic.target", "Restart": "no", "RestartUSec": "100ms", "Result": "success", "RootDirectoryStartOnly": "no", "SameProcessGroup": "no", "SecureBits": "0", "SendSIGHUP": "no", "SendSIGKILL": "yes", "Slice": "system.slice", "StandardError": "inherit", "StandardInput": "null", "StandardOutput": "journal", "StartLimitAction": "none", "StartLimitBurst": "5", "StartLimitInterval": "10000000", "StatusErrno": "0", "StopWhenUnneeded": "no", "SubState": "running", "SyslogLevelPrefix": "yes", "SyslogPriority": "30", "TTYReset": "no", "TTYVHangup": "no", "TTYVTDisallocate": "no", "TimeoutStartUSec": "1min 30s", "TimeoutStopUSec": "1min 30s", "TimerSlackNSec": "50000", "Transient": "no", "Type": "simple", "UMask": "0022", "UnitFileState": "enabled", "WantedBy": "multi-user.target", "Wants": "system.slice", "WatchdogTimestampMonotonic": "0", "WatchdogUSec": "0", } ''' # NOQA import os from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.facts.system.chroot import is_chroot from ansible.module_utils.service import sysv_exists, sysv_is_enabled, fail_if_missing from ansible.module_utils._text import to_native def is_running_service(service_status): return service_status['ActiveState'] in set(['active', 'activating']) def is_deactivating_service(service_status): return service_status['ActiveState'] in set(['deactivating']) def request_was_ignored(out): return '=' not in out and ('ignoring request' in out or 'ignoring command' in out) def parse_systemctl_show(lines): # The output of 'systemctl show' can contain values that span multiple lines. At first glance it # appears that such values are always surrounded by {}, so the previous version of this code # assumed that any value starting with { was a multi-line value; it would then consume lines # until it saw a line that ended with }. However, it is possible to have a single-line value # that starts with { but does not end with } (this could happen in the value for Description=, # for example), and the previous version of this code would then consume all remaining lines as # part of that value. Cryptically, this would lead to Ansible reporting that the service file # couldn't be found. # # To avoid this issue, the following code only accepts multi-line values for keys whose names # start with Exec (e.g., ExecStart=), since these are the only keys whose values are known to # span multiple lines. parsed = {} multival = [] k = None for line in lines: if k is None: if '=' in line: k, v = line.split('=', 1) if k.startswith('Exec') and v.lstrip().startswith('{'): if not v.rstrip().endswith('}'): multival.append(v) continue parsed[k] = v.strip() k = None else: multival.append(line) if line.rstrip().endswith('}'): parsed[k] = '\n'.join(multival).strip() multival = [] k = None return parsed # =========================================== # Main control flow def main(): # initialize module = AnsibleModule( argument_spec=dict( name=dict(type='str', aliases=['service', 'unit']), state=dict(type='str', choices=['reloaded', 'restarted', 'started', 'stopped']), enabled=dict(type='bool'), force=dict(type='bool'), masked=dict(type='bool'), daemon_reload=dict(type='bool', default=False, aliases=['daemon-reload']), daemon_reexec=dict(type='bool', default=False, aliases=['daemon-reexec']), scope=dict(type='str', default='system', choices=['system', 'user', 'global']), no_block=dict(type='bool', default=False), ), supports_check_mode=True, required_one_of=[['state', 'enabled', 'masked', 'daemon_reload', 'daemon_reexec']], required_by=dict( state=('name', ), enabled=('name', ), masked=('name', ), ), ) unit = module.params['name'] if unit is not None: for globpattern in (r"*", r"?", r"["): if globpattern in unit: module.fail_json(msg="This module does not currently support using glob patterns, found '%s' in service name: %s" % (globpattern, unit)) systemctl = module.get_bin_path('systemctl', True) if os.getenv('XDG_RUNTIME_DIR') is None: os.environ['XDG_RUNTIME_DIR'] = '/run/user/%s' % os.geteuid() ''' Set CLI options depending on params ''' # if scope is 'system' or None, we can ignore as there is no extra switch. # The other choices match the corresponding switch if module.params['scope'] != 'system': systemctl += " --%s" % module.params['scope'] if module.params['no_block']: systemctl += " --no-block" if module.params['force']: systemctl += " --force" rc = 0 out = err = '' result = dict( name=unit, changed=False, status=dict(), ) # Run daemon-reload first, if requested if module.params['daemon_reload'] and not module.check_mode: (rc, out, err) = module.run_command("%s daemon-reload" % (systemctl)) if rc != 0: module.fail_json(msg='failure %d during daemon-reload: %s' % (rc, err)) # Run daemon-reexec if module.params['daemon_reexec'] and not module.check_mode: (rc, out, err) = module.run_command("%s daemon-reexec" % (systemctl)) if rc != 0: module.fail_json(msg='failure %d during daemon-reexec: %s' % (rc, err)) if unit: found = False is_initd = sysv_exists(unit) is_systemd = False # check service data, cannot error out on rc as it changes across versions, assume not found (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit)) if rc == 0 and not (request_was_ignored(out) or request_was_ignored(err)): # load return of systemctl show into dictionary for easy access and return if out: result['status'] = parse_systemctl_show(to_native(out).split('\n')) is_systemd = 'LoadState' in result['status'] and result['status']['LoadState'] != 'not-found' is_masked = 'LoadState' in result['status'] and result['status']['LoadState'] == 'masked' # Check for loading error if is_systemd and not is_masked and 'LoadError' in result['status']: module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result['status']['LoadError'])) # Workaround for https://github.com/ansible/ansible/issues/71528 elif err and rc == 1 and 'Failed to parse bus message' in err: result['status'] = parse_systemctl_show(to_native(out).split('\n')) unit_base, sep, suffix = unit.partition('@') unit_search = '{unit_base}{sep}'.format(unit_base=unit_base, sep=sep) (rc, out, err) = module.run_command("{systemctl} list-unit-files '{unit_search}*'".format(systemctl=systemctl, unit_search=unit_search)) is_systemd = unit_search in out (rc, out, err) = module.run_command("{systemctl} is-active '{unit}'".format(systemctl=systemctl, unit=unit)) result['status']['ActiveState'] = out.rstrip('\n') else: # list taken from man systemctl(1) for systemd 244 valid_enabled_states = [ "enabled", "enabled-runtime", "linked", "linked-runtime", "masked", "masked-runtime", "static", "indirect", "disabled", "generated", "transient"] (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit)) if out.strip() in valid_enabled_states: is_systemd = True else: # fallback list-unit-files as show does not work on some systems (chroot) # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit)) if rc == 0: is_systemd = True else: # Check for systemctl command module.run_command(systemctl, check_rc=True) # Does service exist? found = is_systemd or is_initd if is_initd and not is_systemd: module.warn('The service (%s) is actually an init script but the system is managed by systemd' % unit) # mask/unmask the service, if requested, can operate on services before they are installed if module.params['masked'] is not None: # state is not masked unless systemd affirms otherwise (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit)) masked = out.strip() == "masked" if masked != module.params['masked']: result['changed'] = True if module.params['masked']: action = 'mask' else: action = 'unmask' if not module.check_mode: (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit)) if rc != 0: # some versions of system CAN mask/unmask non existing services, we only fail on missing if they don't fail_if_missing(module, found, unit, msg='host') # Enable/disable service startup at boot if requested if module.params['enabled'] is not None: if module.params['enabled']: action = 'enable' else: action = 'disable' fail_if_missing(module, found, unit, msg='host') # do we need to enable the service? enabled = False (rc, out, err) = module.run_command("%s is-enabled '%s' -l" % (systemctl, unit)) # check systemctl result or if it is a init script if rc == 0: enabled = True # Check if the service is indirect or alias and if out contains exactly 1 line of string 'indirect'/ 'alias' it's disabled if out.splitlines() == ["indirect"] or out.splitlines() == ["alias"]: enabled = False elif rc == 1: # if not a user or global user service and both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries if module.params['scope'] == 'system' and \ is_initd and \ not out.strip().endswith('disabled') and \ sysv_is_enabled(unit): enabled = True # default to current state result['enabled'] = enabled # Change enable/disable if needed if enabled != module.params['enabled']: result['changed'] = True if not module.check_mode: (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit)) if rc != 0: module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, out + err)) result['enabled'] = not enabled # set service state if requested if module.params['state'] is not None: fail_if_missing(module, found, unit, msg="host") # default to desired state result['state'] = module.params['state'] # What is current service state? if 'ActiveState' in result['status']: action = None if module.params['state'] == 'started': if not is_running_service(result['status']): action = 'start' elif module.params['state'] == 'stopped': if is_running_service(result['status']) or is_deactivating_service(result['status']): action = 'stop' else: if not is_running_service(result['status']): action = 'start' else: action = module.params['state'][:-2] # remove 'ed' from restarted/reloaded result['state'] = 'started' if action: result['changed'] = True if not module.check_mode: (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit)) if rc != 0: module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, err)) # check for chroot elif is_chroot(module) or os.environ.get('SYSTEMD_OFFLINE') == '1': module.warn("Target is a chroot or systemd is offline. This can lead to false positives or prevent the init system tools from working.") else: # this should not happen? module.fail_json(msg="Service is in unknown state", status=result['status']) module.exit_json(**result) if __name__ == '__main__': main()
Save