@ -64,20 +64,25 @@ options:
validate on python > = 2.7 .9 and never validate on python < = 2.7 .8
required : false
default : ' yes '
choices : [ ' yes ' , ' no ' ]
choices :
- yes
- no
version_added : 2.0
state :
description :
- Monitor state
required : false
default : ' present '
choices : [ ' present ' , ' absent ' ]
choices :
- present
- absent
name :
description :
- Monitor name
required : true
default : null
aliases : [ ' monitor ' ]
aliases :
- monitor
partition :
description :
- Partition for the monitor
@ -88,13 +93,19 @@ options:
- The template type of this monitor template
required : false
default : ' tcp '
choices : [ ' TTYPE_TCP ' , ' TTYPE_TCP_ECHO ' , ' TTYPE_TCP_HALF_OPEN ' ]
choices :
- TTYPE_TCP
- TTYPE_TCP_ECHO
- TTYPE_TCP_HALF_OPEN
parent :
description :
- The parent template of this monitor template
required : false
default : ' tcp '
choices : [ ' tcp ' , ' tcp_echo ' , ' tcp_half_open ' ]
choices :
- tcp
- tcp_echo
- tcp_half_open
parent_partition :
description :
- Partition for the parent monitor
@ -118,7 +129,7 @@ options:
default : none
port :
description :
- p ort address part op the ipport definition . The default API
- P ort address part op the ipport definition . The default API
setting is 0.
required : false
default : none
@ -151,43 +162,37 @@ options:
'''
EXAMPLES = '''
- name : BIGIP F5 | Create TCP Monitor
local_action :
module : bigip_monitor_tcp
state : present
server : " {{ f5server }} "
user : " {{ f5user }} "
password : " {{ f5password }} "
name : " {{ item.monitorname }} "
type : tcp
send : " {{ item.send }} "
receive : " {{ item.receive }} "
with_items : f5monitors - tcp
- name : BIGIP F5 | Create TCP half open Monitor
local_action :
module : bigip_monitor_tcp
state : present
server : " {{ f5server }} "
user : " {{ f5user }} "
password : " {{ f5password }} "
name : " {{ item.monitorname }} "
type : tcp
send : " {{ item.send }} "
receive : " {{ item.receive }} "
with_items : f5monitors - halftcp
- name : BIGIP F5 | Remove TCP Monitor
local_action :
module : bigip_monitor_tcp
state : absent
server : " {{ f5server }} "
user : " {{ f5user }} "
password : " {{ f5password }} "
name : " {{ monitorname }} "
with_flattened :
- f5monitors - tcp
- f5monitors - halftcp
- name : Create TCP Monitor
bigip_monitor_tcp :
state : " present "
server : " lb.mydomain.com "
user : " admin "
password : " secret "
name : " my_tcp_monitor "
type : " tcp "
send : " tcp string to send "
receive : " tcp string to receive "
delegate_to : localhost
- name : Create TCP half open Monitor
bigip_monitor_tcp :
state : " present "
server : " lb.mydomain.com "
user : " admin "
password : " secret "
name : " my_tcp_monitor "
type : " tcp "
send : " tcp string to send "
receive : " http string to receive "
delegate_to : localhost
- name : Remove TCP Monitor
bigip_monitor_tcp :
state : " absent "
server : " lb.mydomain.com "
user : " admin "
password : " secret "
name : " my_tcp_monitor "
'''
TEMPLATE_TYPE = DEFAULT_TEMPLATE_TYPE = ' TTYPE_TCP '
@ -196,7 +201,6 @@ DEFAULT_PARENT = DEFAULT_TEMPLATE_TYPE_CHOICE = DEFAULT_TEMPLATE_TYPE.replace('T
def check_monitor_exists ( module , api , monitor , parent ) :
# hack to determine if monitor exists
result = False
try :
@ -206,7 +210,7 @@ def check_monitor_exists(module, api, monitor, parent):
result = True
else :
module . fail_json ( msg = ' Monitor already exists, but has a different type ( %s ) or parent( %s ) ' % ( ttype , parent ) )
except bigsuds . OperationFailed , e :
except bigsuds . OperationFailed as e :
if " was not found " in str ( e ) :
result = False
else :
@ -216,10 +220,15 @@ def check_monitor_exists(module, api, monitor, parent):
def create_monitor ( api , monitor , template_attributes ) :
try :
api . LocalLB . Monitor . create_template ( templates = [ { ' template_name ' : monitor , ' template_type ' : TEMPLATE_TYPE } ] , template_attributes = [ template_attributes ] )
except bigsuds . OperationFailed , e :
api . LocalLB . Monitor . create_template (
templates = [ {
' template_name ' : monitor ,
' template_type ' : TEMPLATE_TYPE
} ] ,
template_attributes = [ template_attributes ]
)
except bigsuds . OperationFailed as e :
if " already exists " in str ( e ) :
return False
else :
@ -229,10 +238,9 @@ def create_monitor(api, monitor, template_attributes):
def delete_monitor ( api , monitor ) :
try :
api . LocalLB . Monitor . delete_template ( template_names = [ monitor ] )
except bigsuds . OperationFailed , e :
except bigsuds . OperationFailed as e :
# maybe it was deleted since we checked
if " was not found " in str ( e ) :
return False
@ -243,41 +251,46 @@ def delete_monitor(api, monitor):
def check_string_property ( api , monitor , str_property ) :
try :
return str_property == api . LocalLB . Monitor . get_template_string_property ( [ monitor ] , [ str_property [ ' type ' ] ] ) [ 0 ]
except bigsuds . OperationFailed , e :
template_prop = api . LocalLB . Monitor . get_template_string_property (
[ monitor ] , [ str_property [ ' type ' ] ]
) [ 0 ]
return str_property == template_prop
except bigsuds . OperationFailed as e :
# happens in check mode if not created yet
if " was not found " in str ( e ) :
return True
else :
# genuine exception
raise
return True
def set_string_property ( api , monitor , str_property ) :
api . LocalLB . Monitor . set_template_string_property ( template_names = [ monitor ] , values = [ str_property ] )
api . LocalLB . Monitor . set_template_string_property (
template_names = [ monitor ] ,
values = [ str_property ]
)
def check_integer_property ( api , monitor , int_property ) :
try :
return int_property == api . LocalLB . Monitor . get_template_integer_property ( [ monitor ] , [ int_property [ ' type ' ] ] ) [ 0 ]
except bigsuds . OperationFailed , e :
return int_property == api . LocalLB . Monitor . get_template_integer_property (
[ monitor ] , [ int_property [ ' type ' ] ]
) [ 0 ]
except bigsuds . OperationFailed as e :
# happens in check mode if not created yet
if " was not found " in str ( e ) :
return True
else :
# genuine exception
raise
return True
def set_integer_property ( api , monitor , int_property ) :
api . LocalLB . Monitor . set_template_integer_property ( template_names = [ monitor ] , values = [ int_property ] )
api . LocalLB . Monitor . set_template_integer_property (
template_names = [ monitor ] ,
values = [ int_property ]
)
def update_monitor_properties ( api , module , monitor , template_string_properties , template_integer_properties ) :
@ -287,6 +300,7 @@ def update_monitor_properties(api, module, monitor, template_string_properties,
if not module . check_mode :
set_string_property ( api , monitor , str_property )
changed = True
for int_property in template_integer_properties :
if int_property [ ' value ' ] is not None and not check_integer_property ( api , monitor , int_property ) :
if not module . check_mode :
@ -297,34 +311,28 @@ def update_monitor_properties(api, module, monitor, template_string_properties,
def get_ipport ( api , monitor ) :
return api . LocalLB . Monitor . get_template_destination ( template_names = [ monitor ] ) [ 0 ]
def set_ipport ( api , monitor , ipport ) :
try :
api . LocalLB . Monitor . set_template_destination ( template_names = [ monitor ] , destinations = [ ipport ] )
api . LocalLB . Monitor . set_template_destination (
template_names = [ monitor ] , destinations = [ ipport ]
)
return True , " "
except bigsuds . OperationFailed , e :
except bigsuds . OperationFailed as e :
if " Cannot modify the address type of monitor " in str ( e ) :
return False , " Cannot modify the address type of monitor if already assigned to a pool. "
else :
# genuine exception
raise
# ===========================================
# main loop
#
# writing a module for other monitor types should
# only need an updated main() (and monitor specific functions)
def main ( ) :
# begin monitor specific stuff
argument_spec = f5_argument_spec ( )
argument_spec . update ( dict (
meta_args = dict (
name = dict ( required = True ) ,
type = dict ( default = DEFAULT_TEMPLATE_TYPE_CHOICE , choices = TEMPLATE_TYPE_CHOICES ) ,
parent = dict ( default = DEFAULT_PARENT ) ,
@ -337,16 +345,13 @@ def main():
timeout = dict ( required = False , type = ' int ' ) ,
time_until_up = dict ( required = False , type = ' int ' , default = 0 )
)
)
argument_spec . update ( meta_args )
module = AnsibleModule (
argument_spec = argument_spec ,
supports_check_mode = True
)
if not bigsuds_found :
module . fail_json ( msg = " the python bigsuds module is required " )
if module . params [ ' validate_certs ' ] :
import ssl
if not hasattr ( ssl , ' SSLContext ' ) :
@ -382,15 +387,16 @@ def main():
api = bigip_api ( server , user , password , validate_certs , port = server_port )
monitor_exists = check_monitor_exists ( module , api , monitor , parent )
# ipport is a special setting
if monitor_exists : # make sure to not update current settings if not asked
if monitor_exists :
# make sure to not update current settings if not asked
cur_ipport = get_ipport ( api , monitor )
if ip is None :
ip = cur_ipport [ ' ipport ' ] [ ' address ' ]
if port is None :
port = cur_ipport [ ' ipport ' ] [ ' port ' ]
else : # use API defaults if not defined to create it
else :
# use API defaults if not defined to create it
if interval is None :
interval = 5
if timeout is None :
@ -414,39 +420,58 @@ def main():
else :
address_type = ' ATYPE_UNSET '
ipport = { ' address_type ' : address_type ,
' ipport ' : { ' address ' : ip ,
' port ' : port } }
ipport = {
' address_type ' : address_type ,
' ipport ' : {
' address ' : ip ,
' port ' : port
}
}
template_attributes = { ' parent_template ' : parent ,
template_attributes = {
' parent_template ' : parent ,
' interval ' : interval ,
' timeout ' : timeout ,
' dest_ipport ' : ipport ,
' is_read_only ' : False ,
' is_directly_usable ' : True }
' is_directly_usable ' : True
}
# monitor specific stuff
if type == ' TTYPE_TCP ' :
template_string_properties = [ { ' type ' : ' STYPE_SEND ' ,
' value ' : send } ,
{ ' type ' : ' STYPE_RECEIVE ' ,
' value ' : receive } ]
template_string_properties = [
{
' type ' : ' STYPE_SEND ' ,
' value ' : send
} ,
{
' type ' : ' STYPE_RECEIVE ' ,
' value ' : receive
}
]
else :
template_string_properties = [ ]
template_integer_properties = [ { ' type ' : ' ITYPE_INTERVAL ' ,
' value ' : interval } ,
{ ' type ' : ' ITYPE_TIMEOUT ' ,
' value ' : timeout } ,
{ ' type ' : ' ITYPE_TIME_UNTIL_UP ' ,
' value ' : interval } ]
template_integer_properties = [
{
' type ' : ' ITYPE_INTERVAL ' ,
' value ' : interval
} ,
{
' type ' : ' ITYPE_TIMEOUT ' ,
' value ' : timeout
} ,
{
' type ' : ' ITYPE_TIME_UNTIL_UP ' ,
' value ' : time_until_up
}
]
# main logic, monitor generic
try :
result = { ' changed ' : False } # default
if state == ' absent ' :
if monitor_exists :
if not module . check_mode :
@ -455,10 +480,9 @@ def main():
result [ ' changed ' ] | = delete_monitor ( api , monitor )
else :
result [ ' changed ' ] | = True
else : # state present
## check for monitor itself
if not monitor_exists : # create it
else :
# check for monitor itself
if not monitor_exists :
if not module . check_mode :
# again, check changed status here b/c race conditions
# if other task already created it
@ -466,24 +490,20 @@ def main():
else :
result [ ' changed ' ] | = True
# # check for monitor parameters
# check for monitor parameters
# whether it already existed, or was just created, now update
# the update functions need to check for check mode but
# cannot update settings if it doesn't exist which happens in check mode
if monitor_exists and not module . check_mode :
result [ ' changed ' ] | = update_monitor_properties ( api , module , monitor ,
template_string_properties ,
template_integer_properties )
# else assume nothing changed
# we just have to update the ipport if monitor already exists and it's different
if monitor_exists and cur_ipport != ipport :
set_ipport ( api , monitor , ipport )
result [ ' changed ' ] | = True
# else: monitor doesn't exist (check mode) or ipport is already ok
except Exception , e :
except Exception as e :
module . fail_json ( msg = " received exception: %s " % e )
module . exit_json ( * * result )