예제 #1
0
def reconfigure(_host, _idrac_host):
    logger.debug("Reconfiguring host: %s" % _host)
    interfaces = os.path.dirname(__file__) + "/../../conf/idrac_interfaces.yml"

    if is_supported(_host.name):
        badfish = Badfish(_idrac_host, conf["ipmi_username"], conf["ipmi_password"])

        host_type = "foreman"
        if _host.nullos:
            host_type = "director"

        try:
            badfish.change_boot(host_type, interfaces, True)
        except SystemExit as ex:
            logger.debug(ex)
            logger.error("Something went wrong.")
            return
        _host.update(build=False, realeased=True, last_build=datetime.now())
        return
    else:
        _host.update(build=False, realeased=True, last_build=datetime.now())
        return
예제 #2
0
async def move_and_rebuild(host,
                           new_cloud,
                           semaphore,
                           rebuild=False,
                           loop=None):
    build_start = datetime.now()
    logger.debug("Moving and rebuilding host: %s" % host)

    untouchable_hosts = Config["untouchable_hosts"]
    logger.debug("Untouchable hosts: %s" % untouchable_hosts)
    _host_obj = Host.objects(name=host).first()

    if host in untouchable_hosts:
        logger.error("No way...")
        return False

    _target_cloud = Cloud.objects(name=new_cloud).first()

    ipmi_new_pass = (f"{Config['infra_location']}@{_target_cloud.ticket}"
                     if _target_cloud.ticket else Config["ipmi_password"])

    ipmi_set_pass = [
        "user",
        "set",
        "password",
        str(Config["ipmi_cloud_username_id"]),
        ipmi_new_pass,
    ]

    new_semaphore = asyncio.Semaphore(20)
    await execute_ipmi(host, arguments=ipmi_set_pass, semaphore=new_semaphore)

    ipmi_set_operator = [
        "user", "priv",
        str(Config["ipmi_cloud_username_id"]), "0x4"
    ]
    await execute_ipmi(host,
                       arguments=ipmi_set_operator,
                       semaphore=new_semaphore)

    badfish = None
    if rebuild and _target_cloud.name != _host_obj.default_cloud.name:
        if Config.pdu_management:
            # TODO: pdu management
            pass

        try:
            badfish = await badfish_factory(
                "mgmt-%s" % host,
                Config["ipmi_username"],
                Config["ipmi_password"],
                propagate=True,
            )
        except BadfishException:
            logger.error(
                f"Could not initialize Badfish. Verify ipmi credentials for mgmt-{host}."
            )
            return False

        if is_supported(host):
            try:
                interfaces_path = os.path.join(
                    os.path.dirname(__file__),
                    "../../conf/idrac_interfaces.yml")
                await badfish.change_boot("director", interfaces_path)

                # wait 10 minutes for the boot order job to complete
                await asyncio.sleep(600)
            except BadfishException:
                logger.error(
                    f"Could not set boot order via Badfish for mgmt-{host}.")
                return False

        try:
            await badfish.set_power_state("on")
        except BadfishException:
            logger.error(f"Failed to power on {host}")
            return False
        foreman_results = []
        params = [
            {
                "name": "operatingsystems",
                "value": Config["foreman_default_os"],
                "identifier": "title",
            },
            {
                "name": "ptables",
                "value": Config["foreman_default_ptable"]
            },
            {
                "name": "media",
                "value": Config["foreman_default_medium"]
            },
        ]

        foreman = Foreman(
            Config["foreman_api_url"],
            Config["foreman_username"],
            Config["foreman_password"],
            semaphore=semaphore,
            loop=loop,
        )

        set_result = await foreman.set_host_parameter(host, "overcloud",
                                                      "true")
        foreman_results.append(set_result)

        put_result = await foreman.put_parameter(host, "build", 1)
        foreman_results.append(put_result)

        put_param_result = await foreman.put_parameters_by_name(host, params)
        foreman_results.append(put_param_result)

        owner_id = await foreman.get_user_id(new_cloud)
        host_id = await foreman.get_host_id(host)
        put_result = await foreman.put_element("hosts", host_id, "owner_id",
                                               owner_id)
        foreman_results.append(put_result)

        for result in foreman_results:
            if isinstance(result, Exception) or not result:
                logger.error(
                    "There was something wrong setting Foreman host parameters."
                )
                return False
        if is_supported(host):
            try:
                await badfish.boot_to_type(
                    "foreman",
                    os.path.join(os.path.dirname(__file__),
                                 "../../conf/idrac_interfaces.yml"),
                )
                await badfish.reboot_server(graceful=False)
            except BadfishException:
                logger.error(f"Error setting PXE boot via Badfish on {host}.")
                await badfish.reboot_server(graceful=False)
                return False
        else:
            try:
                asyncio.run_coroutine_threadsafe(
                    badfish.unmount_virtual_media(),
                    loop,
                )
            except BadfishException:
                logger.warning(
                    f"Could not unmount virtual media for mgmt-{host}.")

            try:
                ipmi_pxe_persistent = [
                    "chassis",
                    "bootdev",
                    "pxe",
                    "options=persistent",
                ]
                await execute_ipmi(host,
                                   arguments=ipmi_pxe_persistent,
                                   semaphore=new_semaphore)
                await ipmi_reset(host, new_semaphore)
            except Exception as ex:
                logger.debug(ex)
                logger.error(
                    f"There was something wrong setting PXE flag or resetting IPMI on {host}."
                )

    if _target_cloud.name == _host_obj.default_cloud.name:
        if not badfish:
            try:
                badfish = await badfish_factory(
                    "mgmt-%s" % host,
                    Config["ipmi_username"],
                    Config["ipmi_password"],
                    propagate=True,
                )
            except BadfishException:
                logger.error(
                    f"Could not initialize Badfish. Verify ipmi credentials for mgmt-{host}."
                )
                return False

        await badfish.set_power_state("off")
        source_cloud_schedule = Schedule.current_schedule(
            cloud=_host_obj.cloud.name)
        if not source_cloud_schedule:
            _old_cloud_obj = Cloud.objects(name=_host_obj.cloud.name).first()
            _old_cloud_obj.update(vlan=None)

    schedule = Schedule.current_schedule(cloud=_target_cloud,
                                         host=_host_obj).first()
    if schedule:
        schedule.update(build_start=build_start, build_end=datetime.now())
        schedule.save()

    logger.debug("Updating host: %s")
    _host_obj.update(cloud=_target_cloud,
                     build=False,
                     last_build=datetime.now(),
                     validated=False)
    return True
예제 #3
0
    async def post_system_test(self):
        password = f"{Config['infra_location']}@{self.cloud.ticket}"
        foreman = Foreman(
            Config["foreman_api_url"],
            self.cloud.name,
            password,
            loop=self.loop,
        )

        valid_creds = await foreman.verify_credentials()
        if not valid_creds:
            logger.error("Unable to query Foreman for cloud: %s" % self.cloud.name)
            logger.error("Verify Foreman password is correct: %s" % password)
            self.report = (
                self.report
                + "Unable to query Foreman for cloud: %s\n" % self.cloud.name
            )
            self.report = (
                self.report + "Verify Foreman password is correct: %s\n" % password
            )
            return False

        build_hosts = await foreman.get_build_hosts()

        pending = []
        schedules = Schedule.current_schedule(cloud=self.cloud)
        if schedules:
            for schedule in schedules:
                if schedule.host and schedule.host.name in build_hosts:
                    pending.append(schedule.host.name)

            if pending:
                logger.info(
                    "The following hosts are marked for build and will now be rebooted:"
                )
                self.report = (
                    self.report + "The following hosts are marked for build:\n"
                )
                for host in pending:
                    logger.info(host)
                    try:
                        nc = Netcat(host)
                        healthy = await nc.health_check()
                    except OSError:
                        healthy = False
                    if not healthy:
                        logger.warning(
                            "Host %s didn't pass the health check. "
                            "Potential provisioning in process. SKIPPING." % host
                        )
                        continue
                    badfish = None
                    try:
                        badfish = await badfish_factory(
                            "mgmt-" + host,
                            str(Config["ipmi_username"]),
                            str(Config["ipmi_password"]),
                        )
                        if is_supported(host):
                            await badfish.boot_to_type(
                                "foreman",
                                os.path.join(
                                    os.path.dirname(__file__),
                                    "../../conf/idrac_interfaces.yml",
                                ),
                            )
                        else:
                            await badfish.set_next_boot_pxe()
                        await badfish.reboot_server()
                    except BadfishException as ಥ﹏ಥ:
                        logger.debug(ಥ﹏ಥ)
                        if badfish:
                            logger.warning(
                                f"There was something wrong trying to boot from Foreman interface for: {host}"
                            )
                            await badfish.reboot_server()
                        else:
                            logger.error(
                                f"Could not initiate Badfish instance for: {host}"
                            )

                    self.report = self.report + "%s\n" % host
                return False

        failed = False
        for host in self.hosts:
            try:
                badfish = await badfish_factory(
                    "mgmt-" + host.name,
                    str(Config["ipmi_cloud_username"]),
                    password,
                )
                await badfish.validate_credentials()
            except BadfishException:
                logger.info(f"Could not verify badfish credentials for: {host.name}")
                failed = True

        return not failed
예제 #4
0
def move_and_rebuild(host, old_cloud, new_cloud, rebuild=False):
    logger.debug("Moving and rebuilding host: %s" % host)

    untouchable_hosts = conf["untouchable_hosts"]
    logger.debug("Untouchable hosts: %s" % untouchable_hosts)
    _host_obj = Host.objects(name=host).first()
    if not _host_obj.interfaces:
        logger.error("Host has no interfaces defined.")
        return False

    if host in untouchable_hosts:
        logger.error("No way...")
        return False

    _old_cloud_obj = Cloud.objects(name=old_cloud).first()
    _new_cloud_obj = Cloud.objects(name=new_cloud).first()

    logger.debug("Connecting to switch on: %s" %
                 _host_obj.interfaces[0].ip_address)
    _public_vlan_obj = Vlan.objects(cloud=_new_cloud_obj).first()
    for i, interface in enumerate(_host_obj.interfaces):
        ssh_helper = SSHHelper(interface.ip_address, conf["junos_username"])
        old_vlan_out = ssh_helper.run_cmd("show configuration interfaces %s" %
                                          interface.switch_port)
        old_vlan = old_vlan_out[0].split(";")[0].split()[1][7:]
        if not old_vlan:
            logger.warning(
                "Warning: Could not determine the previous VLAN for %s on %s, switch %s, switchport %s"
                % (host, interface.name, interface.ip_address,
                   interface.switch_port))
            old_vlan = get_vlan(_old_cloud_obj, i)

        new_vlan = get_vlan(_new_cloud_obj, i)

        if _public_vlan_obj and i == len(_host_obj.interfaces) - 1:
            logger.info("Setting last interface to public vlan %s." % new_vlan)

            if int(old_vlan) != int(_public_vlan_obj.vlan_id):
                success = juniper_convert_port_public(
                    interface.ip_address, interface.switch_port, str(old_vlan),
                    str(_public_vlan_obj.vlan_id))
                if success:
                    logger.info("Successfully updated switch settings.")
                else:
                    logger.error(
                        "There was something wrong updating switch for %s:%s" %
                        (host, interface.name))
                    return False
        else:

            if int(old_vlan) != int(new_vlan):
                success = juniper_set_port(interface.ip_address,
                                           interface.switch_port,
                                           str(old_vlan), str(new_vlan))
                if success:
                    logger.info("Successfully update switch settings.")
                else:
                    logger.error(
                        "There was something wrong updating switch for %s:%s" %
                        (host, interface.name))
                    return False

        if i == len(_host_obj.interfaces) - 1:
            _old_vlan_obj = Vlan.objects(cloud=_old_cloud_obj).first()
            if _old_vlan_obj:
                _old_vlan_obj.update(cloud=None)

        ssh_helper.disconnect()

    ipmi_new_pass = _new_cloud_obj.ticket if _new_cloud_obj.ticket else conf[
        "$ipmi_password"]

    foreman = Foreman(
        conf["foreman_api_url"],
        conf["foreman_username"],
        conf["foreman_password"],
    )
    foreman.remove_role(_old_cloud_obj.name, _host_obj.name)
    foreman.add_role(_new_cloud_obj.name, _host_obj.name)
    foreman.update_user_password(_new_cloud_obj.name, ipmi_new_pass)

    ipmi_set_pass = [
        "/usr/bin/ipmitool", "-I", "lanplus", "-H",
        "mgmt-%s" % host, "-U", conf["ipmi_username"], "-P",
        conf["ipmi_password"], "user", "set", "password",
        str(conf["ipmi_cloud_username_id"]), ipmi_new_pass
    ]
    logger.debug("ipmi_set_pass: %s" % ipmi_set_pass)
    subprocess.call(ipmi_set_pass)

    ipmi_set_operator = [
        "/usr/bin/ipmitool", "-I", "lanplus", "-H",
        "mgmt-%s" % host, "-U", conf["ipmi_username"], "-P",
        conf["ipmi_password"], "user", "priv",
        str(conf["ipmi_cloud_username_id"]), "0x4"
    ]
    logger.debug("ipmi_set_operator: %s" % ipmi_set_operator)
    subprocess.call(ipmi_set_operator)
    if rebuild and _new_cloud_obj.name != "cloud01":
        badfish = Badfish("mgmt-%s" % host, conf["ipmi_username"],
                          conf["ipmi_password"])

        if "pdu_management" in conf and conf["pdu_management"]:
            # TODO: pdu management
            pass

        if is_supermicro(host):
            ipmi_pxe_persistent = [
                "/usr/bin/ipmitool", "-I", "lanplus", "-H",
                "mgmt-%s" % host, "-U", conf["ipmi_username"], "-P",
                conf["ipmi_password"], "chassis", "bootdev", "pxe", "options",
                "=", "persistent"
            ]
            logger.debug("ipmi_pxe_persistent: %s" % ipmi_pxe_persistent)
            subprocess.call(ipmi_pxe_persistent)

        if is_supported(host):
            try:
                badfish.change_boot(
                    "director",
                    os.path.join(os.path.dirname(__file__),
                                 "../../conf/idrac_interfaces.yml"))
            except SystemExit as ex:
                logger.debug(ex)
                logger.error("Could not set boot order via Badfish.")
                return False

        foreman_success = foreman.remove_extraneous_interfaces(host)

        foreman_success = foreman.set_host_parameter(
            host, "rhel73", "false") and foreman_success
        foreman_success = foreman.set_host_parameter(
            host, "rhel75", "false") and foreman_success
        foreman_success = foreman.set_host_parameter(
            host, "overcloud", "true") and foreman_success
        foreman_success = foreman.put_parameter(host, "build",
                                                1) and foreman_success
        foreman_success = foreman.put_parameter_by_name(
            host, "operatingsystems", conf["foreman_default_os"],
            "title") and foreman_success
        foreman_success = foreman.put_parameter_by_name(
            host, "ptables",
            conf["foreman_default_ptable"]) and foreman_success
        foreman_success = foreman.put_parameter_by_name(
            host, "media", conf["foreman_default_medium"]) and foreman_success
        if not foreman_success:
            logger.error(
                "There was something wrong setting Foreman host parameters.")

        try:
            badfish.set_next_boot_pxe()
            badfish.reboot_server()
        except SystemExit:
            if is_supermicro(host):
                logger.warning("Badfish not yet supported on Supermicro: %s." %
                               host)
            else:
                logger.exception(
                    "There was something wrong setting next PXE boot via Badfish."
                )
                return False

        logger.debug("Updating host: %s")
        _host_obj.update(cloud=_new_cloud_obj,
                         build=False,
                         last_build=datetime.now())
    else:

        logger.debug("Updating host: %s")
        _host_obj.update(cloud=_new_cloud_obj,
                         build=False,
                         last_build=datetime.now())
예제 #5
0
async def move_and_rebuild(host,
                           new_cloud,
                           semaphore,
                           rebuild=False,
                           loop=None):
    build_start = datetime.now()
    logger.debug("Moving and rebuilding host: %s" % host)

    untouchable_hosts = conf["untouchable_hosts"]
    logger.debug("Untouchable hosts: %s" % untouchable_hosts)
    _host_obj = Host.objects(name=host).first()

    if host in untouchable_hosts:
        logger.error("No way...")
        return False

    _new_cloud_obj = Cloud.objects(name=new_cloud).first()

    ipmi_new_pass = (f"{conf['infra_location']}@{_new_cloud_obj.ticket}"
                     if _new_cloud_obj.ticket else conf["ipmi_password"])

    ipmi_set_pass = [
        "user",
        "set",
        "password",
        str(conf["ipmi_cloud_username_id"]),
        ipmi_new_pass,
    ]

    new_semaphore = asyncio.Semaphore(20)
    await execute_ipmi(host, arguments=ipmi_set_pass, semaphore=new_semaphore)

    ipmi_set_operator = [
        "user", "priv",
        str(conf["ipmi_cloud_username_id"]), "0x4"
    ]
    await execute_ipmi(host,
                       arguments=ipmi_set_operator,
                       semaphore=new_semaphore)

    if rebuild and _new_cloud_obj.name != _host_obj.default_cloud.name:
        if "pdu_management" in conf and conf["pdu_management"]:
            # TODO: pdu management
            pass

        if is_supported(host):
            try:
                badfish = await badfish_factory(
                    "mgmt-%s" % host,
                    conf["ipmi_username"],
                    conf["ipmi_password"],
                    propagate=True,
                )
            except BadfishException:
                logger.error(
                    f"Could not initialize Badfish. Verify ipmi credentials for mgmt-{host}."
                )
                return False
            try:
                changed_boot_order = asyncio.run_coroutine_threadsafe(
                    badfish.change_boot(
                        "director",
                        os.path.join(os.path.dirname(__file__),
                                     "../../conf/idrac_interfaces.yml"),
                    ),
                    loop,
                )
                if changed_boot_order:
                    await badfish.reboot_server(graceful=False)
            except BadfishException:
                logger.error(
                    f"Could not set boot order via Badfish for mgmt-{host}.")
                return False

        foreman_results = []
        params = [
            {
                "name": "operatingsystems",
                "value": conf["foreman_default_os"],
                "identifier": "title",
            },
            {
                "name": "ptables",
                "value": conf["foreman_default_ptable"]
            },
            {
                "name": "media",
                "value": conf["foreman_default_medium"]
            },
        ]

        foreman = Foreman(
            conf["foreman_api_url"],
            conf["foreman_username"],
            conf["foreman_password"],
            semaphore=semaphore,
            loop=loop,
        )

        set_result = await foreman.set_host_parameter(host, "overcloud",
                                                      "true")
        foreman_results.append(set_result)

        put_result = await foreman.put_parameter(host, "build", 1)
        foreman_results.append(put_result)

        put_param_result = await foreman.put_parameters_by_name(host, params)
        foreman_results.append(put_param_result)

        owner_id = await foreman.get_user_id(new_cloud)
        host_id = await foreman.get_host_id(host)
        put_result = await foreman.put_element("hosts", host_id, "owner_id",
                                               owner_id)
        foreman_results.append(put_result)

        for result in foreman_results:
            if isinstance(result, Exception) or not result:
                logger.error(
                    "There was something wrong setting Foreman host parameters."
                )
                return False

        healthy = False
        for i in range(RETRIES):
            nc = Netcat(_host_obj.name)
            if nc.health_check():
                healthy = True
                nc.close()
                break
            nc.close()

        if not healthy:
            logger.error("Failed to recover host after changing boot order.")
            return False

        if is_supported(host):
            try:
                await badfish.boot_to_type(
                    "foreman",
                    os.path.join(os.path.dirname(__file__),
                                 "../../conf/idrac_interfaces.yml"),
                )
                await badfish.reboot_server(graceful=False)
            except BadfishException:
                logger.error(f"Error setting PXE boot via Badfish on {host}.")
                await badfish.reboot_server(graceful=False)
                return False
        else:
            try:
                ipmi_pxe_persistent = [
                    "chassis",
                    "bootdev",
                    "pxe",
                    "options",
                    "=",
                    "persistent",
                ]
                await execute_ipmi(host,
                                   arguments=ipmi_pxe_persistent,
                                   semaphore=new_semaphore)
                await ipmi_reset(host, new_semaphore)
            except Exception as ex:
                logger.debug(ex)
                logger.error(
                    f"There was something wrong setting PXE flag or resetting IPMI on {host}."
                )

    schedule = Schedule.current_schedule(cloud=_new_cloud_obj,
                                         host=_host_obj).first()
    if schedule:
        schedule.update(build_start=build_start, build_end=datetime.now())
        schedule.save()

    logger.debug("Updating host: %s")
    _host_obj.update(cloud=_new_cloud_obj,
                     build=False,
                     last_build=datetime.now(),
                     validated=False)
    return True