Fix power command ResetType mapping logic (#59927)

* fix power command ResetType mapping logic

* add changelog fragment
pull/61838/head
Bill Dodd 5 years ago committed by ansibot
parent 823c108fac
commit 2a932ad7cf

@ -0,0 +1,3 @@
---
bugfixes:
- redfish_command - fix power ResetType mapping logic (https://github.com/ansible/ansible/issues/59804)

@ -628,48 +628,91 @@ class RedfishUtils(object):
return result return result
def _map_reset_type(self, reset_type, allowable_values):
equiv_types = {
'On': 'ForceOn',
'ForceOn': 'On',
'ForceOff': 'GracefulShutdown',
'GracefulShutdown': 'ForceOff',
'GracefulRestart': 'ForceRestart',
'ForceRestart': 'GracefulRestart'
}
if reset_type in allowable_values:
return reset_type
if reset_type not in equiv_types:
return reset_type
mapped_type = equiv_types[reset_type]
if mapped_type in allowable_values:
return mapped_type
return reset_type
def manage_system_power(self, command): def manage_system_power(self, command):
key = "Actions" key = "Actions"
reset_type_values = ['On', 'ForceOff', 'GracefulShutdown',
'GracefulRestart', 'ForceRestart', 'Nmi',
'ForceOn', 'PushPowerButton', 'PowerCycle']
# Search for 'key' entry and extract URI from it # command should be PowerOn, PowerForceOff, etc.
if not command.startswith('Power'):
return {'ret': False, 'msg': 'Invalid Command (%s)' % command}
reset_type = command[5:]
# map Reboot to a ResetType that does a reboot
if reset_type == 'Reboot':
reset_type = 'GracefulRestart'
if reset_type not in reset_type_values:
return {'ret': False, 'msg': 'Invalid Command (%s)' % command}
# read the system resource and get the current power state
response = self.get_request(self.root_uri + self.systems_uris[0]) response = self.get_request(self.root_uri + self.systems_uris[0])
if response['ret'] is False: if response['ret'] is False:
return response return response
data = response['data'] data = response['data']
power_state = data["PowerState"] power_state = data.get('PowerState')
if power_state == "On" and command == 'PowerOn': # if power is already in target state, nothing to do
if power_state == "On" and reset_type in ['On', 'ForceOn']:
return {'ret': True, 'changed': False} return {'ret': True, 'changed': False}
if power_state == "Off" and reset_type in ['GracefulShutdown', 'ForceOff']:
if power_state == "Off" and command in ['PowerGracefulShutdown', 'PowerForceOff']:
return {'ret': True, 'changed': False} return {'ret': True, 'changed': False}
reset_action = data[key]["#ComputerSystem.Reset"] # get the #ComputerSystem.Reset Action and target URI
action_uri = reset_action["target"] if key not in data or '#ComputerSystem.Reset' not in data[key]:
allowable_vals = reset_action.get("ResetType@Redfish.AllowableValues", []) return {'ret': False, 'msg': 'Action #ComputerSystem.Reset not found'}
restart_cmd = "GracefulRestart" reset_action = data[key]['#ComputerSystem.Reset']
if "ForceRestart" in allowable_vals and "GracefulRestart" not in allowable_vals: if 'target' not in reset_action:
restart_cmd = "ForceRestart" return {'ret': False,
'msg': 'target URI missing from Action #ComputerSystem.Reset'}
# Define payload accordingly action_uri = reset_action['target']
if command == "PowerOn":
payload = {'ResetType': 'On'} # get AllowableValues from ActionInfo
elif command == "PowerForceOff": allowable_values = None
payload = {'ResetType': 'ForceOff'} if '@Redfish.ActionInfo' in reset_action:
elif command == "PowerForceRestart": action_info_uri = reset_action.get('@Redfish.ActionInfo')
payload = {'ResetType': "ForceRestart"} response = self.get_request(self.root_uri + action_info_uri)
elif command == "PowerGracefulRestart": if response['ret'] is True:
payload = {'ResetType': 'GracefulRestart'} data = response['data']
elif command == "PowerGracefulShutdown": if 'Parameters' in data:
payload = {'ResetType': 'GracefulShutdown'} params = data['Parameters']
elif command == "PowerReboot": for param in params:
if power_state == "On": if param.get('Name') == 'ResetType':
payload = {'ResetType': restart_cmd} allowable_values = param.get('AllowableValues')
else: break
payload = {'ResetType': "On"}
else: # fallback to @Redfish.AllowableValues annotation
return {'ret': False, 'msg': 'Invalid Command'} if allowable_values is None:
allowable_values = reset_action.get('ResetType@Redfish.AllowableValues', [])
# map ResetType to an allowable value if needed
if reset_type not in allowable_values:
reset_type = self._map_reset_type(reset_type, allowable_values)
# define payload
payload = {'ResetType': reset_type}
# POST to Action URI
response = self.post_request(self.root_uri + action_uri, payload) response = self.post_request(self.root_uri + action_uri, payload)
if response['ret'] is False: if response['ret'] is False:
return response return response

Loading…
Cancel
Save