mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Update redfish module for compatibility with VirtualMedia resource location (#5124)
* Update redfish module for compatibility with VirtualMedia resource location from Manager to Systems * Add changelogs fragments for PR 5124 * Update some issue according to the suggestions * update changelogs fragment to list new features in the minor_changes catagory Co-authored-by: Tami YY3 Pan <panyy3@lenovo.com>
This commit is contained in:
parent
57e1e2bd8e
commit
766c109d47
4 changed files with 93 additions and 18 deletions
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- redfish - added new command GetVirtualMedia, VirtualMediaInsert and VirtualMediaEject to Systems category due to Redfish spec changes the virtualMedia resource location from Manager to System (https://github.com/ansible-collections/community.general/pull/5124).
|
|
@ -202,6 +202,16 @@ class RedfishUtils(object):
|
|||
def _init_session(self):
|
||||
pass
|
||||
|
||||
def _get_vendor(self):
|
||||
response = self.get_request(self.root_uri + self.service_root)
|
||||
if response['ret'] is False:
|
||||
return {'ret': False, 'Vendor': ''}
|
||||
data = response['data']
|
||||
if 'Vendor' in data:
|
||||
return {'ret': True, 'Vendor': data["Vendor"]}
|
||||
else:
|
||||
return {'ret': True, 'Vendor': ''}
|
||||
|
||||
def _find_accountservice_resource(self):
|
||||
response = self.get_request(self.root_uri + self.service_root)
|
||||
if response['ret'] is False:
|
||||
|
@ -2162,10 +2172,14 @@ class RedfishUtils(object):
|
|||
result["entries"] = virtualmedia_results
|
||||
return result
|
||||
|
||||
def get_multi_virtualmedia(self):
|
||||
def get_multi_virtualmedia(self, resource_type='Manager'):
|
||||
ret = True
|
||||
entries = []
|
||||
|
||||
# Given resource_type, use the proper URI
|
||||
if resource_type == 'Systems':
|
||||
resource_uris = self.systems_uris
|
||||
elif resource_type == 'Manager':
|
||||
resource_uris = self.manager_uris
|
||||
|
||||
for resource_uri in resource_uris:
|
||||
|
@ -2178,7 +2192,7 @@ class RedfishUtils(object):
|
|||
|
||||
@staticmethod
|
||||
def _find_empty_virt_media_slot(resources, media_types,
|
||||
media_match_strict=True):
|
||||
media_match_strict=True, vendor=''):
|
||||
for uri, data in resources.items():
|
||||
# check MediaTypes
|
||||
if 'MediaTypes' in data and media_types:
|
||||
|
@ -2187,8 +2201,12 @@ class RedfishUtils(object):
|
|||
else:
|
||||
if media_match_strict:
|
||||
continue
|
||||
# if ejected, 'Inserted' should be False
|
||||
if (not data.get('Inserted', False)):
|
||||
# Base on current Lenovo server capability, filter out slot RDOC1/2 and Remote1/2/3/4 which are not supported to Insert/Eject.
|
||||
if vendor == 'Lenovo' and ('RDOC' in uri or 'Remote' in uri):
|
||||
continue
|
||||
# if ejected, 'Inserted' should be False and 'ImageName' cleared
|
||||
if (not data.get('Inserted', False) and
|
||||
not data.get('ImageName')):
|
||||
return uri, data
|
||||
return None, None
|
||||
|
||||
|
@ -2262,7 +2280,7 @@ class RedfishUtils(object):
|
|||
return response
|
||||
return {'ret': True, 'changed': True, 'msg': "VirtualMedia inserted"}
|
||||
|
||||
def virtual_media_insert(self, options):
|
||||
def virtual_media_insert(self, options, resource_type='Manager'):
|
||||
param_map = {
|
||||
'Inserted': 'inserted',
|
||||
'WriteProtected': 'write_protected',
|
||||
|
@ -2279,7 +2297,12 @@ class RedfishUtils(object):
|
|||
media_types = options.get('media_types')
|
||||
|
||||
# locate and read the VirtualMedia resources
|
||||
response = self.get_request(self.root_uri + self.manager_uri)
|
||||
# Given resource_type, use the proper URI
|
||||
if resource_type == 'Systems':
|
||||
resource_uri = self.systems_uri
|
||||
elif resource_type == 'Manager':
|
||||
resource_uri = self.manager_uri
|
||||
response = self.get_request(self.root_uri + resource_uri)
|
||||
if response['ret'] is False:
|
||||
return response
|
||||
data = response['data']
|
||||
|
@ -2288,7 +2311,7 @@ class RedfishUtils(object):
|
|||
|
||||
# Some hardware (such as iLO 4) only supports the Image property on the PATCH operation
|
||||
# Inserted and WriteProtected are not writable
|
||||
if data["FirmwareVersion"].startswith("iLO 4"):
|
||||
if "FirmwareVersion" in data and data["FirmwareVersion"].startswith("iLO 4"):
|
||||
image_only = True
|
||||
|
||||
# Supermicro does also not support Inserted and WriteProtected
|
||||
|
@ -2315,12 +2338,13 @@ class RedfishUtils(object):
|
|||
|
||||
# find an empty slot to insert the media
|
||||
# try first with strict media_type matching
|
||||
vendor = self._get_vendor()['Vendor']
|
||||
uri, data = self._find_empty_virt_media_slot(
|
||||
resources, media_types, media_match_strict=True)
|
||||
resources, media_types, media_match_strict=True, vendor=vendor)
|
||||
if not uri:
|
||||
# if not found, try without strict media_type matching
|
||||
uri, data = self._find_empty_virt_media_slot(
|
||||
resources, media_types, media_match_strict=False)
|
||||
resources, media_types, media_match_strict=False, vendor=vendor)
|
||||
if not uri:
|
||||
return {'ret': False,
|
||||
'msg': "Unable to find an available VirtualMedia resource "
|
||||
|
@ -2378,14 +2402,19 @@ class RedfishUtils(object):
|
|||
return {'ret': True, 'changed': True,
|
||||
'msg': "VirtualMedia ejected"}
|
||||
|
||||
def virtual_media_eject(self, options):
|
||||
def virtual_media_eject(self, options, resource_type='Manager'):
|
||||
image_url = options.get('image_url')
|
||||
if not image_url:
|
||||
return {'ret': False,
|
||||
'msg': "image_url option required for VirtualMediaEject"}
|
||||
|
||||
# locate and read the VirtualMedia resources
|
||||
response = self.get_request(self.root_uri + self.manager_uri)
|
||||
# Given resource_type, use the proper URI
|
||||
if resource_type == 'Systems':
|
||||
resource_uri = self.systems_uri
|
||||
elif resource_type == 'Manager':
|
||||
resource_uri = self.manager_uri
|
||||
response = self.get_request(self.root_uri + resource_uri)
|
||||
if response['ret'] is False:
|
||||
return response
|
||||
data = response['data']
|
||||
|
@ -2395,7 +2424,7 @@ class RedfishUtils(object):
|
|||
# Some hardware (such as iLO 4) only supports the Image property on the PATCH operation
|
||||
# Inserted is not writable
|
||||
image_only = False
|
||||
if data["FirmwareVersion"].startswith("iLO 4"):
|
||||
if "FirmwareVersion" in data and data["FirmwareVersion"].startswith("iLO 4"):
|
||||
image_only = True
|
||||
|
||||
if 'Supermicro' in data['Oem']:
|
||||
|
|
|
@ -505,6 +505,20 @@ EXAMPLES = '''
|
|||
username: operator
|
||||
password: supersecretpwd
|
||||
|
||||
- name: Insert Virtual Media
|
||||
community.general.redfish_command:
|
||||
category: Systems
|
||||
command: VirtualMediaInsert
|
||||
baseuri: "{{ baseuri }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
virtual_media:
|
||||
image_url: 'http://example.com/images/SomeLinux-current.iso'
|
||||
media_types:
|
||||
- CD
|
||||
- DVD
|
||||
resource_id: 1
|
||||
|
||||
- name: Insert Virtual Media
|
||||
community.general.redfish_command:
|
||||
category: Manager
|
||||
|
@ -519,6 +533,17 @@ EXAMPLES = '''
|
|||
- DVD
|
||||
resource_id: BMC
|
||||
|
||||
- name: Eject Virtual Media
|
||||
community.general.redfish_command:
|
||||
category: Systems
|
||||
command: VirtualMediaEject
|
||||
baseuri: "{{ baseuri }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
virtual_media:
|
||||
image_url: 'http://example.com/images/SomeLinux-current.iso'
|
||||
resource_id: 1
|
||||
|
||||
- name: Eject Virtual Media
|
||||
community.general.redfish_command:
|
||||
category: Manager
|
||||
|
@ -593,7 +618,7 @@ from ansible.module_utils.common.text.converters import to_native
|
|||
CATEGORY_COMMANDS_ALL = {
|
||||
"Systems": ["PowerOn", "PowerForceOff", "PowerForceRestart", "PowerGracefulRestart",
|
||||
"PowerGracefulShutdown", "PowerReboot", "SetOneTimeBoot", "EnableContinuousBootOverride", "DisableBootOverride",
|
||||
"IndicatorLedOn", "IndicatorLedOff", "IndicatorLedBlink"],
|
||||
"IndicatorLedOn", "IndicatorLedOff", "IndicatorLedBlink", "VirtualMediaInsert", "VirtualMediaEject"],
|
||||
"Chassis": ["IndicatorLedOn", "IndicatorLedOff", "IndicatorLedBlink"],
|
||||
"Accounts": ["AddUser", "EnableUser", "DeleteUser", "DisableUser",
|
||||
"UpdateUserRole", "UpdateUserPassword", "UpdateUserName",
|
||||
|
@ -766,6 +791,10 @@ def main():
|
|||
result = rf_utils.set_boot_override(boot_opts)
|
||||
elif command.startswith('IndicatorLed'):
|
||||
result = rf_utils.manage_system_indicator_led(command)
|
||||
elif command == 'VirtualMediaInsert':
|
||||
result = rf_utils.virtual_media_insert(virtual_media, category)
|
||||
elif command == 'VirtualMediaEject':
|
||||
result = rf_utils.virtual_media_eject(virtual_media, category)
|
||||
|
||||
elif category == "Chassis":
|
||||
result = rf_utils._find_chassis_resource()
|
||||
|
@ -814,9 +843,9 @@ def main():
|
|||
elif command == 'ClearLogs':
|
||||
result = rf_utils.clear_logs()
|
||||
elif command == 'VirtualMediaInsert':
|
||||
result = rf_utils.virtual_media_insert(virtual_media)
|
||||
result = rf_utils.virtual_media_insert(virtual_media, category)
|
||||
elif command == 'VirtualMediaEject':
|
||||
result = rf_utils.virtual_media_eject(virtual_media)
|
||||
result = rf_utils.virtual_media_eject(virtual_media, category)
|
||||
|
||||
elif category == "Update":
|
||||
# execute only if we find UpdateService resources
|
||||
|
|
|
@ -118,6 +118,19 @@ EXAMPLES = '''
|
|||
ansible.builtin.debug:
|
||||
msg: "{{ result.redfish_facts.virtual_media.entries | to_nice_json }}"
|
||||
|
||||
- name: Get Virtual Media information from Systems
|
||||
community.general.redfish_info:
|
||||
category: Systems
|
||||
command: GetVirtualMedia
|
||||
baseuri: "{{ baseuri }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
register: result
|
||||
|
||||
- name: Print fetched information
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ result.redfish_facts.virtual_media.entries | to_nice_json }}"
|
||||
|
||||
- name: Get Volume Inventory
|
||||
community.general.redfish_info:
|
||||
category: Systems
|
||||
|
@ -303,7 +316,7 @@ CATEGORY_COMMANDS_ALL = {
|
|||
"Systems": ["GetSystemInventory", "GetPsuInventory", "GetCpuInventory",
|
||||
"GetMemoryInventory", "GetNicInventory", "GetHealthReport",
|
||||
"GetStorageControllerInventory", "GetDiskInventory", "GetVolumeInventory",
|
||||
"GetBiosAttributes", "GetBootOrder", "GetBootOverride"],
|
||||
"GetBiosAttributes", "GetBootOrder", "GetBootOverride", "GetVirtualMedia"],
|
||||
"Chassis": ["GetFanInventory", "GetPsuInventory", "GetChassisPower",
|
||||
"GetChassisThermals", "GetChassisInventory", "GetHealthReport"],
|
||||
"Accounts": ["ListUsers"],
|
||||
|
@ -420,6 +433,8 @@ def main():
|
|||
result["boot_override"] = rf_utils.get_multi_boot_override()
|
||||
elif command == "GetHealthReport":
|
||||
result["health_report"] = rf_utils.get_multi_system_health_report()
|
||||
elif command == "GetVirtualMedia":
|
||||
result["virtual_media"] = rf_utils.get_multi_virtualmedia(category)
|
||||
|
||||
elif category == "Chassis":
|
||||
# execute only if we find Chassis resource
|
||||
|
@ -485,7 +500,7 @@ def main():
|
|||
if command == "GetManagerNicInventory":
|
||||
result["manager_nics"] = rf_utils.get_multi_nic_inventory(category)
|
||||
elif command == "GetVirtualMedia":
|
||||
result["virtual_media"] = rf_utils.get_multi_virtualmedia()
|
||||
result["virtual_media"] = rf_utils.get_multi_virtualmedia(category)
|
||||
elif command == "GetLogs":
|
||||
result["log"] = rf_utils.get_logs()
|
||||
elif command == "GetNetworkProtocols":
|
||||
|
|
Loading…
Reference in a new issue