This repository has been archived by the owner on Oct 30, 2018. It is now read-only.
Module to manage F5 GTM virtual servers #555
Closed
Closed
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
b0ef61d
Module to manage f5 virtual servers
0331d35
added support to add/remove virtual server, style updates
b58daf9
Remove redundant checks, rename var bigip to server
d5aa2e7
Wrap main in conditional
c1fec3f
Confirm server exists before trying to create virtual server
c8a19b2
Update default value for parameters, set no_log to true on password p…
235f294
Add return string
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
#!/usr/bin/python | ||
# -*- coding: utf-8 -*- | ||
# | ||
# (c) 2015, Michael Perzel | ||
# | ||
# 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 <http://www.gnu.org/licenses/>. | ||
|
||
DOCUMENTATION = ''' | ||
--- | ||
module: bigip_gtm_virtual_server | ||
short_description: "Manages F5 BIG-IP GTM virtual servers" | ||
description: | ||
- "Manages F5 BIG-IP GTM virtual servers" | ||
version_added: "2.2" | ||
author: 'Michael Perzel' | ||
notes: | ||
- "Requires BIG-IP software version >= 11.4" | ||
- "F5 developed module 'bigsuds' required (see http://devcentral.f5.com)" | ||
- "Best run as a local_action in your playbook" | ||
- "Tested with manager and above account privilege level" | ||
|
||
requirements: | ||
- bigsuds | ||
options: | ||
server: | ||
description: | ||
- BIG-IP host | ||
required: true | ||
user: | ||
description: | ||
- BIG-IP username | ||
required: true | ||
password: | ||
description: | ||
- BIG-IP password | ||
required: true | ||
state: | ||
description: | ||
- Virtual server state | ||
required: false | ||
default: present | ||
choices: ['present', 'absent','enabled','disabled'] | ||
virtual_server_name: | ||
description: | ||
- Virtual server name | ||
required: True | ||
virtual_server_server: | ||
description: | ||
- Virtual server server | ||
required: true | ||
host: | ||
description: | ||
- Virtual server host | ||
required: false | ||
default: None | ||
aliases: ['address'] | ||
port: | ||
description: | ||
- Virtual server port | ||
required: false | ||
default: None | ||
''' | ||
|
||
RETURN = ''' | ||
bigip_gtm_virtual_server: | ||
description: Provides the ability to create, delete, enable, disable GTM virtual servers | ||
returned: success | ||
type: dictionary | ||
''' | ||
|
||
EXAMPLES = ''' | ||
- name: Enable virtual server | ||
local_action: > | ||
bigip_gtm_virtual_server | ||
server=192.168.0.1 | ||
user=admin | ||
password=mysecret | ||
virtual_server_name=myname | ||
virtual_server_server=myserver | ||
state=enabled | ||
''' | ||
|
||
try: | ||
import bigsuds | ||
except ImportError: | ||
bigsuds_found = False | ||
else: | ||
bigsuds_found = True | ||
|
||
def bigip_api(server, user, password): | ||
api = bigsuds.BIGIP(hostname=server, username=user, password=password) | ||
return api | ||
|
||
def server_exists(api, server): | ||
# hack to determine if virtual server exists | ||
result = False | ||
try: | ||
api.GlobalLB.Server.get_object_status([server]) | ||
result = True | ||
except bigsuds.OperationFailed, e: | ||
if "was not found" in str(e): | ||
result = False | ||
else: | ||
# genuine exception | ||
raise | ||
return result | ||
|
||
def virtual_server_exists(api, name, server): | ||
# hack to determine if virtual server exists | ||
result = False | ||
try: | ||
virtual_server_id = {'name': name, 'server': server} | ||
api.GlobalLB.VirtualServerV2.get_object_status([virtual_server_id]) | ||
result = True | ||
except bigsuds.OperationFailed, e: | ||
if "was not found" in str(e): | ||
result = False | ||
else: | ||
# genuine exception | ||
raise | ||
return result | ||
|
||
def add_virtual_server(api, virtual_server_name, virtual_server_server, address, port): | ||
addresses = {'address': address, 'port': port} | ||
virtual_server_id = {'name': virtual_server_name, 'server': virtual_server_server} | ||
api.GlobalLB.VirtualServerV2.create([virtual_server_id], [addresses]) | ||
|
||
def remove_virtual_server(api, virtual_server_name, virtual_server_server): | ||
virtual_server_id = {'name': virtual_server_name, 'server': virtual_server_server} | ||
api.GlobalLB.VirtualServerV2.delete_virtual_server([virtual_server_id]) | ||
|
||
def get_virtual_server_state(api, name, server): | ||
virtual_server_id = {'name': name, 'server': server} | ||
state = api.GlobalLB.VirtualServerV2.get_enabled_state([virtual_server_id]) | ||
state = state[0].split('STATE_')[1].lower() | ||
return state | ||
|
||
def set_virtual_server_state(api, name, server, state): | ||
virtual_server_id = {'name': name, 'server': server} | ||
state = "STATE_%s" % state.strip().upper() | ||
api.GlobalLB.VirtualServerV2.set_enabled_state([virtual_server_id], [state]) | ||
|
||
def main(): | ||
module = AnsibleModule( | ||
argument_spec = dict( | ||
server = dict(type='str', required=True), | ||
user = dict(type='str', required=True), | ||
password = dict(type='str', required=True, no_log=True), | ||
state = dict(type='str', default='present', choices=['present', 'absent', 'enabled', 'disabled']), | ||
host = dict(type='str', default=None, aliases=['address']), | ||
port = dict(type='int', default=None), | ||
virtual_server_name = dict(type='str', required=True), | ||
virtual_server_server = dict(type='str', required=True) | ||
), | ||
supports_check_mode=True | ||
) | ||
|
||
if not bigsuds_found: | ||
module.fail_json(msg="the python bigsuds module is required") | ||
|
||
server = module.params['server'] | ||
user = module.params['user'] | ||
password = module.params['password'] | ||
virtual_server_name = module.params['virtual_server_name'] | ||
virtual_server_server = module.params['virtual_server_server'] | ||
state = module.params['state'] | ||
address = module.params['host'] | ||
port = module.params['port'] | ||
|
||
result = {'changed': False} # default | ||
|
||
try: | ||
api = bigip_api(server, user, password) | ||
|
||
if state == 'absent': | ||
if virtual_server_exists(api, virtual_server_name, virtual_server_server): | ||
if not module.check_mode: | ||
remove_virtual_server(api, virtual_server_name, virtual_server_server) | ||
result = {'changed': True} | ||
else: | ||
# check-mode return value | ||
result = {'changed': True} | ||
elif state == 'present': | ||
if virtual_server_name and virtual_server_server and address and port: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens when address and/or port are not set? |
||
if not virtual_server_exists(api, virtual_server_name, virtual_server_server): | ||
if not module.check_mode: | ||
if server_exists(api, virtual_server_server): | ||
add_virtual_server(api, virtual_server_name, virtual_server_server, address, port) | ||
result = {'changed': True} | ||
else: | ||
module.fail_json(msg="server does not exist") | ||
else: | ||
# check-mode return value | ||
result = {'changed': True} | ||
else: | ||
# virtual server exists -- potentially modify attributes --future feature | ||
result = {'changed': False} | ||
else: | ||
module.fail_json(msg="Address and port are required to create virtual server") | ||
elif state == 'enabled': | ||
if not virtual_server_exists(api, virtual_server_name, virtual_server_server): | ||
module.fail_json(msg="virtual server does not exist") | ||
if state != get_virtual_server_state(api, virtual_server_name, virtual_server_server): | ||
if not module.check_mode: | ||
set_virtual_server_state(api, virtual_server_name, virtual_server_server, state) | ||
result = {'changed': True} | ||
else: | ||
result = {'changed': True} | ||
elif state == 'disabled': | ||
if not virtual_server_exists(api, virtual_server_name, virtual_server_server): | ||
module.fail_json(msg="virtual server does not exist") | ||
if state != get_virtual_server_state(api, virtual_server_name, virtual_server_server): | ||
if not module.check_mode: | ||
set_virtual_server_state(api, virtual_server_name, virtual_server_server, state) | ||
result = {'changed': True} | ||
else: | ||
result = {'changed': True} | ||
|
||
except Exception, e: | ||
module.fail_json(msg="received exception: %s" % e) | ||
|
||
module.exit_json(**result) | ||
|
||
# import module snippets | ||
from ansible.module_utils.basic import * | ||
|
||
if __name__ == '__main__': | ||
main() |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
many modules uses present as default and it became a convention. would you mind using present as default and set required to false?