def _add_boot_device(handle, parent_mo_or_dn, boot_device): """ This method verifies and adds the boot device in the boot order Used by boot_order_precision_set and boot_order_policy_set Args: handle(ImcHandle) boot_device(dict): This is a dictionary of the format {"order":'1', "device-type":"vmedia", "name": "vmedia"} Returns: None """ from imcsdk.imccoreutils import is_platform_m4 log.debug("######### %s" % boot_device) device = _get_device(parent_mo_or_dn, boot_device["device-type"], boot_device["name"]) if device is None: raise ValueError("Unsupported boot-device %s with label %s" % (boot_device["device-type"], boot_device["name"])) device.order = boot_device["order"] device_props = { key: str(value) for key, value in boot_device.items() if key not in ["order", "device-type", "name"] } # For M4, mac_address will not be sent if boot_device['device-type'] == 'pxe' and is_platform_m4(handle): device_props.pop("mac_address", None) if boot_device['device-type'] == 'pxe': device_props.pop("interface_source", None) # If slot == "", do not send it in xml request if boot_device['device-type'] in ['hdd', 'pxe', 'san', 'iscsi']: slot = device_props.get("slot") if slot is None or slot == "": device_props.pop("slot", None) # If subtype == "", do not send it in xml request if boot_device['device-type'] in ['vmedia', 'sdcard', 'usb']: subtype = device_props.get("subtype") if subtype is None or subtype == "": device_props.pop("subtype", None) device.set_prop_multiple(**device_props) if hasattr(device, "state"): device.state = boot_device['state'] # applies for legacy boot order only if type(parent_mo_or_dn) is str: handle.add_mo(device, modify_present=True)
def _get_platform(handle): from imcsdk import imccoreutils as ic if ic.is_platform_m4(handle): return "M4" elif ic.is_platform_m5(handle): return "M5" else: raise ImcOperationError( "_get_platform", "Invalid CIMC Platform '%s'" % handle.model)
def boot_order_precision_set(handle, reboot_on_update="no", reapply="no", configured_boot_mode="Legacy", secure_boot="no", boot_devices=[], server_id=1): """ This method will replace the existing boot order precision with the new one and also set the boot mode This functionality is available only in release EP and above Args: handle (ImcHandle) reboot_on_update (string): "yes", "no" reapply(string): "yes", "no" configured_boot_mode(string): "Legacy", "Uefi", "None" boot_devices (list of dict): format [{"order":'1', "device-type":"vmedia", "name":"vmedia"}, {"order":'2', "device-type":"hdd", "name":"hdd"}] boot-order(string): Order boot-device-type(string): "hdd", "iscsi", "pchstorage", "pxe", "san", "sdcard", "uefishell", "usb", "vmedia" boot-device-name(string): Unique label for the boot device server_id (int): Id of the server to perform this operation on C3260 platforms Returns: LsBootDevPrecision object Examples: boot_order_precision_set( handle, reboot_on_update="no", reapply="no", configured_boot_mode="Uefi", boot_devices = [{"order":'1', "device-type":"vmedia", "name":"vmedia"}, {"order":'2', "device-type":"hdd", "name":"hdd"}] """ from imcsdk.mometa.lsboot.LsbootDef import LsbootDef from imcsdk.mometa.lsboot.LsbootBootSecurity import LsbootBootSecurity from imcsdk.imccoreutils import is_platform_m4 boot_devices = sanitize_input_from_intersight(handle, boot_devices) # Insert version check here to gracefully handle older versions of CIMC # IMC expects the devices to be configured in sorted order boot_devices = sorted(boot_devices, key=lambda x: int(x["order"])) # filter pxe device # enable pxe boot on respective interface # derive logical port pxe.disable_pxeboot_vnics_all(handle) pxe.prepare_pxe_devices(handle, boot_devices) server_dn = imccoreutils.get_server_dn(handle, server_id) # secure boot is a part of LsBootDef boot_policy = LsbootDef(parent_mo_or_dn=server_dn) secure_boot_mo = LsbootBootSecurity(parent_mo_or_dn=boot_policy.dn) if secure_boot == "yes": secure_boot_mo.secure_boot = "enabled" else: secure_boot_mo.secure_boot = "disabled" handle.set_mo(secure_boot_mo) lsbootdev = LsbootDevPrecision(parent_mo_or_dn=server_dn) # clean existing configuration # Need to check if doing this everytime will have any adverse impact boot_order_child_mos = handle.query_children(in_dn=lsbootdev.dn) #check the version as CSCvh47929 fix is applied to later versions for mo in boot_order_child_mos: if str(handle.version) < "3.1(3a)" and mo.get_class_id( ) == "LsbootCdd": # Deletion of LsbootCdd is not supported using XML API for older versions # although CSCvh47929 is fixed # Existing Cdd device will automatically move down the # order when configuring other devices with CDD device's order continue handle.remove_mo(mo) # set the boot order precision related properties and devices lsbootdev.reboot_on_update = reboot_on_update lsbootdev.reapply = reapply if secure_boot == "no": lsbootdev.configured_boot_mode = configured_boot_mode i = 0 #check the version and skip if the device is of type localcdd for device in boot_devices: if device["device-type"] == "cdd" and ( is_platform_m4(handle) or str(handle.version) < "3.1(3a)"): i = i + 1 continue if device['device-type'] == 'pxe' and is_platform_m4( handle) and device['interface_source'] == 'mac': i = i + 1 continue #if the list has cdd, reorder the policy types that are after cdd as cdd will be skipped #and CIMC expects the devices in sorted order. if i != 0: device["order"] = str(int(device["order"]) - i) _add_boot_device(handle, lsbootdev, device) handle.set_mo(lsbootdev) return lsbootdev
def bios_tokens_set(handle, tokens={}, server_id=1): """ Args: handle (ImcHandle) tokens (dictionary) : (key, value) pair of bios tokens with key being the name of the token server_id (int): Id of the server to perform this operation on C3260 platforms. Returns: Dictionary with a failure message, if any. Examples: bios_tokens_set(handle, tokens = { "baudRate": "19200", "intelVtdatsSupport": "enabled", "consoleRedirection": "com-1", "flowControl": "rts-cts", "sataModeSelect": "platform-default", "txtSupport": "platform-default", "packageCstateLimit": "C0 C1 State"}, server_id=2) """ from imcsdk.imccoreutils import load_class, sanitize_xml_parsing_error from imcsdk.mometa.bios.BiosSettings import BiosSettings from imcsdk.imccoremeta import ImcVersion messages = [] ret = {} bios_mo = BiosSettings(parent_mo_or_dn=_get_bios_dn(handle, server_id)) mo_table = _get_bios_mo_table(handle, tokens, server_id) server_mos = _get_server_bios_mo_table(handle, dn=bios_mo.dn) # Prepare the filtered table i.e. send only those MOs that exist on the server table = {k: v for k, v in mo_table.items() if k in server_mos} log.debug("Mo Table Count: %s Values: %s" % (len(mo_table), mo_table)) log.debug("Server Table Count: %s Values: %s" % (len(server_mos), server_mos)) log.debug("Filtered Table Count: %s Values: %s" % (len(table), table)) processed_tokens = [] # Separate the MOs which have only platform-default for mo_name, props in table.items(): non_default_props = { k: v for k, v in props.items() if v != "platform-default" } # if there are no non-default props, it can be batched if len(non_default_props) == 0: # filter properties to only those applicable to the server server_mo_props = server_mos[mo_name] filtered_props = { k: v for k, v in props.items() if k in server_mo_props and server_mo_props[k] } if len(filtered_props) == 0: log.debug("skipping token %s props: %s server_mo_props %s " % (mo_name, props, server_mo_props)) processed_tokens.append(mo_name) continue # load an instance of the class mo_class = load_class(mo_name) filtered_props["_handle"] = handle mo_obj = mo_class(parent_mo_or_dn=bios_mo, **filtered_props) # HACK for CIMC ISSUE. 'rn' is different for M4 and M5 # rn for M5 for this token has been corrected in GP-MR2 if mo_name == "BiosVfSataModeSelect" and \ is_platform_m5(handle) and \ handle.version < ImcVersion("3.1(3a)"): mo_obj.rn = "SataModeSelect" mo_obj.dn = bios_mo.dn + "/" + mo_obj.rn # In HP release, for Janus platform, vp_cbs_cmn_cpu_gen_downcore_ctrl token # does not have a platform default value supported on the endpoint if mo_name == "BiosVfCbsCmnCpuGenDowncoreCtrl" and \ mo_obj.vp_cbs_cmn_cpu_gen_downcore_ctrl == "platform-default" and \ handle.version == ImcVersion("4.0(1a)"): mo_obj.vp_cbs_cmn_cpu_gen_downcore_ctrl = "Auto" # pop the object from the table dictionary processed_tokens.append(mo_name) for each in processed_tokens: table.pop(each) log.debug("Modified Tokens Count: %s Values: %s" % (len(table), table)) # Send all the MOs with default properties in one shot handle.set_mo(bios_mo) # Send the rest of the MOs for mo_name, props in table.items(): d = {} server_mo_props = server_mos[mo_name] filtered_props = { k: v for k, v in props.items() if k in server_mo_props and server_mo_props[k] } # REALLY DIRTY HACK!! # C6 Non Retention - Works on M5, fails on M4 # C6 non Retention - Works on M4, fails on M5 if mo_name == "BiosVfPackageCStateLimit" and is_platform_m4( handle) and "vp_package_c_state_limit" in filtered_props: if filtered_props[ "vp_package_c_state_limit"] == "C6 Non Retention": filtered_props["vp_package_c_state_limit"] = "C6 non Retention" if len(filtered_props) != 0: mo_class = load_class(mo_name) filtered_props["_handle"] = handle try: mo_obj = mo_class(parent_mo_or_dn=bios_mo.dn, **filtered_props) # HACK for CIMC ISSUE. 'rn' is different for M4 and M5 # rn for M5 for this token has been corrected in GP-MR2 if mo_name == "BiosVfSataModeSelect" and \ is_platform_m5(handle) and \ handle.version < ImcVersion("3.1(3a)"): mo_obj.rn = "SataModeSelect" mo_obj.dn = bios_mo.dn + "/" + mo_obj.rn # HP and below only "Disabled" was supported for this token # In HP, "disabled" was also supported and hence need to send the older # version of this value for an older server if mo_name == "BiosVfCDNSupport" and \ mo_obj.vp_cdn_support == "disabled" and \ handle.version < ImcVersion("4.0(1a)"): mo_obj.vp_cdn_support = "Disabled" handle.set_mo(mo_obj) except ImcException as e: d["Object"] = mo_name error = e.error_descr if e.error_code == "ERR-xml-parse-error": error = sanitize_xml_parsing_error(e.error_descr) d["Error"] = error messages.append(d) continue except Exception as e: d["Object"] = mo_name d["Error"] = str(e) messages.append(d) continue message = "" if len(messages) != 0: message = "Following issues were seen during application of BIOS " \ "tokens: \n" for m in messages: message += m["Object"] + ": " + m["Error"] + "\n" ret["msg"] = message ret["msg_params"] = messages ret["changed"] = True return ret
def _remove_pxe_with_mac_for_m4(handle, pxe_devices): from imcsdk.imccoreutils import is_platform_m4 if not is_platform_m4(handle): return pxe_devices return [device for device in pxe_devices if device['interface_source'] != 'mac']