From bcca609bc6693aec600e17db26c7c77f32ceb8d7 Mon Sep 17 00:00:00 2001 From: Yap Sok Ann Date: Mon, 17 Jun 2013 11:29:48 +0800 Subject: [PATCH 1/9] Add OpenRC support to the service module. --- library/system/service | 69 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/library/system/service b/library/system/service index fe3f334bfe..8542dcbdcb 100644 --- a/library/system/service +++ b/library/system/service @@ -54,6 +54,12 @@ options: - Whether the service should start on boot. At least one of state and enabled are required. + runlevel: + required: false + description: + - The runlevel that this service belongs to. Needed by OpenRC system + (e.g. Gentoo), and default to "default" if not set. + arguments: description: - Additional arguments provided on the command line @@ -77,6 +83,7 @@ examples: import platform import os +import re import tempfile import shlex import select @@ -107,8 +114,10 @@ class Service(object): self.state = module.params['state'] self.pattern = module.params['pattern'] self.enable = module.params['enabled'] + self.runlevel = module.params['runlevel'] self.changed = False self.running = None + self.crashed = None self.action = None self.svc_cmd = None self.svc_initscript = None @@ -352,7 +361,7 @@ class LinuxService(Service): def get_service_tools(self): paths = [ '/sbin', '/usr/sbin', '/bin', '/usr/bin' ] - binaries = [ 'service', 'chkconfig', 'update-rc.d', 'initctl', 'systemctl', 'start', 'stop', 'restart' ] + binaries = [ 'service', 'chkconfig', 'update-rc.d', 'rc-service', 'rc-update', 'initctl', 'systemctl', 'start', 'stop', 'restart' ] initpaths = [ '/etc/init.d' ] location = dict() @@ -371,6 +380,11 @@ class LinuxService(Service): elif location.get('update-rc.d', None) and os.path.exists("/etc/init.d/%s" % self.name): # service is managed by with SysV init scripts, but with update-rc.d self.enable_cmd = location['update-rc.d'] + elif location.get('rc-service', None) and not location.get('systemctl', None): + # service is managed by OpenRC + self.svc_cmd = location['rc-service'] + self.enable_cmd = location['rc-update'] + return elif location.get('systemctl', None): # verify service is managed by systemd @@ -427,6 +441,11 @@ class LinuxService(Service): elif initctl_status_stdout.find("start/running") != -1: self.running = True + if self.svc_cmd.endswith("rc-service") and self.running is None: + openrc_rc, openrc_status_stdout, openrc_status_stderr = self.execute_command("%s %s status" % (self.svc_cmd, self.name)) + self.running = "started" in openrc_status_stdout + self.crashed = "crashed" in openrc_status_stderr + # if the job status is still not known check it by response code # For reference, see: # http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html @@ -501,19 +520,44 @@ class LinuxService(Service): elif not self.enable: return - # we change argument depending on real binary used - # update-rc.d wants enable/disable while - # chkconfig wants on/off - # also, systemctl needs the argument order reversed + if self.enable_cmd.endswith("rc-update"): + (rc, out, err) = self.execute_command("%s show" % self.enable_cmd) + for line in out.splitlines(): + service_name, runlevels = line.split('|') + service_name = service_name.strip() + if service_name != self.name: + continue + runlevels = re.split(r'\s+', runlevels) + # service already enabled for the runlevel + if self.enable and self.runlevel in runlevels: + return + # service already disabled for the runlevel + elif not self.enable and self.runlevel not in runlevels: + return + break + else: + # service already disabled altogether + if not self.enable: + return + + # we change argument depending on real binary used: + # - update-rc.d and systemctl wants enable/disable + # - chkconfig wants on/off + # - rc-update wants add/delete + # also, rc-update and systemctl needs the argument order reversed if self.enable: on_off = "on" enable_disable = "enable" + add_delete = "add" else: on_off = "off" enable_disable = "disable" + add_delete = "delete" if self.enable_cmd.endswith("update-rc.d"): args = (self.enable_cmd, self.name, enable_disable) + elif self.enable_cmd.endswith("rc-update"): + args = (self.enable_cmd, add_delete, self.name + " " + self.runlevel) elif self.enable_cmd.endswith("systemctl"): args = (self.enable_cmd, enable_disable, self.name + ".service") else: @@ -534,7 +578,7 @@ class LinuxService(Service): arguments = self.arguments if self.svc_cmd: if not self.svc_cmd.endswith("systemctl"): - # SysV take the form + # SysV and OpenRC take the form svc_cmd = "%s %s" % (self.svc_cmd, self.name) else: # systemd commands take the form @@ -544,15 +588,23 @@ class LinuxService(Service): # upstart svc_cmd = "%s" % self.svc_initscript + # In OpenRC, if a service crashed, we need to reset its status to + # stopped with the zap command, before we can start it back. + if self.svc_cmd.endswith('rc-service') and self.action == 'start' and self.crashed: + self.execute_command("%s zap" % svc_cmd, daemonize=True) + if self.action is not "restart": if svc_cmd != '': - # upstart or systemd + # upstart or systemd or OpenRC rc_state, stdout, stderr = self.execute_command("%s %s %s" % (svc_cmd, self.action, arguments), daemonize=True) else: # SysV rc_state, stdout, stderr = self.execute_command("%s %s %s" % (self.action, self.name, arguments), daemonize=True) + elif self.svc_cmd.endswith('rc-service'): + # All services in OpenRC support restart. + rc_state, stdout, stderr = self.execute_command("%s %s %s" % (svc_cmd, self.action, arguments), daemonize=True) else: - # not all services support restart. Do it the hard way. + # In other systems, not all services support restart. Do it the hard way. if svc_cmd != '': # upstart or systemd rc1, stdout1, stderr1 = self.execute_command("%s %s %s" % (svc_cmd, 'stop', arguments), daemonize=True) @@ -930,6 +982,7 @@ def main(): state = dict(choices=['running', 'started', 'stopped', 'restarted', 'reloaded']), pattern = dict(required=False, default=None), enabled = dict(choices=BOOLEANS, type='bool'), + runlevel = dict(required=False, default='default'), arguments = dict(aliases=['args'], default=''), ), supports_check_mode=True From 886a71e8eb50cb6783845765b55594187e9bad4e Mon Sep 17 00:00:00 2001 From: lwade Date: Mon, 17 Jun 2013 14:35:53 +0100 Subject: [PATCH 2/9] Added placement_group parameter for cluster compute. --- library/cloud/ec2 | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/library/cloud/ec2 b/library/cloud/ec2 index 90dcd833b3..fbcb2d018d 100644 --- a/library/cloud/ec2 +++ b/library/cloud/ec2 @@ -142,6 +142,13 @@ options: required: false default: null aliases: [] + placement_group: + version_added: "1.3" + description: + - placement group for the instance when using EC2 Clustered Compute + required: false + default: null + aliases: [] vpc_subnet_id: version_added: "1.1" description: @@ -223,6 +230,7 @@ def main(): ec2_url = dict(aliases=['EC2_URL']), ec2_secret_key = dict(aliases=['EC2_SECRET_KEY'], no_log=True), ec2_access_key = dict(aliases=['EC2_ACCESS_KEY']), + placement_group = dict(), user_data = dict(), instance_tags = dict(), vpc_subnet_id = dict(), @@ -247,6 +255,7 @@ def main(): ec2_url = module.params.get('ec2_url') ec2_secret_key = module.params.get('ec2_secret_key') ec2_access_key = module.params.get('ec2_access_key') + placement_group = module.params.get('placement_group') user_data = module.params.get('user_data') instance_tags = module.params.get('instance_tags') vpc_subnet_id = module.params.get('vpc_subnet_id') @@ -310,7 +319,6 @@ def main(): count_remaining = count_remaining - len(running_instances) # Both min_count and max_count equal count parameter. This means the launch request is explicit (we want count, or fail) in how many instances we want. - if count_remaining > 0: try: @@ -320,7 +328,8 @@ def main(): 'min_count': count_remaining, 'max_count': count_remaining, 'monitoring_enabled': monitoring, - 'placement': zone, + 'placement': zone, + 'placement_group': placement_group, 'instance_type': instance_type, 'kernel_id': kernel, 'ramdisk_id': ramdisk, From cc12b85e49a73ebb97120adc8caa0061e103532c Mon Sep 17 00:00:00 2001 From: Scott Sturdivant Date: Tue, 18 Jun 2013 09:25:51 -0600 Subject: [PATCH 3/9] Document the 'default' argument for vars_prompt. --- docsite/latest/rst/playbooks2.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docsite/latest/rst/playbooks2.rst b/docsite/latest/rst/playbooks2.rst index 362e6b2058..fd4fa1de79 100644 --- a/docsite/latest/rst/playbooks2.rst +++ b/docsite/latest/rst/playbooks2.rst @@ -186,6 +186,15 @@ in a push-script:: There are full examples of both of these items in the github examples/playbooks directory. +If you have a variable that changes infrequently, it might make sense to +provide a default value that can be overriden. This can be accomplished using +the default argument:: + + vars_prompt: + - name: "release_version" + prompt: "Product release version" + default: "1.0" + An alternative form of vars_prompt allows for hiding input from the user, and may later support some other options, but otherwise works equivalently:: From 48fe7ac19d22ba49508eca022d8452a46bb211fa Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Tue, 18 Jun 2013 17:53:52 +0200 Subject: [PATCH 4/9] Enlarge scope of 'ansible_ssh_user' magic variable Allow to use ansible_ssh_user variable in `sudo_user` or `when` clauses --- lib/ansible/runner/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py index 6adf5512f7..9b204b9d57 100644 --- a/lib/ansible/runner/__init__.py +++ b/lib/ansible/runner/__init__.py @@ -378,6 +378,7 @@ class Runner(object): inject = utils.combine_vars(inject, host_variables) inject = utils.combine_vars(inject, self.module_vars) inject = utils.combine_vars(inject, self.setup_cache[host]) + inject.setdefault('ansible_ssh_user', self.remote_user) inject['hostvars'] = HostVars(self.setup_cache, self.inventory) inject['group_names'] = host_variables.get('group_names', []) inject['groups'] = self.inventory.groups_list() From ba853b8c1a8f119b71d6ed971c01e17ed0767db3 Mon Sep 17 00:00:00 2001 From: Joshua Lund Date: Tue, 18 Jun 2013 12:26:40 -0600 Subject: [PATCH 5/9] Fixed a few small typos --- docsite/latest/rst/playbooks2.rst | 2 +- library/cloud/quantum_router_interface | 2 +- library/notification/mail | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docsite/latest/rst/playbooks2.rst b/docsite/latest/rst/playbooks2.rst index 362e6b2058..3bcdf3ef09 100644 --- a/docsite/latest/rst/playbooks2.rst +++ b/docsite/latest/rst/playbooks2.rst @@ -290,7 +290,7 @@ decide to do something conditionally based on success or failure:: - action: command /bin/something when: result|failed - action: command /bin/something_else - when: result|sucess + when: result|success As a reminder, to see what derived variables are available, you can do:: diff --git a/library/cloud/quantum_router_interface b/library/cloud/quantum_router_interface index dfc01e2928..f85ac1a311 100644 --- a/library/cloud/quantum_router_interface +++ b/library/cloud/quantum_router_interface @@ -239,7 +239,7 @@ def main(): if module.params['state'] == 'absent': port_id = _get_port_id(quantum, module, router_id, subnet_id) if not port_id: - module.exit_json(changed = False, result = "Sucess") + module.exit_json(changed = False, result = "Success") _remove_interface_router(quantum, module, router_id, subnet_id) module.exit_json(changed=True, result="Deleted") diff --git a/library/notification/mail b/library/notification/mail index b3d9dc794f..76d39cc6b2 100644 --- a/library/notification/mail +++ b/library/notification/mail @@ -103,7 +103,7 @@ options: EXAMPLES = ''' # Example playbook sending mail to root -- local_action: mail msg='System ${ansible_hostname} has been sucessfully provisioned.' +- local_action: mail msg='System ${ansible_hostname} has been successfully provisioned.' # Send e-mail to a bunch of users, attaching files - local_action: mail From bb4de94937ad7d9a16cbac7707a5c0781101a380 Mon Sep 17 00:00:00 2001 From: Joshua Lund Date: Tue, 18 Jun 2013 15:01:01 -0600 Subject: [PATCH 6/9] Removed merge conflict header --- library/network/get_url | 1 - 1 file changed, 1 deletion(-) diff --git a/library/network/get_url b/library/network/get_url index 7cc1c5227e..53b0726147 100644 --- a/library/network/get_url +++ b/library/network/get_url @@ -89,7 +89,6 @@ author: Jan-Piet Mens ''' EXAMPLES=''' -<<<<<<< HEAD - name: download foo.conf get_url: url=http://example.com/path/file.conf dest=/etc/foo.conf mode=0440 From e04ee519efc68397c7d1136f08f58818b706dd6a Mon Sep 17 00:00:00 2001 From: Buce Date: Tue, 18 Jun 2013 17:29:28 -0400 Subject: [PATCH 7/9] Fix typo in PKGBUILD ansbile.cfg -> ansible.cfg --- packaging/arch/PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index 9f1b439dcd..3346b4940b 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -41,7 +41,7 @@ package() { python2 setup.py install -O1 --root="$pkgdir" - install -D examples/ansible.cfg "$pkgdir/etc/ansible/ansbile.cfg" + install -D examples/ansible.cfg "$pkgdir/etc/ansible/ansible.cfg" install -D README.md "$pkgdir/usr/share/doc/ansible/README.md" install -D COPYING "$pkgdir/usr/share/doc/ansible/COPYING" From 240a52906e21847097419c1ce95ef1cc609c2d99 Mon Sep 17 00:00:00 2001 From: Jim Tittsler Date: Wed, 19 Jun 2013 10:37:02 +1200 Subject: [PATCH 8/9] spelling ansbile->ansible --- docsite/latest/rst/gettingstarted.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docsite/latest/rst/gettingstarted.rst b/docsite/latest/rst/gettingstarted.rst index 34241673c9..f4f0d47f40 100644 --- a/docsite/latest/rst/gettingstarted.rst +++ b/docsite/latest/rst/gettingstarted.rst @@ -310,7 +310,7 @@ If you would like to access sudo mode, there are also flags to do that: # as bruce, sudoing to batman $ ansible all -m ping -u bruce --sudo --sudo-user batman -(The sudo implementation is changeable in ansbile's configuration file if you happen to want to use a sudo +(The sudo implementation is changeable in ansible's configuration file if you happen to want to use a sudo replacement. Flags passed dot sudo can also be set.) Now run a live command on all of your nodes: From 86bc2ec08a1852a1da3fca815ba21d003c3d7c31 Mon Sep 17 00:00:00 2001 From: Jesse Keating Date: Tue, 18 Jun 2013 16:25:46 -0700 Subject: [PATCH 9/9] pkg option of apt is not required You can use apt module with update_cache and without specifying a package. Update the docs to reflect this. --- library/packaging/apt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/packaging/apt b/library/packaging/apt index dd2fed9e46..d0e86e8082 100644 --- a/library/packaging/apt +++ b/library/packaging/apt @@ -31,7 +31,7 @@ options: pkg: description: - A package name or package specifier with version, like C(foo) or C(foo=1.0) - required: true + required: false default: null state: description: