Beispiel #1
0
    def __init__(self, config, auto_load=True, connectors_dir='/connectors'):
        self.logger = logging.getLogger('dns_update.dispatcher')
        # List of registered connectors
        self.__connectors = []
        # List of modified PTRs
        self.unsaved_ptrs = []
        # Dict of devices. Keyed by hostname (FQDN)
        self.devices = {}
        # Config
        self.config = config
        # DNS
        self.dns = DnsCheck(self.config)

        if auto_load:
            # Autoload all connectors
            path = os.path.dirname(os.path.abspath(__file__)) + connectors_dir
            self.logger.info("Autoload enabled. Searching: '%s'" % path)
            for dirname in [d for d in os.listdir(path) if os.path.isdir(path + '/' + d)]:
                filename = dirname + '_connector.py'
                py = filename[:-3]
                class_name = ''.join([x.capitalize() for x in py.split('_')])
                try:
                    mod = imp.load_source(class_name, path + '/' + dirname + '/' + filename)
                    # Instantiate class
                    if hasattr(mod, class_name):
                        getattr(mod, class_name)(self)
                        self.logger.info("Connector '%s' successfully loaded" % class_name)
                    else:
                        self.logger.error("Connector '%s' couldn't be loaded" % class_name)
                except IOError:
                    self.logger.error("Connector's '%s' directory doesn't have '%s' file" % (class_name, filename))
                    continue
Beispiel #2
0
 def setUp(self):
     logging.basicConfig(
         filename='test/unittest.log',
         format=
         "%(asctime)s - %(levelname)s - %(name)s:%(funcName)s - %(message)s",
         level=logging.DEBUG,
         filemode='w')
     self.dns = DnsCheck(
         config=Config('test/configuration_examples/configuration.json'))
Beispiel #3
0
class Dispatcher:
    """

    Registers connectors (interfaces) to various input and output methods
    Maintains the dict of devices and ptrs

    """

    def __init__(self, config, auto_load=True, connectors_dir='/connectors'):
        self.logger = logging.getLogger('dns_update.dispatcher')
        # List of registered connectors
        self.__connectors = []
        # List of modified PTRs
        self.unsaved_ptrs = []
        # Dict of devices. Keyed by hostname (FQDN)
        self.devices = {}
        # Config
        self.config = config
        # DNS
        self.dns = DnsCheck(self.config)

        if auto_load:
            # Autoload all connectors
            path = os.path.dirname(os.path.abspath(__file__)) + connectors_dir
            self.logger.info("Autoload enabled. Searching: '%s'" % path)
            for dirname in [d for d in os.listdir(path) if os.path.isdir(path + '/' + d)]:
                filename = dirname + '_connector.py'
                py = filename[:-3]
                class_name = ''.join([x.capitalize() for x in py.split('_')])
                try:
                    mod = imp.load_source(class_name, path + '/' + dirname + '/' + filename)
                    # Instantiate class
                    if hasattr(mod, class_name):
                        getattr(mod, class_name)(self)
                        self.logger.info("Connector '%s' successfully loaded" % class_name)
                    else:
                        self.logger.error("Connector '%s' couldn't be loaded" % class_name)
                except IOError:
                    self.logger.error("Connector's '%s' directory doesn't have '%s' file" % (class_name, filename))
                    continue

    def register_connector(self, connector):
        """
        Register connector.
        This is called from Connector's __init__ method
        :param connector: Connector object
        :return:
        """
        self.logger.debug("Register connector '%s; to dispatcher" % connector.__class__.__name__)
        self.__connectors.append(connector)

    def get_connector_list(self):
        return [x.__class__.__name__ for x in self.__connectors]

    def get_connector_config(self, connector):
        connector_name = connector.get_connector_name()
        self.logger.debug("Search for ['%s'] in configuration file" % connector_name)
        return self.config.get_connector_config(connector_name)

    def save_ptr(self, ptr):
        """
        Issue save command on each connector
        :param ptr: PTR dict
        :return:
        """
        self.logger.info("Dispatch save PTR command for %s to all (%d) connectors" % (ptr, len(self.__connectors)))
        for connector in self.__connectors:
            connector.save_ptr(ptr)

    def save_ptrs(self, ptrs):
        """
        Issue save multiple PTRs command on each connector
        :param ptrs: PTR dict
        :return:
        """
        self.logger.info("Dispatch save PTRs command for %d PTRs to all (%d) connectors" % (
            len(ptrs), len(self.__connectors)
        ))
        for connector in self.__connectors:
            connector.save_ptrs(ptrs)

    def load(self):
        """
        Load list of devices from each connector
        Since devices dict is keyed by hostnames, there are no duplicates
        :return:
        """
        # Temporary list
        device_list = []

        self.logger.info("Dispatch load command to all (%d) connectors" % len(self.__connectors))
        # Concatenate device list from each connector to temporary list
        for connector in self.__connectors:
            device_list += filter(lambda x: len(x) > 0, connector.load_devices())

        # Populate devices dict from temporary list
        for device in device_list:
            hostname = self.dns.get_fqdn(device)
            if hostname:
                if hostname not in self.devices:
                    self.devices[hostname] = Device(hostname, self.config, self.dns)
            else:
                self.logger.warning("Hostname '%s' couldn't be resolved. SKipping..." % device)
                pass

        self.logger.info("Loaded %d device(s) from %d connectors" % (len(device_list), len(self.__connectors)))
Beispiel #4
0
                    action="store_true")

args = parser.parse_args()

hostname = args.hostname
check_only = args.check
diff_only = args.diff
terse = args.terse

config = Config(check_only=check_only, diff_only=diff_only, terse=terse)

dispatcher = Dispatcher(config)

print "Loaded connectors: %s" % ', '.join(dispatcher.get_connector_list())

dns = DnsCheck(config=config)
output = TabularUtf8Output()

fqdn = dns.get_fqdn(hostname)
if fqdn:
    d = Device(hostname=fqdn, config=config)
    if d.get_interfaces():
        d.check_ptrs()
        print output.display_device_detailed(d)

        # Filter all PTRs that don't have status equal to STATUS_NOT_UPDATED or STATUS_NOT_CREATED
        ptrs_for_update = {
            k: v
            for k, v in d.get_ptrs().iteritems()
            if v.status in (DnsCheck.STATUS_NOT_UPDATED,
                            DnsCheck.STATUS_NOT_CREATED)
Beispiel #5
0
 def test_get_ptr_zone(self):
     self.assertRaises(ipaddress.AddressValueError, DnsCheck.get_ptr_zone,
                       'x.x.x.x')
     self.assertEqual('2.0.192.in-addr.arpa.',
                      DnsCheck.get_ptr_zone('192.0.2.1'))
     self.assertRaises(ValueError, DnsCheck.get_ptr_zone, '192.0.2')
Beispiel #6
0
class TestDnsCheck(unittest.TestCase):
    def setUp(self):
        logging.basicConfig(
            filename='test/unittest.log',
            format=
            "%(asctime)s - %(levelname)s - %(name)s:%(funcName)s - %(message)s",
            level=logging.DEBUG,
            filemode='w')
        self.dns = DnsCheck(
            config=Config('test/configuration_examples/configuration.json'))

    def test_fqdn_query(self):
        self.assertFalse(self.dns.get_fqdn('asdasd'))
        self.assertFalse(self.dns.get_fqdn(''))
        self.assertFalse(self.dns.get_fqdn('.'))
        self.assertEquals('host1.domain.example.', self.dns.get_fqdn('host1'))
        self.assertEquals('host2.domain.example.', self.dns.get_fqdn('host2'))
        self.assertEquals('host3.domain.example.', self.dns.get_fqdn('host3'))

    def test_a_query(self):
        self.assertFalse(self.dns.get_a('asdasd'))
        self.assertFalse(self.dns.get_a(''))
        self.assertFalse(self.dns.get_a('.'))
        self.assertEquals('192.0.2.1', self.dns.get_a('host1'))
        self.assertEquals('192.0.2.2', self.dns.get_a('host2'))
        self.assertEquals('192.0.2.3', self.dns.get_a('host3'))

    def test_ptr_query(self):
        self.assertRaises(ipaddress.AddressValueError, self.dns.get_ptr,
                          'x.x.x.x')
        self.assertEquals('host1.domain.example.',
                          self.dns.get_ptr('192.0.2.1'))
        self.assertEquals('host2.domain.example.',
                          self.dns.get_ptr('192.0.2.2'))
        self.assertEquals('host3.domain.example.',
                          self.dns.get_ptr('192.0.2.3'))
        self.assertRaises(ValueError, DnsCheck.get_ptr_zone, '192.0.2')

    def test_get_ptr_zone(self):
        self.assertRaises(ipaddress.AddressValueError, DnsCheck.get_ptr_zone,
                          'x.x.x.x')
        self.assertEqual('2.0.192.in-addr.arpa.',
                         DnsCheck.get_ptr_zone('192.0.2.1'))
        self.assertRaises(ValueError, DnsCheck.get_ptr_zone, '192.0.2')

    def test_is_authoritative(self):
        self.assertRaises(ipaddress.AddressValueError,
                          self.dns.is_authoritative, 'x.x.x.x')
        self.assertTrue(self.dns.is_authoritative('192.0.2.1'))
        self.assertTrue(self.dns.is_authoritative('192.0.2.255'))
        self.assertFalse(self.dns.is_authoritative('89.216.119.169'))
        self.assertFalse(self.dns.is_authoritative('109.122.98.1'))
        self.assertFalse(self.dns.is_authoritative('1.1.1.1'))

    def test_check_status(self):
        self.assertRaises(ipaddress.AddressValueError, self.dns.get_status,
                          'x.x.x.x', 'test')
        # OK PTR
        self.assertEqual(
            DnsCheck.STATUS_OK,
            self.dns.get_status('192.0.2.1', 'host1.domain.example.')[1])
        # Authoritative
        # Wrong PTR
        self.assertEqual(
            DnsCheck.STATUS_NOT_UPDATED,
            self.dns.get_status('192.0.2.22', 'localhost.domain.example.')[1])
        # No PTR
        self.assertEqual(
            DnsCheck.STATUS_NOT_CREATED,
            self.dns.get_status('192.0.2.4', 'host4.domain.example.')[1])
        # Not authoritative
        # Wrong PTR
        self.assertEqual(
            DnsCheck.STATUS_NOT_AUTHORITATIVE,
            self.dns.get_status('8.8.8.8', 'wrong.domain.example.')[1])
        # No PTR
        self.assertEqual(
            DnsCheck.STATUS_NOT_AUTHORITATIVE,
            self.dns.get_status('8.8.8.255', 'empty.domain.example.')[1])

        # Wrong IP
        self.assertRaises(ValueError, self.dns.get_status, '192.0.2',
                          'something.domain.example.')
class TestDnsConnector(unittest.TestCase):
    def setUp(self):
        logging.basicConfig(
            filename='test/unittest.log',
            format="%(asctime)s - %(levelname)s - %(name)s:%(funcName)s - %(message)s",
            level=logging.DEBUG,
            filemode='w'
        )
        self.dispatcher = Dispatcher(Config(filename='test/configuration_examples/configuration.json'))
        self.connector = DnsConnector(self.dispatcher)
        self.dns = DnsCheck(config=Config('test/configuration_examples/configuration.json'))

    def test_create(self):
        ptr_dict = {
            'ip_address': u'192.0.2.255',
            'hostname': 'host255.domain.example',
            'if_name': 'Ethernet2/5/5',
            'ptr': 'host255-et2-5-5.domain.example.'
        }
        ptr = Ptr(**ptr_dict)
        self.connector.create_ptr(ptr)
        self.assertEquals('host255-et2-5-5.domain.example.', self.dns.get_ptr('192.0.2.255'))

    def test_update(self):
        ptr_dict = {
            'ip_address': u'192.0.2.255',
            'hostname': 'host255.domain.example',
            'if_name': 'Ethernet2/5/5',
            'ptr': 'host255-et2-5-5.domain.example.'
        }
        ptr = Ptr(**ptr_dict)
        self.connector.create_ptr(ptr)
        self.assertEquals('host255-et2-5-5.domain.example.', self.dns.get_ptr('192.0.2.255'))
        ptr_dict['ptr'] = 'host-et2-5-5.domain.example.'
        ptr = Ptr(**ptr_dict)
        self.connector.create_ptr(ptr)
        self.assertEquals('host-et2-5-5.domain.example.', self.dns.get_ptr('192.0.2.255'))

    def test_delete(self):
        self.connector.delete_ptr('192.0.2.255')
        self.assertNotEquals('host-et2-5-5.domain.example.', self.dns.get_ptr('192.0.2.255'))
        self.assertNotEquals('host255-et2-5-5.domain.example.', self.dns.get_ptr('192.0.2.255'))

    def test_multiple_delete(self):
        ptr1_dict = {
            'ip_address': u'192.0.2.201',
            'hostname': 'host201.domain.example',
            'if_name': 'Ethernet2/0/1',
            'ptr': 'host201-et2-0-1.domain.example.'
        }
        ptr2_dict = {
            'ip_address': u'192.0.2.202',
            'hostname': 'host202.domain.example',
            'if_name': 'Ethernet2/0/2',
            'ptr': 'host202-et2-0-2.domain.example.'
        }
        ptr3_dict = {
            'ip_address': u'192.0.2.203',
            'hostname': 'host203.domain.example',
            'if_name': 'Ethernet2/0/3',
            'ptr': 'host203-et2-0-3.domain.example.'
        }
        ptr1 = Ptr(**ptr1_dict)
        ptr2 = Ptr(**ptr2_dict)
        ptr3 = Ptr(**ptr3_dict)

        self.connector.create_ptr(ptr1)
        self.connector.create_ptr(ptr2)
        self.connector.create_ptr(ptr3)
        self.assertEquals('host201-et2-0-1.domain.example.', self.dns.get_ptr('192.0.2.201'))
        self.assertEquals('host202-et2-0-2.domain.example.', self.dns.get_ptr('192.0.2.202'))
        self.assertEquals('host203-et2-0-3.domain.example.', self.dns.get_ptr('192.0.2.203'))
        self.connector.delete_ptrs(['192.0.2.201','192.0.2.202','192.0.2.203'])
        self.assertNotEquals('host201-et2-0-1.domain.example.', self.dns.get_ptr('192.0.2.201'))
        self.assertNotEquals('host202-et2-0-2.domain.example.', self.dns.get_ptr('192.0.2.202'))
        self.assertNotEquals('host203-et2-0-3.domain.example.', self.dns.get_ptr('192.0.2.203'))