def test_parse_leases_parses_lease(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ lease %(ip)s { starts 5 2010/01/01 00:00:01; ends never; tstp 6 2010/01/02 05:00:00; tsfp 6 2010/01/02 05:00:00; atsfp 6 2010/01/02 05:00:00; cltt 1 2010/01/02 05:00:00; binding state free; next binding state free; rewind binding state free; hardware ethernet %(mac)s; uid "\001\000\234\002\242\2020"; set vendorclass = "PXEClient:Arch:00000:UNDI:002001"; client-hostname foo; abandoned; option agent.circuit-id thing; option agent.remote-id thing; ddns-text foo; ddns-fwd-name foo; ddns-client-fqdn foo; ddns-rev-name foo; vendor-class-identifier foo; bootp; reserved; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_parses_lease(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ lease %(ip)s { starts 5 2010/01/01 00:00:01; ends never; tstp 6 2010/01/02 05:00:00; tsfp 6 2010/01/02 05:00:00; atsfp 6 2010/01/02 05:00:00; cltt 1 2010/01/02 05:00:00; binding state free; next binding state free; rewind binding state free; hardware ethernet %(mac)s; uid "\001\000\234\002\242\2020"; set vendorclass = "PXEClient:Arch:00000:UNDI:002001"; client-hostname foo; abandoned; option agent.circuit-id thing; option agent.remote-id thing; ddns-text foo; ddns-fwd-name foo; ddns-client-fqdn foo; ddns-rev-name foo; vendor-class-identifier foo; bootp; reserved; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_parses_host_rubout(self): leases = parse_leases(dedent("""\ host %s { deleted; } """ % factory.getRandomIPAddress())) self.assertEqual({}, leases)
def test_parse_leases_parses_host_rubout(self): leases = parse_leases( dedent("""\ host %s { deleted; } """ % factory.getRandomIPAddress())) self.assertEqual({}, leases)
def test_parse_leases_treats_missing_end_date_as_eternity(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ lease %(ip)s { hardware ethernet %(mac)s; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_treats_missing_end_date_as_eternity(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ lease %(ip)s { hardware ethernet %(mac)s; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_ignores_expired_leases(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ lease %(ip)s { hardware ethernet %(mac)s; ends 1 2001/01/01 00:00:00; } """ % params)) self.assertEqual({}, leases)
def test_host_declaration_is_like_an_unexpired_lease(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ host %(ip)s { hardware ethernet %(mac)s; fixed-address %(ip)s; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_ignores_expired_leases(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ lease %(ip)s { hardware ethernet %(mac)s; ends 1 2001/01/01 00:00:00; } """ % params)) self.assertEqual({}, leases)
def test_host_declaration_is_like_an_unexpired_lease(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ host %(ip)s { hardware ethernet %(mac)s; fixed-address %(ip)s; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_parses_host(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ host %(ip)s { dynamic; hardware ethernet %(mac)s; fixed-address %(ip)s; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_recognizes_host_deleted_statement_as_rubout(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ host %(ip)s { dynamic; hardware ethernet %(mac)s; fixed-address %(ip)s; deleted; } """ % params)) self.assertEqual({}, leases)
def test_parse_leases_parses_host(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ host %(ip)s { dynamic; hardware ethernet %(mac)s; fixed-address %(ip)s; } """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_ignores_comments(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ # Top comment (ignored). lease %(ip)s { # End-of-line comment (ignored). # Comment in lease block (ignored). hardware ethernet %(mac)s; # EOL comment in lease (ignored). } # Comment right after closing brace (ignored). # End comment (ignored). """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_ignores_incomplete_lease_at_end(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), 'incomplete_ip': factory.getRandomIPAddress(), } leases = parse_leases(dedent("""\ lease %(ip)s { hardware ethernet %(mac)s; } lease %(incomplete_ip)s { starts 5 2010/01/01 00:00:05; """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_ignores_incomplete_lease_at_end(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), 'incomplete_ip': factory.getRandomIPAddress(), } leases = parse_leases( dedent("""\ lease %(ip)s { hardware ethernet %(mac)s; } lease %(incomplete_ip)s { starts 5 2010/01/01 00:00:05; """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_ignores_comments(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ # Top comment (ignored). lease %(ip)s { # End-of-line comment (ignored). # Comment in lease block (ignored). hardware ethernet %(mac)s; # EOL comment in lease (ignored). } # Comment right after closing brace (ignored). # End comment (ignored). """ % params)) self.assertEqual({params['ip']: params['mac']}, leases)
def test_parse_leases_recognizes_host_deleted_statement_as_rubout(self): params = { 'ip': factory.getRandomIPAddress(), 'mac': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ host %(ip)s { dynamic; hardware ethernet %(mac)s; fixed-address %(ip)s; deleted; } """ % params)) self.assertEqual({}, leases)
def test_parse_leases_takes_latest_lease_for_address(self): params = { 'ip': factory.getRandomIPAddress(), 'old_owner': factory.getRandomMACAddress(), 'new_owner': factory.getRandomMACAddress(), } leases = parse_leases(dedent("""\ lease %(ip)s { hardware ethernet %(old_owner)s; } lease %(ip)s { hardware ethernet %(new_owner)s; } """ % params)) self.assertEqual({params['ip']: params['new_owner']}, leases)
def test_parse_leases_takes_latest_lease_for_address(self): params = { 'ip': factory.getRandomIPAddress(), 'old_owner': factory.getRandomMACAddress(), 'new_owner': factory.getRandomMACAddress(), } leases = parse_leases( dedent("""\ lease %(ip)s { hardware ethernet %(old_owner)s; } lease %(ip)s { hardware ethernet %(new_owner)s; } """ % params)) self.assertEqual({params['ip']: params['new_owner']}, leases)
def parse_leases_file(): """Parse the DHCP leases file. :return: A tuple: (timestamp, leases). The `timestamp` is the last modification time of the leases file, and `leases` is a dict mapping leased IP addresses to their associated MAC addresses. None will be returned if the DHCP lease file cannot be found. """ try: with open(get_leases_file(), 'rb') as leases_file: contents = leases_file.read().decode('utf-8') return fstat(leases_file.fileno()).st_mtime, parse_leases(contents) except IOError as exception: # Return None only if the exception is a "No such file or # directory" exception. if exception.errno == errno.ENOENT: return None else: raise
def test_parse_leases_copes_with_empty_file(self): self.assertEqual({}, parse_leases(""))