clean_stale.py 4.68 KB
Newer Older
1 2
#!/usr/bin/env python
from __future__ import absolute_import, division, print_function, unicode_literals
3
import etcd
4
import argparse
5
from nova_router import neighbors, security_groups, dns_rr, setupLogfile
6 7
from scvmm_client import odata
import logging
8
import uuid
9
try:
Sigmund Augdal's avatar
Sigmund Augdal committed
10
    from configparser import SafeConfigParser  # pylint: disable=F0401
11
except ImportError:
Sigmund Augdal's avatar
Sigmund Augdal committed
12
    from ConfigParser import SafeConfigParser  # pylint: disable=F0401
13

14 15 16 17 18
DESCRIPTION = """
Remove ip/mac bindings for VMs that no longer exists.
Also remove mac-addresses from security groups in etcd.
Also reset PTR-records in DNS.
"""
19 20 21 22 23 24


def parse_args():
    parser = argparse.ArgumentParser(description=DESCRIPTION)
    parser.add_argument('--logfile', help="send output to logfile")
    parser.add_argument('--config', default="nova.cfg", help="Use alternative config file")
Sigmund Augdal's avatar
Sigmund Augdal committed
25 26
    parser.add_argument('--noop', action="store_true",
                        help="Don't actually clean nodes, just tell what would have been done")
27 28 29

    return parser.parse_args()

30 31

def main():
32
    args = parse_args()
33
    conf = SafeConfigParser()
34 35
    conf.read(args.config)
    if args.logfile:
36 37
        logging.basicConfig(level=logging.INFO)
        setupLogfile(args.logfile)
38 39 40 41
    else:
        logging.basicConfig(level=logging.INFO,
                            format='%(asctime)s %(name)s %(levelname)s %(message)s')

42
    logging.info("Process starting")
43 44
    etcd_client = etcd.Client(host="nova-gw1.bs.unsi.no",
                              cert=(conf.get('etcd', 'cert'), conf.get('etcd', 'key')),
45
                              ca_cert=conf.get('etcd', 'cacert'), protocol='https')
46 47
    vmm_client = odata.VMMClient(conf.get('spf', 'vmm_baseurl'), conf.get('spf', 'username'),
                                 conf.get('spf', 'password'))
48
    pdns_url = conf.get('pdns', 'url')
49 50 51 52

    nics = set()
    for nic in vmm_client.query_collection("VirtualNetworkAdapters"):
        mac = nic.properties["MACAddress"]
53
        vmnet = nic.properties["VMNetworkId"]
54
        if mac is not None and (vmnet == uuid.UUID("5cc21a4c-a5b9-413d-b607-3ce7020c8b98") or vmnet is None):
55
            nics.add(mac.lower())
56
    for entry in etcd_client.read("/nova/iaas/instances").children:
57 58 59 60
        if not entry.dir:
            next
        mac = entry.key.split("/")[-1].lower()
        if not mac in nics:
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
            if not args.noop:
                neighbors.remove_mac(etcd_client, mac)
            for addrtype in (neighbors.V4, neighbors.V6_LL, neighbors.V6_PUB):
                ipaddr = neighbors.get_ipaddress_from_mac(etcd_client, mac, addrtype)
                if ipaddr is not None:
                    if not args.noop:
                        if addrtype == neighbors.V6_LL:
                            continue
                        dns_rr.reset_ptr(pdns_url, ipaddr, addrtype != neighbors.V4)
                    else:
                        logging.info("Would have removed address {} from mac {}".format(ipaddr, mac))
                        if addrtype == neighbors.V6_LL:
                            continue
                        if addrtype == neighbors.V6_PUB:
                            logging.info("Would have cleaned DNS PTR records for address {}".format(ipaddr))
                            ptr_record = dns_rr.get_ptr_record(pdns_url, ipaddr, addrtype != neighbors.V4)
                            if ptr_record:
                                logging.info("Would have cleaned record: {}".format(ptr_record))
79
                        else:
80 81 82 83 84 85 86
                            # Remove DNS PTR record
                            logging.info("Resetting DNS PTR record for address {}".format(ipaddr))
                            ptr_record = dns_rr.get_ptr_record(pdns_url, ipaddr, addrtype != neighbors.V4)
                            logging.info("Would have updates record: {}".format(ptr_record))
                            if ptr_record:
                                ptr_record['content'] = dns_rr.generate_ptr(ipaddr)
                                logging.info("New name: {}".format(ptr_record['content']))
87 88 89
        else:
            logging.debug("found owner for mac {}".format(mac))

90 91 92 93 94 95 96 97 98 99 100 101 102
    # Remove from security groups
    groups = security_groups.get_security_groups(etcd_client)
    for group in groups:
        _, members = security_groups.get_group_members(etcd_client, group)
        for mac in members:
            if not mac in nics:
                if not args.noop:
                    logging.info("Removing mac {} from security group with id {}".format(mac, group))
                    security_groups.delete_mac_from_group(etcd_client, group, mac)
                else:
                    logging.info("Would have removed mac {} from group with id {}".format(mac, group))


103 104
if __name__ == '__main__':
    main()