mirror of
				https://opendev.org/x/pyghmi
				synced 2025-10-31 19:32:25 +00:00 
			
		
		
		
	Add iDrac virtual cd/floppy
iDRAC does not support standard redfish boot devices, provide oem override in such case to use the OEM interface. Change-Id: I53d7bb1d82035e621802c20f46000760cc8631a8
This commit is contained in:
		| @@ -51,22 +51,6 @@ powerstates = { | ||||
|     'boot': None, | ||||
| } | ||||
|  | ||||
| boot_devices_write = { | ||||
|     'net': 'Pxe', | ||||
|     'network': 'Pxe', | ||||
|     'pxe': 'Pxe', | ||||
|     'hd': 'Hdd', | ||||
|     'usb': 'Usb', | ||||
|     'cd': 'Cd', | ||||
|     'cdrom': 'Cd', | ||||
|     'optical': 'Cd', | ||||
|     'dvd': 'Cd', | ||||
|     'floppy': 'Floppy', | ||||
|     'default': 'None', | ||||
|     'setup': 'BiosSetup', | ||||
|     'bios': 'BiosSetup', | ||||
|     'f1': 'BiosSetup', | ||||
| } | ||||
|  | ||||
| boot_devices_read = { | ||||
|     'BiosSetup': 'setup', | ||||
| @@ -684,31 +668,7 @@ class Command(object): | ||||
|         :raises: PyghmiException on an error. | ||||
|         :returns: dict or True -- If callback is not provided, the response | ||||
|         """ | ||||
|         reqbootdev = bootdev | ||||
|         if (bootdev not in boot_devices_write | ||||
|                 and bootdev not in boot_devices_read): | ||||
|             raise exc.InvalidParameterValue('Unsupported device %s' | ||||
|                                             % repr(bootdev)) | ||||
|         bootdev = boot_devices_write.get(bootdev, bootdev) | ||||
|         if bootdev == 'None': | ||||
|             payload = {'Boot': {'BootSourceOverrideEnabled': 'Disabled'}} | ||||
|         else: | ||||
|             payload = {'Boot': { | ||||
|                 'BootSourceOverrideEnabled': 'Continuous' if persist | ||||
|                                              else 'Once', | ||||
|                 'BootSourceOverrideTarget': bootdev, | ||||
|             }} | ||||
|             if uefiboot is not None: | ||||
|                 uefiboot = 'UEFI' if uefiboot else 'Legacy' | ||||
|                 payload['BootSourceOverrideMode'] = uefiboot | ||||
|                 try: | ||||
|                     self._do_web_request(self.sysurl, payload, method='PATCH') | ||||
|                     return {'bootdev': reqbootdev} | ||||
|                 except Exception: | ||||
|                     del payload['BootSourceOverrideMode'] | ||||
|         thetag = self.sysinfo.get('@odata.etag', None) | ||||
|         self._do_web_request(self.sysurl, payload, method='PATCH', etag=thetag) | ||||
|         return {'bootdev': reqbootdev} | ||||
|         return self.oem.set_bootdev(bootdev, persist, uefiboot, self) | ||||
|  | ||||
|     @property | ||||
|     def _biosurl(self): | ||||
|   | ||||
							
								
								
									
										0
									
								
								pyghmi/redfish/oem/dell/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								pyghmi/redfish/oem/dell/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										47
									
								
								pyghmi/redfish/oem/dell/idrac.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								pyghmi/redfish/oem/dell/idrac.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| # Copyright 2022 Lenovo Corporation | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| import pyghmi.redfish.oem.generic as generic | ||||
|  | ||||
|  | ||||
| class OEMHandler(generic.OEMHandler): | ||||
|  | ||||
|     def __init__(self, sysinfo, sysurl, webclient, cache, gpool=None): | ||||
|         super(OEMHandler, self).__init__(sysinfo, sysurl, webclient, cache, | ||||
|                                          gpool) | ||||
|  | ||||
|     def set_bootdev(self, bootdev, persist=False, uefiboot=None, | ||||
|                     fishclient=None): | ||||
|         # gleaned from web console, under configuration, system settings, | ||||
|         # hardware, first boot device. iDrac presumes that the standard | ||||
|         # explicitly refers only to physical devices. I think the intent | ||||
|         # is the exact opposite for 'removable' media, and thus redirect | ||||
|         # the 'physical' standard to the vFDD/VCD-DVD seen in the idrac | ||||
|         # web gui | ||||
|         if bootdev not in ('floppy', 'cd'): | ||||
|             return super(OEMHandler, self).set_bootdev(bootdev, persist, | ||||
|                                                        uefiboot, fishclient) | ||||
|         payload = {'Attributes': {}} | ||||
|         if persist: | ||||
|             payload['Attributes']['ServerBoot.1.BootOnce'] = 'Disabled' | ||||
|         else: | ||||
|             payload['Attributes']['ServerBoot.1.BootOnce'] = 'Enabled' | ||||
|         if bootdev == 'floppy': | ||||
|             payload['Attributes']['ServerBoot.1.FirstBootDevice'] = 'vFDD' | ||||
|         elif bootdev == 'cd': | ||||
|             payload['Attributes']['ServerBoot.1.FirstBootDevice'] = 'VCD-DVD' | ||||
|         fishclient._do_web_request( | ||||
|             '/redfish/v1/Managers/iDRAC.Embedded.1/Attributes', | ||||
|             payload, method='PATCH') | ||||
|         return {'bootdev': bootdev} | ||||
							
								
								
									
										20
									
								
								pyghmi/redfish/oem/dell/main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								pyghmi/redfish/oem/dell/main.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| # Copyright 2022 Lenovo Corporation | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| from pyghmi.redfish.oem.dell import idrac | ||||
|  | ||||
|  | ||||
| def get_handler(sysinfo, sysurl, webclient, cache, cmd): | ||||
|     return idrac.OEMHandler(sysinfo, sysurl, webclient, cache, | ||||
|                             gpool=cmd._gpool) | ||||
| @@ -1,4 +1,4 @@ | ||||
| # Copyright 2019 Lenovo Corporation | ||||
| # Copyright 2019-2022 Lenovo Corporation | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| @@ -18,6 +18,34 @@ import os | ||||
| import pyghmi.exceptions as exc | ||||
| import pyghmi.media as media | ||||
|  | ||||
| boot_devices_write = { | ||||
|     'net': 'Pxe', | ||||
|     'network': 'Pxe', | ||||
|     'pxe': 'Pxe', | ||||
|     'hd': 'Hdd', | ||||
|     'usb': 'Usb', | ||||
|     'cd': 'Cd', | ||||
|     'cdrom': 'Cd', | ||||
|     'optical': 'Cd', | ||||
|     'dvd': 'Cd', | ||||
|     'floppy': 'Floppy', | ||||
|     'default': 'None', | ||||
|     'setup': 'BiosSetup', | ||||
|     'bios': 'BiosSetup', | ||||
|     'f1': 'BiosSetup', | ||||
| } | ||||
|  | ||||
| boot_devices_read = { | ||||
|     'BiosSetup': 'setup', | ||||
|     'Cd': 'optical', | ||||
|     'Floppy': 'floppy', | ||||
|     'Hdd': 'hd', | ||||
|     'None': 'default', | ||||
|     'Pxe': 'network', | ||||
|     'Usb': 'usb', | ||||
|     'SDCard': 'sdcard', | ||||
| } | ||||
|  | ||||
|  | ||||
| class OEMHandler(object): | ||||
|     hostnic = None | ||||
| @@ -29,6 +57,54 @@ class OEMHandler(object): | ||||
|         self._urlcache = cache | ||||
|         self.webclient = webclient | ||||
|  | ||||
|     def set_bootdev(self, bootdev, persist=False, uefiboot=None, | ||||
|                     fishclient=None): | ||||
|         """Set boot device to use on next reboot | ||||
|  | ||||
|         :param bootdev: | ||||
|                         *network -- Request network boot | ||||
|                         *hd -- Boot from hard drive | ||||
|                         *safe -- Boot from hard drive, requesting 'safe mode' | ||||
|                         *optical -- boot from CD/DVD/BD drive | ||||
|                         *setup -- Boot into setup utility | ||||
|                         *default -- remove any directed boot device request | ||||
|         :param persist: If true, ask that system firmware use this device | ||||
|                         beyond next boot.  Be aware many systems do not honor | ||||
|                         this | ||||
|         :param uefiboot: If true, request UEFI boot explicitly.  If False, | ||||
|                          request BIOS style boot. | ||||
|                          None (default) does not modify the boot mode. | ||||
|         :raises: PyghmiException on an error. | ||||
|         :returns: dict or True -- If callback is not provided, the response | ||||
|         """ | ||||
|         reqbootdev = bootdev | ||||
|         if (bootdev not in boot_devices_write | ||||
|                 and bootdev not in boot_devices_read): | ||||
|             raise exc.InvalidParameterValue('Unsupported device %s' | ||||
|                                             % repr(bootdev)) | ||||
|         bootdev = boot_devices_write.get(bootdev, bootdev) | ||||
|         if bootdev == 'None': | ||||
|             payload = {'Boot': {'BootSourceOverrideEnabled': 'Disabled'}} | ||||
|         else: | ||||
|             payload = {'Boot': { | ||||
|                 'BootSourceOverrideEnabled': 'Continuous' if persist | ||||
|                                              else 'Once', | ||||
|                 'BootSourceOverrideTarget': bootdev, | ||||
|             }} | ||||
|             if uefiboot is not None: | ||||
|                 uefiboot = 'UEFI' if uefiboot else 'Legacy' | ||||
|                 payload['BootSourceOverrideMode'] = uefiboot | ||||
|                 try: | ||||
|                     fishclient._do_web_request(self.sysurl, payload, | ||||
|                                                method='PATCH') | ||||
|                     return {'bootdev': reqbootdev} | ||||
|                 except Exception: | ||||
|                     del payload['BootSourceOverrideMode'] | ||||
|         thetag = fishclient.sysinfo.get('@odata.etag', None) | ||||
|         fishclient._do_web_request(fishclient.sysurl, payload, method='PATCH', | ||||
|                                    etag=thetag) | ||||
|         return {'bootdev': reqbootdev} | ||||
|  | ||||
|     def _get_cache(self, url): | ||||
|         now = os.times()[4] | ||||
|         cachent = self._urlcache.get(url, None) | ||||
|   | ||||
| @@ -12,11 +12,13 @@ | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
|  | ||||
| import pyghmi.redfish.oem.dell.main as dell | ||||
| import pyghmi.redfish.oem.generic as generic | ||||
| import pyghmi.redfish.oem.lenovo.main as lenovo | ||||
|  | ||||
| OEMMAP = { | ||||
|     'Lenovo': lenovo, | ||||
|     'Dell': dell, | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -26,6 +26,6 @@ setuptools.setup( | ||||
|     packages=['pyghmi', 'pyghmi.util', 'pyghmi.ipmi', 'pyghmi.cmd', | ||||
|               'pyghmi.redfish', 'pyghmi.ipmi.private', 'pyghmi.ipmi.oem', | ||||
|               'pyghmi.ipmi.oem.lenovo', 'pyghmi.redfish.oem', | ||||
|               'pyghmi.redfish.oem.lenovo'], | ||||
|               'pyghmi.redfish.oem.dell', 'pyghmi.redfish.oem.lenovo'], | ||||
|     license='Apache License, Version 2.0') | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user