Add polling for zone_present and zone absent
Change-Id: Ie3b19fc64582815b63deffe339147daa34787184
Related-Issue: PROD-25031 (PROD:25031)
diff --git a/_states/designatev2.py b/_states/designatev2.py
index 3f98815..54e532a 100644
--- a/_states/designatev2.py
+++ b/_states/designatev2.py
@@ -1,4 +1,6 @@
+import functools
import logging
+import time
def __virtual__():
@@ -12,12 +14,12 @@
return __salt__['designatev2.{}'.format(fname)](*args, **kwargs) # noqa
-def _resource_present(resource, name, cloud_name, **kwargs):
+def _resource_present(resource, name, cloud_name, waiter=None, **kwargs):
try:
method_name = '{}_get_details'.format(resource)
exact_resource = _designatev2_call(
method_name, name, cloud_name=cloud_name
- )[resource]
+ )
except Exception as e:
if 'ResourceNotFound' in repr(e):
try:
@@ -29,6 +31,10 @@
log.exception('Designate {0} create failed with {1}'.
format(resource, e))
return _failed('create', name, resource)
+ if waiter:
+ if not waiter(name, cloud_name):
+ return _failed('create', name, resource)
+ resp['status'] = 'ACTIVE'
return _succeeded('create', name, resource, resp)
elif 'MultipleResourcesFound' in repr(e):
return _failed('find', name, resource)
@@ -39,23 +45,25 @@
for key in kwargs:
if key not in exact_resource or kwargs[key] != exact_resource[key]:
to_update[key] = kwargs[key]
- try:
- method_name = '{}_update'.format(resource)
- resp = _designatev2_call(
- method_name, name, cloud_name=cloud_name, **to_update
- )
- except Exception as e:
- log.exception('Designate {0} update failed with {1}'.format(resource, e))
- return _failed('update', name, resource)
- return _succeeded('update', name, resource, resp)
+ if to_update:
+ try:
+ method_name = '{}_update'.format(resource)
+ resp = _designatev2_call(
+ method_name, name, cloud_name=cloud_name, **to_update
+ )
+ except Exception as e:
+ log.exception('Designate {0} update failed with {1}'.format(resource, e))
+ return _failed('update', name, resource)
+ return _succeeded('update', name, resource, resp)
+ return _succeeded('no_changes', name, resource)
-def _resource_absent(resource, name, cloud_name):
+def _resource_absent(resource, name, cloud_name, waiter=None):
try:
method_name = '{}_get_details'.format(resource)
_designatev2_call(
method_name, name, cloud_name=cloud_name
- )[resource]
+ )
except Exception as e:
if 'ResourceNotFound' in repr(e):
return _succeeded('absent', name, resource)
@@ -69,16 +77,41 @@
except Exception as e:
log.error('Designate delete {0} failed with {1}'.format(resource, e))
return _failed('delete', name, resource)
+ if waiter:
+ if not waiter:
+ return _failed('delete', name, resource)
return _succeeded('delete', name, resource)
+def _poll_for_zone(zone_name, cloud_name, checker, retry=5, timeout=2):
+ while retry:
+ zones = _designatev2_call('zone_list', name=zone_name,
+ cloud_name=cloud_name)['zones']
+ if checker(zones):
+ return True
+ time.sleep(timeout)
+ retry -= 1
+ return False
+
+
def zone_present(name, cloud_name, email, **kwargs):
kwargs.update({'email': email})
- return _resource_present('zone', name, cloud_name, **kwargs)
+ return _resource_present(
+ 'zone', name, cloud_name,
+ functools.partial(
+ _poll_for_zone,
+ checker=lambda zones: len(zones) and
+ zones[0]['status'] == 'ACTIVE',
+ **kwargs.pop('waiter_config', {})),
+ **kwargs)
-def zone_absent(name, cloud_name):
- return _resource_absent('zone', name, cloud_name)
+def zone_absent(name, cloud_name, **kwargs):
+ return _resource_absent(
+ 'zone', name, cloud_name,
+ waiter=functools.partial(
+ _poll_for_zone, checker=lambda zones: not len(zones),
+ **kwargs.pop('waiter_config', {})))
def _succeeded(op, name, resource, changes=None):