linode.errors.ApiError: 400: Linode busy
1) create linode
2) add private
3) add root disk (with stackscript)
4) add swap disk
My issue comes sometimes on steeps 2 or 3, very often I get the following error: "linode.errors.ApiError: 400: Linode busy.", If I add few seconds of delay between every steep usually it works, but I would like to know the following:
How can I determine if the linode is busy or not? (linode.status seams to be something apart from this "state")
Why it is a 400 status code? As far I concern, 400 code is from something error generated on client side.
Thank you so much.
2 Replies
The "Linode Busy" message occurs when a Linode is in the middle of a process that is preventing you from completing your request. The 400 status code reflects a "Bad Request" since your request is not able to be completed when sent. You'd see this when you try to add a disk while your Linode is deleting another disk, for example, which lines up with what you've described. Adding a delay to each step will be your best option for preventing these types of conflicts, since - as you've noted - the Linode can be busy for several seconds after its status changes. One option to add a delay is by creating a loop that obtains the current date/time and breaks when it reaches the date/time of its initial round plus the desired number of seconds.
I'm not sure if the original poster is satisfied with the answer. Many things are missing from the explanation.
So, he asked how can we determine if a linode is busy (he is asking about the generic way of using API). I also understand that adding some delays in the script will definitely work as the busy status is only temporary but that is not efficient (if linode is not busy, then you are adding unnecessary wait in the script that will make it slow).
The big question is if the linode itself is able to tell when it is busy and blocking some actions then why don't we have that API for us? I believe he is looking for the generic API to determine if a linode is busy performing some actions that do not exist in the API documentation.
Again, after a few years, this question came up. I'm asking again:
How can you determine if the current linode is busy or not based on the error message that the linode itself able to tell neatly in a json format like below:
{
"errors": [
{
"reason": "Linode busy."
}
]
}
The error above can be obtained when performing specific actions only but is there a generic way to determine this like how we determine the current linode status using the below API:
linode_id=123
linode_status=$(linode-cli--json --pretty --suppress-warnings linodes view "${linode_id}" | jq -r ".[] | .status")
echo "${linode_status}"
You can see the above code it will return one of the following linode statuses below:
running offline booting rebooting shutting_down provisioning deleting migrating rebuilding cloning restoring stopped
that status however does not include the secret busy status that he and I are looking for.
o̶r̶ m̶a̶y̶b̶e̶ s̶o̶m̶e̶ o̶f̶ t̶h̶e̶ s̶t̶a̶t̶u̶s̶e̶s̶ i̶n̶ l̶i̶n̶o̶d̶e̶ a̶b̶o̶v̶e̶ l̶i̶k̶e̶ r̶e̶b̶o̶o̶t̶i̶n̶g̶, s̶h̶u̶t̶t̶i̶n̶g̶_̶d̶o̶w̶n̶ w̶i̶l̶l̶ r̶e̶t̶u̶r̶n̶ t̶h̶e̶ l̶i̶n̶o̶d̶e̶ b̶u̶s̶y̶ s̶t̶a̶t̶u̶s̶ w̶h̶e̶n̶ p̶e̶r̶f̶o̶r̶m̶i̶n̶g̶ a̶c̶t̶i̶o̶n̶s̶?̶ S̶o̶, w̶e̶ s̶h̶o̶u̶l̶d̶ u̶s̶e̶ t̶h̶i̶s̶ s̶t̶a̶t̶u̶s̶ i̶n̶s̶t̶e̶a̶d̶ b̶e̶f̶o̶r̶e̶ p̶e̶r̶f̶o̶r̶m̶i̶n̶g̶ r̶e̶s̶t̶r̶i̶c̶t̶e̶d̶ a̶c̶t̶i̶o̶n̶s̶?̶ T̶h̶e̶ q̶u̶e̶s̶t̶i̶o̶n̶ i̶s̶ w̶h̶i̶c̶h̶ s̶t̶a̶t̶u̶s̶ f̶r̶o̶m̶ t̶h̶e̶ 1̶2̶ s̶t̶a̶t̶u̶s̶e̶s̶ a̶b̶o̶v̶e̶ w̶i̶l̶l̶ s̶h̶o̶w̶ t̶h̶e̶ e̶r̶r̶o̶r̶ "L̶i̶n̶o̶d̶e̶ b̶u̶s̶y̶." w̶h̶e̶n̶ p̶e̶r̶f̶o̶r̶m̶i̶n̶g̶ s̶o̶m̶e̶ r̶e̶s̶t̶r̶i̶c̶t̶e̶d̶ a̶c̶t̶i̶o̶n̶s̶?̶ T̶h̶i̶s̶ i̶s̶ a̶l̶s̶o̶ n̶o̶t̶ d̶o̶c̶u̶m̶e̶n̶t̶e̶d̶
I found out that "Linode Busy" status not only came from the linode status I mention above. It happens with other cases such as when I'm creating a new disk and then when the disk is not yet ready and I immediately issued another command to create a new disk then I will have the "Linode Busy" error. I hope that we can determine this with API as sometimes this Busy status can take a little bit longer we don't know when it will finish.
Any best way to determine this "Linode Busy" status through API without manually performing some restricted actions that lead to "Linode Busy"?
Also, he added the 400 status code. I also have the same question as the http 400 response from the "Linode Busy" status is not useful at all because this response code is the same response that we get when performing restricted actions with failed status. So, we will not be able to use this 400 code to determine that linode is busy because we already have that same code if it is failed (you are making this secret "Linode Busy" status hard to be determined for us).
Hope someone can explain this. Thank you.
EDIT
I think I found the workaround for this, so I'm able to determine some busy states in linode on disk operation (such as creating) and linode operation (such as rebooting). So, I must create a resuable API function that will always perform a check to see they are free from this status. This is part of my larger code. So, you can call check_linode_busy_status when performing things that related to linode or check_linode_disk_busy_status when performing things related to disk.
check_linode_busy_status() {
local linode_status
while :; do
[[ ${scripting} == "false" ]] && echo "[${caller}]: Checking linode status --linode-label ${linode_label} ..."
linode_status=$(curl -Ss -H "Authorization: Bearer ${LINODE_DNS_API_KEY}" --url https://api.linode.com/v4/linode/instances | ${jq_bin} -r ".data[] | select(.label == \"${linode_label}\") | .status")
status_handler check --curl-status "$?"
if [[ "${linode_status}" == +(booting|rebooting|shutting_down|provisioning|deleting|migrating|rebuilding|cloning|restoring) ]]; then
[[ ${scripting} == "false" ]] && echo "[${caller}]: Warning, linode is busy with the following status: ${linode_status}. Waiting for normal status ..."
else
break
fi
done
}
# This is use to free up linode disk busy status
check_linode_disk_busy_status() {
while :; do
[[ ${scripting} == "false" ]] && echo "[${caller}]: Checking linode disk status --linode-label ${linode_label} ..."
linode_id=$(curl -Ss -H "Authorization: Bearer ${LINODE_DNS_API_KEY}" --url https://api.linode.com/v4/linode/instances | ${jq_bin} -r ".data[] | select(.label == \"${linode_label}\") | .id")
# Normally we interested with the last one
disk_status=$(curl -s -H "Content-Type: application/json" -H "Authorization: Bearer ${LINODE_DNS_API_KEY}" --url "https://api.linode.com/v4/linode/instances/${linode_id}/disks" | ${jq_bin} -r ".data[] | .status" | tail -n1)
status_handler check --curl-status "$?"
if [[ "${disk_status}" == +(not ready) ]]; then
[[ ${scripting} == "false" ]] && echo "[${caller}]: Warning, linode disk is busy with the following status: ${disk_status}. Waiting for normal status ..."
else
break
fi
done
}