Python script that clusters two BIG-IPs

Problem this snippet solves:

This script automates the clustering of two BIG-IPs and performs some pre-clustering validation (NTP, CM device configuration, matching TMOS)

How to use this snippet:

Configure your BIG-IPs hostnames, CM device characteristics, NTP, etc and execute the script.

Code :

#!/usr/bin/env python3

# Import the proper python modules we'll need
import datetime
import time
import requests
import sys
import json

from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

#
# Declare functions
#

def abort_script(reason):
    print('*** Aborting script execution! ***')
    if len(str(reason)) > 0:
        print('ERROR: ' + str(reason))
    sys.exit(2)

def icontrol_get(host,username,password,path):
    apiCall = requests.session()
    apiCall.headers.update({'Content-type':'application/json'})
    apiCall.auth = (username,password)
    apiUri = 'https://' + host + '/mgmt/tm' + path
    try:
        apiResponse = apiCall.get(apiUri,verify=False)
    except requests.exceptions.RequestException as e:
        abort_script(str(e))
    return(apiResponse.text)

def icontrol_post(host,username,password,path,api_payload):
    apiCall = requests.session()
    apiCall.headers.update({'Content-type':'application/json'})
    apiCall.auth = (username,password)
    apiUri = 'https://' + host + '/mgmt/tm' + path
    try:
        apiResponse = apiCall.post(apiUri,verify=False,data=json.dumps(api_payload))
    except requests.exceptions.RequestException as e:
        abort_script(str(e))
    return(apiResponse.text)

def icontrol_put(host,username,password,path,api_payload):
    apiCall = requests.session()
    apiCall.headers.update({'Content-type':'application/json'})
    apiCall.auth = (username,password)
    apiUri = 'https://' + host + '/mgmt/tm' + path
    try:
        apiResponse = apiCall.put(apiUri,verify=False,data=json.dumps(api_payload))
    except requests.exceptions.RequestException as e:
        abort_script(str(e))
    return(apiResponse.text)

def icontrol_patch(host,username,password,path,api_payload):
    apiCall = requests.session()
    apiCall.headers.update({'Content-type':'application/json'})
    apiCall.auth = (username,password)
    apiUri = 'https://' + host + '/mgmt/tm' + path
    try:
        apiResponse = apiCall.patch(apiUri,verify=False,data=json.dumps(api_payload))
    except requests.exceptions.RequestException as e:
        abort_script(str(e))
    return(apiResponse.text)

def icontrol_delete(host,username,password,path,object):
    apiCall = requests.session()
    apiCall.headers.update({'Content-type':'application/json'})
    apiCall.auth = (username,password)
    apiUri = 'https://' + host + '/mgmt/tm' + path + object
    try:
        apiResponse = apiCall.delete(apiUri,verify=False)
    except requests.exceptions.RequestException as e:
        abort_script(str(e))
    return(apiResponse.text)

def icontrol_test_connection(host,username,password):
    apiCall = requests.session()
    apiCall.headers.update({'Content-type':'application/json'})
    apiCall.auth = (username,password)
    apiUri = 'https://' + host + '/mgmt/tm/sys/clock'
    try:
        apiResponse = apiCall.get(apiUri,verify=False)
    except requests.exceptions.RequestException as e:
        abort_script(str(e))
    if '"kind"' in apiResponse.text:
        testresult = True
    else:
        testresult = False
    return(testresult)

def icontrol_save_config(host,username,password):
    apiCall = requests.session()
    apiCall.headers.update({'Content-type':'application/json'})
    apiCall.auth = (username,password)
    apiUri = 'https://' + host + '/mgmt/tm/sys/config'
    try:
        apiResponse = apiCall.post(apiUri,verify=False,data=json.dumps({'command':'save'}))
    except requests.exceptions.RequestException as e:
        abort_script(str(e))
    return(apiResponse.text)

#
# We will save variables in the primary and standby variables, which we'll define now
#

primary = {}
standby = {}

###############################
# Pre-clustering Verification
###############################

#
# Ask for the cluster member mgmt IP addresses, usernames and passwords
#

primary['mgmt_ip'] = input('Enter the management IP address of the primary node: ')
primary['username'] = input('Enter the username for the primary node: ')
primary['password'] = input('Password: ')
standby['mgmt_ip'] = input('Enter the management IP address of the secondary node: ')
standby['username'] = input('Enter the username for the secondary node: ')
standby['password'] = input('Password: ')
print('Enter the desired device group name on the BIG-IPs')
cluster_group_name = input('[If you\'re unsure, enter failover-bigip]: ')

#
# Test iControl REST connectivity
#

print('Testing API connectivity to the primary node')
primary_test = icontrol_test_connection(primary['mgmt_ip'],primary['username'],primary['password'])
if primary_test == True:
    print('  Successfully connected to the primary node')
else:
    abort_script('Could not connect to the primary node during API check')

print('Testing API connectivity to the secondary node')
secondary_test = icontrol_test_connection(standby['mgmt_ip'],standby['username'],standby['password'])
if secondary_test == True:
    print('  Successfully connected to the secondary node')
else:
    abort_script('Could not connect to the secondary node during API check')

#
# Gather details about each node
#

apiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/global-settings/')
primary['hostname'] = json.loads(apiResponse)['hostname']

apiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/global-settings/')
standby['hostname'] = json.loads(apiResponse)['hostname']

apiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/cm/device/')
primary['cm_devices'] = json.loads(apiResponse)['items']
for current_cm_device in primary['cm_devices']:
    if current_cm_device['selfDevice'] == 'true':
        primary['cm_properties'] = current_cm_device
        primary['cm_name'] = current_cm_device['name']
        primary['sw_version'] = current_cm_device['version']
        primary['sw_build'] = current_cm_device['build']

apiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/cm/device/')
standby['cm_devices'] = json.loads(apiResponse)['items']
for current_cm_device in standby['cm_devices']:
    if current_cm_device['selfDevice'] == 'true':
        standby['cm_properties'] = current_cm_device
        standby['cm_name'] = current_cm_device['name']
        standby['sw_version'] = current_cm_device['version']
        standby['sw_build'] = current_cm_device['build']

#
# Verify that the TMOS versions match between nodes
#

if not (primary['sw_version'] == standby['sw_version']) and (primary['sw_build'] == standby['sw_build']):
    abort_script('Software mismatch on cluster members!')

#
# Verify that the CM device has been configured from default
#

if primary['cm_name'] == 'bigip1' or standby['cm_name'] == 'bigip1':
    abort_script('A cluster member was found to have the default CM device name. Please run the configuration script.')

#
# Verify NTP is configured
#

print('Checking for NTP server configuration on primary')
apiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/ntp')
if 'servers' in apiResponse:
    primary['ntp_servers'] = json.loads(apiResponse)['servers']
    primary['timezone'] = json.loads(apiResponse)['timezone']
    print('  Success!')
else:
    abort_script('NTP not configured on cluster member!')

print('Checking for NTP server configuration on secondary')
apiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/ntp')
if 'servers' in apiResponse:
    standby['ntp_servers'] = json.loads(apiResponse)['servers']
    standby['timezone'] = json.loads(apiResponse)['timezone']
    print('  Success!')
else:
    abort_script('NTP not configured on cluster member!')

#
# Verify host clocks are in sync
#
print('Verifying device clock sync')
apiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/clock')
primary['clock_timestamp']=json.loads(apiResponse)['entries']['https://localhost/mgmt/tm/sys/clock/0']['nestedStats']['entries']['fullDate']['description'][:16]

apiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/clock')
standby['clock_timestamp'] = json.loads(apiResponse)['entries']['https://localhost/mgmt/tm/sys/clock/0']['nestedStats']['entries']['fullDate']['description'][:16]

if primary['clock_timestamp'] != standby['clock_timestamp']:
    abort_script('Device clocks are out of sync!')
else:
    print('  Success!')

#
# Show details about each node and ask user for final verification to continue
#
print('\nPrimary details')
print(' - Mgmt IP: ' + primary['mgmt_ip'])
print(' - Hostname: ' + primary['hostname'])
print(' - Cluster Device Name: ' + primary['cm_name'])
print(' - Version ' + primary['sw_version'] + ', build ' + primary['sw_build'])
print(' - Time zone: ' + primary['timezone'])
print(' - NTP servers: ' + str(primary['ntp_servers']))
print('\nSecondary details')
print(' - Mgmt IP: ' + standby['mgmt_ip'])
print(' - Hostname: ' + standby['hostname'])
print(' - Cluster Device Name: ' + standby['cm_name'])
print(' - Version ' + standby['sw_version'] + ', build ' + standby['sw_build'])
print(' - Time zone: ' + standby['timezone'])
print(' - NTP servers: ' + str(standby['ntp_servers']))
print('\nThis is the last chance to abort before issuing the clustering commands!\n')
confirmation = input('Enter YES to continue ')
if not confirmation == 'YES':
    abort_script('User cancelled at final confirmation!')

#######################
# Clustering Commands
#######################

#
# Save the config on each device
#

print('Saving the device configuration on the primary')
save_result = icontrol_save_config(primary['mgmt_ip'],primary['username'],primary['password'])
if '"kind"' in save_result:
    print("  Configuration saved successfully.")
else:
    abort_script("Configuration could not be successfully saved! " + save_result)

print('Saving the device configuration on the secondary')
save_result = icontrol_save_config(standby['mgmt_ip'],standby['username'],standby['password'])
if '"kind"' in save_result:
    print("  Configuration saved successfully.")
else:
    abort_script("Configuration could not be successfully saved! " + save_result)


#
# Save a pre-clustering UCS on each box for rollback
#

ucs_filename = 'pre-cluster-script-{:%Y-%m-%d-%H%M%S}.ucs'.format(datetime.datetime.utcnow())
print('Saving UCS to /var/local/ucs/' + ucs_filename + ' on primary device')
ucs_create_result = icontrol_post(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/ucs',{'command':'save','name':ucs_filename})

print('Saving UCS to /var/local/ucs/' + ucs_filename + ' on secondary device')
ucs_create_result = icontrol_post(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/ucs',{'command':'save','name':ucs_filename})

#
# Add the secondary to the primary as a peer
#

print('Adding the nodes to the trust domain')
apiResponse = icontrol_post(primary['mgmt_ip'],primary['username'],primary['password'],'/cm/add-to-trust',{
    'command':'run',
    'name':'Root',
    'caDevice':True,
    'device':standby['mgmt_ip'],
    'deviceName':standby['cm_name'],
    'username':standby['username'],
    'password':standby['password']
})
if '"kind":"tm:cm:add-to-trust:runstate"' in apiResponse:
    print('  Command issued successfully but clustering must be verified!')
else:
    abort_script('Error! ' + apiResponse)

#
# Verify status of members
#

print('Verifying trust sync status on the primary')
apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')
if '"mode":{"description":"trust-only"}' in apiResponse:
    print('  Devices are in sync!')
else:
    print('Sleeping 60 seconds to allow devices to discover and sync')
    time.sleep(60)
    apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')
    if '"mode":{"description":"trust-only"}' in apiResponse:
        print('  Devices are in sync!')
    else:
        abort_script('Error! Devices not syncing! ' + apiResponse)

print('Verifying trust sync status on the secondary')
apiResponse = icontrol_get(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/sync-status')
if '"mode":{"description":"trust-only"}' in apiResponse:
    print('  Devices are in sync!')
else:
    print('Sleeping 60 seconds to allow devices to discover and sync')
    time.sleep(60)
    apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')
    if '"mode":{"description":"trust-only"}' in apiResponse:
        print('  Devices are in sync!')
    else:
        abort_script('Error! Devices not syncing!' + apiResponse)

#
# Create the device group
#

print('Creating the ' + cluster_group_name + ' device group')
apiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group',{
    'name':cluster_group_name,
    'type':'sync-failover'
})
if '"kind":"tm:cm:device-group:device-groupstate"' in apiResponse:
    print('  Success!')
elif '"01020066:3:' in apiResponse:
    print('  WARNING! Device group already created! Ignoring and continuing script execution!')
else:
    abort_script('Error! ' + apiResponse)

#
# Add both devices to the device group
#

print('Adding the primary node to the device group')
apiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group/' + cluster_group_name + '/devices',{
    'name':primary['cm_name']
})
if '"kind":"tm:cm:device-group:devices:devicesstate"' in apiResponse:
    print('  Success!')
elif '"code":409,"message":"01020037:3:' in apiResponse:
    print('  WARNING! Device is already a member of the device group! Ignoring and continuing script execution!')
else:
    abort_script('Error! ' + apiResponse)

print('Adding the secondary node to the device group')
apiResponse = icontrol_post(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/device-group/' + cluster_group_name + '/devices',{
    'name':standby['cm_name']
})
if '"kind":"tm:cm:device-group:devices:devicesstate"' in apiResponse:
    print('  Success!')
elif '"code":409,"message":"01020037:3:' in apiResponse:
    print('  WARNING! Device is already a member of the device group! Ignoring and continuing script execution!')
else:
    abort_script('Error! ' + apiResponse)

#
# Enable auto-sync on both members
#

print('Enabling auto-sync on the primary member')
apiResponse = icontrol_patch(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group/' + cluster_group_name,{
    'autoSync':'enabled'
})
if '"kind":"tm:cm:device-group:device-groupstate"' and '"autoSync":"enabled"' in apiResponse:
    print('  Success!')
else:
    abort_script('Error! ' + apiResponse)

print('Enabling auto-sync on the secondary member')
apiResponse = icontrol_patch(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/device-group/' + cluster_group_name,{
    'autoSync':'enabled'
})
if '"kind":"tm:cm:device-group:device-groupstate"' and '"autoSync":"enabled"' in apiResponse:
    print('  Success!')
else:
    abort_script('Error! ' + apiResponse)

#
# Save the config on each device
#

print('Saving the device configuration on the primary')
save_result = icontrol_save_config(primary['mgmt_ip'],primary['username'],primary['password'])
if '"kind"' in save_result:
    print("  Configuration saved successfully.")
else:
    abort_script("Configuration could not be successfully saved! " + save_result)

print('Saving the device configuration on the secondary')
save_result = icontrol_save_config(standby['mgmt_ip'],standby['username'],standby['password'])
if '"kind"' in save_result:
    print("  Configuration saved successfully.")
else:
    abort_script("Configuration could not be successfully saved! " + save_result)


###############################
# Post-clustering steps
###############################

#
# Force the initial sync
#

print('Forcing configuration sync between peers')
apiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/config-sync',{
    'command':'run',
    'utilCmdArgs':'to-group ' + cluster_group_name
})
if '"kind":"tm:cm:config-sync:runstate"' in apiResponse:
    print('  Command issued successfully but sync status must be verified!')
else:
    abort_script('Error! ' + apiResponse)

#
# Verify sync status of members
#

print('Verifying trust sync status on the primary')
apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')
if '"description":"failover-bigip (In Sync): All devices in the device group are in sync"':
    print('  Success!')
else:
    print('Sleeping 30 seconds to allow devices to fully sync')
    time.sleep(30)
    if '"description":"failover-bigip (In Sync): All devices in the device group are in sync"':
        print('  Devices are in sync!')
    else:
        abort_script('Error! Devices not syncing!')

print('Verifying trust sync status on the primary')
apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')
if '"description":"failover-bigip (In Sync): All devices in the device group are in sync"':
    print('  Success!')
else:
    print('Sleeping 30 seconds to allow devices to fully sync')
    time.sleep(30)
    if '"description":"failover-bigip (In Sync): All devices in the device group are in sync"':
        print('  Devices are in sync!')
    else:
        abort_script('Error! Devices not syncing!')

#
# Force the primary to active state, if necessary
#

print('Foricng the primary node to active status')
apiResponse = icontrol_post(standby['mgmt_ip'], standby['username'], standby['password'], '/sys/failover',{
    'command':'run',
    'standby':True,
    'traffic-group':'traffic-group-1'
})
if '"kind":"tm:sys:failover:runstate"' in apiResponse:
    print('  Success!')
else:
    abort_script('Error! ' + apiResponse)

################
# End of Script
################

print('\nEnd of execution. Script has completed.')
SystemExit()

Tested this on version:

12.1
Published Aug 13, 2019
Version 1.0
No CommentsBe the first to comment
"}},"componentScriptGroups({\"componentId\":\"custom.widget.Beta_MetaNav\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Beta_Footer\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[\"message:283549\"],\"name\":\"TkbMessagePage\",\"props\":{},\"url\":\"https://community.f5.com/kb/codeshare/python-script-that-clusters-two-big-ips/283549\"}}})":{"__typename":"ComponentRenderResult","html":"
 
 
 
 
 

\"F5 ©2024 F5, Inc. All rights reserved.
Trademarks Policies Privacy California Privacy Do Not Sell My Personal Information
"}},"componentScriptGroups({\"componentId\":\"custom.widget.Beta_Footer\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[\"message:283549\"],\"name\":\"TkbMessagePage\",\"props\":{},\"url\":\"https://community.f5.com/kb/codeshare/python-script-that-clusters-two-big-ips/283549\"}}})":{"__typename":"ComponentRenderResult","html":" "}},"componentScriptGroups({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[\"message:283549\"],\"name\":\"TkbMessagePage\",\"props\":{},\"url\":\"https://community.f5.com/kb/codeshare/python-script-that-clusters-two-big-ips/283549\"}}})":{"__typename":"ComponentRenderResult","html":"
"}},"componentScriptGroups({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/QueryHandler\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageCustomFields\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageCustomFields-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRevision\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRevision-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageReplyButton\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageReplyButton-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageAuthorBio\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/guides/GuideBottomNavigation\"]})":[{"__ref":"CachedAsset:text:en_US-components/guides/GuideBottomNavigation-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/tags/TagView/TagViewChip\"]})":[{"__ref":"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserRank\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserRank-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserRegistrationDate\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserRegistrationDate-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/customComponent/CustomComponent\"]})":[{"__ref":"CachedAsset:text:en_US-components/customComponent/CustomComponent-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/ranks/UserRankLabel\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1744046271000"}]},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Former Member","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"dd-MMM-yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":null,"possibleValues":["en-US","de-DE"]},"repliesSortOrder":{"__typename":"InheritableStringSettingWithPossibleValues","key":"config.user_replies_sort_order","value":"DEFAULT","localValue":"DEFAULT","possibleValues":["DEFAULT","LIKES","PUBLISH_TIME","REVERSE_PUBLISH_TIME"]}},"deleted":false},"CachedAsset:pages-1746693049844":{"__typename":"CachedAsset","id":"pages-1746693049844","value":[{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.MvpProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/mvp-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.AdvocacyProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/advocacy-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.NonCustomer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/non-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Customer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.Learn","type":"COMMUNITY","urlPath":"/c/how-do-i/learn","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1739501996000,"localOverride":null,"page":{"id":"Test","type":"CUSTOM","urlPath":"/custom-test-2","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.Community","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/community","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.ContributeCode","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/contribute-code","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.Learn.AboutIrules","type":"COMMUNITY","urlPath":"/c/how-do-i/learn/about-irules","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Support","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-support","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.SecurityIncident","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/security-incident","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI","type":"COMMUNITY","urlPath":"/c/how-do-i","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}","userBanned":"We're sorry, but you have been banned from using this site.","userBannedReason":"You have been banned for the following reason: {reason}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/cmstMjgtQ3U0RXo2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/cmstMjgtQ3U0RXo2","height":0,"width":0,"mimeType":"image/svg+xml"},"Rank:rank:28":{"__typename":"Rank","id":"rank:28","position":5,"name":"Employee","color":"C20025","icon":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/cmstMjgtQ3U0RXo2\"}"},"rankStyle":"OUTLINE"},"User:user:190002":{"__typename":"User","id":"user:190002","uid":190002,"login":"G-Rob","deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xOTAwMDItMjE1NDVpQzdCNEVGMTE0QUVGRkI3OA"},"rank":{"__ref":"Rank:rank:28"},"email":"","messagesCount":63,"biography":null,"topicsCount":17,"kudosReceivedCount":31,"kudosGivenCount":43,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":null,"registrationTime":"2019-05-16T14:13:21.000-07:00","confirmEmailStatus":null},"followersCount":null,"solutionsCount":6},"Category:category:CrowdSRC":{"__typename":"Category","id":"category:CrowdSRC","entityType":"CATEGORY","displayId":"CrowdSRC","nodeType":"category","depth":1,"title":"CrowdSRC","shortTitle":"CrowdSRC","parent":{"__ref":"Category:category:top"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","entityType":"CATEGORY","displayId":"top","nodeType":"category","depth":0,"title":"Top","shortTitle":"Top"},"Tkb:board:codeshare":{"__typename":"Tkb","id":"board:codeshare","entityType":"TKB","displayId":"codeshare","nodeType":"board","depth":2,"conversationStyle":"TKB","repliesProperties":{"__typename":"RepliesProperties","sortOrder":"PUBLISH_TIME","repliesFormat":"threaded"},"tagProperties":{"__typename":"TagNodeProperties","tagsEnabled":{"__typename":"PolicyResult","failureReason":null}},"requireTags":true,"tagType":"FREEFORM_AND_PRESET","description":"Have some code. Share some code.","title":"CodeShare","shortTitle":"CodeShare","parent":{"__ref":"Category:category:CrowdSRC"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:zihoc95639"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:CrowdSRC"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"theme":{"__ref":"Theme:customTheme1"},"boardPolicies":{"__typename":"BoardPolicies","canViewSpamDashBoard":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.access_spam_quarantine.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.access_spam_quarantine.allowed.accessDenied","args":[]}},"canArchiveMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.content_archivals.enable_content_archival_settings.accessDenied","key":"error.lithium.policies.content_archivals.enable_content_archival_settings.accessDenied","args":[]}},"canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}},"canReadNode":{"__typename":"PolicyResult","failureReason":null}},"isManualSortOrderAvailable":false,"tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"TkbTopicMessage:message:283549":{"__typename":"TkbTopicMessage","uid":283549,"subject":"Python script that clusters two BIG-IPs","id":"message:283549","revisionNum":1,"repliesCount":0,"author":{"__ref":"User:user:190002"},"depth":0,"hasGivenKudo":false,"helpful":null,"board":{"__ref":"Tkb:board:codeshare"},"conversation":{"__ref":"Conversation:conversation:283549"},"messagePolicies":{"__typename":"MessagePolicies","canPublishArticleOnEdit":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_edit_workflow_action.accessDenied","args":[]}},"canModerateSpamMessage":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","key":"error.lithium.policies.feature.moderation_spam.action.moderate_entity.allowed.accessDenied","args":[]}}},"contentWorkflow":{"__typename":"ContentWorkflow","state":"PUBLISH","scheduledPublishTime":null,"scheduledTimezone":null,"userContext":{"__typename":"MessageWorkflowContext","canSubmitForReview":null,"canEdit":false,"canRecall":null,"canSubmitForPublication":null,"canReturnToAuthor":null,"canPublish":null,"canReturnToReview":null,"canSchedule":false},"shortScheduledTimezone":null},"readOnly":false,"editFrozen":false,"moderationData":{"__ref":"ModerationData:moderation_data:283549"},"teaser":"","body":"

Problem this snippet solves:

This script automates the clustering of two BIG-IPs and performs some pre-clustering validation (NTP, CM device configuration, matching TMOS)

How to use this snippet:

Configure your BIG-IPs hostnames, CM device characteristics, NTP, etc and execute the script.

Code :

#!/usr/bin/env python3\n\n# Import the proper python modules we'll need\nimport datetime\nimport time\nimport requests\nimport sys\nimport json\n\nfrom requests.packages.urllib3.exceptions import InsecureRequestWarning\n\nrequests.packages.urllib3.disable_warnings(InsecureRequestWarning)\n\n#\n# Declare functions\n#\n\ndef abort_script(reason):\n    print('*** Aborting script execution! ***')\n    if len(str(reason)) > 0:\n        print('ERROR: ' + str(reason))\n    sys.exit(2)\n\ndef icontrol_get(host,username,password,path):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.get(apiUri,verify=False)\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_post(host,username,password,path,api_payload):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.post(apiUri,verify=False,data=json.dumps(api_payload))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_put(host,username,password,path,api_payload):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.put(apiUri,verify=False,data=json.dumps(api_payload))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_patch(host,username,password,path,api_payload):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.patch(apiUri,verify=False,data=json.dumps(api_payload))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_delete(host,username,password,path,object):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path + object\n    try:\n        apiResponse = apiCall.delete(apiUri,verify=False)\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_test_connection(host,username,password):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm/sys/clock'\n    try:\n        apiResponse = apiCall.get(apiUri,verify=False)\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    if '\"kind\"' in apiResponse.text:\n        testresult = True\n    else:\n        testresult = False\n    return(testresult)\n\ndef icontrol_save_config(host,username,password):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm/sys/config'\n    try:\n        apiResponse = apiCall.post(apiUri,verify=False,data=json.dumps({'command':'save'}))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\n#\n# We will save variables in the primary and standby variables, which we'll define now\n#\n\nprimary = {}\nstandby = {}\n\n###############################\n# Pre-clustering Verification\n###############################\n\n#\n# Ask for the cluster member mgmt IP addresses, usernames and passwords\n#\n\nprimary['mgmt_ip'] = input('Enter the management IP address of the primary node: ')\nprimary['username'] = input('Enter the username for the primary node: ')\nprimary['password'] = input('Password: ')\nstandby['mgmt_ip'] = input('Enter the management IP address of the secondary node: ')\nstandby['username'] = input('Enter the username for the secondary node: ')\nstandby['password'] = input('Password: ')\nprint('Enter the desired device group name on the BIG-IPs')\ncluster_group_name = input('[If you\\'re unsure, enter failover-bigip]: ')\n\n#\n# Test iControl REST connectivity\n#\n\nprint('Testing API connectivity to the primary node')\nprimary_test = icontrol_test_connection(primary['mgmt_ip'],primary['username'],primary['password'])\nif primary_test == True:\n    print('  Successfully connected to the primary node')\nelse:\n    abort_script('Could not connect to the primary node during API check')\n\nprint('Testing API connectivity to the secondary node')\nsecondary_test = icontrol_test_connection(standby['mgmt_ip'],standby['username'],standby['password'])\nif secondary_test == True:\n    print('  Successfully connected to the secondary node')\nelse:\n    abort_script('Could not connect to the secondary node during API check')\n\n#\n# Gather details about each node\n#\n\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/global-settings/')\nprimary['hostname'] = json.loads(apiResponse)['hostname']\n\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/global-settings/')\nstandby['hostname'] = json.loads(apiResponse)['hostname']\n\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/cm/device/')\nprimary['cm_devices'] = json.loads(apiResponse)['items']\nfor current_cm_device in primary['cm_devices']:\n    if current_cm_device['selfDevice'] == 'true':\n        primary['cm_properties'] = current_cm_device\n        primary['cm_name'] = current_cm_device['name']\n        primary['sw_version'] = current_cm_device['version']\n        primary['sw_build'] = current_cm_device['build']\n\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/cm/device/')\nstandby['cm_devices'] = json.loads(apiResponse)['items']\nfor current_cm_device in standby['cm_devices']:\n    if current_cm_device['selfDevice'] == 'true':\n        standby['cm_properties'] = current_cm_device\n        standby['cm_name'] = current_cm_device['name']\n        standby['sw_version'] = current_cm_device['version']\n        standby['sw_build'] = current_cm_device['build']\n\n#\n# Verify that the TMOS versions match between nodes\n#\n\nif not (primary['sw_version'] == standby['sw_version']) and (primary['sw_build'] == standby['sw_build']):\n    abort_script('Software mismatch on cluster members!')\n\n#\n# Verify that the CM device has been configured from default\n#\n\nif primary['cm_name'] == 'bigip1' or standby['cm_name'] == 'bigip1':\n    abort_script('A cluster member was found to have the default CM device name. Please run the configuration script.')\n\n#\n# Verify NTP is configured\n#\n\nprint('Checking for NTP server configuration on primary')\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/ntp')\nif 'servers' in apiResponse:\n    primary['ntp_servers'] = json.loads(apiResponse)['servers']\n    primary['timezone'] = json.loads(apiResponse)['timezone']\n    print('  Success!')\nelse:\n    abort_script('NTP not configured on cluster member!')\n\nprint('Checking for NTP server configuration on secondary')\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/ntp')\nif 'servers' in apiResponse:\n    standby['ntp_servers'] = json.loads(apiResponse)['servers']\n    standby['timezone'] = json.loads(apiResponse)['timezone']\n    print('  Success!')\nelse:\n    abort_script('NTP not configured on cluster member!')\n\n#\n# Verify host clocks are in sync\n#\nprint('Verifying device clock sync')\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/clock')\nprimary['clock_timestamp']=json.loads(apiResponse)['entries']['https://localhost/mgmt/tm/sys/clock/0']['nestedStats']['entries']['fullDate']['description'][:16]\n\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/clock')\nstandby['clock_timestamp'] = json.loads(apiResponse)['entries']['https://localhost/mgmt/tm/sys/clock/0']['nestedStats']['entries']['fullDate']['description'][:16]\n\nif primary['clock_timestamp'] != standby['clock_timestamp']:\n    abort_script('Device clocks are out of sync!')\nelse:\n    print('  Success!')\n\n#\n# Show details about each node and ask user for final verification to continue\n#\nprint('\\nPrimary details')\nprint(' - Mgmt IP: ' + primary['mgmt_ip'])\nprint(' - Hostname: ' + primary['hostname'])\nprint(' - Cluster Device Name: ' + primary['cm_name'])\nprint(' - Version ' + primary['sw_version'] + ', build ' + primary['sw_build'])\nprint(' - Time zone: ' + primary['timezone'])\nprint(' - NTP servers: ' + str(primary['ntp_servers']))\nprint('\\nSecondary details')\nprint(' - Mgmt IP: ' + standby['mgmt_ip'])\nprint(' - Hostname: ' + standby['hostname'])\nprint(' - Cluster Device Name: ' + standby['cm_name'])\nprint(' - Version ' + standby['sw_version'] + ', build ' + standby['sw_build'])\nprint(' - Time zone: ' + standby['timezone'])\nprint(' - NTP servers: ' + str(standby['ntp_servers']))\nprint('\\nThis is the last chance to abort before issuing the clustering commands!\\n')\nconfirmation = input('Enter YES to continue ')\nif not confirmation == 'YES':\n    abort_script('User cancelled at final confirmation!')\n\n#######################\n# Clustering Commands\n#######################\n\n#\n# Save the config on each device\n#\n\nprint('Saving the device configuration on the primary')\nsave_result = icontrol_save_config(primary['mgmt_ip'],primary['username'],primary['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\nprint('Saving the device configuration on the secondary')\nsave_result = icontrol_save_config(standby['mgmt_ip'],standby['username'],standby['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\n\n#\n# Save a pre-clustering UCS on each box for rollback\n#\n\nucs_filename = 'pre-cluster-script-{:%Y-%m-%d-%H%M%S}.ucs'.format(datetime.datetime.utcnow())\nprint('Saving UCS to /var/local/ucs/' + ucs_filename + ' on primary device')\nucs_create_result = icontrol_post(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/ucs',{'command':'save','name':ucs_filename})\n\nprint('Saving UCS to /var/local/ucs/' + ucs_filename + ' on secondary device')\nucs_create_result = icontrol_post(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/ucs',{'command':'save','name':ucs_filename})\n\n#\n# Add the secondary to the primary as a peer\n#\n\nprint('Adding the nodes to the trust domain')\napiResponse = icontrol_post(primary['mgmt_ip'],primary['username'],primary['password'],'/cm/add-to-trust',{\n    'command':'run',\n    'name':'Root',\n    'caDevice':True,\n    'device':standby['mgmt_ip'],\n    'deviceName':standby['cm_name'],\n    'username':standby['username'],\n    'password':standby['password']\n})\nif '\"kind\":\"tm:cm:add-to-trust:runstate\"' in apiResponse:\n    print('  Command issued successfully but clustering must be verified!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Verify status of members\n#\n\nprint('Verifying trust sync status on the primary')\napiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\nif '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n    print('  Devices are in sync!')\nelse:\n    print('Sleeping 60 seconds to allow devices to discover and sync')\n    time.sleep(60)\n    apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\n    if '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing! ' + apiResponse)\n\nprint('Verifying trust sync status on the secondary')\napiResponse = icontrol_get(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/sync-status')\nif '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n    print('  Devices are in sync!')\nelse:\n    print('Sleeping 60 seconds to allow devices to discover and sync')\n    time.sleep(60)\n    apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\n    if '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing!' + apiResponse)\n\n#\n# Create the device group\n#\n\nprint('Creating the ' + cluster_group_name + ' device group')\napiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group',{\n    'name':cluster_group_name,\n    'type':'sync-failover'\n})\nif '\"kind\":\"tm:cm:device-group:device-groupstate\"' in apiResponse:\n    print('  Success!')\nelif '\"01020066:3:' in apiResponse:\n    print('  WARNING! Device group already created! Ignoring and continuing script execution!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Add both devices to the device group\n#\n\nprint('Adding the primary node to the device group')\napiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group/' + cluster_group_name + '/devices',{\n    'name':primary['cm_name']\n})\nif '\"kind\":\"tm:cm:device-group:devices:devicesstate\"' in apiResponse:\n    print('  Success!')\nelif '\"code\":409,\"message\":\"01020037:3:' in apiResponse:\n    print('  WARNING! Device is already a member of the device group! Ignoring and continuing script execution!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\nprint('Adding the secondary node to the device group')\napiResponse = icontrol_post(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/device-group/' + cluster_group_name + '/devices',{\n    'name':standby['cm_name']\n})\nif '\"kind\":\"tm:cm:device-group:devices:devicesstate\"' in apiResponse:\n    print('  Success!')\nelif '\"code\":409,\"message\":\"01020037:3:' in apiResponse:\n    print('  WARNING! Device is already a member of the device group! Ignoring and continuing script execution!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Enable auto-sync on both members\n#\n\nprint('Enabling auto-sync on the primary member')\napiResponse = icontrol_patch(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group/' + cluster_group_name,{\n    'autoSync':'enabled'\n})\nif '\"kind\":\"tm:cm:device-group:device-groupstate\"' and '\"autoSync\":\"enabled\"' in apiResponse:\n    print('  Success!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\nprint('Enabling auto-sync on the secondary member')\napiResponse = icontrol_patch(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/device-group/' + cluster_group_name,{\n    'autoSync':'enabled'\n})\nif '\"kind\":\"tm:cm:device-group:device-groupstate\"' and '\"autoSync\":\"enabled\"' in apiResponse:\n    print('  Success!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Save the config on each device\n#\n\nprint('Saving the device configuration on the primary')\nsave_result = icontrol_save_config(primary['mgmt_ip'],primary['username'],primary['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\nprint('Saving the device configuration on the secondary')\nsave_result = icontrol_save_config(standby['mgmt_ip'],standby['username'],standby['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\n\n###############################\n# Post-clustering steps\n###############################\n\n#\n# Force the initial sync\n#\n\nprint('Forcing configuration sync between peers')\napiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/config-sync',{\n    'command':'run',\n    'utilCmdArgs':'to-group ' + cluster_group_name\n})\nif '\"kind\":\"tm:cm:config-sync:runstate\"' in apiResponse:\n    print('  Command issued successfully but sync status must be verified!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Verify sync status of members\n#\n\nprint('Verifying trust sync status on the primary')\napiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\nif '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n    print('  Success!')\nelse:\n    print('Sleeping 30 seconds to allow devices to fully sync')\n    time.sleep(30)\n    if '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing!')\n\nprint('Verifying trust sync status on the primary')\napiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\nif '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n    print('  Success!')\nelse:\n    print('Sleeping 30 seconds to allow devices to fully sync')\n    time.sleep(30)\n    if '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing!')\n\n#\n# Force the primary to active state, if necessary\n#\n\nprint('Foricng the primary node to active status')\napiResponse = icontrol_post(standby['mgmt_ip'], standby['username'], standby['password'], '/sys/failover',{\n    'command':'run',\n    'standby':True,\n    'traffic-group':'traffic-group-1'\n})\nif '\"kind\":\"tm:sys:failover:runstate\"' in apiResponse:\n    print('  Success!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n################\n# End of Script\n################\n\nprint('\\nEnd of execution. Script has completed.')\nSystemExit()

Tested this on version:

12.1","body@stringLength":"18605","rawBody":"

Problem this snippet solves:

This script automates the clustering of two BIG-IPs and performs some pre-clustering validation (NTP, CM device configuration, matching TMOS)

How to use this snippet:

Configure your BIG-IPs hostnames, CM device characteristics, NTP, etc and execute the script.

Code :

#!/usr/bin/env python3\n\n# Import the proper python modules we'll need\nimport datetime\nimport time\nimport requests\nimport sys\nimport json\n\nfrom requests.packages.urllib3.exceptions import InsecureRequestWarning\n\nrequests.packages.urllib3.disable_warnings(InsecureRequestWarning)\n\n#\n# Declare functions\n#\n\ndef abort_script(reason):\n    print('*** Aborting script execution! ***')\n    if len(str(reason)) > 0:\n        print('ERROR: ' + str(reason))\n    sys.exit(2)\n\ndef icontrol_get(host,username,password,path):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.get(apiUri,verify=False)\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_post(host,username,password,path,api_payload):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.post(apiUri,verify=False,data=json.dumps(api_payload))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_put(host,username,password,path,api_payload):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.put(apiUri,verify=False,data=json.dumps(api_payload))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_patch(host,username,password,path,api_payload):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path\n    try:\n        apiResponse = apiCall.patch(apiUri,verify=False,data=json.dumps(api_payload))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_delete(host,username,password,path,object):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm' + path + object\n    try:\n        apiResponse = apiCall.delete(apiUri,verify=False)\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\ndef icontrol_test_connection(host,username,password):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm/sys/clock'\n    try:\n        apiResponse = apiCall.get(apiUri,verify=False)\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    if '\"kind\"' in apiResponse.text:\n        testresult = True\n    else:\n        testresult = False\n    return(testresult)\n\ndef icontrol_save_config(host,username,password):\n    apiCall = requests.session()\n    apiCall.headers.update({'Content-type':'application/json'})\n    apiCall.auth = (username,password)\n    apiUri = 'https://' + host + '/mgmt/tm/sys/config'\n    try:\n        apiResponse = apiCall.post(apiUri,verify=False,data=json.dumps({'command':'save'}))\n    except requests.exceptions.RequestException as e:\n        abort_script(str(e))\n    return(apiResponse.text)\n\n#\n# We will save variables in the primary and standby variables, which we'll define now\n#\n\nprimary = {}\nstandby = {}\n\n###############################\n# Pre-clustering Verification\n###############################\n\n#\n# Ask for the cluster member mgmt IP addresses, usernames and passwords\n#\n\nprimary['mgmt_ip'] = input('Enter the management IP address of the primary node: ')\nprimary['username'] = input('Enter the username for the primary node: ')\nprimary['password'] = input('Password: ')\nstandby['mgmt_ip'] = input('Enter the management IP address of the secondary node: ')\nstandby['username'] = input('Enter the username for the secondary node: ')\nstandby['password'] = input('Password: ')\nprint('Enter the desired device group name on the BIG-IPs')\ncluster_group_name = input('[If you\\'re unsure, enter failover-bigip]: ')\n\n#\n# Test iControl REST connectivity\n#\n\nprint('Testing API connectivity to the primary node')\nprimary_test = icontrol_test_connection(primary['mgmt_ip'],primary['username'],primary['password'])\nif primary_test == True:\n    print('  Successfully connected to the primary node')\nelse:\n    abort_script('Could not connect to the primary node during API check')\n\nprint('Testing API connectivity to the secondary node')\nsecondary_test = icontrol_test_connection(standby['mgmt_ip'],standby['username'],standby['password'])\nif secondary_test == True:\n    print('  Successfully connected to the secondary node')\nelse:\n    abort_script('Could not connect to the secondary node during API check')\n\n#\n# Gather details about each node\n#\n\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/global-settings/')\nprimary['hostname'] = json.loads(apiResponse)['hostname']\n\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/global-settings/')\nstandby['hostname'] = json.loads(apiResponse)['hostname']\n\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/cm/device/')\nprimary['cm_devices'] = json.loads(apiResponse)['items']\nfor current_cm_device in primary['cm_devices']:\n    if current_cm_device['selfDevice'] == 'true':\n        primary['cm_properties'] = current_cm_device\n        primary['cm_name'] = current_cm_device['name']\n        primary['sw_version'] = current_cm_device['version']\n        primary['sw_build'] = current_cm_device['build']\n\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/cm/device/')\nstandby['cm_devices'] = json.loads(apiResponse)['items']\nfor current_cm_device in standby['cm_devices']:\n    if current_cm_device['selfDevice'] == 'true':\n        standby['cm_properties'] = current_cm_device\n        standby['cm_name'] = current_cm_device['name']\n        standby['sw_version'] = current_cm_device['version']\n        standby['sw_build'] = current_cm_device['build']\n\n#\n# Verify that the TMOS versions match between nodes\n#\n\nif not (primary['sw_version'] == standby['sw_version']) and (primary['sw_build'] == standby['sw_build']):\n    abort_script('Software mismatch on cluster members!')\n\n#\n# Verify that the CM device has been configured from default\n#\n\nif primary['cm_name'] == 'bigip1' or standby['cm_name'] == 'bigip1':\n    abort_script('A cluster member was found to have the default CM device name. Please run the configuration script.')\n\n#\n# Verify NTP is configured\n#\n\nprint('Checking for NTP server configuration on primary')\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/ntp')\nif 'servers' in apiResponse:\n    primary['ntp_servers'] = json.loads(apiResponse)['servers']\n    primary['timezone'] = json.loads(apiResponse)['timezone']\n    print('  Success!')\nelse:\n    abort_script('NTP not configured on cluster member!')\n\nprint('Checking for NTP server configuration on secondary')\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/ntp')\nif 'servers' in apiResponse:\n    standby['ntp_servers'] = json.loads(apiResponse)['servers']\n    standby['timezone'] = json.loads(apiResponse)['timezone']\n    print('  Success!')\nelse:\n    abort_script('NTP not configured on cluster member!')\n\n#\n# Verify host clocks are in sync\n#\nprint('Verifying device clock sync')\napiResponse = icontrol_get(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/clock')\nprimary['clock_timestamp']=json.loads(apiResponse)['entries']['https://localhost/mgmt/tm/sys/clock/0']['nestedStats']['entries']['fullDate']['description'][:16]\n\napiResponse = icontrol_get(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/clock')\nstandby['clock_timestamp'] = json.loads(apiResponse)['entries']['https://localhost/mgmt/tm/sys/clock/0']['nestedStats']['entries']['fullDate']['description'][:16]\n\nif primary['clock_timestamp'] != standby['clock_timestamp']:\n    abort_script('Device clocks are out of sync!')\nelse:\n    print('  Success!')\n\n#\n# Show details about each node and ask user for final verification to continue\n#\nprint('\\nPrimary details')\nprint(' - Mgmt IP: ' + primary['mgmt_ip'])\nprint(' - Hostname: ' + primary['hostname'])\nprint(' - Cluster Device Name: ' + primary['cm_name'])\nprint(' - Version ' + primary['sw_version'] + ', build ' + primary['sw_build'])\nprint(' - Time zone: ' + primary['timezone'])\nprint(' - NTP servers: ' + str(primary['ntp_servers']))\nprint('\\nSecondary details')\nprint(' - Mgmt IP: ' + standby['mgmt_ip'])\nprint(' - Hostname: ' + standby['hostname'])\nprint(' - Cluster Device Name: ' + standby['cm_name'])\nprint(' - Version ' + standby['sw_version'] + ', build ' + standby['sw_build'])\nprint(' - Time zone: ' + standby['timezone'])\nprint(' - NTP servers: ' + str(standby['ntp_servers']))\nprint('\\nThis is the last chance to abort before issuing the clustering commands!\\n')\nconfirmation = input('Enter YES to continue ')\nif not confirmation == 'YES':\n    abort_script('User cancelled at final confirmation!')\n\n#######################\n# Clustering Commands\n#######################\n\n#\n# Save the config on each device\n#\n\nprint('Saving the device configuration on the primary')\nsave_result = icontrol_save_config(primary['mgmt_ip'],primary['username'],primary['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\nprint('Saving the device configuration on the secondary')\nsave_result = icontrol_save_config(standby['mgmt_ip'],standby['username'],standby['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\n\n#\n# Save a pre-clustering UCS on each box for rollback\n#\n\nucs_filename = 'pre-cluster-script-{:%Y-%m-%d-%H%M%S}.ucs'.format(datetime.datetime.utcnow())\nprint('Saving UCS to /var/local/ucs/' + ucs_filename + ' on primary device')\nucs_create_result = icontrol_post(primary['mgmt_ip'],primary['username'],primary['password'],'/sys/ucs',{'command':'save','name':ucs_filename})\n\nprint('Saving UCS to /var/local/ucs/' + ucs_filename + ' on secondary device')\nucs_create_result = icontrol_post(standby['mgmt_ip'],standby['username'],standby['password'],'/sys/ucs',{'command':'save','name':ucs_filename})\n\n#\n# Add the secondary to the primary as a peer\n#\n\nprint('Adding the nodes to the trust domain')\napiResponse = icontrol_post(primary['mgmt_ip'],primary['username'],primary['password'],'/cm/add-to-trust',{\n    'command':'run',\n    'name':'Root',\n    'caDevice':True,\n    'device':standby['mgmt_ip'],\n    'deviceName':standby['cm_name'],\n    'username':standby['username'],\n    'password':standby['password']\n})\nif '\"kind\":\"tm:cm:add-to-trust:runstate\"' in apiResponse:\n    print('  Command issued successfully but clustering must be verified!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Verify status of members\n#\n\nprint('Verifying trust sync status on the primary')\napiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\nif '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n    print('  Devices are in sync!')\nelse:\n    print('Sleeping 60 seconds to allow devices to discover and sync')\n    time.sleep(60)\n    apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\n    if '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing! ' + apiResponse)\n\nprint('Verifying trust sync status on the secondary')\napiResponse = icontrol_get(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/sync-status')\nif '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n    print('  Devices are in sync!')\nelse:\n    print('Sleeping 60 seconds to allow devices to discover and sync')\n    time.sleep(60)\n    apiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\n    if '\"mode\":{\"description\":\"trust-only\"}' in apiResponse:\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing!' + apiResponse)\n\n#\n# Create the device group\n#\n\nprint('Creating the ' + cluster_group_name + ' device group')\napiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group',{\n    'name':cluster_group_name,\n    'type':'sync-failover'\n})\nif '\"kind\":\"tm:cm:device-group:device-groupstate\"' in apiResponse:\n    print('  Success!')\nelif '\"01020066:3:' in apiResponse:\n    print('  WARNING! Device group already created! Ignoring and continuing script execution!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Add both devices to the device group\n#\n\nprint('Adding the primary node to the device group')\napiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group/' + cluster_group_name + '/devices',{\n    'name':primary['cm_name']\n})\nif '\"kind\":\"tm:cm:device-group:devices:devicesstate\"' in apiResponse:\n    print('  Success!')\nelif '\"code\":409,\"message\":\"01020037:3:' in apiResponse:\n    print('  WARNING! Device is already a member of the device group! Ignoring and continuing script execution!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\nprint('Adding the secondary node to the device group')\napiResponse = icontrol_post(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/device-group/' + cluster_group_name + '/devices',{\n    'name':standby['cm_name']\n})\nif '\"kind\":\"tm:cm:device-group:devices:devicesstate\"' in apiResponse:\n    print('  Success!')\nelif '\"code\":409,\"message\":\"01020037:3:' in apiResponse:\n    print('  WARNING! Device is already a member of the device group! Ignoring and continuing script execution!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Enable auto-sync on both members\n#\n\nprint('Enabling auto-sync on the primary member')\napiResponse = icontrol_patch(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/device-group/' + cluster_group_name,{\n    'autoSync':'enabled'\n})\nif '\"kind\":\"tm:cm:device-group:device-groupstate\"' and '\"autoSync\":\"enabled\"' in apiResponse:\n    print('  Success!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\nprint('Enabling auto-sync on the secondary member')\napiResponse = icontrol_patch(standby['mgmt_ip'], standby['username'], standby['password'], '/cm/device-group/' + cluster_group_name,{\n    'autoSync':'enabled'\n})\nif '\"kind\":\"tm:cm:device-group:device-groupstate\"' and '\"autoSync\":\"enabled\"' in apiResponse:\n    print('  Success!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Save the config on each device\n#\n\nprint('Saving the device configuration on the primary')\nsave_result = icontrol_save_config(primary['mgmt_ip'],primary['username'],primary['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\nprint('Saving the device configuration on the secondary')\nsave_result = icontrol_save_config(standby['mgmt_ip'],standby['username'],standby['password'])\nif '\"kind\"' in save_result:\n    print(\"  Configuration saved successfully.\")\nelse:\n    abort_script(\"Configuration could not be successfully saved! \" + save_result)\n\n\n###############################\n# Post-clustering steps\n###############################\n\n#\n# Force the initial sync\n#\n\nprint('Forcing configuration sync between peers')\napiResponse = icontrol_post(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/config-sync',{\n    'command':'run',\n    'utilCmdArgs':'to-group ' + cluster_group_name\n})\nif '\"kind\":\"tm:cm:config-sync:runstate\"' in apiResponse:\n    print('  Command issued successfully but sync status must be verified!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n#\n# Verify sync status of members\n#\n\nprint('Verifying trust sync status on the primary')\napiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\nif '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n    print('  Success!')\nelse:\n    print('Sleeping 30 seconds to allow devices to fully sync')\n    time.sleep(30)\n    if '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing!')\n\nprint('Verifying trust sync status on the primary')\napiResponse = icontrol_get(primary['mgmt_ip'], primary['username'], primary['password'], '/cm/sync-status')\nif '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n    print('  Success!')\nelse:\n    print('Sleeping 30 seconds to allow devices to fully sync')\n    time.sleep(30)\n    if '\"description\":\"failover-bigip (In Sync): All devices in the device group are in sync\"':\n        print('  Devices are in sync!')\n    else:\n        abort_script('Error! Devices not syncing!')\n\n#\n# Force the primary to active state, if necessary\n#\n\nprint('Foricng the primary node to active status')\napiResponse = icontrol_post(standby['mgmt_ip'], standby['username'], standby['password'], '/sys/failover',{\n    'command':'run',\n    'standby':True,\n    'traffic-group':'traffic-group-1'\n})\nif '\"kind\":\"tm:sys:failover:runstate\"' in apiResponse:\n    print('  Success!')\nelse:\n    abort_script('Error! ' + apiResponse)\n\n################\n# End of Script\n################\n\nprint('\\nEnd of execution. Script has completed.')\nSystemExit()

Tested this on version:

12.1","kudosSumWeight":0,"postTime":"2019-08-13T05:42:08.000-07:00","images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"attachments":{"__typename":"AttachmentConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[]},"tags":{"__typename":"TagConnection","pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null},"edges":[{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDE","node":{"__typename":"Tag","id":"tag:BIG-IP","text":"BIG-IP","time":"2022-01-24T02:29:45.031-08:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDI","node":{"__typename":"Tag","id":"tag:devops","text":"devops","time":"2011-10-19T17:50:55.000-07:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDM","node":{"__typename":"Tag","id":"tag:iControlREST","text":"iControlREST","time":"2022-01-24T02:29:46.488-08:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}},{"__typename":"TagEdge","cursor":"MjUuM3wyLjF8b3wxMHxfTlZffDQ","node":{"__typename":"Tag","id":"tag:Super-NetOps","text":"Super-NetOps","time":"2022-01-24T02:30:05.430-08:00","lastActivityTime":null,"messagesCount":null,"followersCount":null}}]},"timeToRead":9,"rawTeaser":"","introduction":"","currentRevision":{"__ref":"Revision:revision:283549_1"},"latestVersion":{"__typename":"FriendlyVersion","major":"1","minor":"0"},"metrics":{"__typename":"MessageMetrics","views":357},"visibilityScope":"PUBLIC","canonicalUrl":null,"seoTitle":null,"seoDescription":null,"placeholder":false,"originalMessageForPlaceholder":null,"contributors":{"__typename":"UserConnection","edges":[]},"nonCoAuthorContributors":{"__typename":"UserConnection","edges":[]},"coAuthors":{"__typename":"UserConnection","edges":[{"__typename":"UserEdge","node":{"__ref":"User:user:190002"}}]},"tkbMessagePolicies":{"__typename":"TkbMessagePolicies","canDoAuthoringActionsOnTkb":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.tkb.policy_can_do_authoring_action.accessDenied","key":"error.lithium.policies.tkb.policy_can_do_authoring_action.accessDenied","args":[]}}},"archivalData":null,"replies":{"__typename":"MessageConnection","edges":[],"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"customFields":[],"revisions({\"constraints\":{\"isPublished\":{\"eq\":true}},\"first\":1})":{"__typename":"RevisionConnection","totalCount":1}},"Conversation:conversation:283549":{"__typename":"Conversation","id":"conversation:283549","solved":false,"topic":{"__ref":"TkbTopicMessage:message:283549"},"lastPostingActivityTime":"2019-08-13T05:42:08.000-07:00","lastPostTime":"2019-08-13T05:42:08.000-07:00","unreadReplyCount":0,"isSubscribed":false},"ModerationData:moderation_data:283549":{"__typename":"ModerationData","id":"moderation_data:283549","status":"APPROVED","rejectReason":null,"isReportedAbuse":false,"rejectUser":null,"rejectTime":null,"rejectActorType":null},"Revision:revision:283549_1":{"__typename":"Revision","id":"revision:283549_1","lastEditTime":"2019-08-13T05:42:08.000-07:00"},"CachedAsset:theme:customTheme1-1746691843538":{"__typename":"CachedAsset","id":"theme:customTheme1-1746691843538","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["custom"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"JimmyPackets-512-1702592938213.png","imageLastModified":"1702592945815","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"f5_logo_fix-1704824537976.svg","imageLastModified":"1704824540697","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1600px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_PAGE_CONTENT","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"5px","borderRadius":"5px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"14px","paddingXHero":"42px","fontStyle":"NORMAL","fontWeight":"400","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-400)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-300)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"NONE","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.06)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-primary)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","defaultMessageFontFamily":"var(--lia-bs-font-family-base)","forumColor":"#0C5C8D","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#62C026","blogColor":"#730015","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#C20025","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#F3704B","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#EE4B5B","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#491B62","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#949494","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0C5C8D","secondary":"#333333","bodyText":"#222222","bodyBg":"#F5F5F5","info":"#1D9CD3","success":"#62C026","warning":"#FFD651","danger":"#C20025","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#C20025","#081B85","#009639","#B3C6D7","#7CC0EB","#F29A36"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Inter","fontStyle":"NORMAL","fontWeight":"600","h1FontSize":"30px","h2FontSize":"25px","h3FontSize":"20px","h4FontSize":"18px","h5FontSize":"16px","h6FontSize":"16px","lineHeight":"1.2","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":null,"imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"14px","defaultMessageHeaderMarginBottom":"10px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"14px","specialMessageHeaderMarginBottom":"10px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Atkinson Hyperlegible","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.3","fontSizeBase":"15px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"13px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1744046271000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:quilt:f5.prod:pages/kbs/TkbMessagePage:board:codeshare-1746691841779":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/kbs/TkbMessagePage:board:codeshare-1746691841779","value":{"id":"TkbMessagePage","container":{"id":"Common","headerProps":{"backgroundImageProps":null,"backgroundColor":null,"addComponents":null,"removeComponents":["community.widget.bannerWidget"],"componentOrder":null,"__typename":"QuiltContainerSectionProps"},"headerComponentProps":{"community.widget.breadcrumbWidget":{"disableLastCrumbForDesktop":false}},"footerProps":null,"footerComponentProps":null,"items":[{"id":"message-list","layout":"MAIN_SIDE","bgColor":"transparent","showTitle":true,"showDescription":true,"textPosition":"CENTER","textColor":"var(--lia-bs-body-color)","sectionEditLevel":null,"bgImage":null,"disableSpacing":null,"edgeToEdgeDisplay":null,"fullHeight":null,"showBorder":null,"__typename":"MainSideQuiltSection","columnMap":{"main":[{"id":"tkbs.widget.tkbArticleWidget","className":"lia-tkb-container","props":{"contributorListType":"panel","showHelpfulness":false,"showTimestamp":true,"showGuideNavigationSection":true,"showVersion":true,"lazyLoad":false,"editLevel":"CONFIGURE"},"__typename":"QuiltComponent"}],"side":[{"id":"featuredWidgets.widget.featuredContentWidget","className":null,"props":{"instanceId":"featuredWidgets.widget.featuredContentWidget-1702666556326","layoutProps":{"layout":"card","layoutOptions":{"useRepliesCount":false,"useAuthorRank":false,"useTimeToRead":true,"useKudosCount":false,"useViewCount":true,"usePreviewMedia":true,"useBody":false,"useCenteredCardContent":false,"useTags":true,"useTimestamp":false,"useBoardLink":true,"useAuthorLink":false,"useSolvedBadge":true}},"titleSrOnly":false,"showPager":true,"pageSize":3,"lazyLoad":true},"__typename":"QuiltComponent"},{"id":"messages.widget.relatedContentWidget","className":null,"props":{"hideIfEmpty":true,"enablePagination":true,"useTitle":true,"listVariant":{"type":"listGroup"},"pageSize":3,"style":"list","pagerVariant":{"type":"loadMore"},"viewVariant":{"type":"inline","props":{"useRepliesCount":true,"useMedia":true,"useAuthorRank":false,"useNode":true,"useTimeToRead":true,"useSpoilerFreeBody":true,"useKudosCount":true,"useNodeLink":true,"useViewCount":true,"usePreviewMedia":false,"useBody":false,"timeStampType":"postTime","useTags":true,"clampSubjectLines":2,"useBoardIcon":false,"useMessageTimeLink":true,"clampBodyLines":3,"useTextBody":true,"useSolvedBadge":true,"useAvatar":true,"useAuthorLogin":true,"useUnreadCount":true}},"lazyLoad":true,"panelType":"divider"},"__typename":"QuiltComponent"}],"__typename":"MainSideSectionColumns"}}],"__typename":"QuiltContainer"},"__typename":"Quilt","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1744046271000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-pages/kbs/TkbMessagePage-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-pages/kbs/TkbMessagePage-1744046271000","value":{"title":"{contextMessageSubject} | {communityTitle}","errorMissing":"This article cannot be found","name":"TKB Message Page","section.message-list.title":"","archivedMessageTitle":"This Content Has Been Archived","section.erPqcf.title":"","section.erPqcf.description":"","section.message-list.description":""},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1744046271000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"CachedAsset:quiltWrapper:f5.prod:Common:1746691797456":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1746691797456","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":"header.jpg","backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"LEFT_CENTER","lastModified":"1702932449000","__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.GainsightShared","props":{"widgetVisibility":"signedInOnly","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Beta_MetaNav","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"community.widget.navbarWidget","props":{"showUserName":false,"showRegisterLink":true,"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","linkFontWeight":"700","controllerHighlightColor":"hsla(30, 100%, 50%)","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkFontSize":"15px","linkBoxShadowHover":"none","backgroundOpacity":0.4,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","linkTextBorderBottom":"none","hamburgerColor":"var(--lia-nav-controller-icon-color)","brandLogoHeight":"48px","linkLetterSpacing":"normal","linkBgHoverColor":"transparent","collapseMenuDividerOpacity":0.16,"paddingBottom":"10px","dropdownPaddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"0","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","linkJustifyContent":"center","linkColor":"var(--lia-bs-primary)","collapseMenuDividerBg":"var(--lia-nav-link-color)","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-primary)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid #0C5C8D","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","linkPaddingX":"10px","paddingTop":"10px","linkPaddingY":"5px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkBgColor":"transparent","linkDropdownPaddingY":"9px","controllerIconColor":"#0C5C8D","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"#0C5C8D"},"links":{"sideLinks":[],"mainLinks":[{"children":[{"linkType":"INTERNAL","id":"migrated-link-1","params":{"boardId":"TechnicalForum","categoryId":"Forums"},"routeName":"ForumBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-2","params":{"boardId":"WaterCooler","categoryId":"Forums"},"routeName":"ForumBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-0","params":{"categoryId":"Forums"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-4","params":{"boardId":"codeshare","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-5","params":{"boardId":"communityarticles","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-3","params":{"categoryId":"CrowdSRC"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-7","params":{"boardId":"TechnicalArticles","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"article-series","params":{"boardId":"article-series","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"security-insights","params":{"boardId":"security-insights","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-8","params":{"boardId":"DevCentralNews","categoryId":"Articles"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-6","params":{"categoryId":"Articles"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-10","params":{"categoryId":"CommunityGroups"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"migrated-link-11","params":{"categoryId":"F5-Groups"},"routeName":"CategoryPage"}],"linkType":"INTERNAL","id":"migrated-link-9","params":{"categoryId":"GroupsCategory"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-12","params":{"boardId":"Events","categoryId":"top"},"routeName":"EventBoardPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-13","params":{"boardId":"Suggestions","categoryId":"top"},"routeName":"IdeaBoardPage"},{"children":[],"linkType":"EXTERNAL","id":"Common-external-link","url":"https://community.f5.com/c/how-do-i","target":"SELF"}]},"className":"QuiltComponent_lia-component-edit-mode__lQ9Z6","showSearchIcon":false},"__typename":"QuiltComponent"},{"id":"community.widget.bannerWidget","props":{"backgroundColor":"transparent","visualEffects":{"showBottomBorder":false},"backgroundImageProps":{"backgroundSize":"COVER","backgroundPosition":"CENTER_CENTER","backgroundRepeat":"NO_REPEAT"},"fontColor":"#222222"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"var(--lia-bs-primary)","linkHighlightColor":"#FFFFFF","visualEffects":{"showBottomBorder":false},"backgroundOpacity":60,"linkTextColor":"#FFFFFF"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"var(--lia-bs-body-color)","items":[{"id":"custom.widget.Beta_Footer","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Tag_Manager_Helper","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Consent_Blackbar","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:component:custom.widget.GainsightShared-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.GainsightShared-en-us-1746691863249","value":{"component":{"id":"custom.widget.GainsightShared","template":{"id":"GainsightShared","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.GainsightShared","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_MetaNav-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-us-1746691863249","value":{"component":{"id":"custom.widget.Beta_MetaNav","template":{"id":"Beta_MetaNav","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_MetaNav","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_Footer-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-us-1746691863249","value":{"component":{"id":"custom.widget.Beta_Footer","template":{"id":"Beta_Footer","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_Footer","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Tag_Manager_Helper-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-us-1746691863249","value":{"component":{"id":"custom.widget.Tag_Manager_Helper","template":{"id":"Tag_Manager_Helper","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Tag_Manager_Helper","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Consent_Blackbar-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-us-1746691863249","value":{"component":{"id":"custom.widget.Consent_Blackbar","template":{"id":"Consent_Blackbar","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Consent_Blackbar","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1744046271000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBanner-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBanner-1744046271000","value":{"messageMarkedAsSpam":"This post has been marked as spam","messageMarkedAsSpam@board:TKB":"This article has been marked as spam","messageMarkedAsSpam@board:BLOG":"This post has been marked as spam","messageMarkedAsSpam@board:FORUM":"This discussion has been marked as spam","messageMarkedAsSpam@board:OCCASION":"This event has been marked as spam","messageMarkedAsSpam@board:IDEA":"This idea has been marked as spam","manageSpam":"Manage Spam","messageMarkedAsAbuse":"This post has been marked as abuse","messageMarkedAsAbuse@board:TKB":"This article has been marked as abuse","messageMarkedAsAbuse@board:BLOG":"This post has been marked as abuse","messageMarkedAsAbuse@board:FORUM":"This discussion has been marked as abuse","messageMarkedAsAbuse@board:OCCASION":"This event has been marked as abuse","messageMarkedAsAbuse@board:IDEA":"This idea has been marked as abuse","preModCommentAuthorText":"This comment will be published as soon as it is approved","preModCommentModeratorText":"This comment is awaiting moderation","messageMarkedAsOther":"This post has been rejected due to other reasons","messageMarkedAsOther@board:TKB":"This article has been rejected due to other reasons","messageMarkedAsOther@board:BLOG":"This post has been rejected due to other reasons","messageMarkedAsOther@board:FORUM":"This discussion has been rejected due to other reasons","messageMarkedAsOther@board:OCCASION":"This event has been rejected due to other reasons","messageMarkedAsOther@board:IDEA":"This idea has been rejected due to other reasons","messageArchived":"This post was archived on {date}","relatedUrl":"View Related Content","relatedContentText":"Showing related content","archivedContentLink":"View Archived Content"},"localOverride":false},"CachedAsset:text:en_US-components/tkbs/TkbArticleWidget-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/tkbs/TkbArticleWidget-1744046271000","value":{},"localOverride":false},"Category:category:Forums":{"__typename":"Category","id":"category:Forums","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Forum:board:TechnicalForum":{"__typename":"Forum","id":"board:TechnicalForum","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Forum:board:WaterCooler":{"__typename":"Forum","id":"board:WaterCooler","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Articles":{"__typename":"Category","id":"category:Articles","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:TechnicalArticles":{"__typename":"Tkb","id":"board:TechnicalArticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:DevCentralNews":{"__typename":"Tkb","id":"board:DevCentralNews","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:GroupsCategory":{"__typename":"Category","id":"category:GroupsCategory","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:F5-Groups":{"__typename":"Category","id":"category:F5-Groups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:CommunityGroups":{"__typename":"Category","id":"category:CommunityGroups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Occasion:board:Events":{"__typename":"Occasion","id":"board:Events","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"occasionPolicies":{"__typename":"OccasionPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Idea:board:Suggestions":{"__typename":"Idea","id":"board:Suggestions","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"ideaPolicies":{"__typename":"IdeaPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:communityarticles":{"__typename":"Tkb","id":"board:communityarticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:security-insights":{"__typename":"Tkb","id":"board:security-insights","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:article-series":{"__typename":"Tkb","id":"board:article-series","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"QueryVariables:TopicReplyList:message:283549:1":{"__typename":"QueryVariables","id":"TopicReplyList:message:283549:1","value":{"id":"message:283549","first":10,"sorts":{"postTime":{"direction":"ASC"}},"repliesFirst":3,"repliesFirstDepthThree":1,"repliesSorts":{"postTime":{"direction":"ASC"}},"useAvatar":true,"useAuthorLogin":true,"useAuthorRank":true,"useBody":true,"useKudosCount":true,"useTimeToRead":false,"useMedia":false,"useReadOnlyIcon":false,"useRepliesCount":true,"useSearchSnippet":false,"useAcceptedSolutionButton":false,"useSolvedBadge":false,"useAttachments":false,"attachmentsFirst":5,"useTags":true,"useNodeAncestors":false,"useUserHoverCard":false,"useNodeHoverCard":false,"useModerationStatus":true,"usePreviewSubjectModal":false,"useMessageStatus":true}},"ROOT_MUTATION":{"__typename":"Mutation"},"CachedAsset:text:en_US-components/community/Navbar-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1744046271000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","migrated-link-9":"Groups","migrated-link-7":"Technical Articles","migrated-link-8":"DevCentral News","migrated-link-1":"Technical Forum","migrated-link-10":"Community Groups","migrated-link-2":"Water Cooler","migrated-link-11":"F5 Groups","Common-external-link":"How Do I...?","migrated-link-0":"Forums","article-series":"Article Series","migrated-link-5":"Community Articles","migrated-link-6":"Articles","security-insights":"Security Insights","migrated-link-3":"CrowdSRC","migrated-link-4":"CodeShare","migrated-link-12":"Events","migrated-link-13":"Suggestions"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1744046271000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1744046271000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1744046271000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1744046271000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1744046271000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewStandard-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewStandard-1744046271000","value":{"anonymous":"Anonymous","author":"{messageAuthorLogin}","authorBy":"{messageAuthorLogin}","board":"{messageBoardTitle}","replyToUser":" to {parentAuthor}","showMoreReplies":"Show More","replyText":"Reply","repliesText":"Replies","markedAsSolved":"Marked as Solution","movedMessagePlaceholder.BLOG":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.TKB":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.FORUM":"{count, plural, =0 {This reply has been} other {These replies have been} }","movedMessagePlaceholder.IDEA":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholder.OCCASION":"{count, plural, =0 {This comment has been} other {These comments have been} }","movedMessagePlaceholderUrlText":"moved.","messageStatus":"Status: ","statusChanged":"Status changed: {previousStatus} to {currentStatus}","statusAdded":"Status added: {status}","statusRemoved":"Status removed: {status}","labelExpand":"expand replies","labelCollapse":"collapse replies","unhelpfulReason.reason1":"Content is outdated","unhelpfulReason.reason2":"Article is missing information","unhelpfulReason.reason3":"Content is for a different Product","unhelpfulReason.reason4":"Doesn't match what I was searching for"},"localOverride":false},"CachedAsset:text:en_US-components/messages/ThreadedReplyList-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/ThreadedReplyList-1744046271000","value":{"title":"{count, plural, one{# Reply} other{# Replies}}","title@board:BLOG":"{count, plural, one{# Comment} other{# Comments}}","title@board:TKB":"{count, plural, one{# Comment} other{# Comments}}","title@board:IDEA":"{count, plural, one{# Comment} other{# Comments}}","title@board:OCCASION":"{count, plural, one{# Comment} other{# Comments}}","noRepliesTitle":"No Replies","noRepliesTitle@board:BLOG":"No Comments","noRepliesTitle@board:TKB":"No Comments","noRepliesTitle@board:IDEA":"No Comments","noRepliesTitle@board:OCCASION":"No Comments","noRepliesDescription":"Be the first to reply","noRepliesDescription@board:BLOG":"Be the first to comment","noRepliesDescription@board:TKB":"Be the first to comment","noRepliesDescription@board:IDEA":"Be the first to comment","noRepliesDescription@board:OCCASION":"Be the first to comment","messageReadOnlyAlert:BLOG":"Comments have been turned off for this post","messageReadOnlyAlert:TKB":"Comments have been turned off for this article","messageReadOnlyAlert:IDEA":"Comments have been turned off for this idea","messageReadOnlyAlert:FORUM":"Replies have been turned off for this discussion","messageReadOnlyAlert:OCCASION":"Comments have been turned off for this event"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyCallToAction-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyCallToAction-1744046271000","value":{"leaveReply":"Leave a reply...","leaveReply@board:BLOG@message:root":"Leave a comment...","leaveReply@board:TKB@message:root":"Leave a comment...","leaveReply@board:IDEA@message:root":"Leave a comment...","leaveReply@board:OCCASION@message:root":"Leave a comment...","repliesTurnedOff.FORUM":"Replies are turned off for this topic","repliesTurnedOff.BLOG":"Comments are turned off for this topic","repliesTurnedOff.TKB":"Comments are turned off for this topic","repliesTurnedOff.IDEA":"Comments are turned off for this topic","repliesTurnedOff.OCCASION":"Comments are turned off for this topic","infoText":"Stop poking me!"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1744046271000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1744046271000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1744046271000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1744046271000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageCustomFields-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageCustomFields-1744046271000","value":{"CustomField.default.label":"Value of {name}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRevision-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRevision-1744046271000","value":{"lastUpdatedDatePublished":"{publishCount, plural, one{Published} other{Updated}} {date}","lastUpdatedDateDraft":"Created {date}","version":"Version {major}.{minor}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageReplyButton-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageReplyButton-1744046271000","value":{"repliesCount":"{count}","title":"Reply","title@board:BLOG@message:root":"Comment","title@board:TKB@message:root":"Comment","title@board:IDEA@message:root":"Comment","title@board:OCCASION@message:root":"Comment"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageAuthorBio-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageAuthorBio-1744046271000","value":{"sendMessage":"Send Message","actionMessage":"Follow this blog board to get notified when there's new activity","coAuthor":"CO-PUBLISHER","contributor":"CONTRIBUTOR","userProfile":"View Profile","iconlink":"Go to {name} {type}"},"localOverride":false},"CachedAsset:text:en_US-components/guides/GuideBottomNavigation-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/guides/GuideBottomNavigation-1744046271000","value":{"nav.label":"Previous/Next Page","nav.previous":"Previous","nav.next":"Next"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagView/TagViewChip-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagView/TagViewChip-1744046271000","value":{"tagLabelName":"Tag name {tagName}"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1744046271000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserRank-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserRank-1744046271000","value":{"rankName":"{rankName}","userRank":"Author rank {rankName}"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserRegistrationDate-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserRegistrationDate-1744046271000","value":{"noPrefix":"{date}","withPrefix":"Joined {date}"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1744046271000","value":{"errorMessage":"Error rendering component id: {customComponentId}","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1744046271000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/ranks/UserRankLabel-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/ranks/UserRankLabel-1744046271000","value":{"altTitle":"Icon for {rankName} rank"},"localOverride":false}}}},"page":"/kbs/TkbMessagePage/TkbMessagePage","query":{"boardId":"codeshare","messageSubject":"python-script-that-clusters-two-big-ips","messageId":"283549"},"buildId":"-gVUpXaWnPcjlrLJZ92B7","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"f5","openTelemetryServiceVersion":"25.3.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false,"inboxMuteWipFeatureEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/customComponent/CustomComponent/CustomComponent.tsx","./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/tkbs/TkbArticleWidget/TkbArticleWidget.tsx","./components/messages/MessageView/MessageViewStandard/MessageViewStandard.tsx","./components/messages/ThreadedReplyList/ThreadedReplyList.tsx","./components/customComponent/CustomComponentContent/TemplateContent.tsx","../shared/client/components/common/List/UnwrappedList/UnwrappedList.tsx","./components/tags/TagView/TagView.tsx","./components/tags/TagView/TagViewChip/TagViewChip.tsx","./components/customComponent/CustomComponentContent/HtmlContent.tsx","./components/customComponent/CustomComponentContent/CustomComponentScripts.tsx"],"appGip":true,"scriptLoader":[]}