Ejemplo n.º 1
0
def main():
    parser = argparse.ArgumentParser(
        description="Queries an iDRAC to determine if it is ready to process "
        "commands.",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    ArgHelper.add_ip_service_tag(parser)
    ArgHelper.add_instack_arg(parser)
    LoggingHelper.add_argument(parser)

    args = parser.parse_args()

    LoggingHelper.configure_logging(args.logging_level)

    ip_service_tag = args.ip_service_tag
    node_definition = args.node_definition

    return_code = 0

    try:
        node = CredentialHelper.get_node_from_instack(ip_service_tag,
                                                      node_definition)
        if not node:
            raise ValueError("Unable to find {} in {}".format(
                ip_service_tag, node_definition))
        drac_ip = node["pm_addr"]
        drac_user = node["pm_user"]
        drac_password = node["pm_password"]

        drac_client = DRACClient(drac_ip, drac_user, drac_password)

        ready = drac_client.is_idrac_ready()

        if ready:
            LOG.info("iDRAC is ready")
        else:
            return_code = 1
            LOG.info("iDRAC is NOT ready")
    except:  # noqa: E501
        LOG.exception("An exception occurred:")
        return_code = 2

    sys.exit(return_code)
Ejemplo n.º 2
0
def config_idrac(instack_lock,
                 ip_service_tag,
                 node_definition=Constants.INSTACKENV_FILENAME,
                 model_properties=Utils.get_model_properties(
                     Constants.MODEL_PROPERTIES_FILENAME),
                 pxe_nic=None,
                 password=None,
                 skip_nic_config=False):
    node = CredentialHelper.get_node_from_instack(ip_service_tag,
                                                  node_definition)
    if not node:
        raise ValueError("Unable to find {} in {}".format(
            ip_service_tag, node_definition))
    drac_ip = node["pm_addr"]
    drac_user = node["pm_user"]
    drac_password = node["pm_password"]
    ironic_driver = node["pm_type"]

    if ironic_driver != "idrac":
        LOG.info("{} is using the {} driver.  No iDRAC configuration is "
                 "possible.".format(ip_service_tag, ironic_driver))

        if pxe_nic:
            LOG.warning("Ignoring specified PXE NIC ({})".format(pxe_nic))

        if password:
            LOG.warning("Ignoring specified password")

        return

    drac_client = DRACClient(drac_ip, drac_user, drac_password)

    reset_idrac(drac_client, ip_service_tag)

    # Clear out any pending jobs in the job queue and fix the condition where
    # there are no pending jobs, but the iDRAC thinks there are
    clear_job_queue(drac_client, ip_service_tag)
    if skip_nic_config:
        target_boot_mode = BootModeHelper.get_boot_mode(drac_client)
    elif BootModeHelper.is_boot_order_flexibly_programmable(drac_client):
        target_boot_mode = boot_mode_helper.DRAC_BOOT_MODE_UEFI
    else:
        target_boot_mode = boot_mode_helper.DRAC_BOOT_MODE_BIOS
    config_boot_mode(drac_client, ip_service_tag, node, target_boot_mode)

    job_ids = list()
    reboot_required = False

    pxe_nic_fqdd = get_pxe_nic_fqdd(pxe_nic, model_properties, drac_client)

    if skip_nic_config:
        provisioning_mac = get_nic_mac_address(drac_client, pxe_nic_fqdd)
        LOG.info("Skipping NIC configuration")
    else:
        # Configure the NIC port to PXE boot or not
        reboot_required_nic, nic_job_ids, provisioning_mac = \
            configure_nics_boot_settings(drac_client,
                                         ip_service_tag,
                                         pxe_nic_fqdd,
                                         node,
                                         target_boot_mode)

        reboot_required = reboot_required or reboot_required_nic
        if nic_job_ids:
            job_ids.extend(nic_job_ids)

    # Do initial idrac configuration
    reboot_required_idrac, idrac_job_id = config_idrac_settings(
        drac_client, ip_service_tag, password, node)
    reboot_required = reboot_required or reboot_required_idrac
    if idrac_job_id:
        job_ids.append(idrac_job_id)

    # If we need to reboot, then add a job for it
    if reboot_required:
        LOG.info("Rebooting {} to apply configuration".format(ip_service_tag))

        job_id = drac_client.create_reboot_job()
        job_ids.append(job_id)

    success = True
    if job_ids:
        drac_client.schedule_job_execution(job_ids, start_time='TIME_NOW')

        LOG.info("Waiting for iDRAC configuration to complete on {}".format(
            ip_service_tag))
        LOG.info("Do not unplug {}".format(ip_service_tag))

        # If the user set the password, then we need to change creds
        if password:
            new_drac_client = DRACClient(drac_ip, drac_user, password)

            # Try every 10 seconds over 2 minutes to connect with the new creds
            password_changed = False
            retries = 12
            while not password_changed and retries > 0:
                try:
                    LOG.debug("Attempting to access the iDRAC on {} with the "
                              "new password".format(ip_service_tag))
                    new_drac_client.is_idrac_ready()
                    password_changed = True
                except exceptions.WSManInvalidResponse as ex:
                    if "unauthorized" in str(ex).lower():
                        LOG.debug(
                            "Got an unauthorized exception on {}, so "
                            "sleeping and trying again".format(ip_service_tag))
                        retries -= 1
                        if retries > 0:
                            sleep(10)
                    else:
                        raise

            # If the new creds were successful then use them.  If they were not
            # successful then assume the attempt to change the password failed
            # and stick with the original creds
            if password_changed:
                LOG.debug(
                    "Successfully changed the password on {}.  "
                    "Switching to the new password".format(ip_service_tag))
                drac_client = new_drac_client
            else:
                success = False
                LOG.warning("Failed to change the password on {}".format(
                    ip_service_tag))

        all_jobs_succeeded = wait_for_jobs_to_complete(job_ids, drac_client,
                                                       ip_service_tag)

        if not all_jobs_succeeded:
            success = False

    if success and target_boot_mode == boot_mode_helper.DRAC_BOOT_MODE_BIOS:
        success = config_hard_disk_drive_boot_sequence(drac_client,
                                                       ip_service_tag)

    # We always want to update the password for the node in the instack file
    # if the user requested a password change and the iDRAC config job was
    # successful regardless of if the other jobs succeeded or not.
    new_password = None
    if password:
        job_status = drac_client.get_job(idrac_job_id).status

        if JobHelper.job_succeeded(job_status):
            new_password = password

    if new_password is not None or \
        "provisioning_mac" not in node or \
        ("provisioning_mac" in node
         and node["provisioning_mac"] != provisioning_mac):

        # Synchronize to prevent thread collisions while saving the instack
        # file
        if instack_lock is not None:
            LOG.debug("Acquiring the lock")
            instack_lock.acquire()
        try:
            if instack_lock is not None:
                LOG.debug("Clearing and reloading instack")
                # Force a reload of the instack file
                CredentialHelper.clear_instack_cache()
                node = CredentialHelper.get_node_from_instack(
                    ip_service_tag, node_definition)
            if new_password is not None:
                node["pm_password"] = new_password

            node["provisioning_mac"] = provisioning_mac

            LOG.debug("Saving instack")
            CredentialHelper.save_instack(node_definition)
        finally:
            if instack_lock is not None:
                LOG.debug("Releasing the lock")
                instack_lock.release()

    if success:
        LOG.info("Completed configuration of the iDRAC on {}".format(
            ip_service_tag))
    else:
        raise RuntimeError("An error occurred while configuring the iDRAC "
                           "on {}".format(drac_ip))