Hi there
I am trying to patch some settings programmatically, for example the virtual IP of the cluster, but i encounter an interesting issue with the E-Tag mismatch although i am sure it’s right.
Here is my function:
def update_vip(cluster_name, cluster_uuid, old_vip, new_vip, api_credentials, pc_endpoint) -> None:
"""
This function is updating the VIP of the cluster
@param cluster_name[str] -> this parameter is the name of the cluster
@param cluster_uuid[str] -> this parameter is the UUID of the cluster
@param old_vip[str] -> this parameter is the current VIP of the cluster
@param new_vip[str] -> this parameter is the new VIP of the cluster
@param api_credentials[dict] -> this parameter is the API credentials used to connect to the cluster
@param pc_endpoint[str] -> this parameter is the endpoint of the cluster
Returns nothing
"""
viplog.info(f'Updating VIP on cluster {cluster_name}. Old VIP: {old_vip} New VIP: {new_vip}')
# make the API call to get all clusters from PC
config = ntnx_clustermgmt_py_client.Configuration()
# IPv4/IPv6 address or FQDN of the cluster
config.host = pc_endpoint
# Port to which to connect to
config.port = 9440
# Max retry attempts while reconnecting on a loss of connection
config.max_retry_attempts = 3
# Backoff factor to use during retry attempts
config.backoff_factor = 3
# UserName to connect to the cluster
config.username = api_credentials['username']
# Password to connect to the cluster
config.password = api_credentials['password']
# Please add authorization information here if needed.
client = ntnx_clustermgmt_py_client.ApiClient(configuration=config)
clusters_api = ntnx_clustermgmt_py_client.ClustersApi(api_client=client)
# get the cluster object so that we can extract the E-Tag header
max_retries = 3
for attempt in range(max_retries):
try:
api_response = clusters_api.get_cluster_by_id(extId=cluster_uuid)
break
except ntnx_clustermgmt_py_client.rest.ApiException as e:
if attempt < max_retries - 1:
continue
else:
raise ValueError(f'ERROR getting the cluster {cluster_name} from PC {pc_endpoint} during E-Tag extraction: {e}')
# Extract E-Tag Header
etag_value = ntnx_clustermgmt_py_client.ApiClient.get_etag(api_response)
cluster = api_response.data
# assign the new VIP to the cluster object
cluster.network.external_address.ipv4.value = new_vip
# update the cluster
max_retries = 3
for attempt in range(max_retries):
try:
api_response = clusters_api.update_cluster_by_id(extId=cluster_uuid, body=cluster, if_match=etag_value)
break
except ntnx_clustermgmt_py_client.rest.ApiException as e:
if attempt < max_retries - 1:
continue
else:
raise ValueError(f'ERROR updating cluster {cluster_name} configuration: {e}')
# Extract E-Tag Header
etag_value = ntnx_clustermgmt_py_client.ApiClient.get_etag(api_response)
In the API reference, they suggest the following piece of code for packing the cluster configuration:
cluster = ntnx_clustermgmt_py_client.Cluster()
# Cluster object initializations here...
However, since I already have my cluster and i only want to change a little piece of configuration, i prefer to pack my cluster config using the existing config, with
cluster = api_response.data
and then patch the parameter i want to patch with the new value
# assign the new VIP to the cluster object
cluster.network.external_address.ipv4.value = new_vip
then of course, submit the modified configuration
api_response = clusters_api.update_cluster_by_id(extId=cluster_uuid, body=cluster, if_match=etag_value)
However, since this is not the recommended approach, i am wondering if the Etag error i get is actually just a bad error handling by NTX APIs but it might be that i do not submit the cluster configuration correctly.
Here is the error:
Error Status: 412
'{"data":{"error":[{"$reserved":{"$fv":"v4.r0"},"$objectType":"clustermgmt.v4.error.AppMessage","message":"Failed to perform the operation because Etag provided doesn\'t match.","severity":"ERROR","code":"CLU-10004","locale":"en_US","errorGroup":"CLUSTERMGMT_INVALID_INPUT"}],"$reserved":{"$fv":"v4.r0"},"$objectType":"clustermgmt.v4.error.ErrorResponse"},"$reserved":{"$fv":"v4.r0"},"$objectType":"clustermgmt.v4.config.UpdateClusterApiResponse"}'
What am i missing here? Do i really have to create the cluster config with cluster = ntnx_clustermgmt_py_client.Cluster() then pack all the config inside?… that would be pitty.
Also, before i was doing this with PATCH on APIv2, but there is no PATCH in APIv4 yet.