diff --git a/system/at b/system/at index ffac9d1d535..274aa1dd77d 100644 --- a/system/at +++ b/system/at @@ -25,13 +25,8 @@ short_description: Schedule the execution of a command or scripts via the at com description: - Use this module to schedule a command or script to run once in the future. - All jobs are executed in the a queue. -version_added: "0.0" +version_added: "1.5" options: - user: - description: - - The user to execute the at command as. - required: false - default: null command: description: - A command to be executed in the future. @@ -42,22 +37,26 @@ options: - An existing script to be executed in the future. required: false default: null - unit_count: + count: description: - The count of units in the future to execute the command or script. required: true - unit_type: + units: description: - The type of units in the future to execute the command or script. required: true choices: ["minutes", "hours", "days", "weeks"] - action: + state: description: - - The action to take for the job defaulting to add. Unique will verify that there is only one entry in the queue. - - Delete will remove all existing queued jobs. - required: true - choices: ["add", "delete", "unique"] - default: add + - The state dictates if the command or script_file should be evaluated as present(added) or absent(deleted). + required: false + choices: ["present", "absent"] + default: "present" + unique: + description: + - If a matching job is present a new job will not be added. + required: false + default: false requirements: - at author: Richard Isaacson @@ -65,33 +64,41 @@ author: Richard Isaacson EXAMPLES = ''' # Schedule a command to execute in 20 minutes as root. -- at: command="ls -d / > /dev/null" unit_count=20 unit_type="minutes" - -# Schedule a script to execute in 1 hour as the neo user. -- at: script_file="/some/script.sh" user="neo" unit_count=1 unit_type="hours" +- at: command="ls -d / > /dev/null" count=20 units="minutes" # Match a command to an existing job and delete the job. -- at: command="ls -d / > /dev/null" action="delete" +- at: command="ls -d / > /dev/null" state="absent" # Schedule a command to execute in 20 minutes making sure it is unique in the queue. -- at: command="ls -d / > /dev/null" action="unique" unit_count=20 unit_type="minutes" +- at: command="ls -d / > /dev/null" unique=true count=20 units="minutes" ''' import os import tempfile +def add_job(module, result, at_cmd, count, units, command, script_file): + at_command = "%s now + %s %s -f %s" % (at_cmd, count, units, script_file) + rc, out, err = module.run_command(at_command, check_rc=True) + if command: + os.unlink(script_file) + result['changed'] = True -def matching_jobs(module, at_cmd, script_file, user=None): +def delete_job(module, result, at_cmd, command, script_file): + for matching_job in matching_jobs(module, at_cmd, script_file): + at_command = "%s -d %s" % (at_cmd, matching_job) + rc, out, err = module.run_command(at_command, check_rc=True) + result['changed'] = True + if command: + os.unlink(script_file) + module.exit_json(**result) + +def matching_jobs(module, at_cmd, script_file): matching_jobs = [] atq_cmd = module.get_bin_path('atq', True) # Get list of job numbers for the user. atq_command = "%s" % (atq_cmd) - if user: - atq_command = "su '%s' -c '%s'" % (user, atq_command) - rc, out, err = module.run_command(atq_command) - if rc != 0: - module.fail_json(msg=err) + rc, out, err = module.run_command(atq_command, check_rc=True) current_jobs = out.splitlines() if len(current_jobs) == 0: return matching_jobs @@ -104,100 +111,85 @@ def matching_jobs(module, at_cmd, script_file, user=None): for current_job in current_jobs: split_current_job = current_job.split() at_command = "%s -c %s" % (at_cmd, split_current_job[0]) - if user: - at_command = "su '%s' -c '%s'" % (user, at_command) - rc, out, err = module.run_command(at_command) - if rc != 0: - module.fail_json(msg=err) + rc, out, err = module.run_command(at_command, check_rc=True) if script_file_string in out: matching_jobs.append(split_current_job[0]) # Return the list. return matching_jobs +def create_tempfile(command): + filed, script_file = tempfile.mkstemp(prefix='at') + fileh = os.fdopen(filed, 'w') + fileh.write(command) + fileh.close() + return script_file + #================================================ def main(): module = AnsibleModule( argument_spec = dict( - user=dict(required=False), - command=dict(required=False), - script_file=dict(required=False), - unit_count=dict(required=False, + command=dict(required=False, + type='str'), + script_file=dict(required=False, + type='str'), + count=dict(required=False, type='int'), - unit_type=dict(required=False, + units=dict(required=False, default=None, - choices=["minutes", "hours", "days", "weeks"], - type="str"), - action=dict(required=False, - default="add", - choices=["add", "delete", "unique"], - type="str") + choices=['minutes', 'hours', 'days', 'weeks'], + type='str'), + state=dict(required=False, + default='present', + choices=['present', 'absent'], + type='str'), + unique=dict(required=False, + default=False, + type='bool') ), - supports_check_mode = False, + mutually_exclusive = [['command', 'script_file']], + required_one_of = [['command', 'script_file']], + supports_check_mode = False ) at_cmd = module.get_bin_path('at', True) - user = module.params['user'] command = module.params['command'] script_file = module.params['script_file'] - unit_count = module.params['unit_count'] - unit_type = module.params['unit_type'] - action = module.params['action'] + count = module.params['count'] + units = module.params['units'] + state = module.params['state'] + unique = module.params['unique'] - if ((action == 'add') and (not unit_count or not unit_type)): - module.fail_json(msg="add action requires unit_count and unit_type") - - if (not command) and (not script_file): - module.fail_json(msg="command or script_file not specified") - - if command and script_file: - module.fail_json(msg="command and script_file are mutually exclusive") + if ((state == 'present') and (not count or not units)): + module.fail_json(msg="present state requires count and units") result = {} - result['action'] = action + result['state'] = state result['changed'] = False # If command transform it into a script_file if command: - filed, script_file = tempfile.mkstemp(prefix='at') - fileh = os.fdopen(filed, 'w') - fileh.write(command) - fileh.close() + script_file = create_tempfile(command) - # if delete then return - if action == 'delete': - for matching_job in matching_jobs(module, at_cmd, script_file, user): - at_command = "%s -d %s" % (at_cmd, matching_job) - if user: - at_command = "su '%s' -c '%s'" % (user, at_ccommand) - rc, out, err = module.run_command(at_command) - if rc != 0: - module.fail_json(msg=err) - result['changed'] = True - module.exit_json(**result) + # if absent remove existing and return + if state == 'absent': + delete_job(module, result, at_cmd, command, script_file) # if unique if existing return unchanged - if action == 'unique': - if len(matching_jobs(module, at_cmd, script_file, user)) != 0: + if unique: + if len(matching_jobs(module, at_cmd, script_file)) != 0: + if command: + os.unlink(script_file) module.exit_json(**result) result['script_file'] = script_file - result['unit_count'] = unit_count - result['unit_type'] = unit_type + result['count'] = count + result['units'] = units - at_command = "%s now + %s %s -f %s" % (at_cmd, unit_count, unit_type, script_file) - if user: - # We expect that if this is an installed the permissions are already correct for the user to execute it. - at_command = "su '%s' -c '%s'" % (user, at_command) - rc, out, err = module.run_command(at_command) - if rc != 0: - module.fail_json(msg=err) - if command: - os.unlink(script_file) - result['changed'] = True + add_job(module, result, at_cmd, count, units, command, script_file) module.exit_json(**result)