diff options
author | Andris Zeila <andris.zeila@zabbix.com> | 2022-11-11 11:28:02 +0300 |
---|---|---|
committer | Andris Zeila <andris.zeila@zabbix.com> | 2022-11-11 11:32:11 +0300 |
commit | ce2a5cacabb71328a9a66bba10e2257ea5cde15c (patch) | |
tree | 79e12f39565c52b7ecd2230ddcbe8be333ca323a | |
parent | 8f8c59ee64649f779e535deb8f713d1cf394acd2 (diff) |
........S. [ZBX-19813] improved interface update during LLD linking and changed interface copying during template linking to use similar logic as API
Merge in ZBX/zabbix from feature/ZBX-19813-6.2 to release/6.2
* commit '8f28ff9f636f929c86776fefdf65f5cf2ae3dc78':
........S. [ZBX-19813] improved interface update during LLD linking and changed interface copying during template linking to use similar logic as API
(cherry picked from commit de192ff23245b89d6d6d76a503d8a4ae71726b48)
-rw-r--r-- | ChangeLog.d/bugfix/ZBX-19813 | 1 | ||||
-rw-r--r-- | src/libs/zbxdbwrap/host.c | 743 | ||||
-rw-r--r-- | src/zabbix_server/lld/lld_host.c | 433 | ||||
-rw-r--r-- | src/zabbix_server/operations.c | 5 |
4 files changed, 465 insertions, 717 deletions
diff --git a/ChangeLog.d/bugfix/ZBX-19813 b/ChangeLog.d/bugfix/ZBX-19813 new file mode 100644 index 00000000000..bc3de5fb538 --- /dev/null +++ b/ChangeLog.d/bugfix/ZBX-19813 @@ -0,0 +1 @@ +........S. [ZBX-19813] reworked inteface updates in template linking and lld (wiper) diff --git a/src/libs/zbxdbwrap/host.c b/src/libs/zbxdbwrap/host.c index f9236e5ae76..1579ad1846a 100644 --- a/src/libs/zbxdbwrap/host.c +++ b/src/libs/zbxdbwrap/host.c @@ -2056,75 +2056,29 @@ ZBX_PTR_VECTOR_IMPL(macros, zbx_macros_prototype_t *) typedef struct { - char *community_orig; char *community; - char *securityname_orig; char *securityname; - char *authpassphrase_orig; char *authpassphrase; - char *privpassphrase_orig; char *privpassphrase; - char *contextname_orig; char *contextname; - unsigned char securitylevel_orig; unsigned char securitylevel; - unsigned char authprotocol_orig; unsigned char authprotocol; - unsigned char privprotocol_orig; unsigned char privprotocol; - unsigned char version_orig; unsigned char version; - unsigned char bulk_orig; unsigned char bulk; -#define ZBX_FLAG_HPINTERFACE_SNMP_RESET_FLAG __UINT64_C(0x00000000) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_TYPE __UINT64_C(0x00000001) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_BULK __UINT64_C(0x00000002) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_COMMUNITY __UINT64_C(0x00000004) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECNAME __UINT64_C(0x00000008) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECLEVEL __UINT64_C(0x00000010) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPASS __UINT64_C(0x00000020) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPASS __UINT64_C(0x00000040) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPROTOCOL __UINT64_C(0x00000080) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPROTOCOL __UINT64_C(0x00000100) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_CONTEXT __UINT64_C(0x00000200) -#define ZBX_FLAG_HPINTERFACE_SNMP_UPDATE \ - (ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_TYPE | ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_BULK | \ - ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_COMMUNITY | ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECNAME | \ - ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECLEVEL | ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPASS | \ - ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPASS | ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPROTOCOL | \ - ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPROTOCOL | ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_CONTEXT) -#define ZBX_FLAG_HPINTERFACE_SNMP_CREATE __UINT64_C(0x00000400) - zbx_uint64_t flags; } zbx_interface_prototype_snmp_t; typedef struct { zbx_uint64_t interfaceid; - unsigned char main_orig; unsigned char main; - unsigned char type_orig; unsigned char type; - unsigned char useip_orig; unsigned char useip; - char *ip_orig; char *ip; - char *dns_orig; char *dns; - char *port_orig; char *port; -#define ZBX_FLAG_HPINTERFACE_RESET_FLAG __UINT64_C(0x00000000) -#define ZBX_FLAG_HPINTERFACE_UPDATE_MAIN __UINT64_C(0x00000001) -#define ZBX_FLAG_HPINTERFACE_UPDATE_TYPE __UINT64_C(0x00000002) -#define ZBX_FLAG_HPINTERFACE_UPDATE_USEIP __UINT64_C(0x00000004) -#define ZBX_FLAG_HPINTERFACE_UPDATE_IP __UINT64_C(0x00000008) -#define ZBX_FLAG_HPINTERFACE_UPDATE_DNS __UINT64_C(0x00000010) -#define ZBX_FLAG_HPINTERFACE_UPDATE_PORT __UINT64_C(0x00000020) -#define ZBX_FLAG_HPINTERFACE_UPDATE \ - (ZBX_FLAG_HPINTERFACE_UPDATE_MAIN | ZBX_FLAG_HPINTERFACE_UPDATE_TYPE | \ - ZBX_FLAG_HPINTERFACE_UPDATE_USEIP | ZBX_FLAG_HPINTERFACE_UPDATE_IP | \ - ZBX_FLAG_HPINTERFACE_UPDATE_DNS | ZBX_FLAG_HPINTERFACE_UPDATE_PORT) - zbx_uint64_t flags; + union _data { zbx_interface_prototype_snmp_t *snmp; @@ -2189,32 +2143,8 @@ static void DBhost_interface_free(zbx_interfaces_prototype_t *interface) zbx_free(interface->dns); zbx_free(interface->port); - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_IP)) - zbx_free(interface->ip_orig); - - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_DNS)) - zbx_free(interface->dns_orig); - - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_PORT)) - zbx_free(interface->port_orig); - if (INTERFACE_TYPE_SNMP == interface->type) { - if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_COMMUNITY)) - zbx_free(interface->data.snmp->community_orig); - - if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECNAME)) - zbx_free(interface->data.snmp->securityname_orig); - - if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPASS)) - zbx_free(interface->data.snmp->authpassphrase_orig); - - if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPASS)) - zbx_free(interface->data.snmp->privpassphrase_orig); - - if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_CONTEXT)) - zbx_free(interface->data.snmp->contextname_orig); - zbx_free(interface->data.snmp->community); zbx_free(interface->data.snmp->securityname); zbx_free(interface->data.snmp->authpassphrase); @@ -2780,168 +2710,6 @@ static int DBhost_prototypes_macro_make(zbx_vector_macros_t *hostmacros, zbx_uin /****************************************************************************** * * - * Purpose: fill empty value in interfaces with input parameters * - * * - * Parameters: interfaces - [IN/OUT] list of host interfaces * - * interfaceid - [IN] interface id * - * del_snmp_ids - [IN/OUT] list of SNMP interfaces to delete * - * ifmain - [IN] interface main * - * type - [IN] interface type * - * useip - [IN] interface useip * - * ip - [IN] interface ip * - * dns - [IN] interface dns * - * port - [IN] interface port * - * snmp_type - [IN] interface_snmp version * - * bulk - [IN] interface_snmp bulk * - * community - [IN] interface_snmp community * - * securityname - [IN] interface_snmp securityname * - * securitylevel - [IN] interface_snmp securitylevel * - * authpassphrase - [IN] interface_snmp authpassphrase * - * privpassphrase - [IN] interface_snmp privpassphrase * - * authprotocol - [IN] interface_snmp authprotocol * - * privprotocol - [IN] interface_snmp privprotocol * - * contextname - [IN] interface_snmp contextname * - * * - * Return value: SUCCEED - the host interface was found * - * FAIL - in the other case * - ******************************************************************************/ -static int DBhost_prototypes_interface_make(zbx_vector_interfaces_t *interfaces, zbx_uint64_t interfaceid, - zbx_vector_uint64_t *del_snmp_ids, unsigned char ifmain, unsigned char type, unsigned char useip, - const char *ip, const char *dns, const char *port, unsigned char snmp_type, unsigned char bulk, - const char *community, const char *securityname, unsigned char securitylevel, - const char *authpassphrase, const char *privpassphrase, unsigned char authprotocol, - unsigned char privprotocol, const char *contextname) -{ - zbx_interfaces_prototype_t *interface; - int i; - - for (i = 0; i < interfaces->values_num; i++) - { - interface = interfaces->values[i]; - - if (0 == interface->interfaceid) - { - interface->interfaceid = interfaceid; - - if (interface->main != ifmain) - { - interface->flags |= ZBX_FLAG_HPINTERFACE_UPDATE_MAIN; - interface->main_orig = ifmain; - } - - if (interface->type != type) - { - interface->flags |= ZBX_FLAG_HPINTERFACE_UPDATE_TYPE; - interface->type_orig = type; - } - - if (interface->useip != useip) - { - interface->flags |= ZBX_FLAG_HPINTERFACE_UPDATE_USEIP; - interface->useip_orig = useip; - } - - if (0 != strcmp(interface->ip, ip)) - { - interface->flags |= ZBX_FLAG_HPINTERFACE_UPDATE_IP; - interface->ip_orig = zbx_strdup(NULL, ip); - } - - if (0 != strcmp(interface->dns, dns)) - { - interface->flags |= ZBX_FLAG_HPINTERFACE_UPDATE_DNS; - interface->dns_orig = zbx_strdup(NULL, dns); - } - - if (0 != strcmp(interface->port, port)) - { - interface->flags |= ZBX_FLAG_HPINTERFACE_UPDATE_PORT; - interface->port_orig = zbx_strdup(NULL, port); - } - - if (INTERFACE_TYPE_SNMP == interface->type) - { - zbx_interface_prototype_snmp_t *snmp = interface->data.snmp; - - if (INTERFACE_TYPE_SNMP == type) - { - if (snmp->version != snmp_type) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_TYPE; - snmp->version_orig = snmp_type; - } - - if (snmp->bulk != bulk) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_BULK; - snmp->bulk_orig = bulk; - } - - if (0 != strcmp(snmp->community, community)) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_COMMUNITY; - snmp->community_orig = zbx_strdup(NULL, community); - } - - if (0 != strcmp(snmp->securityname, securityname)) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECNAME; - snmp->securityname_orig = zbx_strdup(NULL, securityname); - } - - if (snmp->securitylevel != securitylevel) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECLEVEL; - snmp->securitylevel_orig = securitylevel; - } - - if (0 != strcmp(snmp->authpassphrase, authpassphrase)) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPASS; - snmp->authpassphrase_orig = zbx_strdup(NULL, authpassphrase); - } - - if (0 != strcmp(snmp->privpassphrase, privpassphrase)) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPASS; - snmp->privpassphrase_orig = zbx_strdup(NULL, privpassphrase); - } - - if (snmp->authprotocol != authprotocol) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPROTOCOL; - snmp->authprotocol_orig = authprotocol; - } - - if (snmp->privprotocol != privprotocol) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPROTOCOL; - snmp->privprotocol_orig = privprotocol; - } - - if (0 != strcmp(snmp->contextname, contextname)) - { - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_CONTEXT; - snmp->contextname_orig = zbx_strdup(NULL, contextname); - } - } - else - snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_CREATE; - } - else if (INTERFACE_TYPE_SNMP == type) - { - zbx_vector_uint64_append(del_snmp_ids, interfaceid); - } - - return SUCCEED; - } - } - - return FAIL; -} - -/****************************************************************************** - * * * Parameters: host_prototypes - [IN/OUT] list of host prototypes * * should be sorted by templateid * * del_macroids - [OUT] sorted list of host macroids which * @@ -3215,6 +2983,113 @@ static void DBhost_prototypes_tags_make(zbx_vector_ptr_t *host_prototypes) zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } +static int host_prototype_interfaces_compare(const zbx_interfaces_prototype_t *ifold, + const zbx_interfaces_prototype_t *ifnew) +{ + if (ifold->type != ifnew->type) + return FAIL; + + if (ifold->main != ifnew->main) + return FAIL; + + if (ifold->useip != ifnew->useip) + return FAIL; + + if (0 != strcmp(ifold->ip, ifnew->ip)) + return FAIL; + + if (0 != strcmp(ifold->dns, ifnew->dns)) + return FAIL; + + if (0 != strcmp(ifold->port, ifnew->port)) + return FAIL; + + if (INTERFACE_TYPE_SNMP == ifold->type) + { + if (ifold->data.snmp->version != ifnew->data.snmp->version) + return FAIL; + + if (ifold->data.snmp->bulk != ifnew->data.snmp->bulk) + return FAIL; + + if (0 != strcmp(ifold->data.snmp->community, ifnew->data.snmp->community)) + return FAIL; + + if (0 != strcmp(ifold->data.snmp->securityname, ifnew->data.snmp->securityname)) + return FAIL; + + if (ifold->data.snmp->securitylevel != ifnew->data.snmp->securitylevel) + return FAIL; + + if (0 != strcmp(ifold->data.snmp->authpassphrase, ifnew->data.snmp->authpassphrase)) + return FAIL; + + if (0 != strcmp(ifold->data.snmp->privpassphrase, ifnew->data.snmp->privpassphrase)) + return FAIL; + + if (ifold->data.snmp->authprotocol != ifnew->data.snmp->authprotocol) + return FAIL; + + if (ifold->data.snmp->privprotocol != ifnew->data.snmp->privprotocol) + return FAIL; + + if (0 != strcmp(ifold->data.snmp->contextname, ifnew->data.snmp->contextname)) + return FAIL; + } + + return SUCCEED; +} + +static void host_prototype_interfaces_make(zbx_uint64_t hostid, zbx_vector_ptr_t *host_prototypes, + zbx_vector_interfaces_t *old_interfaces, zbx_vector_uint64_t *del_interfaceids) +{ + int i, j; + zbx_host_prototype_t *host_prototype; + + for (i = 0; i < host_prototypes->values_num; i++) + { + host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i]; + + if (host_prototype->hostid == hostid) + break; + } + + if (i == host_prototypes->values_num) + { + THIS_SHOULD_NEVER_HAPPEN; + goto out; + } + + /* find matching interfaces */ + + for (i = 0; i < host_prototype->interfaces.values_num; i++) + { + zbx_interfaces_prototype_t *interface = (zbx_interfaces_prototype_t *) + host_prototype->interfaces.values[i]; + + if (0 != interface->interfaceid) + continue; + + for (j = 0; j < old_interfaces->values_num; j++) + { + if (SUCCEED == host_prototype_interfaces_compare(old_interfaces->values[j], interface)) + { + interface->interfaceid = old_interfaces->values[j]->interfaceid; + DBhost_interface_free(old_interfaces->values[j]); + zbx_vector_interfaces_remove_noorder(old_interfaces, j); + break; + } + } + } + + /* remove deleted/modified interfaces */ + for (i = 0; i < old_interfaces->values_num; i++) + zbx_vector_uint64_append(del_interfaceids, old_interfaces->values[i]->interfaceid); +out: + zbx_vector_interfaces_clear_ext(old_interfaces, DBhost_interface_free); +} + + /****************************************************************************** * * * Purpose: prepare interfaces to be added, updated or removed from DB * @@ -3222,15 +3097,12 @@ static void DBhost_prototypes_tags_make(zbx_vector_ptr_t *host_prototypes) * should be sorted by templateid * * del_interfaceids - [OUT] sorted list of host interface * * ids which should be deleted * - * del_snmp_interfaceids - [OUT] sorted list of host snmp * - * interface ids which should be * - * deleted * * * * Comments: auxiliary function for DBcopy_template_host_prototypes() * * * ******************************************************************************/ static void DBhost_prototypes_interfaces_make(zbx_vector_ptr_t *host_prototypes, - zbx_vector_uint64_t *del_interfaceids, zbx_vector_uint64_t *del_snmp_interfaceids) + zbx_vector_uint64_t *del_interfaceids) { DB_RESULT result; DB_ROW row; @@ -3293,13 +3165,6 @@ static void DBhost_prototypes_interfaces_make(zbx_vector_ptr_t *host_prototypes, interface->ip = zbx_strdup(NULL, row[4]); interface->dns = zbx_strdup(NULL, row[5]); interface->port = zbx_strdup(NULL, row[6]); - interface->flags = ZBX_FLAG_HPINTERFACE_RESET_FLAG; - interface->main_orig = 0; - interface->type_orig = 0; - interface->useip_orig = 0; - interface->ip_orig = NULL; - interface->dns_orig = NULL; - interface->port_orig = NULL; if (INTERFACE_TYPE_SNMP == interface->type) { @@ -3317,18 +3182,7 @@ static void DBhost_prototypes_interfaces_make(zbx_vector_ptr_t *host_prototypes, ZBX_STR2UCHAR(snmp->authprotocol, row[14]); ZBX_STR2UCHAR(snmp->privprotocol, row[15]); snmp->contextname = zbx_strdup(NULL, row[16]); - snmp->flags = ZBX_FLAG_HPINTERFACE_SNMP_RESET_FLAG; interface->data.snmp = snmp; - snmp->community_orig = NULL; - snmp->securityname_orig = NULL; - snmp->authpassphrase_orig = NULL; - snmp->privpassphrase_orig = NULL; - snmp->contextname_orig = NULL; - snmp->securitylevel_orig = 0; - snmp->authprotocol_orig = 0; - snmp->privprotocol_orig = 0; - snmp->version_orig = 0; - snmp->bulk_orig = 0; } else interface->data.snmp = NULL; @@ -3354,6 +3208,11 @@ static void DBhost_prototypes_interfaces_make(zbx_vector_ptr_t *host_prototypes, if (0 != hostids.values_num) { + zbx_vector_interfaces_t old_interfaces; + zbx_uint64_t last_hostid = 0; + + zbx_vector_interfaces_create(&old_interfaces); + zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); sql_offset = 0; @@ -3374,85 +3233,55 @@ static void DBhost_prototypes_interfaces_make(zbx_vector_ptr_t *host_prototypes, { ZBX_STR2UINT64(hostid, row[1]); - for (i = 0; i < host_prototypes->values_num; i++) + if (0 != last_hostid && hostid != last_hostid) { - host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i]; - - if (host_prototype->hostid == hostid) - { - unsigned char type; - uint64_t interfaceid; - - ZBX_STR2UINT64(interfaceid, row[0]); - ZBX_STR2UCHAR(type, row[3]); - - if (INTERFACE_TYPE_SNMP == type) - { - if (FAIL == DBhost_prototypes_interface_make( - &host_prototype->interfaces, interfaceid, - del_snmp_interfaceids, - (unsigned char)atoi(row[2]), /* main */ - type, - (unsigned char)atoi(row[4]), /* useip */ - row[5], /* ip */ - row[6], /* dns */ - row[7], /* port */ - (unsigned char)atoi(row[8]), /* version */ - (unsigned char)atoi(row[9]), /* bulk */ - row[10], /* community */ - row[11], /* securityname */ - (unsigned char)atoi(row[12]), /* securitylevel */ - row[13], /* authpassphrase */ - row[14], /* privpassphrase */ - (unsigned char)atoi(row[15]), /* authprotocol */ - (unsigned char)atoi(row[16]), /* privprotocol */ - row[17])) /* contextname */ - { - zbx_vector_uint64_append(del_interfaceids, interfaceid); - - zbx_audit_host_prototype_create_entry(ZBX_AUDIT_ACTION_UPDATE, - host_prototype->hostid, host_prototype->host); - - zbx_audit_host_prototype_update_json_delete_interface( - host_prototype->hostid, interfaceid); - } - } - else - { - if (FAIL == DBhost_prototypes_interface_make( - &host_prototype->interfaces, interfaceid, - del_snmp_interfaceids, - (unsigned char)atoi(row[2]), /* main */ - type, - (unsigned char)atoi(row[4]), /* useip */ - row[5], /* ip */ - row[6], /* dns */ - row[7], /* port */ - 0, 0, NULL, NULL, 0, NULL, NULL, 0, 0, NULL)) - { - zbx_vector_uint64_append(del_interfaceids, interfaceid); + host_prototype_interfaces_make(last_hostid, host_prototypes, &old_interfaces, + del_interfaceids); + } - zbx_audit_host_prototype_create_entry(ZBX_AUDIT_ACTION_UPDATE, - host_prototype->hostid, host_prototype->host); + last_hostid = hostid; - zbx_audit_host_prototype_update_json_delete_interface( - host_prototype->hostid, interfaceid); - } - } + interface = (zbx_interfaces_prototype_t *)zbx_malloc(NULL, sizeof(zbx_interfaces_prototype_t)); + ZBX_STR2UINT64(interface->interfaceid, row[0]); + ZBX_STR2UCHAR(interface->main, row[2]); + ZBX_STR2UCHAR(interface->type, row[3]); + ZBX_STR2UCHAR(interface->useip, row[4]); + interface->ip = zbx_strdup(NULL, row[5]); + interface->dns = zbx_strdup(NULL, row[6]); + interface->port = zbx_strdup(NULL, row[7]); - break; - } + if (INTERFACE_TYPE_SNMP == interface->type) + { + zbx_interface_prototype_snmp_t *snmp; + + snmp = (zbx_interface_prototype_snmp_t *)zbx_malloc(NULL, + sizeof(zbx_interface_prototype_snmp_t)); + ZBX_STR2UCHAR(snmp->version, row[8]); + ZBX_STR2UCHAR(snmp->bulk, row[9]); + snmp->community = zbx_strdup(NULL, row[10]); + snmp->securityname = zbx_strdup(NULL, row[11]); + ZBX_STR2UCHAR(snmp->securitylevel, row[12]); + snmp->authpassphrase = zbx_strdup(NULL, row[13]); + snmp->privpassphrase = zbx_strdup(NULL, row[14]); + ZBX_STR2UCHAR(snmp->authprotocol, row[15]); + ZBX_STR2UCHAR(snmp->privprotocol, row[16]); + snmp->contextname = zbx_strdup(NULL, row[17]); + interface->data.snmp = snmp; } + else + interface->data.snmp = NULL; - /* no interfaces found for this host prototype, but there must be at least one */ - if (i == host_prototypes->values_num) - THIS_SHOULD_NEVER_HAPPEN; + zbx_vector_interfaces_append(&old_interfaces, interface); } DBfree_result(result); + + if (0 != old_interfaces.values_num) + host_prototype_interfaces_make(last_hostid, host_prototypes, &old_interfaces, del_interfaceids); + + zbx_vector_interfaces_destroy(&old_interfaces); } zbx_vector_uint64_sort(del_interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); - zbx_vector_uint64_sort(del_snmp_interfaceids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_vector_uint64_destroy(&hostids); zbx_free(sql); @@ -3462,144 +3291,18 @@ static void DBhost_prototypes_interfaces_make(zbx_vector_ptr_t *host_prototypes, /****************************************************************************** * * - * Purpose: prepare sql for update record of interface_snmp table * - * * - * Parameters: hostid - [IN] host identifier * - * interfaceid - [IN] snmp interface id; * - * snmp - [IN] snmp interface prototypes for update * - * sql - [IN/OUT] sql string * - * sql_alloc - [IN/OUT] size of sql string * - * sql_offset - [IN/OUT] offset in sql string * - * * - ******************************************************************************/ -static void DBhost_prototypes_interface_snmp_prepare_sql(zbx_uint64_t hostid, const zbx_uint64_t interfaceid, - const zbx_interface_prototype_snmp_t *snmp, char **sql, size_t *sql_alloc, size_t *sql_offset) -{ - const char *d = ""; - char *esc; - - zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "update interface_snmp set "); - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_TYPE)) - { - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "version=%d", (int)snmp->version); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_version(hostid, interfaceid, - snmp->version_orig, snmp->version); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_BULK)) - { - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sbulk=%d", d, (int)snmp->bulk); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_bulk(hostid, interfaceid, snmp->bulk_orig, - snmp->bulk); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_COMMUNITY)) - { - esc = DBdyn_escape_string(snmp->community); - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%scommunity='%s'", d, esc); - zbx_free(esc); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_community(hostid, interfaceid, - snmp->community_orig, snmp->community); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECNAME)) - { - esc = DBdyn_escape_string(snmp->securityname); - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssecurityname='%s'", d, esc); - zbx_free(esc); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_securityname(hostid, interfaceid, - snmp->securityname_orig, snmp->securityname); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_SECLEVEL)) - { - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssecuritylevel=%d", d, (int)snmp->securitylevel); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_securitylevel(hostid, interfaceid, - snmp->securitylevel_orig, snmp->securitylevel); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPASS)) - { - esc = DBdyn_escape_string(snmp->authpassphrase); - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sauthpassphrase='%s'", d, esc); - zbx_free(esc); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_authpassphrase(hostid, interfaceid, - snmp->authpassphrase_orig, snmp->authpassphrase); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPASS)) - { - esc = DBdyn_escape_string(snmp->privpassphrase); - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sprivpassphrase='%s'", d, esc); - zbx_free(esc); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_privpassphrase(hostid, interfaceid, - snmp->privpassphrase_orig, snmp->privpassphrase); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_AUTHPROTOCOL)) - { - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sauthprotocol=%d", d, (int)snmp->authprotocol); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_authprotocol(hostid, interfaceid, - snmp->authprotocol_orig, snmp->authprotocol); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_PRIVPROTOCOL)) - { - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sprivprotocol=%d", d, (int)snmp->privprotocol); - d = ","; - - zbx_audit_host_prototype_update_json_update_interface_privprotocol(hostid, interfaceid, - snmp->privprotocol_orig, snmp->privprotocol); - } - - if (0 != (snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE_CONTEXT)) - { - esc = DBdyn_escape_string(snmp->contextname); - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%scontextname='%s'", d, esc); - zbx_free(esc); - - zbx_audit_host_prototype_update_json_update_interface_contextname(hostid, interfaceid, - snmp->contextname_orig, snmp->contextname); - } - - zbx_snprintf_alloc(sql, sql_alloc, sql_offset, " where interfaceid=" ZBX_FS_UI64 ";\n", interfaceid); - - DBexecute_overflowed_sql(sql, sql_alloc, sql_offset); -} - -/****************************************************************************** - * * * Purpose: auxiliary function for DBcopy_template_host_prototypes() * * * * Parameters: host_prototypes - [IN] vector of host prototypes * * del_hosttemplateids - [IN] host template ids for delete * * del_hostmacroids - [IN] host macro ids for delete * * del_interfaceids - [IN] interface ids for delete * - * del_snmpids - [IN] SNMP interface ids for delete * * db_insert_htemplates - [IN/OUT] templates insert structure * * * ******************************************************************************/ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, const zbx_vector_uint64_t *del_hosttemplateids, const zbx_vector_uint64_t *del_hostmacroids, - const zbx_vector_uint64_t *del_interfaceids, const zbx_vector_uint64_t *del_snmpids, - zbx_db_insert_t *db_insert_htemplates) + const zbx_vector_uint64_t *del_interfaceids, zbx_db_insert_t *db_insert_htemplates) { char *sql1 = NULL, *sql2 = NULL, *name_esc, *value_esc; size_t sql1_alloc = ZBX_KIBIBYTE, sql1_offset = 0, @@ -3611,8 +3314,8 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, hosttagid = 0, interfaceid = 0; int i, j, new_hosts = 0, new_hosts_templates = 0, new_group_prototypes = 0, upd_group_prototypes = 0, new_hostmacros = 0, upd_hostmacros = 0, - new_tags = 0, new_interfaces = 0, upd_interfaces = 0, new_snmp = 0, - upd_snmp = 0, new_inventory_modes = 0, upd_inventory_modes = 0, res = SUCCEED; + new_tags = 0, new_interfaces = 0, new_snmp = 0, + new_inventory_modes = 0, upd_inventory_modes = 0, res = SUCCEED; zbx_db_insert_t db_insert, db_insert_hdiscovery, db_insert_gproto, db_insert_hmacro, db_insert_tag, db_insert_iface, db_insert_snmp, db_insert_inventory_mode; @@ -3717,21 +3420,21 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, interface = host_prototype->interfaces.values[j]; if (0 == interface->interfaceid) - new_interfaces++; - else if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE)) - upd_interfaces++; - - if (INTERFACE_TYPE_SNMP == interface->type) { - if (0 == interface->interfaceid) - interface->data.snmp->flags |= ZBX_FLAG_HPINTERFACE_SNMP_CREATE; + new_interfaces++; - if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_CREATE)) - new_snmp++; - else if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE)) - upd_snmp++; + if (INTERFACE_TYPE_SNMP == interface->type) + new_snmp++; } } + + for (j = 0; j < del_interfaceids->values_num; j++) + { + zbx_audit_host_prototype_create_entry(ZBX_AUDIT_ACTION_UPDATE, host_prototype->hostid, + host_prototype->host); + zbx_audit_host_prototype_update_json_delete_interface(host_prototype->hostid, + del_interfaceids->values[j]); + } } if (0 != new_hosts) @@ -3755,8 +3458,7 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, hosttemplateid = DBget_maxid_num("hosts_templates", new_hosts_templates); if (0 != del_hosttemplateids->values_num || 0 != del_hostmacroids->values_num || 0 != del_tagids.values_num || - 0 != del_snmpids->values_num || 0 != del_interfaceids->values_num || - 0 != del_inventory_modes_hostids.values_num) + 0 != del_interfaceids->values_num || 0 != del_inventory_modes_hostids.values_num) { sql2 = (char *)zbx_malloc(sql2, sql2_alloc); zbx_DBbegin_multiple_update(&sql2, &sql2_alloc, &sql2_offset); @@ -3786,14 +3488,6 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n"); } - if (0 != del_snmpids->values_num) - { - zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from interface_snmp where"); - DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "interfaceid", - del_snmpids->values, del_snmpids->values_num); - zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, ";\n"); - } - if (0 != del_interfaceids->values_num) { zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from interface where"); @@ -4108,87 +3802,8 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, zbx_audit_host_prototype_update_json_add_interfaces(host_prototype->hostid, interface->interfaceid, interface->main, interface->type, interface->useip, interface->ip, interface->dns, atoi(interface->port)); - } - else if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE)) - { - const char *d = ""; - - zbx_strcpy_alloc(&sql1, &sql1_alloc, &sql1_offset, "update interface set "); - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_MAIN)) - { - zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%smain=%d", d, - interface->main); - d = ","; - zbx_audit_host_prototype_update_json_update_interface_main( - host_prototype->hostid, interface->interfaceid, - interface->main_orig, interface->main); - } - - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_TYPE)) - { - zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%stype=%d", d, - interface->type); - d = ","; - zbx_audit_host_prototype_update_json_update_interface_type( - host_prototype->hostid, interface->interfaceid, - interface->type_orig, interface->type); - } - - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_USEIP)) - { - zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%suseip=%d", d, - interface->useip); - d = ","; - zbx_audit_host_prototype_update_json_update_interface_useip( - host_prototype->hostid, interface->interfaceid, - interface->useip_orig, interface->useip); - } - - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_IP)) - { - value_esc = DBdyn_escape_string(interface->ip); - zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sip='%s'", d, value_esc); - zbx_free(value_esc); - d = ","; - zbx_audit_host_prototype_update_json_update_interface_ip( - host_prototype->hostid, interface->interfaceid, - interface->ip_orig, interface->ip); - } - - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_DNS)) - { - value_esc = DBdyn_escape_string(interface->dns); - zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sdns='%s'", d, - value_esc); - zbx_free(value_esc); - d = ","; - zbx_audit_host_prototype_update_json_update_interface_dns( - host_prototype->hostid, interface->interfaceid, - interface->dns_orig, interface->dns); - } - - if (0 != (interface->flags & ZBX_FLAG_HPINTERFACE_UPDATE_PORT)) - { - value_esc = DBdyn_escape_string(interface->port); - zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "%sport='%s'", d, - value_esc); - zbx_free(value_esc); - zbx_audit_host_prototype_update_json_update_interface_port( - host_prototype->hostid, interface->interfaceid, - atoi(interface->port_orig), atoi(interface->port)); - } - - zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, - " where interfaceid=" ZBX_FS_UI64 ";\n", interface->interfaceid); - - if (FAIL == (res = DBexecute_overflowed_sql(&sql1, &sql1_alloc, &sql1_offset))) - break; - } - - if (INTERFACE_TYPE_SNMP == interface->type) - { - if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_CREATE)) + if (INTERFACE_TYPE_SNMP == interface->type) { zbx_db_insert_add_values(&db_insert_snmp, interface->interfaceid, (int)interface->data.snmp->version, @@ -4214,14 +3829,6 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, interface->data.snmp->contextname, interface->interfaceid); } - else if (0 != (interface->data.snmp->flags & ZBX_FLAG_HPINTERFACE_SNMP_UPDATE)) - { - zbx_audit_host_prototype_update_json_update_interface_details_create_entry( - host_prototype->hostid, interface->interfaceid); - DBhost_prototypes_interface_snmp_prepare_sql(host_prototype->hostid, - interface->interfaceid, interface->data.snmp, &sql1, - &sql1_alloc, &sql1_offset); - } } } } @@ -4308,7 +3915,7 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, } if (SUCCEED == res && (NULL != sql1 || new_hosts != host_prototypes->values_num || 0 != upd_group_prototypes || - 0 != upd_hostmacros || 0 != upd_interfaces || 0 != upd_snmp || 0 != upd_inventory_modes)) + 0 != upd_hostmacros || 0 != upd_inventory_modes)) { zbx_DBend_multiple_update(&sql1, &sql1_alloc, &sql1_offset); @@ -4319,8 +3926,7 @@ static void DBhost_prototypes_save(const zbx_vector_ptr_t *host_prototypes, if (SUCCEED == res && (NULL != sql2 || 0 != del_hosttemplateids->values_num || 0 != del_hostmacroids->values_num || 0 != del_tagids.values_num || - 0 != del_interfaceids->values_num || 0 != del_snmpids->values_num || - 0 != del_inventory_modes_hostids.values_num)) + 0 != del_interfaceids->values_num || 0 != del_inventory_modes_hostids.values_num)) { zbx_DBend_multiple_update(&sql2, &sql2_alloc, &sql2_offset); @@ -4367,27 +3973,24 @@ static void DBcopy_template_host_prototypes(zbx_uint64_t hostid, zbx_vector_uint if (0 != host_prototypes.values_num) { - zbx_vector_uint64_t del_hosttemplateids, del_group_prototypeids, del_macroids, del_interfaceids, - del_snmp_interfaceids; + zbx_vector_uint64_t del_hosttemplateids, del_group_prototypeids, del_macroids, del_interfaceids; zbx_vector_uint64_create(&del_hosttemplateids); zbx_vector_uint64_create(&del_group_prototypeids); zbx_vector_uint64_create(&del_macroids); zbx_vector_uint64_create(&del_interfaceids); - zbx_vector_uint64_create(&del_snmp_interfaceids); DBhost_prototypes_templates_make(&host_prototypes, &del_hosttemplateids); DBhost_prototypes_groups_make(&host_prototypes, &del_group_prototypeids); DBhost_prototypes_macros_make(&host_prototypes, &del_macroids); DBhost_prototypes_tags_make(&host_prototypes); - DBhost_prototypes_interfaces_make(&host_prototypes, &del_interfaceids, &del_snmp_interfaceids); + DBhost_prototypes_interfaces_make(&host_prototypes, &del_interfaceids); DBhost_prototypes_save(&host_prototypes, &del_hosttemplateids, &del_macroids, - &del_interfaceids, &del_snmp_interfaceids, db_insert_htemplates); + &del_interfaceids, db_insert_htemplates); DBgroup_prototypes_delete(&del_group_prototypeids); zbx_vector_uint64_destroy(&del_macroids); zbx_vector_uint64_destroy(&del_group_prototypeids); - zbx_vector_uint64_destroy(&del_snmp_interfaceids); zbx_vector_uint64_destroy(&del_interfaceids); zbx_vector_uint64_destroy(&del_hosttemplateids); } diff --git a/src/zabbix_server/lld/lld_host.c b/src/zabbix_server/lld/lld_host.c index 1e1a96c55b2..45502dcc33e 100644 --- a/src/zabbix_server/lld/lld_host.c +++ b/src/zabbix_server/lld/lld_host.c @@ -145,6 +145,9 @@ typedef struct } zbx_lld_interface_t; +ZBX_PTR_VECTOR_DECL(lld_interface, zbx_lld_interface_t *) +ZBX_PTR_VECTOR_IMPL(lld_interface, zbx_lld_interface_t *) + static void lld_interface_free(zbx_lld_interface_t *interface) { zbx_free(interface->port); @@ -3795,152 +3798,265 @@ static void lld_interfaces_get(zbx_uint64_t id, zbx_vector_ptr_t *interfaces, un zbx_vector_ptr_sort(interfaces, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC); } -static void lld_interface_make(zbx_vector_ptr_t *interfaces, zbx_uint64_t parent_interfaceid, - zbx_uint64_t interfaceid, unsigned char type, unsigned char main, unsigned char useip, const char *ip, - const char *dns, const char *port, unsigned char snmp_type, unsigned char bulk, const char *community, - const char *securityname, unsigned char securitylevel, const char *authpassphrase, - const char *privpassphrase, unsigned char authprotocol, unsigned char privprotocol, - const char *contextname) +/****************************************************************************** + * * + * Purpose: check if two interfaces match by comparing all fields (including * + * prototype interface id) * + * * + * Parameters: ifold - [IN] the old (existing) interface * + * ifnew - [IN] the new (discovered) interface * + * * + * Return value: The interface fields update bitmask in low 32 bits and * + * snmp fields update bitmask in high 32 bits * + * * + ******************************************************************************/ +static zbx_uint64_t lld_interface_compare(const zbx_lld_interface_t *ifold, const zbx_lld_interface_t *ifnew) { - zbx_lld_interface_t *interface = NULL; - int i, interface_found = 0; + zbx_uint64_t flags = 0, snmp_flags = 0; - for (i = 0; i < interfaces->values_num; i++) - { - interface = (zbx_lld_interface_t *)interfaces->values[i]; + if (ifold->type != ifnew->type) + flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE; - if (0 != interface->interfaceid) - continue; + if (ifold->main != ifnew->main) + flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN; - if (interface->parent_interfaceid == parent_interfaceid) - { - interface_found = 1; - break; - } + if (ifold->useip != ifnew->useip) + flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP; + + if (0 != strcmp(ifold->ip, ifnew->ip)) + flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_IP; + + if (0 != strcmp(ifold->dns, ifnew->dns)) + flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS; + + if (0 != strcmp(ifold->port, ifnew->port)) + flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT; + + if (ifold->flags != ifnew->flags) + { + if (0 == ifold->flags) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE; + else + flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_REMOVE; + + /* Add all field update to make snmp type change low priority match. */ + /* When saving create/remove flags are checked before update, so */ + /* adding update flags won't affect interface saving. */ + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE; } - if (0 == interface_found) + if (INTERFACE_TYPE_SNMP == ifold->type && INTERFACE_TYPE_SNMP == ifnew->type) { - /* interface should be deleted */ - interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t)); + if (ifold->data.snmp->version != ifnew->data.snmp->version) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_TYPE; - interface->interfaceid = interfaceid; - interface->parent_interfaceid = 0; - interface->type = type; - interface->main = main; - interface->useip = 0; - interface->ip = NULL; - interface->dns = NULL; - interface->port = NULL; - interface->ip_orig = NULL; - interface->dns_orig = NULL; - interface->port_orig = NULL; - interface->data.snmp = NULL; - interface->main_orig = main; - interface->type_orig = type; - interface->useip_orig = 0; - interface->flags = ZBX_FLAG_LLD_INTERFACE_REMOVE; + if (ifold->data.snmp->bulk != ifnew->data.snmp->bulk) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_BULK; - zbx_vector_ptr_append(interfaces, interface); + if (0 != strcmp(ifold->data.snmp->community, ifnew->data.snmp->community)) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_COMMUNITY; + + if (0 != strcmp(ifold->data.snmp->securityname, ifnew->data.snmp->securityname)) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECNAME; + + if (ifold->data.snmp->securitylevel != ifnew->data.snmp->securitylevel) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECLEVEL; + + if (0 != strcmp(ifold->data.snmp->authpassphrase, ifnew->data.snmp->authpassphrase)) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPASS; + + if (0 != strcmp(ifold->data.snmp->privpassphrase, ifnew->data.snmp->privpassphrase)) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPASS; + + if (ifold->data.snmp->authprotocol != ifnew->data.snmp->authprotocol) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPROTOCOL; + + if (ifold->data.snmp->privprotocol != ifnew->data.snmp->privprotocol) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPROTOCOL; + + if (0 != strcmp(ifold->data.snmp->contextname, ifnew->data.snmp->contextname)) + snmp_flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_CONTEXT; } - else + + return (snmp_flags << 32) | flags; +} + +typedef struct +{ + zbx_lld_interface_t *ifold; + zbx_lld_interface_t *ifnew; + int diff_num; + zbx_uint64_t flags; +} +zbx_if_update_t; + +ZBX_PTR_VECTOR_DECL(if_update, zbx_if_update_t *) +ZBX_PTR_VECTOR_IMPL(if_update, zbx_if_update_t *) + +static int lld_if_update_compare(const void *d1, const void *d2) +{ + const zbx_if_update_t *u1 = *(const zbx_if_update_t * const *)d1; + const zbx_if_update_t *u2 = *(const zbx_if_update_t * const *)d2; + + return u1->diff_num - u2->diff_num; +} + +static zbx_uint64_t popcount64(zbx_uint64_t mask) +{ + mask -= (mask >> 1) & __UINT64_C(0x5555555555555555); + mask = (mask & __UINT64_C(0x3333333333333333)) + (mask >> 2 & __UINT64_C(0x3333333333333333)); + return ((mask + (mask >> 4)) & __UINT64_C(0xf0f0f0f0f0f0f0f)) * __UINT64_C(0x101010101010101) >> 56; +} + +static void lld_interfaces_link(const zbx_lld_interface_t *ifold, zbx_lld_interface_t *ifnew, zbx_uint64_t flags) +{ + ifnew->interfaceid = ifold->interfaceid; + ifnew->flags |= (flags & 0xffffffff); + + if (0 != (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE)) + ifnew->type_orig = ifold->type; + + if (0 != (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN)) + ifnew->main_orig = ifold->main; + + if (0 != (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP)) + ifnew->useip_orig = ifold->useip; + + if (0 != (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_IP)) + ifnew->ip_orig = zbx_strdup(NULL, ifold->ip); + + if (0 != (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS)) + ifnew->dns_orig = zbx_strdup(NULL, ifold->dns); + + if (0 != (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT)) + ifnew->port_orig = zbx_strdup(NULL, ifold->port); + + if (0 != (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS)) { - /* interface already has been added */ - if (interface->type != type) + ifnew->data.snmp->flags |= (flags >> 32); + + if (0 == (ifnew->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE)) { - interface->type_orig = type; - interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_TYPE; + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_TYPE)) + ifnew->data.snmp->version_orig = ifold->data.snmp->version; - if (INTERFACE_TYPE_SNMP == type) - interface->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_REMOVE; + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_BULK)) + ifnew->data.snmp->bulk_orig = ifold->data.snmp->bulk; - if (INTERFACE_TYPE_SNMP == interface->type) - interface->data.snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_CREATE; - } - if (interface->main != main) - { - interface->main_orig = main; - interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_MAIN; - } - if (interface->useip != useip) - { - interface->useip_orig = useip; - interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_USEIP; - } - if (0 != strcmp(interface->ip, ip)) - { - interface->ip_orig = zbx_strdup(NULL, ip); - interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_IP; - } - if (0 != strcmp(interface->dns, dns)) - { - interface->dns_orig = zbx_strdup(NULL, dns); - interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_DNS; + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_COMMUNITY)) + ifnew->data.snmp->community_orig = zbx_strdup(NULL, ifold->data.snmp->community); + + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECNAME)) + ifnew->data.snmp->securityname_orig = zbx_strdup(NULL, ifold->data.snmp->securityname); + + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECLEVEL)) + ifnew->data.snmp->securitylevel_orig = ifold->data.snmp->securitylevel; + + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPASS)) + ifnew->data.snmp->authpassphrase_orig = zbx_strdup(NULL, ifold->data.snmp->authpassphrase); + + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPASS)) + ifnew->data.snmp->privpassphrase_orig = zbx_strdup(NULL, ifold->data.snmp->privpassphrase); + + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPROTOCOL)) + ifnew->data.snmp->authprotocol_orig = ifold->data.snmp->authprotocol; + + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPROTOCOL)) + ifnew->data.snmp->privprotocol_orig = ifold->data.snmp->privprotocol; + + if (0 != (ifnew->data.snmp->flags & ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_CONTEXT)) + ifnew->data.snmp->contextname_orig = zbx_strdup(NULL, ifold->data.snmp->contextname); } - if (0 != strcmp(interface->port, port)) + } +} + +static void lld_host_interfaces_make(zbx_uint64_t hostid, zbx_vector_ptr_t *hosts, + zbx_vector_lld_interface_t *interfaces) +{ + int i, j; + zbx_lld_host_t *host; + zbx_if_update_t *update; + zbx_vector_if_update_t updates; + + if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) + { + zbx_vector_lld_interface_clear_ext(interfaces, lld_interface_free); + THIS_SHOULD_NEVER_HAPPEN; + return; + } + + host = (zbx_lld_host_t *)hosts->values[i]; + + /* prepare old-new interface match matrix as vector, sorted by least number of unmatched fields */ + + zbx_vector_if_update_create(&updates); + + for (i = 0; i < host->interfaces.values_num; i++) + { + zbx_lld_interface_t *ifnew = (zbx_lld_interface_t *)host->interfaces.values[i]; + + for (j = 0; j < interfaces->values_num; j++) { - interface->port_orig = zbx_strdup(NULL, port); - interface->flags |= ZBX_FLAG_LLD_INTERFACE_UPDATE_PORT; + if (ifnew->parent_interfaceid != interfaces->values[j]->parent_interfaceid) + continue; + + update = (zbx_if_update_t *)zbx_malloc(NULL, sizeof(zbx_if_update_t)); + update->ifnew = ifnew; + update->ifold = interfaces->values[j]; + update->flags = lld_interface_compare(update->ifold, update->ifnew); + update->diff_num = popcount64(update->flags); + + zbx_vector_if_update_append(&updates, update); } + } - if (INTERFACE_TYPE_SNMP == interface->type && interface->type == type) - { - zbx_lld_interface_snmp_t *snmp = interface->data.snmp; + zbx_vector_if_update_sort(&updates, lld_if_update_compare); - if (snmp->version != snmp_type) - { - snmp->version_orig = snmp_type; - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_TYPE; - } - if (snmp->bulk != bulk) - { - snmp->bulk_orig = bulk; - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_BULK; - } - if (0 != strcmp(snmp->community, community)) - { - snmp->community_orig = zbx_strdup(NULL, community); - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_COMMUNITY; - } - if (0 != strcmp(snmp->securityname, securityname)) - { - snmp->securityname_orig = zbx_strdup(NULL, securityname); - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECNAME; - } - if (snmp->securitylevel != securitylevel) - { - snmp->securitylevel_orig = securitylevel; - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_SECLEVEL; - } - if (0 != strcmp(snmp->authpassphrase, authpassphrase)) - { - snmp->authpassphrase_orig = zbx_strdup(NULL, authpassphrase); - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPASS; - } - if (0 != strcmp(snmp->privpassphrase, privpassphrase)) - { - snmp->privpassphrase_orig = zbx_strdup(NULL, privpassphrase); - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPASS; - } - if (snmp->authprotocol != authprotocol) - { - snmp->authprotocol_orig = authprotocol; - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_AUTHPROTOCOL; - } - if (snmp->privprotocol != privprotocol) + /* update new interface id to matching old interface id and set update flags accordingly */ + + while (0 != updates.values_num) + { + update = updates.values[0]; + + lld_interfaces_link(update->ifold, update->ifnew, update->flags); + + zbx_vector_if_update_remove(&updates, 0); + + for (i = 0; i < updates.values_num;) + { + if (update->ifnew == updates.values[i]->ifnew || update->ifold == updates.values[i]->ifold) { - snmp->privprotocol_orig = privprotocol; - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_PRIVPROTOCOL; + zbx_free(updates.values[i]); + zbx_vector_if_update_remove(&updates, i); } - if (0 != strcmp(snmp->contextname, contextname)) + else + i++; + } + + for (i = 0; i < interfaces->values_num;) + { + if (interfaces->values[i] == update->ifold) { - snmp->contextname_orig = zbx_strdup(NULL, contextname); - snmp->flags |= ZBX_FLAG_LLD_INTERFACE_SNMP_UPDATE_CONTEXT; + lld_interface_free(interfaces->values[i]); + zbx_vector_lld_interface_remove_noorder(interfaces, i); + break; } + else + i++; } + + zbx_free(update); } - interface->interfaceid = interfaceid; + /* mark leftover old interfaces to be removed */ + + for (i = 0; i < interfaces->values_num; i++) + interfaces->values[i]->flags |= ZBX_FLAG_LLD_INTERFACE_REMOVE; + + zbx_vector_ptr_append_array(&host->interfaces, (void **)interfaces->values, interfaces->values_num); + zbx_vector_lld_interface_clear(interfaces); + + zbx_vector_if_update_destroy(&updates); } /****************************************************************************** @@ -3959,7 +4075,7 @@ static void lld_interfaces_make(const zbx_vector_ptr_t *interfaces, zbx_vector_p DB_ROW row; int i, j; zbx_vector_uint64_t hostids; - zbx_uint64_t parent_interfaceid, hostid, interfaceid; + zbx_uint64_t hostid; zbx_lld_host_t *host; zbx_lld_interface_t *new_interface, *interface; @@ -4056,8 +4172,12 @@ static void lld_interfaces_make(const zbx_vector_ptr_t *interfaces, zbx_vector_p if (0 != hostids.values_num) { - char *sql = NULL; - size_t sql_alloc = 0, sql_offset = 0; + char *sql = NULL; + size_t sql_alloc = 0, sql_offset = 0; + zbx_vector_lld_interface_t old_interfaces; + zbx_uint64_t last_hostid = 0; + + zbx_vector_lld_interface_create(&old_interfaces); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select hi.hostid,id.parent_interfaceid,hi.interfaceid,hi.type,hi.main,hi.useip,hi.ip," @@ -4070,6 +4190,7 @@ static void lld_interfaces_make(const zbx_vector_ptr_t *interfaces, zbx_vector_p " on hi.interfaceid=s.interfaceid" " where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hi.hostid", hostids.values, hostids.values_num); + zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by hi.hostid"); result = DBselect("%s", sql); @@ -4077,39 +4198,61 @@ static void lld_interfaces_make(const zbx_vector_ptr_t *interfaces, zbx_vector_p while (NULL != (row = DBfetch(result))) { - unsigned char interface_type; - ZBX_STR2UINT64(hostid, row[0]); - ZBX_DBROW2UINT64(parent_interfaceid, row[1]); - ZBX_DBROW2UINT64(interfaceid, row[2]); - if (FAIL == (i = zbx_vector_ptr_bsearch(hosts, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))) - { - THIS_SHOULD_NEVER_HAPPEN; - continue; - } + if (0 != last_hostid && hostid != last_hostid) + lld_host_interfaces_make(last_hostid, hosts, &old_interfaces); - host = (zbx_lld_host_t *)hosts->values[i]; - ZBX_STR2UCHAR(interface_type, row[3]); + last_hostid = hostid; + + interface = (zbx_lld_interface_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_t)); + memset(interface, 0, sizeof(zbx_lld_interface_t)); + + ZBX_DBROW2UINT64(interface->parent_interfaceid, row[1]); + ZBX_DBROW2UINT64(interface->interfaceid, row[2]); + ZBX_STR2UCHAR(interface->type, row[3]); + ZBX_STR2UCHAR(interface->main, row[4]); + ZBX_STR2UCHAR(interface->useip, row[5]); + interface->ip = zbx_strdup(NULL, row[6]); + interface->dns = zbx_strdup(NULL, row[7]); + interface->port = zbx_strdup(NULL, row[8]); - if (INTERFACE_TYPE_SNMP == interface_type) + if (INTERFACE_TYPE_SNMP == interface->type) { - lld_interface_make(&host->interfaces, parent_interfaceid, interfaceid, - interface_type, (unsigned char)atoi(row[4]), - (unsigned char)atoi(row[5]), row[6], row[7], row[8], - (unsigned char)atoi(row[9]), (unsigned char)atoi(row[10]), row[11], - row[12], (unsigned char)atoi(row[13]), row[14], row[15], - (unsigned char)atoi(row[16]), (unsigned char)atoi(row[17]), row[18]); + zbx_lld_interface_snmp_t *snmp; + + snmp = (zbx_lld_interface_snmp_t *)zbx_malloc(NULL, sizeof(zbx_lld_interface_snmp_t)); + memset(snmp, 0, sizeof(zbx_lld_interface_snmp_t)); + + ZBX_STR2UCHAR(snmp->version, row[9]); + ZBX_STR2UCHAR(snmp->bulk, row[10]); + snmp->community = zbx_strdup(NULL, row[11]); + snmp->securityname = zbx_strdup(NULL, row[12]); + ZBX_STR2UCHAR(snmp->securitylevel, row[13]); + snmp->authpassphrase = zbx_strdup(NULL, row[14]); + snmp->privpassphrase = zbx_strdup(NULL, row[15]); + ZBX_STR2UCHAR(snmp->authprotocol, row[16]); + ZBX_STR2UCHAR(snmp->privprotocol, row[17]); + snmp->contextname = zbx_strdup(NULL, row[18]); + + snmp->flags = 0x00; + interface->flags = ZBX_FLAG_LLD_INTERFACE_SNMP_DATA_EXISTS; + interface->data.snmp = snmp; } else { - lld_interface_make(&host->interfaces, parent_interfaceid, interfaceid, - interface_type, (unsigned char)atoi(row[4]), - (unsigned char)atoi(row[5]), row[6], row[7], row[8], - 0, 0, NULL, NULL, 0, NULL, NULL,0, 0, NULL); + interface->flags = 0x00; + interface->data.snmp = NULL; } + + zbx_vector_lld_interface_append(&old_interfaces, interface); } DBfree_result(result); + + if (0 != old_interfaces.values_num) + lld_host_interfaces_make(last_hostid, hosts, &old_interfaces); + + zbx_vector_lld_interface_destroy(&old_interfaces); } zbx_vector_uint64_destroy(&hostids); diff --git a/src/zabbix_server/operations.c b/src/zabbix_server/operations.c index 197fd6f809b..309814fb22c 100644 --- a/src/zabbix_server/operations.c +++ b/src/zabbix_server/operations.c @@ -300,12 +300,13 @@ static zbx_uint64_t add_discovered_host(const ZBX_DB_EVENT *event, int *status, " where h.hostid=i.hostid" " and i.ip=ds.ip" " and h.status in (%d,%d)" + " and h.flags<>%d" " and h.proxy_hostid%s" " and ds.dhostid=" ZBX_FS_UI64 - " and h.flags <> %d" " order by h.hostid", HOST_STATUS_MONITORED, HOST_STATUS_NOT_MONITORED, - DBsql_id_cmp(proxy_hostid), dhostid, ZBX_FLAG_DISCOVERY_PROTOTYPE); + ZBX_FLAG_DISCOVERY_PROTOTYPE, + DBsql_id_cmp(proxy_hostid), dhostid); if (NULL != (row2 = DBfetch(result2))) { |