@ -274,13 +274,13 @@ class Host(object):
parameters [ ' proxy_hostid ' ] = proxy_id
parameters [ ' proxy_hostid ' ] = proxy_id
if visible_name :
if visible_name :
parameters [ ' name ' ] = visible_name
parameters [ ' name ' ] = visible_name
if tls_psk_identity :
if tls_psk_identity is not None :
parameters [ ' tls_psk_identity ' ] = tls_psk_identity
parameters [ ' tls_psk_identity ' ] = tls_psk_identity
if tls_psk :
if tls_psk is not None :
parameters [ ' tls_psk ' ] = tls_psk
parameters [ ' tls_psk ' ] = tls_psk
if tls_issuer :
if tls_issuer is not None :
parameters [ ' tls_issuer ' ] = tls_issuer
parameters [ ' tls_issuer ' ] = tls_issuer
if tls_subject :
if tls_subject is not None :
parameters [ ' tls_subject ' ] = tls_subject
parameters [ ' tls_subject ' ] = tls_subject
if description :
if description :
parameters [ ' description ' ] = description
parameters [ ' description ' ] = description
@ -353,7 +353,7 @@ class Host(object):
# get host by host name
# get host by host name
def get_host_by_host_name ( self , host_name ) :
def get_host_by_host_name ( self , host_name ) :
host_list = self . _zapi . host . get ( { ' output ' : ' extend ' , ' filter' : { ' host ' : [ host_name ] } } )
host_list = self . _zapi . host . get ( { ' output ' : ' extend ' , ' selectInventory' : ' extend ' , ' filter' : { ' host ' : [ host_name ] } } )
if len ( host_list ) < 1 :
if len ( host_list ) < 1 :
self . _module . fail_json ( msg = " Host not found: %s " % host_name )
self . _module . fail_json ( msg = " Host not found: %s " % host_name )
else :
else :
@ -429,7 +429,9 @@ class Host(object):
# check all the properties before link or clear template
# check all the properties before link or clear template
def check_all_properties ( self , host_id , host_groups , status , interfaces , template_ids ,
def check_all_properties ( self , host_id , host_groups , status , interfaces , template_ids ,
exist_interfaces , host , proxy_id , visible_name , description , host_name ) :
exist_interfaces , host , proxy_id , visible_name , description , host_name ,
inventory_mode , inventory_zabbix , tls_accept , tls_psk_identity , tls_psk ,
tls_issuer , tls_subject , tls_connect ) :
# get the existing host's groups
# get the existing host's groups
exist_host_groups = self . get_host_groups_by_host_id ( host_id )
exist_host_groups = self . get_host_groups_by_host_id ( host_id )
if set ( host_groups ) != set ( exist_host_groups ) :
if set ( host_groups ) != set ( exist_host_groups ) :
@ -453,14 +455,51 @@ class Host(object):
return True
return True
# Check whether the visible_name has changed; Zabbix defaults to the technical hostname if not set.
# Check whether the visible_name has changed; Zabbix defaults to the technical hostname if not set.
if host [ ' name ' ] != visible_name and host [ ' name ' ] != host_name :
if visible_name :
return True
if host [ ' name ' ] != visible_name and host [ ' name ' ] != host_name :
return True
# The Zabbbix API returns an empty description as an empty string
if description is None :
# Only compare description if it is given as a module parameter
description = ' '
if description :
if host [ ' description ' ] != description :
if host [ ' description ' ] != description :
return True
return True
if inventory_mode :
if host [ ' inventory ' ] :
if int ( host [ ' inventory ' ] [ ' inventory_mode ' ] ) != self . inventory_mode_numeric ( inventory_mode ) :
return True
elif inventory_mode != ' disabled ' :
return True
if inventory_zabbix :
proposed_inventory = copy . deepcopy ( host [ ' inventory ' ] )
proposed_inventory . update ( inventory_zabbix )
if proposed_inventory != host [ ' inventory ' ] :
return True
if tls_accept is not None :
if int ( host [ ' tls_accept ' ] ) != tls_accept :
return True
if tls_psk_identity is not None :
if host [ ' tls_psk_identity ' ] != tls_psk_identity :
return True
if tls_psk is not None :
if host [ ' tls_psk ' ] != tls_psk :
return True
if tls_issuer is not None :
if host [ ' tls_issuer ' ] != tls_issuer :
return True
if tls_subject is not None :
if host [ ' tls_subject ' ] != tls_subject :
return True
if tls_connect is not None :
if int ( host [ ' tls_connect ' ] ) != tls_connect :
return True
return False
return False
@ -479,13 +518,13 @@ class Host(object):
templates_clear_list = list ( templates_clear )
templates_clear_list = list ( templates_clear )
request_str = { ' hostid ' : host_id , ' templates ' : template_id_list , ' templates_clear ' : templates_clear_list ,
request_str = { ' hostid ' : host_id , ' templates ' : template_id_list , ' templates_clear ' : templates_clear_list ,
' tls_connect ' : tls_connect , ' tls_accept ' : tls_accept }
' tls_connect ' : tls_connect , ' tls_accept ' : tls_accept }
if tls_psk_identity :
if tls_psk_identity is not None :
request_str [ ' tls_psk_identity ' ] = tls_psk_identity
request_str [ ' tls_psk_identity ' ] = tls_psk_identity
if tls_psk :
if tls_psk is not None :
request_str [ ' tls_psk ' ] = tls_psk
request_str [ ' tls_psk ' ] = tls_psk
if tls_issuer :
if tls_issuer is not None :
request_str [ ' tls_issuer ' ] = tls_issuer
request_str [ ' tls_issuer ' ] = tls_issuer
if tls_subject :
if tls_subject is not None :
request_str [ ' tls_subject ' ] = tls_subject
request_str [ ' tls_subject ' ] = tls_subject
try :
try :
if self . _module . check_mode :
if self . _module . check_mode :
@ -494,6 +533,15 @@ class Host(object):
except Exception as e :
except Exception as e :
self . _module . fail_json ( msg = " Failed to link template to host: %s " % e )
self . _module . fail_json ( msg = " Failed to link template to host: %s " % e )
def inventory_mode_numeric ( self , inventory_mode ) :
if inventory_mode == " automatic " :
return int ( 1 )
elif inventory_mode == " manual " :
return int ( 0 )
elif inventory_mode == " disabled " :
return int ( - 1 )
return inventory_mode
# Update the host inventory_mode
# Update the host inventory_mode
def update_inventory_mode ( self , host_id , inventory_mode ) :
def update_inventory_mode ( self , host_id , inventory_mode ) :
@ -501,12 +549,7 @@ class Host(object):
if not inventory_mode :
if not inventory_mode :
return
return
if inventory_mode == " automatic " :
inventory_mode = self . inventory_mode_numeric ( inventory_mode )
inventory_mode = int ( 1 )
elif inventory_mode == " manual " :
inventory_mode = int ( 0 )
elif inventory_mode == " disabled " :
inventory_mode = int ( - 1 )
# watch for - https://support.zabbix.com/browse/ZBX-6033
# watch for - https://support.zabbix.com/browse/ZBX-6033
request_str = { ' hostid ' : host_id , ' inventory_mode ' : inventory_mode }
request_str = { ' hostid ' : host_id , ' inventory_mode ' : inventory_mode }
@ -621,20 +664,24 @@ def main():
if interface [ ' type ' ] == 1 :
if interface [ ' type ' ] == 1 :
ip = interface [ ' ip ' ]
ip = interface [ ' ip ' ]
# Use proxy specified, or set to 0
if proxy :
proxy_id = host . get_proxyid_by_proxy_name ( proxy )
else :
proxy_id = 0
# check if host exist
# check if host exist
is_host_exist = host . is_host_exist ( host_name )
is_host_exist = host . is_host_exist ( host_name )
if is_host_exist :
if is_host_exist :
# Use proxy specified, or set to None when updating host
if proxy :
proxy_id = host . get_proxyid_by_proxy_name ( proxy )
else :
proxy_id = 0
# get host id by host name
# get host id by host name
zabbix_host_obj = host . get_host_by_host_name ( host_name )
zabbix_host_obj = host . get_host_by_host_name ( host_name )
host_id = zabbix_host_obj [ ' hostid ' ]
host_id = zabbix_host_obj [ ' hostid ' ]
# If proxy is not specified as a module parameter, use the existing setting
if proxy is None :
proxy_id = zabbix_host_obj [ ' proxy_hostid ' ]
if state == " absent " :
if state == " absent " :
# remove host
# remove host
host . delete_host ( host_id , host_name )
host . delete_host ( host_id , host_name )
@ -646,14 +693,18 @@ def main():
host_groups = host . get_host_groups_by_host_id ( host_id )
host_groups = host . get_host_groups_by_host_id ( host_id )
group_ids = host . get_group_ids_by_group_names ( host_groups )
group_ids = host . get_group_ids_by_group_names ( host_groups )
if not force :
# get existing host's interfaces
# get existing groups, interfaces and templates and merge them with ones provided as an argument
exist_interfaces = host . _zapi . hostinterface . get ( { ' output ' : ' extend ' , ' hostids ' : host_id } )
# we do not want to overwrite anything if force: no is explicitly used, we just want to add new ones
for group_id in host . get_group_ids_by_group_names ( host . get_host_groups_by_host_id ( host_id ) ) :
# if no interfaces were specified with the module, start with an empty list
if group_id not in group_id s:
if not interface s:
group_ids . append ( group_id )
interfaces = [ ]
for interface in host . _zapi . hostinterface . get ( { ' output ' : ' extend ' , ' hostids ' : host_id } ) :
# When force=no is specified, append existing interfaces to interfaces to update. When
# no interfaces have been specified, copy existing interfaces as specified from the API.
# Do the same with templates and host groups.
if not force or not interfaces :
for interface in copy . deepcopy ( exist_interfaces ) :
# remove values not used during hostinterface.add/update calls
# remove values not used during hostinterface.add/update calls
for key in interface . keys ( ) :
for key in interface . keys ( ) :
if key in [ ' interfaceid ' , ' hostid ' , ' bulk ' ] :
if key in [ ' interfaceid ' , ' hostid ' , ' bulk ' ] :
@ -666,54 +717,38 @@ def main():
if interface not in interfaces :
if interface not in interfaces :
interfaces . append ( interface )
interfaces . append ( interface )
if not force or link_templates is None :
template_ids = list ( set ( template_ids + host . get_host_templates_by_host_id ( host_id ) ) )
template_ids = list ( set ( template_ids + host . get_host_templates_by_host_id ( host_id ) ) )
# get exist host's interfaces
if not force :
exist_interfaces = host . _zapi . hostinterface . get ( { ' output ' : ' extend ' , ' hostids ' : host_id } )
for group_id in host . get_group_ids_by_group_names ( host . get_host_groups_by_host_id ( host_id ) ) :
exist_interfaces_copy = copy . deepcopy ( exist_interfaces )
if group_id not in group_ids :
group_ids . append ( group_id )
# update host
# update host
interfaces_len = len ( interfaces ) if interfaces else 0
if host . check_all_properties ( host_id , host_groups , status , interfaces , template_ids ,
exist_interfaces , zabbix_host_obj , proxy_id , visible_name ,
if len ( exist_interfaces ) > interfaces_len :
description , host_name , inventory_mode , inventory_zabbix ,
if host . check_all_properties ( host_id , host_groups , status , interfaces , template_ids ,
tls_accept , tls_psk_identity , tls_psk , tls_issuer , tls_subject , tls_connect ) :
exist_interfaces , zabbix_host_obj , proxy_id , visible_name , description , host_name ) :
host . link_or_clear_template ( host_id , template_ids , tls_connect , tls_accept , tls_psk_identity ,
host . link_or_clear_template ( host_id , template_ids , tls_connect , tls_accept , tls_psk_identity ,
tls_psk , tls_issuer , tls_subject )
tls_psk , tls_issuer , tls_subject )
host . update_host ( host_name , group_ids , status , host_id ,
host . update_host ( host_name , group_ids , status , host_id ,
interfaces , exist_interfaces , proxy_id , visible_name , description , tls_connect , tls_accept ,
interfaces , exist_interfaces , proxy_id , visible_name , description , tls_connect , tls_accept ,
tls_psk_identity , tls_psk , tls_issuer , tls_subject )
tls_psk_identity , tls_psk , tls_issuer , tls_subject )
host . update_inventory_mode ( host_id , inventory_mode )
module . exit_json ( changed = True ,
host . update_inventory_zabbix ( host_id , inventory_zabbix )
result = " Successfully update host %s ( %s ) and linked with template ' %s ' "
% ( host_name , ip , link_templates ) )
module . exit_json ( changed = True ,
else :
result = " Successfully update host %s ( %s ) and linked with template ' %s ' "
module . exit_json ( changed = False )
% ( host_name , ip , link_templates ) )
else :
else :
if host . check_all_properties ( host_id , host_groups , status , interfaces , template_ids ,
module . exit_json ( changed = False )
exist_interfaces_copy , zabbix_host_obj , proxy_id , visible_name , description , host_name ) :
host . update_host ( host_name , group_ids , status , host_id , interfaces , exist_interfaces , proxy_id ,
visible_name , description , tls_connect , tls_accept , tls_psk_identity , tls_psk , tls_issuer ,
tls_subject )
host . link_or_clear_template ( host_id , template_ids , tls_connect , tls_accept , tls_psk_identity ,
tls_psk , tls_issuer , tls_subject )
host . update_inventory_mode ( host_id , inventory_mode )
host . update_inventory_zabbix ( host_id , inventory_zabbix )
module . exit_json ( changed = True ,
result = " Successfully update host %s ( %s ) and linked with template ' %s ' "
% ( host_name , ip , link_templates ) )
else :
module . exit_json ( changed = False )
else :
else :
if state == " absent " :
if state == " absent " :
# the host is already deleted.
# the host is already deleted.
module . exit_json ( changed = False )
module . exit_json ( changed = False )
# Use proxy specified, or set to 0 when adding new host
if proxy :
proxy_id = host . get_proxyid_by_proxy_name ( proxy )
else :
proxy_id = 0
if not group_ids :
if not group_ids :
module . fail_json ( msg = " Specify at least one group for creating host ' %s ' . " % host_name )
module . fail_json ( msg = " Specify at least one group for creating host ' %s ' . " % host_name )