pyIPAM - Docker Plugin for IPAM written in Python
Jacek Kowalski
2026-03-11 84f4c254b4cc0b0bb3307ec742edf9555c6fd475
Add validate=0 option to allow duplicate address assignments
3 files modified
28 ■■■■■ changed files
README.md 9 ●●●●● patch | view | raw | blame | history
lib/Ipam.py 3 ●●●● patch | view | raw | blame | history
test/IpamPoolTest.py 16 ●●●●● patch | view | raw | blame | history
README.md
@@ -42,6 +42,15 @@
In this mode all IP addresses are handed out from the subnet,
including ones that would be "network address" and "broadcast address"!
`validate=0`
Do not validate duplicate IP address assignment. This IPAM plugin would
then happily hand out already-used addresses if such were manually specified.
This option does not affect automatic assignments.
Note that this module does not track how many times the IP was handed out,
hence if two containers have the same IP and one of them stops,
IP will be marked as free!
## Manual packaging
In order to test this module in development environment, you can build it
lib/Ipam.py
@@ -41,6 +41,7 @@
        if not self.subpool.subnet_of(self.pool):
            raise InputValidationException('Subpool must be a subnet of pool')
        self.validate = self.options.get('validate', '1') == '1'
        self.ptp = self.options.get('ptp', '0') == '1'
        self.allocations = set()
@@ -84,7 +85,7 @@
            raise InputValidationException('Requested address does not belong to a pool')
        address = str(address)
        if self._is_allocated(address):
        if self.validate and self._is_allocated(address):
            raise InputValidationException('Requested address {} is already used'.format(address))
        self.allocations.add(address)
test/IpamPoolTest.py
@@ -310,3 +310,19 @@
        self.assertEqual(pool.allocate(), 'fe80::1/128')
        self.assertEqual(pool.allocate(), 'fe80::2/128')
        self.assertEqual(pool.allocate(), 'fe80::3/128')
class TestPoolWithoutValidation(unittest.TestCase):
    def test_pool_allocate_duplicates_ipv4(self):
        pool = Pool(pool='127.0.0.0/30', options={'validate': '0'})
        self.assertEqual(pool.allocate(), '127.0.0.1/30')
        self.assertEqual(pool.allocate(), '127.0.0.2/30')
        self.assertEqual(pool.allocate('127.0.0.1'), '127.0.0.1/30')
        self.assertEqual(pool.allocate('127.0.0.1'), '127.0.0.1/30')
    def test_pool_allocate_duplicates_ipv6(self):
        pool = Pool(pool='fe80::/126', options={'validate': '0'})
        self.assertEqual(pool.allocate(), 'fe80::1/126')
        self.assertEqual(pool.allocate(), 'fe80::2/126')
        self.assertEqual(pool.allocate(), 'fe80::3/126')
        self.assertEqual(pool.allocate('fe80::1'), 'fe80::1/126')
        self.assertEqual(pool.allocate('fe80::1'), 'fe80::1/126')