コード例 #1
0
def parse_args():
    """Parse and return command line arguments, validate the host."""
    parser = lib.get_base_parser('Automated reimaging of a single host')
    parser.add_argument(
        '--rename',
        help='FQDN of the new name to rename this host to while reimaging')
    parser.add_argument(
        '--rename-mgmt',
        help='FQDN of the new name management interface, see --rename')
    parser.add_argument('host',
                        metavar='HOST',
                        action='store',
                        help='FQDN of the host to be reimaged')
    parser.add_argument('mgmt',
                        metavar='MGMT',
                        action='store',
                        nargs='?',
                        default=None,
                        help='FQDN of the management interface for the host')

    args = parser.parse_args()

    fqdns = [args.host]

    if args.rename is not None:
        fqdns.append(args.rename)
        if args.no_pxe:
            raise argparse.ArgumentTypeError(
                'The --rename option cannot be used in conjunction with --no-pxe.'
            )

    # Gather the management interfaces, if missing
    if args.mgmt is None:
        mgmts = lib.get_mgmts([args.host])
        args.mgmt = mgmts[args.host]
    else:
        mgmts = {args.host: args.mgmt}

    fqdns.append(args.mgmt)
    if args.rename is not None and args.rename_mgmt is None:
        mgmts.update(lib.get_mgmts([args.rename]))
        fqdns.append(mgmts[args.rename])

    # Perform a quick sanity check on the host and mgmt
    for name in fqdns:
        if '.' not in name or not lib.HOSTS_PATTERN.match(name):
            raise argparse.ArgumentTypeError(
                "Expected FQDN, got '{name}'".format(name=name))

            if not lib.is_hostname_valid(name):
                raise argparse.ArgumentTypeError(
                    "Unable to resolve host '{name}'".format(name=name))

    for mgmt in mgmts.values():
        if '.mgmt.' not in mgmt:
            raise argparse.ArgumentTypeError(
                'The MGMT parameter {} does not follow the *.mgmt.* format'.
                format(mgmt))

    return args
コード例 #2
0
def run(args, user, log_path):
    """Run the reimage for all the hosts in subproceesses."""
    # Setup
    phab_client = lib.get_phabricator_client()
    lib.ensure_ipmi_password()
    mgmts = lib.get_mgmts(args.hosts)

    # Check that IPMI is working for all the hosts
    for host in args.hosts:
        lib.check_remote_ipmi(mgmts[host])

    # Initialize data structures
    procs = {}
    retcodes = defaultdict(list)

    # Validate hosts
    if not args.new:
        lib.validate_hosts(args.hosts, no_raise=args.no_verify)

    # Update the Phabricator task
    if args.phab_task_id is not None:
        lib.phabricator_task_update(
            phab_client, args.phab_task_id,
            lib.PHAB_COMMENT_PRE.format(user=user,
                                        hostname=socket.getfqdn(),
                                        hosts=args.hosts,
                                        log=log_path))

    # Run the reimage for each host in a child process
    try:
        for host in args.hosts:
            proc = reimage_host(host, mgmts[host], args)
            if args.sequential:
                retcodes[host] = proc.wait()
                time.sleep(args.sleep)
            else:
                procs[host] = proc

        if procs:
            retcodes = wait_for_childrens(procs)
    except KeyboardInterrupt:
        # Terminate childrens
        if procs:
            for process in procs:
                process.terminate()
        else:
            proc.terminate()

        raise

    # Comment on the Phabricator task
    if args.phab_task_id is not None:
        phabricator_message = lib.get_phabricator_post_message(retcodes)
        lib.phabricator_task_update(phab_client, args.phab_task_id,
                                    phabricator_message)

    if max(retcodes.keys()) > 0:
        return 1

    return 0
コード例 #3
0
def main():
    """Run the script."""
    script_name = os.path.basename(__file__)
    args = parse_args()
    user = lib.get_running_user()
    phab_client = lib.get_phabricator_client()
    is_valid_host = lib.is_hostname_valid(args.host)
    actions = []

    if not is_valid_host and not args.force:
        logger.error(
            "{host} is not a valid hostname. Aborting.".format(host=args.host))
        return 1

    # Remove from Puppet and PuppetDB
    lib.puppet_remove_host(args.host)
    actions += ['Revoked Puppet certificate', 'Removed from PuppetDB']

    # Downtime on Icinga both the host and the mgmt host, they will be removed by Puppet
    if is_valid_host:
        try:
            lib.icinga_downtime(args.host,
                                user,
                                args.phab_task_id,
                                title=script_name)
            actions.append('Downtimed host on Icinga')
        except RuntimeError:
            actions.append(
                'Skipped downtime host on Icinga (likely already removed)')

        mgmts = lib.get_mgmts([args.host])
        try:
            lib.icinga_downtime(mgmts[args.host],
                                user,
                                args.phab_task_id,
                                title=script_name)
            actions.append('Downtimed mgmt interface on Icinga')
        except RuntimeError:
            actions.append(
                'Skipped downtime mgmt interface on Icinga (likely already removed)'
            )

    # Remove from DebMonitor
    lib.debmonitor_remove_host(args.host)
    actions.append('Removed from DebMonitor')

    message = (
        '{script} was executed by {user} for {host} and performed the following actions:\n'
        '- {actions}').format(script=script_name,
                              user=user,
                              host=args.host,
                              actions='\n- '.join(actions))
    lib.phabricator_task_update(phab_client, args.phab_task_id, message)

    return 0