Add node deploy state
Change-Id: Iabe428bf35664dab6b56a00cb20691f7256ffea0
Related-Issue: PROD-26188 (PROD:26188)
(cherry picked from commit 2cd70515cd0966ab247966c3c68bd45ceb7c64c3)
diff --git a/_states/ironicv1.py b/_states/ironicv1.py
index 2505f68..53f7f36 100644
--- a/_states/ironicv1.py
+++ b/_states/ironicv1.py
@@ -1,4 +1,6 @@
+import collections
import logging
+import time
log = logging.getLogger(__name__)
@@ -282,6 +284,79 @@
return _failed('find', name, resource)
+def enroll_to_state(name, node_names, cloud_name,
+ pool_size=3, sleep_time=5, timeout=600, **kwargs):
+ """
+
+ :param name: name of target state
+ :param node_names: list of node names
+ :param cloud_name:
+ :param pool_size: max size of nodes to change state in one moment
+ :param sleep_time: time between checking states
+ :param timeout: global timeout
+ """
+ microversion = kwargs.pop('microversion', '1.32')
+ Transition = collections.namedtuple('Transition',
+ ('action', 'success', 'failures'))
+ transition_map = {
+ 'enroll': Transition('manage', 'manageable', ('enroll',)),
+ 'manageable': Transition('provide', 'available', ('clean failed',)),
+ 'available': Transition('active', 'active', ('deploy failed',)),
+ }
+ nodes = [
+ {'name': node, 'status': 'new', 'result': None,
+ 'current_state': 'enroll'}
+ for node in node_names
+ ]
+ counter = 0
+ while nodes and timeout > 0:
+ for node in nodes:
+ api_node = _ironicv1_call('node_get_details', node['name'],
+ cloud_name=cloud_name,
+ microversion=microversion)
+ if api_node['provision_state'] == name:
+ node['status'] = 'done'
+ node['result'] = 'success'
+ counter -= 1
+ elif (api_node['provision_state']
+ == transition_map[node['current_state']].success):
+ new_state = transition_map[node['current_state']].success
+ _ironicv1_call('node_provision_state_change', node['name'],
+ transition_map[new_state].action,
+ cloud_name=cloud_name,
+ microversion=microversion)
+ node['current_state'] = new_state
+ elif (node['status'] == 'processing'
+ and not api_node['target_provision_state']
+ and (api_node['provision_state']
+ in transition_map[api_node['provision_state']].failures)
+ ):
+ node['status'] = 'done'
+ node['result'] = 'failure'
+ counter -= 1
+ elif counter < pool_size:
+ if node['status'] == 'new':
+ _ironicv1_call(
+ 'node_provision_state_change', node['name'],
+ transition_map[node['current_state']].action,
+ cloud_name=cloud_name, microversion=microversion)
+ node['status'] = 'processing'
+ counter += 1
+ else:
+ continue
+ else:
+ break
+ nodes = filter(
+ lambda node: node['status'] in ['new', 'processing'], nodes)
+ time.sleep(sleep_time)
+ timeout -= sleep_time
+ return _succeeded('update', name, 'node_states',
+ {'result': filter(
+ lambda node: node['name'] in node_names,
+ _ironicv1_call('node_list', cloud_name=cloud_name,
+ microversion=microversion)['nodes'])})
+
+
def _succeeded(op, name, resource, changes=None):
msg_map = {
'create': '{0} {1} created',