fix: improve actions waiting timeout based on data (#488)

##### SUMMARY

Some action waiting time have been set to an arbitrary number, which
could force the users to wait for too long, while we could have raised a
timeout.

This changes the arbitrary numbers with rough estimate based on the
average actions time and some leeway.
This commit is contained in:
Jonas L 2024-04-15 11:01:12 +02:00 committed by GitHub
parent 04835d543f
commit 07095529a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 113 additions and 69 deletions

View file

@ -202,7 +202,9 @@ class AnsibleHCloudCertificate(AnsibleHCloud):
if not self.module.check_mode:
try:
resp = self.client.certificates.create_managed(**params)
resp.action.wait_until_finished(max_retries=1000)
# Action should take 60 to 90 seconds on average, wait for 5m to
# allow DNS or Let's Encrypt slowdowns.
resp.action.wait_until_finished(max_retries=300)
except HCloudException as exception:
self.fail_json_hcloud(exception)

View file

@ -216,7 +216,8 @@ class AnsibleHCloudFloatingIP(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self.hcloud_floating_ip.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_floating_ip.change_protection(delete=delete_protection)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -261,7 +262,8 @@ class AnsibleHCloudFloatingIP(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None and delete_protection != self.hcloud_floating_ip.protection["delete"]:
if not self.module.check_mode:
self.hcloud_floating_ip.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_floating_ip.change_protection(delete=delete_protection)
action.wait_until_finished()
self._mark_as_changed()
self._get_floating_ip()

View file

@ -213,12 +213,13 @@ class AnsibleHCloudLoadBalancer(AnsibleHCloud):
if not self.module.check_mode:
resp = self.client.load_balancers.create(**params)
resp.action.wait_until_finished(max_retries=1000)
resp.action.wait_until_finished()
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self._get_load_balancer()
self.hcloud_load_balancer.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_load_balancer.change_protection(delete=delete_protection)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -235,7 +236,8 @@ class AnsibleHCloudLoadBalancer(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None and delete_protection != self.hcloud_load_balancer.protection["delete"]:
if not self.module.check_mode:
self.hcloud_load_balancer.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_load_balancer.change_protection(delete=delete_protection)
action.wait_until_finished()
self._mark_as_changed()
self._get_load_balancer()
@ -245,9 +247,11 @@ class AnsibleHCloudLoadBalancer(AnsibleHCloud):
):
if not self.module.check_mode:
if disable_public_interface is True:
self.hcloud_load_balancer.disable_public_interface().wait_until_finished()
action = self.hcloud_load_balancer.disable_public_interface()
action.wait_until_finished()
else:
self.hcloud_load_balancer.enable_public_interface().wait_until_finished()
action = self.hcloud_load_balancer.enable_public_interface()
action.wait_until_finished()
self._mark_as_changed()
load_balancer_type = self.module.params.get("load_balancer_type")
@ -259,17 +263,17 @@ class AnsibleHCloudLoadBalancer(AnsibleHCloud):
if not new_load_balancer_type:
self.module.fail_json(msg="unknown load balancer type")
if not self.module.check_mode:
self.hcloud_load_balancer.change_type(
action = self.hcloud_load_balancer.change_type(
load_balancer_type=new_load_balancer_type,
).wait_until_finished(max_retries=1000)
)
action.wait_until_finished()
self._mark_as_changed()
algorithm = self.module.params.get("algorithm")
if algorithm is not None and self.hcloud_load_balancer.algorithm.type != algorithm:
self.hcloud_load_balancer.change_algorithm(
algorithm=LoadBalancerAlgorithm(type=algorithm)
).wait_until_finished()
action = self.hcloud_load_balancer.change_algorithm(algorithm=LoadBalancerAlgorithm(type=algorithm))
action.wait_until_finished()
self._mark_as_changed()
self._get_load_balancer()

View file

@ -139,7 +139,8 @@ class AnsibleHCloudLoadBalancerNetwork(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_load_balancer.attach_to_network(**params).wait_until_finished()
action = self.hcloud_load_balancer.attach_to_network(**params)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
@ -159,9 +160,8 @@ class AnsibleHCloudLoadBalancerNetwork(AnsibleHCloud):
if self.hcloud_load_balancer_network is not None and self.hcloud_load_balancer is not None:
if not self.module.check_mode:
try:
self.hcloud_load_balancer.detach_from_network(
self.hcloud_load_balancer_network.network
).wait_until_finished()
action = self.hcloud_load_balancer.detach_from_network(self.hcloud_load_balancer_network.network)
action.wait_until_finished()
self._mark_as_changed()
except HCloudException as exception:
self.fail_json_hcloud(exception)

View file

@ -368,9 +368,8 @@ class AnsibleHCloudLoadBalancerService(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_load_balancer.add_service(LoadBalancerService(**params)).wait_until_finished(
max_retries=1000
)
action = self.hcloud_load_balancer.add_service(LoadBalancerService(**params))
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -464,9 +463,8 @@ class AnsibleHCloudLoadBalancerService(AnsibleHCloud):
changed = True
if not self.module.check_mode:
self.hcloud_load_balancer.update_service(LoadBalancerService(**params)).wait_until_finished(
max_retries=1000
)
action = self.hcloud_load_balancer.update_service(LoadBalancerService(**params))
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._get_load_balancer()
@ -492,9 +490,8 @@ class AnsibleHCloudLoadBalancerService(AnsibleHCloud):
if self.hcloud_load_balancer_service is not None:
if not self.module.check_mode:
try:
self.hcloud_load_balancer.delete_service(self.hcloud_load_balancer_service).wait_until_finished(
max_retries=1000
)
action = self.hcloud_load_balancer.delete_service(self.hcloud_load_balancer_service)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()

View file

@ -224,7 +224,8 @@ class AnsibleHCloudLoadBalancerTarget(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_load_balancer.add_target(**params).wait_until_finished()
action = self.hcloud_load_balancer.add_target(**params)
action.wait_until_finished()
except APIException as exception:
if exception.code == "locked" or exception.code == "conflict":
self._create_load_balancer_target()
@ -269,7 +270,8 @@ class AnsibleHCloudLoadBalancerTarget(AnsibleHCloud):
use_private_ip=False,
)
try:
self.hcloud_load_balancer.remove_target(target).wait_until_finished()
action = self.hcloud_load_balancer.remove_target(target)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()

View file

@ -164,7 +164,8 @@ class AnsibleHCloudNetwork(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self._get_network()
self.hcloud_network.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_network.change_protection(delete=delete_protection)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -188,7 +189,8 @@ class AnsibleHCloudNetwork(AnsibleHCloud):
ip_range = self.module.params.get("ip_range")
if ip_range is not None and ip_range != self.hcloud_network.ip_range:
if not self.module.check_mode:
self.hcloud_network.change_ip_range(ip_range=ip_range).wait_until_finished()
action = self.hcloud_network.change_ip_range(ip_range=ip_range)
action.wait_until_finished()
self._mark_as_changed()
expose_routes_to_vswitch = self.module.params.get("expose_routes_to_vswitch")
@ -203,7 +205,8 @@ class AnsibleHCloudNetwork(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None and delete_protection != self.hcloud_network.protection["delete"]:
if not self.module.check_mode:
self.hcloud_network.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_network.change_protection(delete=delete_protection)
action.wait_until_finished()
self._mark_as_changed()
except HCloudException as exception:
self.fail_json_hcloud(exception)

View file

@ -232,7 +232,8 @@ class AnsibleHCloudPrimaryIP(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self.hcloud_primary_ip.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_primary_ip.change_protection(delete=delete_protection)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -258,7 +259,8 @@ class AnsibleHCloudPrimaryIP(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None and delete_protection != self.hcloud_primary_ip.protection["delete"]:
if not self.module.check_mode:
self.hcloud_primary_ip.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_primary_ip.change_protection(delete=delete_protection)
action.wait_until_finished()
self._mark_as_changed()
self._get_primary_ip()

View file

@ -276,7 +276,8 @@ class AnsibleHCloudReverseDNS(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_resource.change_dns_ptr(**params).wait_until_finished()
action = self.hcloud_resource.change_dns_ptr(**params)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -293,7 +294,8 @@ class AnsibleHCloudReverseDNS(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_resource.change_dns_ptr(**params).wait_until_finished()
action = self.hcloud_resource.change_dns_ptr(**params)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()

View file

@ -129,7 +129,8 @@ class AnsibleHCloudRoute(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_network.add_route(route=route).wait_until_finished()
action = self.hcloud_network.add_route(route=route)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
@ -149,7 +150,8 @@ class AnsibleHCloudRoute(AnsibleHCloud):
if self.hcloud_route is not None and self.hcloud_network is not None:
if not self.module.check_mode:
try:
self.hcloud_network.delete_route(self.hcloud_route).wait_until_finished()
action = self.hcloud_network.delete_route(self.hcloud_route)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()

View file

@ -469,7 +469,9 @@ class AnsibleHCloudServer(AnsibleHCloud):
try:
resp = self.client.servers.create(**params)
self.result["root_password"] = resp.root_password
resp.action.wait_until_finished(max_retries=1000)
# Action should take 60 to 90 seconds on average, but can be >10m when creating a
# server from a custom images
resp.action.wait_until_finished(max_retries=1800)
for action in resp.next_actions:
action.wait_until_finished()
@ -481,16 +483,18 @@ class AnsibleHCloudServer(AnsibleHCloud):
backups = self.module.params.get("backups")
if backups:
self._get_server()
self.hcloud_server.enable_backup().wait_until_finished()
action = self.hcloud_server.enable_backup()
action.wait_until_finished()
delete_protection = self.module.params.get("delete_protection")
rebuild_protection = self.module.params.get("rebuild_protection")
if delete_protection is not None and rebuild_protection is not None:
self._get_server()
self.hcloud_server.change_protection(
action = self.hcloud_server.change_protection(
delete=delete_protection,
rebuild=rebuild_protection,
).wait_until_finished()
)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -568,17 +572,20 @@ class AnsibleHCloudServer(AnsibleHCloud):
self._mark_as_changed()
elif not rescue_mode and self.hcloud_server.rescue_enabled is True:
if not self.module.check_mode:
self.hcloud_server.disable_rescue().wait_until_finished()
action = self.hcloud_server.disable_rescue()
action.wait_until_finished()
self._mark_as_changed()
backups = self.module.params.get("backups")
if backups and self.hcloud_server.backup_window is None:
if not self.module.check_mode:
self.hcloud_server.enable_backup().wait_until_finished()
action = self.hcloud_server.enable_backup()
action.wait_until_finished()
self._mark_as_changed()
elif backups is not None and not backups and self.hcloud_server.backup_window is not None:
if not self.module.check_mode:
self.hcloud_server.disable_backup().wait_until_finished()
action = self.hcloud_server.disable_backup()
action.wait_until_finished()
self._mark_as_changed()
if self.module.params.get("firewalls") is not None:
@ -612,10 +619,11 @@ class AnsibleHCloudServer(AnsibleHCloud):
or rebuild_protection != self.hcloud_server.protection["rebuild"]
):
if not self.module.check_mode:
self.hcloud_server.change_protection(
action = self.hcloud_server.change_protection(
delete=delete_protection,
rebuild=rebuild_protection,
).wait_until_finished()
)
action.wait_until_finished()
self._mark_as_changed()
self._get_server()
except HCloudException as exception:
@ -636,7 +644,8 @@ class AnsibleHCloudServer(AnsibleHCloud):
# Remove if current is defined
if current is not None:
if not self.module.check_mode:
self.hcloud_server.remove_from_placement_group().wait_until_finished()
action = self.hcloud_server.remove_from_placement_group()
action.wait_until_finished()
self._mark_as_changed()
# Return if parameter is falsy
@ -646,7 +655,8 @@ class AnsibleHCloudServer(AnsibleHCloud):
# Assign new
self.stop_server_if_forced()
if not self.module.check_mode:
self.hcloud_server.add_to_placement_group(placement_group).wait_until_finished()
action = self.hcloud_server.add_to_placement_group(placement_group)
action.wait_until_finished()
self._mark_as_changed()
def _update_server_server_type(self) -> None:
@ -662,14 +672,16 @@ class AnsibleHCloudServer(AnsibleHCloud):
self.stop_server_if_forced()
upgrade_disk = self.module.params.get("upgrade_disk")
# Upgrading the disk takes some more time
upgrade_timeout = 1000 if upgrade_disk else 100
# Upgrading a server takes 160 seconds on average, upgrading the disk should
# take more time
upgrade_timeout = 600 if upgrade_disk else 180
if not self.module.check_mode:
self.hcloud_server.change_type(
action = self.hcloud_server.change_type(
server_type=self._get_server_type(),
upgrade_disk=upgrade_disk,
).wait_until_finished(upgrade_timeout)
)
action.wait_until_finished(max_retries=upgrade_timeout)
self._mark_as_changed()
def _update_server_ip(self, kind: Literal["ipv4", "ipv6"]) -> None:
@ -689,7 +701,8 @@ class AnsibleHCloudServer(AnsibleHCloud):
if current is not None:
self.stop_server_if_forced()
if not self.module.check_mode:
self.client.primary_ips.unassign(current).wait_until_finished()
action = self.client.primary_ips.unassign(current)
action.wait_until_finished()
self._mark_as_changed()
# Return if parameter is falsy or resource is disabled
@ -699,11 +712,12 @@ class AnsibleHCloudServer(AnsibleHCloud):
# Assign new
self.stop_server_if_forced()
if not self.module.check_mode:
self.client.primary_ips.assign(
action = self.client.primary_ips.assign(
primary_ip,
assignee_id=self.hcloud_server.id,
assignee_type="server",
).wait_until_finished()
)
action.wait_until_finished()
self._mark_as_changed()
def _update_server_networks(self) -> None:
@ -815,7 +829,8 @@ class AnsibleHCloudServer(AnsibleHCloud):
if self.hcloud_server:
if self.hcloud_server.status != Server.STATUS_RUNNING:
if not self.module.check_mode:
self.client.servers.power_on(self.hcloud_server).wait_until_finished()
action = self.client.servers.power_on(self.hcloud_server)
action.wait_until_finished()
self._mark_as_changed()
self._get_server()
except HCloudException as exception:
@ -826,7 +841,8 @@ class AnsibleHCloudServer(AnsibleHCloud):
if self.hcloud_server:
if self.hcloud_server.status != Server.STATUS_OFF:
if not self.module.check_mode:
self.client.servers.power_off(self.hcloud_server).wait_until_finished()
action = self.client.servers.power_off(self.hcloud_server)
action.wait_until_finished()
self._mark_as_changed()
self._get_server()
except HCloudException as exception:
@ -872,7 +888,8 @@ class AnsibleHCloudServer(AnsibleHCloud):
self._get_server()
if self.hcloud_server is not None:
if not self.module.check_mode:
self.client.servers.delete(self.hcloud_server).wait_until_finished()
action = self.client.servers.delete(self.hcloud_server)
action.wait_until_finished()
self._mark_as_changed()
self.hcloud_server = None
except HCloudException as exception:

View file

@ -164,7 +164,8 @@ class AnsibleHCloudServerNetwork(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_server.attach_to_network(**params).wait_until_finished()
action = self.hcloud_server.attach_to_network(**params)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
@ -182,7 +183,8 @@ class AnsibleHCloudServerNetwork(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_server.change_alias_ips(**params).wait_until_finished()
action = self.hcloud_server.change_alias_ips(**params)
action.wait_until_finished()
except APIException as exception:
self.fail_json_hcloud(exception)
@ -204,7 +206,8 @@ class AnsibleHCloudServerNetwork(AnsibleHCloud):
if self.hcloud_server_network is not None and self.hcloud_server is not None:
if not self.module.check_mode:
try:
self.hcloud_server.detach_from_network(self.hcloud_server_network.network).wait_until_finished()
action = self.hcloud_server.detach_from_network(self.hcloud_server_network.network)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()

View file

@ -173,7 +173,8 @@ class AnsibleHCloudSubnetwork(AnsibleHCloud):
if not self.module.check_mode:
try:
self.hcloud_network.add_subnet(subnet=NetworkSubnet(**params)).wait_until_finished()
action = self.hcloud_network.add_subnet(subnet=NetworkSubnet(**params))
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
@ -193,7 +194,8 @@ class AnsibleHCloudSubnetwork(AnsibleHCloud):
if self.hcloud_subnetwork is not None and self.hcloud_network is not None:
if not self.module.check_mode:
try:
self.hcloud_network.delete_subnet(self.hcloud_subnetwork).wait_until_finished()
action = self.hcloud_network.delete_subnet(self.hcloud_subnetwork)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()

View file

@ -216,7 +216,8 @@ class AnsibleHCloudVolume(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None:
self._get_volume()
self.hcloud_volume.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_volume.change_protection(delete=delete_protection)
action.wait_until_finished()
except HCloudException as exception:
self.fail_json_hcloud(exception)
self._mark_as_changed()
@ -228,7 +229,8 @@ class AnsibleHCloudVolume(AnsibleHCloud):
if size:
if self.hcloud_volume.size < size:
if not self.module.check_mode:
self.hcloud_volume.resize(size).wait_until_finished()
action = self.hcloud_volume.resize(size)
action.wait_until_finished()
self._mark_as_changed()
elif self.hcloud_volume.size > size:
self.module.warn("Shrinking of volumes is not supported")
@ -239,12 +241,14 @@ class AnsibleHCloudVolume(AnsibleHCloud):
if self.hcloud_volume.server is None or self.hcloud_volume.server.name != server.name:
if not self.module.check_mode:
automount = self.module.params.get("automount", False)
self.hcloud_volume.attach(server, automount=automount).wait_until_finished()
action = self.hcloud_volume.attach(server, automount=automount)
action.wait_until_finished()
self._mark_as_changed()
else:
if self.hcloud_volume.server is not None:
if not self.module.check_mode:
self.hcloud_volume.detach().wait_until_finished()
action = self.hcloud_volume.detach()
action.wait_until_finished()
self._mark_as_changed()
labels = self.module.params.get("labels")
@ -256,7 +260,8 @@ class AnsibleHCloudVolume(AnsibleHCloud):
delete_protection = self.module.params.get("delete_protection")
if delete_protection is not None and delete_protection != self.hcloud_volume.protection["delete"]:
if not self.module.check_mode:
self.hcloud_volume.change_protection(delete=delete_protection).wait_until_finished()
action = self.hcloud_volume.change_protection(delete=delete_protection)
action.wait_until_finished()
self._mark_as_changed()
self._get_volume()
@ -276,7 +281,8 @@ class AnsibleHCloudVolume(AnsibleHCloud):
if self.hcloud_volume is not None:
if not self.module.check_mode:
if self.hcloud_volume.server is not None:
self.hcloud_volume.detach().wait_until_finished()
action = self.hcloud_volume.detach()
action.wait_until_finished()
self.client.volumes.delete(self.hcloud_volume)
self._mark_as_changed()
self.hcloud_volume = None