1<script type="text/x-jquery-tmpl" id="hostInterfaceRow"> 2<tr class="interfaceRow" id="hostInterfaceRow_#{iface.interfaceid}" data-interfaceid="#{iface.interfaceid}"> 3 <td class="interface-drag-control <?= ZBX_STYLE_TD_DRAG_ICON ?>"> 4 <div class="<?= ZBX_STYLE_DRAG_ICON ?>"></div> 5 <input type="hidden" name="interfaces[#{iface.interfaceid}][items]" value="#{iface.items}" /> 6 <input type="hidden" name="interfaces[#{iface.interfaceid}][locked]" value="#{iface.locked}" /> 7 </td> 8 <td class="interface-ip"> 9 <input type="hidden" name="interfaces[#{iface.interfaceid}][isNew]" value="#{iface.isNew}"> 10 <input type="hidden" name="interfaces[#{iface.interfaceid}][interfaceid]" value="#{iface.interfaceid}"> 11 <input type="hidden" id="interface_type_#{iface.interfaceid}" name="interfaces[#{iface.interfaceid}][type]" value="#{iface.type}"> 12 <input name="interfaces[#{iface.interfaceid}][ip]" type="text" style="width: <?= ZBX_TEXTAREA_INTERFACE_IP_WIDTH ?>px" maxlength="64" value="#{iface.ip}"> 13 <div class="interface-bulk"> 14 <input type="checkbox" id="interfaces_#{iface.interfaceid}_bulk" name="interfaces[#{iface.interfaceid}][bulk]" value="1" #{attrs.checked_bulk}> 15 <label for="interfaces_#{iface.interfaceid}_bulk"><?= _('Use bulk requests') ?></label> 16 </div> 17 </td> 18 <td class="interface-dns"> 19 <input name="interfaces[#{iface.interfaceid}][dns]" type="text" style="width: <?= ZBX_TEXTAREA_INTERFACE_DNS_WIDTH ?>px" maxlength="64" value="#{iface.dns}"> 20 </td> 21 <?= (new CCol( 22 (new CRadioButtonList('interfaces[#{iface.interfaceid}][useip]', null)) 23 ->addValue(_('IP'), INTERFACE_USE_IP, 'interfaces[#{iface.interfaceid}][useip]['.INTERFACE_USE_IP.']') 24 ->addValue(_('DNS'), INTERFACE_USE_DNS, 25 'interfaces[#{iface.interfaceid}][useip]['.INTERFACE_USE_DNS.']' 26 ) 27 ->setModern(true) 28 ))->toString() 29 ?> 30 <td class="interface-port"> 31 <input name="interfaces[#{iface.interfaceid}][port]" type="text" style="width: <?= ZBX_TEXTAREA_INTERFACE_PORT_WIDTH ?>px" maxlength="64" value="#{iface.port}"> 32 </td> 33 <td class="interface-default"> 34 <input class="mainInterface" type="radio" id="interface_main_#{iface.interfaceid}" name="mainInterfaces[#{iface.type}]" value="#{iface.interfaceid}"> 35 <label class="checkboxLikeLabel" for="interface_main_#{iface.interfaceid}" style="height: 16px; width: 16px;"></label> 36 </td> 37 <td class="<?= ZBX_STYLE_NOWRAP ?> interface-control"> 38 <button class="<?= ZBX_STYLE_BTN_LINK ?> remove" type="button" id="removeInterface_#{iface.interfaceid}" data-interfaceid="#{iface.interfaceid}" #{attrs.disabled}><?= _('Remove') ?></button> 39 </td> 40</tr> 41</script> 42 43<script type="text/javascript"> 44 var hostInterfacesManager = (function() { 45 'use strict'; 46 47 var rowTemplate = new Template(jQuery('#hostInterfaceRow').html()), 48 ports = { 49 agent: 10050, 50 snmp: 161, 51 jmx: 12345, 52 ipmi: 623 53 }, 54 allHostInterfaces = {}; 55 56 function renderHostInterfaceRow(hostInterface) { 57 var domAttrs = getDomElementsAttrsForInterface(hostInterface), 58 domId = getDomIdForRowInsert(hostInterface.type), 59 domRow; 60 61 jQuery(domId).before(rowTemplate.evaluate({iface: hostInterface, attrs: domAttrs})); 62 63 domRow = jQuery('#hostInterfaceRow_' + hostInterface.interfaceid); 64 65 if (hostInterface.type != <?= INTERFACE_TYPE_SNMP ?>) { 66 jQuery('.interface-bulk', domRow).remove(); 67 } 68 69 jQuery('#interfaces_' + hostInterface.interfaceid + '_useip_' + hostInterface.useip).prop('checked', true); 70 71 if (hostInterface.locked > 0) { 72 addNotDraggableIcon(domRow); 73 } 74 else { 75 addDraggableIcon(domRow); 76 } 77 } 78 79 function resetMainInterfaces() { 80 var typeInterfaces, 81 hostInterfaces = getMainInterfacesByType(); 82 83 for (var hostInterfaceType in hostInterfaces) { 84 typeInterfaces = hostInterfaces[hostInterfaceType]; 85 86 if (!typeInterfaces.main && typeInterfaces.all.length) { 87 for (var i = 0; i < typeInterfaces.all.length; i++) { 88 if (allHostInterfaces[typeInterfaces.all[i]].main === '1') { 89 typeInterfaces.main = allHostInterfaces[typeInterfaces.all[i]].interfaceid; 90 } 91 } 92 if (!typeInterfaces.main) { 93 typeInterfaces.main = typeInterfaces.all[0]; 94 allHostInterfaces[typeInterfaces.main].main = '1'; 95 } 96 } 97 } 98 99 for (var hostInterfaceType in hostInterfaces){ 100 typeInterfaces = hostInterfaces[hostInterfaceType]; 101 102 if (typeInterfaces.main) { 103 jQuery('#interface_main_' + typeInterfaces.main).prop('checked', true); 104 } 105 } 106 } 107 108 function getMainInterfacesByType() { 109 var hostInterface, 110 types = {}; 111 types[getHostInterfaceNumericType('agent')] = {main: null, all: []}; 112 types[getHostInterfaceNumericType('snmp')] = {main: null, all: []}; 113 types[getHostInterfaceNumericType('jmx')] = {main: null, all: []}; 114 types[getHostInterfaceNumericType('ipmi')] = {main: null, all: []}; 115 116 for (var hostInterfaceId in allHostInterfaces) { 117 hostInterface = allHostInterfaces[hostInterfaceId]; 118 119 types[hostInterface.type].all.push(hostInterfaceId); 120 if (hostInterface.main === '1') { 121 if (types[hostInterface.type].main !== null) { 122 throw new Error('Multiple default interfaces for same type.'); 123 } 124 types[hostInterface.type].main = hostInterfaceId; 125 } 126 } 127 return types; 128 } 129 130 function addDraggableIcon(domElement) { 131 domElement.draggable({ 132 handle: 'div.<?= ZBX_STYLE_DRAG_ICON ?>', 133 revert: 'invalid', 134 helper: function(event) { 135 var hostInterfaceId = jQuery(this).data('interfaceid'); 136 var clone = jQuery(this).clone(); 137 // Make sure to update names for all radio and checkboxes for them not to affect selection of 138 // originals. 139 // If original is addressed by any means (ex. by ID), make sure, to update these means in clone, 140 // for clone not to be addressed in place of original. 141 clone.find("[name$='[useip]']").each(function(){ 142 jQuery(this).attr('name','interfaces[' + hostInterfaceId + '][useip_handle]'); 143 }); 144 clone.find("#interface_main_" + hostInterfaceId) 145 .attr('name','mainInterfaces[handle]') 146 .attr('id','interface_main_' + hostInterfaceId + '_handle'); 147 return clone; 148 }, 149 start: function(event, ui) { 150 jQuery(ui.helper).css({'z-index': '1000'}); 151 // Visibility is added to original element to hide it, while helper is beeing moved, but to keep 152 // it's place visually. 153 jQuery(this).css({'visibility': 'hidden'}); 154 }, 155 stop: function(event, ui) { 156 resetMainInterfaces(); 157 jQuery(this).css({'visibility': ''}); 158 } 159 }); 160 } 161 162 function addNotDraggableIcon(domElement) { 163 jQuery('td.<?= ZBX_STYLE_TD_DRAG_ICON ?> div.<?= ZBX_STYLE_DRAG_ICON ?>', domElement) 164 .addClass('<?= ZBX_STYLE_DISABLED ?>') 165 .hover( 166 function (event) { 167 hintBox.showHint(event, this, 168 <?= CJs::encodeJson(_('Interface is used by items that require this type of the interface.')) ?> 169 ); 170 }, 171 function (event) { 172 hintBox.hideHint(event, this); 173 } 174 ); 175 } 176 177 function getDomElementsAttrsForInterface(hostInterface) { 178 var attrs = { 179 disabled: '' 180 }; 181 182 if (hostInterface.items > 0) { 183 attrs.disabled = 'disabled="disabled"'; 184 } 185 186 if (hostInterface.type == <?= INTERFACE_TYPE_SNMP ?>) { 187 if (hostInterface.bulk == 1) { 188 attrs.checked_bulk = 'checked=checked'; 189 } 190 else { 191 attrs.checked_bulk = ''; 192 } 193 } 194 195 return attrs; 196 } 197 198 function getDomIdForRowInsert(hostInterfaceType) { 199 var footerRowId; 200 201 switch (hostInterfaceType) { 202 case getHostInterfaceNumericType('agent'): 203 footerRowId = '#agentInterfacesFooter'; 204 break; 205 case getHostInterfaceNumericType('snmp'): 206 footerRowId = '#SNMPInterfacesFooter'; 207 break; 208 case getHostInterfaceNumericType('jmx'): 209 footerRowId = '#JMXInterfacesFooter'; 210 break; 211 case getHostInterfaceNumericType('ipmi'): 212 footerRowId = '#IPMIInterfacesFooter'; 213 break; 214 default: 215 throw new Error('Unknown host interface type.'); 216 } 217 return footerRowId; 218 } 219 220 function createNewHostInterface(hostInterfaceType) { 221 var newInterface = { 222 isNew: true, 223 useip: 1, 224 type: getHostInterfaceNumericType(hostInterfaceType), 225 port: ports[hostInterfaceType], 226 ip: '127.0.0.1' 227 }; 228 229 if (newInterface.type == <?= INTERFACE_TYPE_SNMP ?>) { 230 newInterface.bulk = 1; 231 } 232 233 newInterface.interfaceid = 1; 234 while (allHostInterfaces[newInterface.interfaceid] !== void(0)) { 235 newInterface.interfaceid++; 236 } 237 238 addHostInterface(newInterface); 239 240 return newInterface; 241 } 242 243 function addHostInterface(hostInterface) { 244 allHostInterfaces[hostInterface.interfaceid] = hostInterface; 245 } 246 247 function moveRowToAnotherTypeTable(hostInterfaceId, newHostInterfaceType) { 248 var newDomId = getDomIdForRowInsert(newHostInterfaceType); 249 250 jQuery('#interface_main_' + hostInterfaceId).attr('name', 'mainInterfaces[' + newHostInterfaceType + ']'); 251 jQuery('#interface_main_' + hostInterfaceId).prop('checked', false); 252 jQuery('#interface_type_' + hostInterfaceId).val(newHostInterfaceType); 253 jQuery('#hostInterfaceRow_' + hostInterfaceId).insertBefore(newDomId); 254 } 255 256 return { 257 add: function(hostInterfaces) { 258 for (var i = 0; i < hostInterfaces.length; i++) { 259 addHostInterface(hostInterfaces[i]); 260 renderHostInterfaceRow(hostInterfaces[i]); 261 } 262 resetMainInterfaces(); 263 }, 264 265 addNew: function(type) { 266 var hostInterface = createNewHostInterface(type); 267 268 allHostInterfaces[hostInterface.interfaceid] = hostInterface; 269 renderHostInterfaceRow(hostInterface); 270 resetMainInterfaces(); 271 }, 272 273 remove: function(hostInterfaceId) { 274 delete allHostInterfaces[hostInterfaceId]; 275 }, 276 277 setType: function(hostInterfaceId, typeName) { 278 var newTypeNum = getHostInterfaceNumericType(typeName); 279 280 if (allHostInterfaces[hostInterfaceId].type !== newTypeNum) { 281 moveRowToAnotherTypeTable(hostInterfaceId, newTypeNum); 282 allHostInterfaces[hostInterfaceId].type = newTypeNum; 283 allHostInterfaces[hostInterfaceId].main = '0'; 284 } 285 }, 286 287 resetMainInterfaces: function() { 288 resetMainInterfaces(); 289 }, 290 291 setMainInterface: function(hostInterfaceId) { 292 var interfacesByType = getMainInterfacesByType(), 293 newMainInterfaceType = allHostInterfaces[hostInterfaceId].type, 294 oldMainInterfaceId = interfacesByType[newMainInterfaceType].main; 295 296 if (hostInterfaceId !== oldMainInterfaceId) { 297 allHostInterfaces[hostInterfaceId].main = '1'; 298 allHostInterfaces[oldMainInterfaceId].main = '0'; 299 } 300 }, 301 302 setUseipForInterface: function(hostInterfaceId, useip) { 303 allHostInterfaces[hostInterfaceId].useip = useip; 304 }, 305 306 disable: function() { 307 jQuery('.interface-drag-control, .interface-control').html(''); 308 jQuery('.interfaceRow').find('input') 309 .removeAttr('id') 310 .removeAttr('name'); 311 jQuery('.interfaceRow').find('input[type="text"]').attr('readonly', true); 312 jQuery('.interfaceRow').find('input[type="radio"], input[type="checkbox"]').attr('disabled', true); 313 } 314 } 315 }()); 316 317 jQuery(document).ready(function() { 318 'use strict'; 319 320 jQuery('#hostlist').on('click', 'button.remove', function() { 321 var interfaceId = jQuery(this).data('interfaceid'); 322 jQuery('#hostInterfaceRow_' + interfaceId).remove(); 323 hostInterfacesManager.remove(interfaceId); 324 hostInterfacesManager.resetMainInterfaces(); 325 }); 326 327 jQuery('#hostlist').on('click', 'input[type=radio].mainInterface', function() { 328 var interfaceId = jQuery(this).val(); 329 hostInterfacesManager.setMainInterface(interfaceId); 330 }); 331 332 jQuery('#hostlist').on('click', 'input[type=radio][id*="_useip_"]', function() { 333 var interfaceId = jQuery(this).attr('id').match(/\d+/); 334 hostInterfacesManager.setUseipForInterface(interfaceId[0], jQuery(this).val()); 335 }); 336 337 jQuery('#tls_connect, #tls_in_psk, #tls_in_cert').change(function() { 338 // If certificate is selected or checked. 339 if (jQuery('input[name=tls_connect]:checked').val() == <?= HOST_ENCRYPTION_CERTIFICATE ?> 340 || jQuery('#tls_in_cert').is(':checked')) { 341 jQuery('#tls_issuer, #tls_subject').closest('li').show(); 342 } 343 else { 344 jQuery('#tls_issuer, #tls_subject').closest('li').hide(); 345 } 346 347 // If PSK is selected or checked. 348 if (jQuery('input[name=tls_connect]:checked').val() == <?= HOST_ENCRYPTION_PSK ?> 349 || jQuery('#tls_in_psk').is(':checked')) { 350 jQuery('#tls_psk, #tls_psk_identity').closest('li').show(); 351 } 352 else { 353 jQuery('#tls_psk, #tls_psk_identity').closest('li').hide(); 354 } 355 }); 356 357 jQuery('#agentInterfaces, #SNMPInterfaces, #JMXInterfaces, #IPMIInterfaces').parent().droppable({ 358 tolerance: 'pointer', 359 drop: function(event, ui) { 360 var hostInterfaceTypeName = jQuery(this).data('type'), 361 hostInterfaceId = ui.draggable.data('interfaceid'); 362 363 if (getHostInterfaceNumericType(hostInterfaceTypeName) == <?= INTERFACE_TYPE_SNMP ?>) { 364 if (jQuery('.interface-bulk', jQuery('#hostInterfaceRow_' + hostInterfaceId)).length == 0) { 365 var bulkDiv = jQuery('<div>', { 366 'class': 'interface-bulk' 367 }); 368 369 // append checkbox 370 bulkDiv.append(jQuery('<input>', { 371 id: 'interfaces_' + hostInterfaceId + '_bulk', 372 type: 'checkbox', 373 name: 'interfaces[' + hostInterfaceId + '][bulk]', 374 value: 1, 375 checked: true 376 })); 377 378 // append label 379 bulkDiv.append(jQuery('<label>', { 380 'for': 'interfaces_' + hostInterfaceId + '_bulk', 381 text: '<?= _('Use bulk requests') ?>' 382 })); 383 384 jQuery('.interface-ip', jQuery('#hostInterfaceRow_' + hostInterfaceId)).append(bulkDiv); 385 } 386 } 387 else { 388 jQuery('.interface-bulk', jQuery('#hostInterfaceRow_' + hostInterfaceId)).remove(); 389 } 390 391 hostInterfacesManager.setType(hostInterfaceId, hostInterfaceTypeName); 392 }, 393 activate: function(event, ui) { 394 if (!jQuery(this).find(ui.draggable).length) { 395 jQuery(this).addClass('<?= ZBX_STYLE_DRAG_DROP_AREA ?>'); 396 } 397 }, 398 deactivate: function(event, ui) { 399 jQuery(this).removeClass('<?= ZBX_STYLE_DRAG_DROP_AREA ?>'); 400 } 401 }); 402 403 jQuery('#addAgentInterface').on('click', function() { 404 hostInterfacesManager.addNew('agent'); 405 }); 406 jQuery('#addSNMPInterface').on('click', function() { 407 hostInterfacesManager.addNew('snmp'); 408 }); 409 jQuery('#addJMXInterface').on('click', function() { 410 hostInterfacesManager.addNew('jmx'); 411 }); 412 jQuery('#addIPMIInterface').on('click', function() { 413 hostInterfacesManager.addNew('ipmi'); 414 }); 415 416 // radio button of inventory modes was clicked 417 jQuery('input[name=inventory_mode]').click(function() { 418 // action depending on which button was clicked 419 var inventoryFields = jQuery('#inventorylist :input:gt(2)'); 420 421 switch (jQuery(this).val()) { 422 case '<?= HOST_INVENTORY_DISABLED ?>': 423 inventoryFields.prop('disabled', true); 424 jQuery('.populating_item').hide(); 425 break; 426 case '<?= HOST_INVENTORY_MANUAL ?>': 427 inventoryFields.prop('disabled', false); 428 jQuery('.populating_item').hide(); 429 break; 430 case '<?= HOST_INVENTORY_AUTOMATIC ?>': 431 inventoryFields.prop('disabled', false); 432 inventoryFields.filter('.linked_to_item').prop('disabled', true); 433 jQuery('.populating_item').show(); 434 break; 435 } 436 }); 437 438 /** 439 * Mass update 440 */ 441 jQuery('#mass_replace_tpls').on('change', function() { 442 jQuery('#mass_clear_tpls').prop('disabled', !this.checked); 443 }).change(); 444 445 // Refresh field visibility on document load. 446 if ((jQuery('#tls_accept').val() & <?= HOST_ENCRYPTION_NONE ?>) == <?= HOST_ENCRYPTION_NONE ?>) { 447 jQuery('#tls_in_none').prop('checked', true); 448 } 449 if ((jQuery('#tls_accept').val() & <?= HOST_ENCRYPTION_PSK ?>) == <?= HOST_ENCRYPTION_PSK ?>) { 450 jQuery('#tls_in_psk').prop('checked', true); 451 } 452 if ((jQuery('#tls_accept').val() & <?= HOST_ENCRYPTION_CERTIFICATE ?>) == <?= HOST_ENCRYPTION_CERTIFICATE ?>) { 453 jQuery('#tls_in_cert').prop('checked', true); 454 } 455 456 jQuery('input[name=tls_connect]').trigger('change'); 457 458 // Depending on checkboxes, create a value for hidden field 'tls_accept'. 459 jQuery('#hostForm').submit(function() { 460 var tls_accept = 0x00; 461 462 if (jQuery('#tls_in_none').is(':checked')) { 463 tls_accept |= <?= HOST_ENCRYPTION_NONE ?>; 464 } 465 if (jQuery('#tls_in_psk').is(':checked')) { 466 tls_accept |= <?= HOST_ENCRYPTION_PSK ?>; 467 } 468 if (jQuery('#tls_in_cert').is(':checked')) { 469 tls_accept |= <?= HOST_ENCRYPTION_CERTIFICATE ?>; 470 } 471 472 jQuery('#tls_accept').val(tls_accept); 473 }); 474 }); 475 476 function getHostInterfaceNumericType(typeName) { 477 var typeNum; 478 479 switch (typeName) { 480 case 'agent': 481 typeNum = '<?= INTERFACE_TYPE_AGENT ?>'; 482 break; 483 case 'snmp': 484 typeNum = '<?= INTERFACE_TYPE_SNMP ?>'; 485 break; 486 case 'jmx': 487 typeNum = '<?= INTERFACE_TYPE_JMX ?>'; 488 break; 489 case 'ipmi': 490 typeNum = '<?= INTERFACE_TYPE_IPMI ?>'; 491 break; 492 default: 493 throw new Error('Unknown host interface type name.'); 494 } 495 return typeNum; 496 } 497</script> 498