Ejemplo n.º 1
0
def main(argv=None):
    script = 'clean-old-aggregates'
    slack = Slackbot(args.slack, script_name=script) if args.slack else None

    try:
        term_leases = [
            lease for lease in leases.values() if is_terminated(lease)
        ]
        old_aggregates = [
            aggs for aggs in (aggregates_for_lease(lease)
                              for lease in term_leases) if aggs != None
        ]
        aggregate_list = list(itertools.chain(*old_aggregates))
        errors, reports = clear_aggregates(aggregate_list)
        orphan_list = orphan_find(aggregates)

        for orphan in orphan_list:
            destiny = has_active_allocation(orphan)
            host = osrest.blazar.host(auth, orphan)
            if destiny is None:
                reports.append(
                    "Error identifying allocation for orphan host {}.".format(
                        orphan))
            elif destiny is False:
                reports.append(
                    "Returning orphan host {} to freepool.".format(orphan) +
                    "\n")
                osrest.nova.aggregate_add_host(auth, 1,
                                               host['hypervisor_hostname'])
            else:
                destination_agg = [
                    aggr['id'] for aggr in aggregates.values()
                    if aggr['name'] == destiny
                ][0]
                reports.append(
                    "Moving orphan host {} to destined aggregate {}.".format(
                        orphan, destination_agg))
                osrest.nova.aggregate_add_host(auth, destination_agg,
                                               host['hypervisor_hostname'])

        old_allocations = query.blazar_find_old_host_alloc(conn)
        for alloc in old_allocations:
            hostname, lease_id = del_expired_alloc(conn, alloc)
            reports.append(
                "Deleted host_allocation for host {} matching expired lease {}."
                .format(hostname, lease_id))
        conn.db.commit()

        if reports:
            str_report = '\n'.join(reports)
            if slack:
                if errors:
                    slack.error(str_report)
                else:
                    slack.message(str_report)
    except:
        if slack:
            slack.exception()
        raise
def main(argv=None):
    if argv is None:
        argv = sys.argv

    parser = base_parser('Fixes issues with orphaned resource providers.')
    mysqlargs = MySqlArgs({
        'user': '******',
        'password': '',
        'host': 'localhost',
        'port': 3306,
    })
    mysqlargs.inject(parser)

    parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='Quiet mode. No output if there was nothing to do.')
    parser.add_argument('action',
                        choices=['info', 'update'],
                        help='Just display info or actually update them?')

    args = parser.parse_args(argv[1:])
    mysqlargs.extract(args)

    slack = Slackbot(
        args.slack,
        script_name='orphan-resource-providers') if args.slack else None

    try:
        db = mysqlargs.connect()

        update_count = resource_providers_fixer(db=db,
                                                describe=args.action == 'info',
                                                quiet=args.quiet)

        if args.action == 'update':
            if update_count > 0:
                message = ('Commanded update of *{} resource providers*'.
                           format(update_count))

                print(message)

                slack.message(message)
            elif not args.quiet:
                print('No resource providers to delete')
    except:
        if slack:
            slack.exception()
        raise
Ejemplo n.º 3
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    parser = base_parser('Floating IP and port reclaimer.')
    mysqlargs = MySqlArgs({
        'user': '******',
        'password': '',
        'host': 'localhost',
        'port': 3306,
    })
    mysqlargs.inject(parser)

    parser.add_argument('-w', '--whitelist', type=str,
        help='File of project/tenant IDs/names to ignore, one per line. '
             'Ignores case and dashes.')
    parser.add_argument('action', choices=['info', 'delete'],
        help='Just display info or actually delete them?')
    parser.add_argument('type', choices=list(RESOURCE_QUERY),
        help='Grab floating IPs or ports?')
    parser.add_argument('idle_days', type=float,
        help='Number of days since last active instance in project was '
        'deleted to consider it idle.')

    args = parser.parse_args(argv[1:])
    mysqlargs.extract(args)
    auth = osapi.Authv2.from_env_or_args(args=args)

    slack = Slackbot(args.slack, script_name='neutron-reaper') if args.slack else None

    whitelist = set()
    if args.whitelist:
        with open(args.whitelist) as f:
            whitelist = {line for line in f}

    db = mysqlargs.connect()
    db.version = query.ROCKY

    try:
        to_delete = find_reapable_resources(db=db, auth=auth, type_=args.type, idle_days=args.idle_days, whitelist=whitelist)

        thing = '{}{}'.format(
            {'ip': 'floating IP', 'port': 'port'}[args.type],
            ('' if len(to_delete) == 1 else 's'),
        )

        if to_delete:
            if args.action == 'delete':
                for resource_id in to_delete:
                    RESOURCE_DELETE_COMMAND[args.type](auth, resource_id)
                message = (
                    'Commanded deletion of *{} {}* ({:.0f} day grace-period)'
                    .format(len(to_delete), thing, args.idle_days)
                )

                print(message)

                if slack:
                    slack.message(message)
            else:
                print((
                    'Found *{} {}* to delete ({:.0f} day grace-period):\n{}'
                    .format(len(to_delete), thing, args.idle_days, to_delete)
                ))
        else:
            print('No {} to delete ({:.0f} day grace-period)'.format(thing, args.idle_days))

    except:
        if slack:
            slack.exception()
        raise
def main(argv=None):
    if argv is None:
        argv = sys.argv

    parser = base_parser('Reserve nodes for maintenance')
    append_global_identity_args(parser, argv)

    mysqlargs = MySqlArgs({
        'user': '******',
        'password': '',
        'host': 'localhost',
        'port': 3306,
    })
    mysqlargs.inject(parser)

    parser.add_argument('--operator',
                        type=str,
                        required=True,
                        help='Chameleon account username of the operator')
    parser.add_argument('--nodes',
                        type=str,
                        required=True,
                        help='node ids or node names; comma separated')
    parser.add_argument('--reason',
                        type=str,
                        required=True,
                        help='maintenance reasons')
    parser.add_argument('--dry-run',
                        action="store_true",
                        help='perform a trial run without making reservations')
    parser.add_argument(
        '--start-time',
        type=valid_date,
        default=None,
        help=
        'lease start time (YYYY-mm-DD HH:MM:SS); if not given, start at the earliest possible datetime'
    )
    parser.add_argument(
        '--estimate-hours',
        type=int,
        default=168,
        help=
        'estimated hours required for maintenance; default is 168 hours (1 week)'
    )

    args = parser.parse_args(argv[1:])

    slack = Slackbot(
        args.slack,
        script_name='maintenance-reservation') if args.slack else None

    # connect to database
    mysqlargs.extract(args)
    db = mysqlargs.connect()

    # keystone authentication
    auth_args = {
        'auth_url': args.os_auth_url,
        'username': args.os_username,
        'password': args.os_password,
        'project_name': args.os_project_name,
        'region_name': args.os_region_name,
        'interface': 'public'
    }
    if args.os_user_domain_name:
        auth_args['user_domain_name'] = args.os_user_domain_name
    if args.os_project_domain_name:
        auth_args['project_domain_name'] = args.os_project_domain_name
    # get admin session for node information
    admin_sess = get_session(**auth_args)
    # get maint session for creating lease
    auth_args['project_name'] = 'maintenance'
    maint_sess = get_session(**auth_args)

    try:
        # get node details
        nodes = get_nodes(admin_sess, args.nodes.split(','))

        report_info = {}
        for node in nodes:
            lease_start_time = args.start_time
            if not lease_start_time:
                # find the earliest reservation time for the node
                lease_start_time = get_node_earliest_reserve_time(
                    db, node.uuid, args.estimate_hours)
            else:
                # convert to utc
                lease_start_time = lease_start_time.replace(
                    tzinfo=tz.tzlocal()).astimezone(tz.gettz('UTC'))
            # reserve
            reserve_args = {
                'sess': maint_sess,
                'node': node,
                'start_time': lease_start_time,
                'requested_hours': args.estimate_hours,
                'reason': args.reason,
                'operator': args.operator,
                'dryrun': args.dry_run
            }
            start_time_str, end_time_str = reserve(**reserve_args)
            report_info[node.name] = (start_time_str, end_time_str)

        # summary
        report_lines = [('Node {node_name} at {region} is under maintenance '
                         'from {start_time} to {end_time}').format(
                             node_name=key,
                             region=args.os_region_name,
                             start_time=value[0],
                             end_time=value[1])
                        for key, value in report_info.items()]

        if report_lines:
            report = '\n'.join(report_lines)

            print(report)

            if slack:
                slack.message(report)
        else:
            print('nothing reserved!')
    except:
        if slack:
            slack.exception()
        raise
Ejemplo n.º 5
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    parser = base_parser('floating IP reaper')
    mysqlargs = MySqlArgs({
        'user': '******',
        'password': '',
        'host': 'localhost',
        'port': 3306,
    })
    mysqlargs.inject(parser)

    parser.add_argument(
        '-w',
        '--whitelist',
        type=str,
        help='File of project/tenant IDs to ignore, one per line.')
    parser.add_argument(
        '--grace-days',
        type=int,
        required=True,
        help='Number of days since last used to consider to be idle')
    parser.add_argument('--dryrun', help='dryrun mode', action='store_true')

    args = parser.parse_args(argv[1:])
    mysqlargs.extract(args)
    auth = osapi.Auth.from_env_or_args(args=args)

    slack = Slackbot(args.slack,
                     script_name='floatingip-reaper') if args.slack else None

    whitelist = set()
    if args.whitelist:
        with open(args.whitelist) as f:
            whitelist = {line.rstrip('\n') for line in f}

    db = mysqlargs.connect()
    db.version = query.ROCKY

    try:
        result = reaper(db=db,
                        auth=auth,
                        grace_days=args.grace_days,
                        whitelist=whitelist,
                        dryrun=args.dryrun)
        if result and not args.dryrun:
            message_lines = []
            for proj, ips in result.items():
                message_lines.append(
                    'Reclaimed *{} floating ips* from project {} ({:.0f} day grace-period)'
                    .format(str(len(ips)), proj, args.grace_days))
            message = '\n'.join(message_lines)
            print(message)

            if slack:
                slack.message(message)
    except:
        if slack:
            slack.exception()
        raise
Ejemplo n.º 6
0
def main(argv=None):
    if argv is None:
        argv = sys.argv

    parser = base_parser('Unutilized Lease Reaper')
    parser.add_argument('-w',
                        '--warn-hours',
                        type=int,
                        help='Number of hours after which to warn user.',
                        default=DEFAULT_WARN_HOURS)
    parser.add_argument('-r',
                        '--grace-hours',
                        type=int,
                        help='Number of hours after which to remove lease.',
                        default=DEFAULT_GRACE_HOURS)
    parser.add_argument('action',
                        choices=['info', 'delete'],
                        help='Just display info or actually delete them?')
    parser.add_argument('--sender',
                        type=str,
                        help='Email address of sender.',
                        default='*****@*****.**')

    args = parser.parse_args(argv[1:])
    auth = osapi.Auth.from_env_or_args(args=args)

    assert args.grace_hours > args.warn_hours, (
        "Grace hours must be greater than warning period.")

    if args.slack:
        slack = Slackbot(args.slack, script_name='unutilized-leases-reaper')
    else:
        slack = None

    try:
        sender = args.sender
        warn_period = args.warn_hours
        grace_period = args.grace_hours
        warn, terminate = find_leases_in_violation(auth, warn_period,
                                                   grace_period)

        if (len(warn) + len(terminate) > 0):
            if args.action == 'delete':
                for lease in warn:
                    if lease not in terminate:
                        send_notification(
                            auth, lease, sender, warn_period, grace_period,
                            "Your lease {} is idle and may be terminated.".
                            format(lease['name']),
                            _email.IDLE_LEASE_WARNING_EMAIL_BODY)

                for lease in terminate:
                    blazar.lease_delete(auth, lease['id'])
                    send_notification(
                        auth, lease, sender, warn_period, grace_period,
                        "Your lease {} has been terminated.".format(
                            lease['name']),
                        _email.IDLE_LEASE_TERMINATION_EMAIL_BODY)

                message = ('Warned deletion of *{} idle leases* '
                           'Commanded deletion of *{} idle leases* '
                           '(Unutilized lease violation)'.format(
                               len(warn), len(terminate)))

                print(message)

                if slack:
                    slack.message(message)
            else:
                pprint(
                    dict(warn=[
                        dict(lease_id=l['id'],
                             nodes=[n['uuid'] for n in l['nodes']])
                        for l in warn
                    ],
                         terminate=[
                             dict(lease_id=l['id'],
                                  nodes=[n['uuid'] for n in l['nodes']])
                             for l in terminate
                         ]))
        else:
            print('No leases to warn or delete.')
    except Exception:
        if slack:
            slack.exception()
        raise