#!/usr/bin/python # -*- coding: utf-8 -*- # # (c) 2016, René Moser # # This file is part of Ansible # # Ansible 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. # # Ansible 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 Ansible. If not, see . ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['stableinterface'], 'supported_by': 'community'} DOCUMENTATION = ''' --- module: cs_router short_description: Manages routers on Apache CloudStack based clouds. description: - Start, restart, stop and destroy routers. - C(state=present) is not able to create routers, use M(cs_network) instead. version_added: "2.2" author: "René Moser (@resmo)" options: name: description: - Name of the router. required: true service_offering: description: - Name or id of the service offering of the router. domain: description: - Domain the router is related to. account: description: - Account the router is related to. project: description: - Name of the project the router is related to. zone: description: - Name of the zone the router is deployed in. - If not set, all zones are used. version_added: "2.4" state: description: - State of the router. default: 'present' choices: [ 'present', 'absent', 'started', 'stopped', 'restarted' ] poll_async: description: - Poll async jobs until job has finished. default: yes type: bool extends_documentation_fragment: cloudstack ''' EXAMPLES = ''' # Ensure the router has the desired service offering, no matter if # the router is running or not. - local_action: module: cs_router name: r-40-VM service_offering: System Offering for Software Router # Ensure started - local_action: module: cs_router name: r-40-VM state: started # Ensure started with desired service offering. # If the service offerings changes, router will be rebooted. - local_action: module: cs_router name: r-40-VM service_offering: System Offering for Software Router state: started # Ensure stopped - local_action: module: cs_router name: r-40-VM state: stopped # Remove a router - local_action: module: cs_router name: r-40-VM state: absent ''' RETURN = ''' --- id: description: UUID of the router. returned: success type: string sample: 04589590-ac63-4ffc-93f5-b698b8ac38b6 name: description: Name of the router. returned: success type: string sample: r-40-VM created: description: Date of the router was created. returned: success type: string sample: 2014-12-01T14:57:57+0100 template_version: description: Version of the system VM template. returned: success type: string sample: 4.5.1 requires_upgrade: description: Whether the router needs to be upgraded to the new template. returned: success type: bool sample: false redundant_state: description: Redundant state of the router. returned: success type: string sample: UNKNOWN role: description: Role of the router. returned: success type: string sample: VIRTUAL_ROUTER zone: description: Name of zone the router is in. returned: success type: string sample: ch-gva-2 service_offering: description: Name of the service offering the router has. returned: success type: string sample: System Offering For Software Router state: description: State of the router. returned: success type: string sample: Active domain: description: Domain the router is related to. returned: success type: string sample: ROOT account: description: Account the router is related to. returned: success type: string sample: admin ''' from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.cloudstack import ( AnsibleCloudStack, cs_argument_spec, cs_required_together, ) class AnsibleCloudStackRouter(AnsibleCloudStack): def __init__(self, module): super(AnsibleCloudStackRouter, self).__init__(module) self.returns = { 'serviceofferingname': 'service_offering', 'version': 'template_version', 'requiresupgrade': 'requires_upgrade', 'redundantstate': 'redundant_state', 'role': 'role' } self.router = None def get_service_offering_id(self): service_offering = self.module.params.get('service_offering') if not service_offering: return None args = { 'issystem': True } service_offerings = self.query_api('listServiceOfferings', **args) if service_offerings: for s in service_offerings['serviceoffering']: if service_offering in [s['name'], s['id']]: return s['id'] self.module.fail_json(msg="Service offering '%s' not found" % service_offering) def get_router(self): if not self.router: router = self.module.params.get('name') args = { 'projectid': self.get_project(key='id'), 'account': self.get_account(key='name'), 'domainid': self.get_domain(key='id'), 'listall': True, 'fetch_list': True, } if self.module.params.get('zone'): args['zoneid'] = self.get_zone(key='id') routers = self.query_api('listRouters', **args) if routers: for r in routers: if router.lower() in [r['name'].lower(), r['id']]: self.router = r break return self.router def start_router(self): router = self.get_router() if not router: self.module.fail_json(msg="Router not found") if router['state'].lower() != "running": self.result['changed'] = True args = { 'id': router['id'], } if not self.module.check_mode: res = self.query_api('startRouter', **args) poll_async = self.module.params.get('poll_async') if poll_async: router = self.poll_job(res, 'router') return router def stop_router(self): router = self.get_router() if not router: self.module.fail_json(msg="Router not found") if router['state'].lower() != "stopped": self.result['changed'] = True args = { 'id': router['id'], } if not self.module.check_mode: res = self.query_api('stopRouter', **args) poll_async = self.module.params.get('poll_async') if poll_async: router = self.poll_job(res, 'router') return router def reboot_router(self): router = self.get_router() if not router: self.module.fail_json(msg="Router not found") self.result['changed'] = True args = { 'id': router['id'], } if not self.module.check_mode: res = self.query_api('rebootRouter', **args) poll_async = self.module.params.get('poll_async') if poll_async: router = self.poll_job(res, 'router') return router def absent_router(self): router = self.get_router() if router: self.result['changed'] = True args = { 'id': router['id'], } if not self.module.check_mode: res = self.query_api('destroyRouter', **args) poll_async = self.module.params.get('poll_async') if poll_async: self.poll_job(res, 'router') return router def present_router(self): router = self.get_router() if not router: self.module.fail_json(msg="Router can not be created using the API, see cs_network.") args = { 'id': router['id'], 'serviceofferingid': self.get_service_offering_id(), } state = self.module.params.get('state') if self.has_changed(args, router): self.result['changed'] = True if not self.module.check_mode: current_state = router['state'].lower() self.stop_router() router = self.query_api('changeServiceForRouter', **args) if state in ['restarted', 'started']: router = self.start_router() # if state=present we get to the state before the service # offering change. elif state == "present" and current_state == "running": router = self.start_router() elif state == "started": router = self.start_router() elif state == "stopped": router = self.stop_router() elif state == "restarted": router = self.reboot_router() return router def main(): argument_spec = cs_argument_spec() argument_spec.update(dict( name=dict(required=True), service_offering=dict(), state=dict(choices=['present', 'started', 'stopped', 'restarted', 'absent'], default="present"), domain=dict(), account=dict(), project=dict(), zone=dict(), poll_async=dict(type='bool', default=True), )) module = AnsibleModule( argument_spec=argument_spec, required_together=cs_required_together(), supports_check_mode=True ) acs_router = AnsibleCloudStackRouter(module) state = module.params.get('state') if state in ['absent']: router = acs_router.absent_router() else: router = acs_router.present_router() result = acs_router.get_result(router) module.exit_json(**result) if __name__ == '__main__': main()