231 lines
8.1 KiB
Python
231 lines
8.1 KiB
Python
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
|
#
|
|
# 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 sushy
|
|
from sushy.resources import base
|
|
|
|
from proliantutils import exception
|
|
from proliantutils import log
|
|
from proliantutils.redfish.resources.system import constants as sys_cons
|
|
from proliantutils.redfish.resources.system import iscsi
|
|
from proliantutils.redfish.resources.system import mappings
|
|
from proliantutils.redfish import utils
|
|
|
|
LOG = log.get_logger(__name__)
|
|
|
|
BOOT_SOURCE_TARGET_TO_PARTIAL_STRING_MAP = {
|
|
sushy.BOOT_SOURCE_TARGET_CD: ('HPE Virtual CD-ROM',),
|
|
sushy.BOOT_SOURCE_TARGET_PXE: ('NIC', 'PXE'),
|
|
sushy.BOOT_SOURCE_TARGET_UEFI_TARGET: ('ISCSI',),
|
|
sushy.BOOT_SOURCE_TARGET_HDD: ('Logical Drive', 'HDD', 'Storage', 'LogVol')
|
|
}
|
|
|
|
|
|
class BIOSSettings(base.ResourceBase):
|
|
"""Class that defines the functionality for BIOS Resources."""
|
|
|
|
boot_mode = base.MappedField(["Attributes", "BootMode"],
|
|
mappings.GET_BIOS_BOOT_MODE_MAP)
|
|
|
|
sriov = base.MappedField(['Attributes', 'Sriov'], mappings.SRIOV_MAP)
|
|
|
|
tpm_state = base.MappedField(["Attributes", "TpmState"], mappings.TPM_MAP)
|
|
|
|
cpu_vt = base.MappedField(["Attributes", "ProcVirtualization"],
|
|
mappings.CPUVT_MAP)
|
|
|
|
_iscsi_settings = None
|
|
|
|
_pending_settings = None
|
|
_boot_settings = None
|
|
_base_configs = None
|
|
|
|
@property
|
|
def pending_settings(self):
|
|
"""Property to provide reference to bios_pending_settings instance
|
|
|
|
It is calculated once when the first time it is queried. On refresh,
|
|
this property gets reset.
|
|
"""
|
|
if self._pending_settings is None:
|
|
self._pending_settings = BIOSPendingSettings(
|
|
self._conn,
|
|
utils.get_subresource_path_by(
|
|
self, ["@Redfish.Settings", "SettingsObject"]),
|
|
redfish_version=self.redfish_version)
|
|
|
|
return self._pending_settings
|
|
|
|
@property
|
|
def boot_settings(self):
|
|
"""Property to provide reference to bios boot instance
|
|
|
|
It is calculated once when the first time it is queried. On refresh,
|
|
this property gets reset.
|
|
"""
|
|
if self._boot_settings is None:
|
|
self._boot_settings = BIOSBootSettings(
|
|
self._conn,
|
|
utils.get_subresource_path_by(
|
|
self, ["Oem", "Hpe", "Links", "Boot"]),
|
|
redfish_version=self.redfish_version)
|
|
|
|
return self._boot_settings
|
|
|
|
@property
|
|
def iscsi_settings(self):
|
|
"""Property to provide reference to bios iscsi instance
|
|
|
|
It is calculated once when the first time it is queried. On refresh,
|
|
this property gets reset.
|
|
"""
|
|
if self._iscsi_settings is None:
|
|
self._iscsi_settings = iscsi.ISCSISettings(
|
|
self._conn,
|
|
utils.get_subresource_path_by(
|
|
self, ["Oem", "Hpe", "Links", "iScsi"]),
|
|
redfish_version=self.redfish_version)
|
|
|
|
return self._iscsi_settings
|
|
|
|
def _get_base_configs(self):
|
|
"""Method that returns object of bios base configs."""
|
|
if self._base_configs is None:
|
|
self._base_configs = BIOSBaseConfigs(
|
|
self._conn, utils.get_subresource_path_by(
|
|
self, ["Oem", "Hpe", "Links", "BaseConfigs"]),
|
|
redfish_version=self.redfish_version)
|
|
|
|
return self._base_configs
|
|
|
|
def update_bios_to_default(self):
|
|
"""Updates bios default settings"""
|
|
self.pending_settings.update_bios_data_by_post(
|
|
self._get_base_configs().default_config)
|
|
|
|
def refresh(self):
|
|
super(BIOSSettings, self).refresh()
|
|
self._pending_settings = None
|
|
self._boot_settings = None
|
|
self._base_configs = None
|
|
self._iscsi_settings = None
|
|
|
|
|
|
class BIOSBaseConfigs(base.ResourceBase):
|
|
"""Class that defines the functionality for BIOS base configuration."""
|
|
|
|
default_config = base.Field(
|
|
"BaseConfigs", adapter=lambda base_configs: base_configs[0]['default'])
|
|
|
|
|
|
class BIOSPendingSettings(base.ResourceBase):
|
|
"""Class that defines the functionality for BIOS pending settings."""
|
|
|
|
boot_mode = base.MappedField(["Attributes", "BootMode"],
|
|
mappings.GET_BIOS_BOOT_MODE_MAP)
|
|
|
|
def set_pending_boot_mode(self, boot_mode):
|
|
"""Sets the boot mode of the system for next boot.
|
|
|
|
:param boot_mode: either sys_cons.BIOS_BOOT_MODE_LEGACY_BIOS,
|
|
sys_cons.BIOS_BOOT_MODE_UEFI.
|
|
"""
|
|
bios_properties = {
|
|
'BootMode': mappings.GET_BIOS_BOOT_MODE_MAP_REV.get(boot_mode)
|
|
}
|
|
|
|
if boot_mode == sys_cons.BIOS_BOOT_MODE_UEFI:
|
|
bios_properties['UefiOptimizedBoot'] = 'Enabled'
|
|
|
|
self.update_bios_data_by_patch(bios_properties)
|
|
|
|
def update_bios_data_by_post(self, data):
|
|
"""Update bios data by post
|
|
|
|
:param data: default bios config data
|
|
"""
|
|
bios_settings_data = {
|
|
'Attributes': data
|
|
}
|
|
self._conn.post(self.path, data=bios_settings_data)
|
|
|
|
def update_bios_data_by_patch(self, data):
|
|
"""Update bios data by patch
|
|
|
|
:param data: default bios config data
|
|
"""
|
|
bios_settings_data = {
|
|
'Attributes': data
|
|
}
|
|
self._conn.patch(self.path, data=bios_settings_data)
|
|
|
|
|
|
class BIOSBootSettings(base.ResourceBase):
|
|
|
|
boot_sources = base.Field("BootSources", adapter=list)
|
|
persistent_boot_config_order = base.Field("PersistentBootConfigOrder",
|
|
adapter=list)
|
|
|
|
def get_persistent_boot_device(self):
|
|
"""Get current persistent boot device set for the host
|
|
|
|
:returns: persistent boot device for the system
|
|
:raises: IloError, on an error from iLO.
|
|
"""
|
|
boot_string = None
|
|
if not self.persistent_boot_config_order or not self.boot_sources:
|
|
msg = ('Boot sources or persistent boot config order not found')
|
|
LOG.debug(msg)
|
|
raise exception.IloError(msg)
|
|
|
|
preferred_boot_device = self.persistent_boot_config_order[0]
|
|
for boot_source in self.boot_sources:
|
|
if ((boot_source.get("StructuredBootString") is not None) and (
|
|
preferred_boot_device ==
|
|
boot_source.get("StructuredBootString"))):
|
|
boot_string = boot_source["BootString"]
|
|
break
|
|
else:
|
|
msg = (('Persistent boot device failed, as no matched boot '
|
|
'sources found for device: %(persistent_boot_device)s')
|
|
% {'persistent_boot_device': preferred_boot_device})
|
|
LOG.debug(msg)
|
|
raise exception.IloError(msg)
|
|
|
|
for key, value in BOOT_SOURCE_TARGET_TO_PARTIAL_STRING_MAP.items():
|
|
for val in value:
|
|
if val in boot_string:
|
|
return key
|
|
return sushy.BOOT_SOURCE_TARGET_NONE
|
|
|
|
def get_uefi_boot_string(self, mac):
|
|
"""Get uefi iscsi boot string for the host
|
|
|
|
:returns: iscsi boot string for the system
|
|
:raises: IloError, on an error from iLO.
|
|
"""
|
|
boot_sources = self.boot_sources
|
|
if not boot_sources:
|
|
msg = ('Boot sources are not found')
|
|
LOG.debug(msg)
|
|
raise exception.IloError(msg)
|
|
|
|
for boot_source in boot_sources:
|
|
if (mac.upper() in boot_source['UEFIDevicePath'] and
|
|
'iSCSI' in boot_source['UEFIDevicePath']):
|
|
return boot_source['StructuredBootString']
|
|
else:
|
|
msg = ('MAC provided "%s" is Invalid' % mac)
|
|
raise exception.IloInvalidInputError(msg)
|