Fix SetOneTimeBoot to use standard ComputerSystem 'Boot' property (#54201)

* fix SetOneTimeBoot to use standard ComputerSystem 'Boot' property

* add support for UefiTarget and UefiBootNext boot sources
This commit is contained in:
Bill Dodd 2019-05-02 07:50:41 -05:00 committed by John R Barker
parent eb7190264e
commit 2614e823df
2 changed files with 97 additions and 15 deletions

View file

@ -815,9 +815,13 @@ class RedfishUtils(object):
return response return response
return {'ret': True, 'changed': True, 'msg': "Set BIOS to default settings"} return {'ret': True, 'changed': True, 'msg': "Set BIOS to default settings"}
def set_one_time_boot_device(self, bootdevice): def set_one_time_boot_device(self, bootdevice, uefi_target, boot_next):
result = {} result = {}
key = "Bios" key = "Boot"
if not bootdevice:
return {'ret': False,
'msg': "bootdevice option required for SetOneTimeBoot"}
# Search for 'key' entry and extract URI from it # Search for 'key' entry and extract URI from it
response = self.get_request(self.root_uri + self.systems_uris[0]) response = self.get_request(self.root_uri + self.systems_uris[0])
@ -829,23 +833,65 @@ class RedfishUtils(object):
if key not in data: if key not in data:
return {'ret': False, 'msg': "Key %s not found" % key} return {'ret': False, 'msg': "Key %s not found" % key}
bios_uri = data[key]["@odata.id"] boot = data[key]
response = self.get_request(self.root_uri + bios_uri) annotation = 'BootSourceOverrideTarget@Redfish.AllowableValues'
if response['ret'] is False: if annotation in boot:
return response allowable_values = boot[annotation]
data = response['data'] if isinstance(allowable_values, list) and bootdevice not in allowable_values:
return {'ret': False,
'msg': "Boot device %s not in list of allowable values (%s)" %
(bootdevice, allowable_values)}
boot_mode = data[u'Attributes']["BootMode"] # read existing values
if boot_mode == "Uefi": enabled = boot.get('BootSourceOverrideEnabled')
payload = {"Boot": {"BootSourceOverrideTarget": "UefiTarget", "UefiTargetBootSourceOverride": bootdevice}} target = boot.get('BootSourceOverrideTarget')
cur_uefi_target = boot.get('UefiTargetBootSourceOverride')
cur_boot_next = boot.get('BootNext')
if bootdevice == 'UefiTarget':
if not uefi_target:
return {'ret': False,
'msg': "uefi_target option required to SetOneTimeBoot for UefiTarget"}
if enabled == 'Once' and target == bootdevice and uefi_target == cur_uefi_target:
# If properties are already set, no changes needed
return {'ret': True, 'changed': False}
payload = {
'Boot': {
'BootSourceOverrideEnabled': 'Once',
'BootSourceOverrideTarget': bootdevice,
'UefiTargetBootSourceOverride': uefi_target
}
}
elif bootdevice == 'UefiBootNext':
if not boot_next:
return {'ret': False,
'msg': "boot_next option required to SetOneTimeBoot for UefiBootNext"}
if enabled == 'Once' and target == bootdevice and boot_next == cur_boot_next:
# If properties are already set, no changes needed
return {'ret': True, 'changed': False}
payload = {
'Boot': {
'BootSourceOverrideEnabled': 'Once',
'BootSourceOverrideTarget': bootdevice,
'BootNext': boot_next
}
}
else: else:
payload = {"Boot": {"BootSourceOverrideTarget": bootdevice}} if enabled == 'Once' and target == bootdevice:
# If properties are already set, no changes needed
return {'ret': True, 'changed': False}
payload = {
'Boot': {
'BootSourceOverrideEnabled': 'Once',
'BootSourceOverrideTarget': bootdevice
}
}
response = self.patch_request(self.root_uri + self.systems_uris[0], payload) response = self.patch_request(self.root_uri + self.systems_uris[0], payload)
if response['ret'] is False: if response['ret'] is False:
return response return response
return {'ret': True} return {'ret': True, 'changed': True}
def set_bios_attributes(self, attr): def set_bios_attributes(self, attr):
result = {} result = {}

View file

@ -74,6 +74,16 @@ options:
default: 10 default: 10
type: int type: int
version_added: '2.8' version_added: '2.8'
uefi_target:
required: false
description:
- UEFI target when bootdevice is "UefiTarget"
version_added: "2.9"
boot_next:
required: false
description:
- BootNext target when bootdevice is "UefiBootNext"
version_added: "2.9"
author: "Jose Delarosa (@jose-delarosa)" author: "Jose Delarosa (@jose-delarosa)"
''' '''
@ -96,6 +106,26 @@ EXAMPLES = '''
username: "{{ username }}" username: "{{ username }}"
password: "{{ password }}" password: "{{ password }}"
- name: Set one-time boot device to UefiTarget of "/0x31/0x33/0x01/0x01"
redfish_command:
category: Systems
command: SetOneTimeBoot
bootdevice: "UefiTarget"
uefi_target: "/0x31/0x33/0x01/0x01"
baseuri: "{{ baseuri }}"
username: "{{ username }}"
password: "{{ password }}"
- name: Set one-time boot device to BootNext target of "Boot0001"
redfish_command:
category: Systems
command: SetOneTimeBoot
bootdevice: "UefiBootNext"
boot_next: "Boot0001"
baseuri: "{{ baseuri }}"
username: "{{ username }}"
password: "{{ password }}"
- name: Set chassis indicator LED to blink - name: Set chassis indicator LED to blink
redfish_command: redfish_command:
category: Chassis category: Chassis
@ -183,7 +213,9 @@ def main():
new_password=dict(no_log=True), new_password=dict(no_log=True),
roleid=dict(), roleid=dict(),
bootdevice=dict(), bootdevice=dict(),
timeout=dict(type='int', default=10) timeout=dict(type='int', default=10),
uefi_target=dict(),
boot_next=dict()
), ),
supports_check_mode=False supports_check_mode=False
) )
@ -248,7 +280,10 @@ def main():
if "Power" in command: if "Power" in command:
result = rf_utils.manage_system_power(command) result = rf_utils.manage_system_power(command)
elif command == "SetOneTimeBoot": elif command == "SetOneTimeBoot":
result = rf_utils.set_one_time_boot_device(module.params['bootdevice']) result = rf_utils.set_one_time_boot_device(
module.params['bootdevice'],
module.params['uefi_target'],
module.params['boot_next'])
elif category == "Chassis": elif category == "Chassis":
result = rf_utils._find_chassis_resource(rf_uri) result = rf_utils._find_chassis_resource(rf_uri)
@ -283,7 +318,8 @@ def main():
# Return data back or fail with proper message # Return data back or fail with proper message
if result['ret'] is True: if result['ret'] is True:
del result['ret'] del result['ret']
module.exit_json(changed=True, msg='Action was successful') changed = result.get('changed', True)
module.exit_json(changed=changed, msg='Action was successful')
else: else:
module.fail_json(msg=to_native(result['msg'])) module.fail_json(msg=to_native(result['msg']))