diff options
author | Robin Miller <robin.miller@jamfsoftware.com> | 2015-05-26 12:55:48 -0500 |
---|---|---|
committer | Robin Miller <robin.miller@jamfsoftware.com> | 2015-05-26 12:55:48 -0500 |
commit | 48c83a0d9d45bac26a33cbea40a06232149ed3e9 (patch) | |
tree | 06587b8a55d3c1d57ae3605263d1bfa3fa38e0d8 | |
parent | 0e572aa3f489e27e21bb8c238bbba4adef56fa37 (diff) | |
parent | 58c6c3dd039ef5cd8ae3262abb2490e9d4d966aa (diff) | |
download | ansible-modules-core-48c83a0d9d45bac26a33cbea40a06232149ed3e9.tar.gz |
Merge remote-tracking branch 'upstream/devel' into devel
-rw-r--r-- | cloud/openstack/_quantum_network.py (renamed from cloud/openstack/quantum_network.py) | 1 | ||||
-rw-r--r-- | cloud/openstack/os_network.py | 107 | ||||
-rw-r--r-- | cloud/openstack/os_server_actions.py | 192 | ||||
-rw-r--r-- | system/service.py | 24 |
4 files changed, 322 insertions, 2 deletions
diff --git a/cloud/openstack/quantum_network.py b/cloud/openstack/_quantum_network.py index ff8b2683..93b10880 100644 --- a/cloud/openstack/quantum_network.py +++ b/cloud/openstack/_quantum_network.py @@ -30,6 +30,7 @@ DOCUMENTATION = ''' --- module: quantum_network version_added: "1.4" +deprecated: Deprecated in 2.0. Use os_network instead short_description: Creates/Removes networks from OpenStack description: - Add or Remove network from OpenStack. diff --git a/cloud/openstack/os_network.py b/cloud/openstack/os_network.py new file mode 100644 index 00000000..b77a7e33 --- /dev/null +++ b/cloud/openstack/os_network.py @@ -0,0 +1,107 @@ +#!/usr/bin/python + +# Copyright (c) 2014 Hewlett-Packard Development Company, L.P. +# Copyright (c) 2013, Benno Joy <benno@ansible.com> +# +# This module is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software. If not, see <http://www.gnu.org/licenses/>. + +try: + import shade + HAS_SHADE = True +except ImportError: + HAS_SHADE = False + +DOCUMENTATION = ''' +--- +module: os_network +short_description: Creates/Removes networks from OpenStack +extends_documentation_fragment: openstack +version_added: "2.0" +description: + - Add or Remove network from OpenStack. +options: + name: + description: + - Name to be assigned to the network. + required: true + shared: + description: + - Whether this network is shared or not. + required: false + default: false + admin_state_up: + description: + - Whether the state should be marked as up or down. + required: false + default: true + state: + description: + - Indicate desired state of the resource. + choices: ['present', 'absent'] + required: false + default: present +requirements: ["shade"] +''' + +EXAMPLES = ''' +- os_network: + name=t1network + state=present +''' + + +def main(): + argument_spec = openstack_full_argument_spec( + name=dict(required=True), + shared=dict(default=False, type='bool'), + admin_state_up=dict(default=True, type='bool'), + ) + + module_kwargs = openstack_module_kwargs() + module = AnsibleModule(argument_spec, **module_kwargs) + + if not HAS_SHADE: + module.fail_json(msg='shade is required for this module') + + state = module.params['state'] + name = module.params['name'] + shared = module.params['shared'] + admin_state_up = module.params['admin_state_up'] + + try: + cloud = shade.openstack_cloud(**module.params) + net = cloud.get_network(name) + + if state == 'present': + if not net: + net = cloud.create_network(name, shared, admin_state_up) + module.exit_json(changed=True, result="Created", id=net['id']) + else: + module.exit_json(changed=False, result="Success", id=net['id']) + + elif state == 'absent': + if not net: + module.exit_json(changed=False, result="Success") + else: + cloud.delete_network(name) + module.exit_json(changed=True, result="Deleted") + + except shade.OpenStackCloudException as e: + module.fail_json(msg=e.message) + + +# this is magic, see lib/ansible/module_common.py +from ansible.module_utils.basic import * +from ansible.module_utils.openstack import * +main() diff --git a/cloud/openstack/os_server_actions.py b/cloud/openstack/os_server_actions.py new file mode 100644 index 00000000..2b739df4 --- /dev/null +++ b/cloud/openstack/os_server_actions.py @@ -0,0 +1,192 @@ +#!/usr/bin/python +# coding: utf-8 -*- + +# Copyright (c) 2015, Jesse Keating <jlk@derpops.bike> +# +# This module is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software. If not, see <http://www.gnu.org/licenses/>. + + +try: + import shade + from shade import meta + HAS_SHADE = True +except ImportError: + HAS_SHADE = False + + +DOCUMENTATION = ''' +--- +module: os_server_actions +short_description: Perform actions on Compute Instances from OpenStack +extends_documentation_fragment: openstack +version_added: "2.0" +description: + - Perform server actions on an existing compute instance from OpenStack. + This module does not return any data other than changed true/false. +options: + server: + description: + - Name or ID of the instance + required: true + wait: + description: + - If the module should wait for the instance action to be performed. + required: false + default: 'yes' + timeout: + description: + - The amount of time the module should wait for the instance to perform + the requested action. + required: false + default: 180 + action: + description: + - Perform the given action. The lock and unlock actions always return + changed as the servers API does not provide lock status. + choices: [pause, unpause, lock, unlock, suspend, resume] + default: present +requirements: + - "python >= 2.6" + - "shade" +''' + +EXAMPLES = ''' +# Pauses a compute instance +- os_server_actions: + action: pause + auth: + auth_url: https://mycloud.openstack.blueboxgrid.com:5001/v2.0 + username: admin + password: admin + project_name: admin + server: vm1 + timeout: 200 +''' + +_action_map = {'pause': 'PAUSED', + 'unpause': 'ACTIVE', + 'lock': 'ACTIVE', # API doesn't show lock/unlock status + 'unlock': 'ACTIVE', + 'suspend': 'SUSPENDED', + 'resume': 'ACTIVE',} + +_admin_actions = ['pause', 'unpause', 'suspend', 'resume', 'lock', 'unlock'] + +def _wait(timeout, cloud, server, action): + """Wait for the server to reach the desired state for the given action.""" + + for count in shade._iterate_timeout( + timeout, + "Timeout waiting for server to complete %s" % action): + try: + server = cloud.get_server(server.id) + except Exception: + continue + + if server.status == _action_map[action]: + return + + if server.status == 'ERROR': + module.fail_json(msg="Server reached ERROR state while attempting to %s" % action) + +def _system_state_change(action, status): + """Check if system state would change.""" + if status == _action_map[action]: + return False + return True + +def main(): + argument_spec = openstack_full_argument_spec( + server=dict(required=True), + action=dict(required=True, choices=['pause', 'unpause', 'lock', 'unlock', 'suspend', + 'resume']), + ) + + module_kwargs = openstack_module_kwargs() + module = AnsibleModule(argument_spec, supports_check_mode=True, **module_kwargs) + + if not HAS_SHADE: + module.fail_json(msg='shade is required for this module') + + action = module.params['action'] + wait = module.params['wait'] + timeout = module.params['timeout'] + + try: + if action in _admin_actions: + cloud = shade.operator_cloud(**module.params) + else: + cloud = shade.openstack_cloud(**module.params) + server = cloud.get_server(module.params['server']) + if not server: + module.fail_json(msg='Could not find server %s' % server) + status = server.status + + if module.check_mode: + module.exit_json(changed=_system_state_change(action, status)) + + if action == 'pause': + if not _system_state_change(action, status): + module.exit_json(changed=False) + + cloud.nova_client.servers.pause(server=server.id) + if wait: + _wait(timeout, cloud, server, action) + module.exit_json(changed=True) + + elif action == 'unpause': + if not _system_state_change(action, status): + module.exit_json(changed=False) + + cloud.nova_client.servers.unpause(server=server.id) + if wait: + _wait(timeout, cloud, server, action) + module.exit_json(changed=True) + + elif action == 'lock': + # lock doesn't set a state, just do it + cloud.nova_client.servers.lock(server=server.id) + module.exit_json(changed=True) + + elif action == 'unlock': + # unlock doesn't set a state, just do it + cloud.nova_client.servers.unlock(server=server.id) + module.exit_json(changed=True) + + elif action == 'suspend': + if not _system_state_change(action, status): + module.exit_json(changed=False) + + cloud.nova_client.servers.suspend(server=server.id) + if wait: + _wait(timeout, cloud, server, action) + module.exit_json(changed=True) + + elif action == 'resume': + if not _system_state_change(action, status): + module.exit_json(changed=False) + + cloud.nova_client.servers.resume(server=server.id) + if wait: + _wait(timeout, cloud, server, action) + module.exit_json(changed=True) + + except shade.OpenStackCloudException as e: + module.fail_json(msg=e.message, extra_data=e.extra_data) + +# this is magic, see lib/ansible/module_common.py +from ansible.module_utils.basic import * +from ansible.module_utils.openstack import * +if __name__ == '__main__': + main() diff --git a/system/service.py b/system/service.py index 14c0026d..856361ac 100644 --- a/system/service.py +++ b/system/service.py @@ -72,6 +72,14 @@ options: description: - Additional arguments provided on the command line aliases: [ 'args' ] + must_exist: + required: false + default: true + version_added: "2.0" + description: + - Avoid a module failure if the named service does not exist. Useful + for opportunistically starting/stopping/restarting a list of + potential services. ''' EXAMPLES = ''' @@ -95,6 +103,9 @@ EXAMPLES = ''' # Example action to restart network service for interface eth0 - service: name=network state=restarted args=eth0 + +# Example action to restart nova-compute if it exists +- service: name=nova-compute state=restarted must_exist=no ''' import platform @@ -468,7 +479,11 @@ class LinuxService(Service): self.enable_cmd = location['chkconfig'] if self.enable_cmd is None: - self.module.fail_json(msg="no service or tool found for: %s" % self.name) + if self.module.params['must_exist']: + self.module.fail_json(msg="no service or tool found for: %s" % self.name) + else: + # exiting without change on non-existent service + self.module.exit_json(changed=False, exists=False) # If no service control tool selected yet, try to see if 'service' is available if self.svc_cmd is None and location.get('service', False): @@ -476,7 +491,11 @@ class LinuxService(Service): # couldn't find anything yet if self.svc_cmd is None and not self.svc_initscript: - self.module.fail_json(msg='cannot find \'service\' binary or init script for service, possible typo in service name?, aborting') + if self.module.params['must_exist']: + self.module.fail_json(msg='cannot find \'service\' binary or init script for service, possible typo in service name?, aborting') + else: + # exiting without change on non-existent service + self.module.exit_json(changed=False, exists=False) if location.get('initctl', False): self.svc_initctl = location['initctl'] @@ -1400,6 +1419,7 @@ def main(): enabled = dict(type='bool'), runlevel = dict(required=False, default='default'), arguments = dict(aliases=['args'], default=''), + must_exist = dict(type='bool', default=True), ), supports_check_mode=True ) |