99e398125b
This patch begins work on an 'IPManager' class that further decouples IP/CIDR manipulation from the openstack-ansible configuration handling logic. With this patchset, a new implementation is provided and tested in isolation, with integration into and replacement of existing code set for follow up patchsets. The aim is also to provide a working implementation based on a proposed IP management API for use with plugins. The proposed API is provided as the IPBasePlugin class, and generic expectations of the API are documented there. A few notable changes exist in the new IPManager class versus the existing codebase: - The Queue.Queue class is not used, but rather a plain, randomized list. Reviewing the existing implementation, there does not appear to be a need to use the specialized queue class. - USED_IPS is moved into a set associated with a given IPManager object. The expectation is that dynamic_inventory.py will treat IPManager as a singleton, but this implementation allows for replacing that singleton in test cases, or using multiple instances in some other context. While the lib/ip.py file is not intended to be executed, the python shebang line was provided in order to comply with our tox linting searches. Change-Id: I06729ac2bc1688a39255f2c8ea0d14131b5c2560
151 lines
4.8 KiB
Python
151 lines
4.8 KiB
Python
#!/usr/bin/env python
|
|
import os
|
|
from os import path
|
|
import sys
|
|
import unittest
|
|
|
|
LIB_DIR = path.join(os.getcwd(), 'lib')
|
|
|
|
sys.path.append(LIB_DIR)
|
|
|
|
import ip
|
|
|
|
|
|
class TestIPManager(unittest.TestCase):
|
|
def test_basic_instantiation(self):
|
|
manager = ip.IPManager()
|
|
|
|
self.assertEqual({}, manager.queues)
|
|
self.assertEqual(set(), manager.used)
|
|
|
|
def test_verbose_instantiation(self):
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/24'},
|
|
used_ips=set(['192.168.0.0', '192.168.0.255']))
|
|
self.assertEqual(2, len(manager.used))
|
|
self.assertEqual(254, len(manager.queues['test']))
|
|
|
|
def test__instantiation_with_used_list(self):
|
|
manager = ip.IPManager(used_ips=['192.168.0.0', '192.168.0.255'])
|
|
|
|
self.assertEqual(2, len(manager.used))
|
|
|
|
def test_verbose_instantiation_duplicated_ips(self):
|
|
manager = ip.IPManager(used_ips=['192.168.0.0', '192.168.0.0'])
|
|
|
|
self.assertEqual(1, len(manager.used))
|
|
|
|
def test_deleting_used(self):
|
|
manager = ip.IPManager(used_ips=set(['192.168.1.1']))
|
|
|
|
del manager.used
|
|
|
|
self.assertEqual(set(), manager.used)
|
|
|
|
def test_getitem(self):
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/24'})
|
|
|
|
self.assertEqual(manager.queues['test'], manager['test'])
|
|
|
|
def test_loading_queue(self):
|
|
manager = ip.IPManager()
|
|
manager.load('test', '192.168.0.0/24')
|
|
self.assertEqual(254, len(manager.queues['test']))
|
|
|
|
def test_loading_network_excludes(self):
|
|
manager = ip.IPManager()
|
|
manager.load('test', '192.168.0.0/24')
|
|
self.assertNotIn('192.168.0.0', manager.queues['test'])
|
|
self.assertNotIn('192.168.0.255', manager.queues['test'])
|
|
|
|
def test_loading_used_ips(self):
|
|
manager = ip.IPManager()
|
|
manager.load('test', '192.168.0.0/24')
|
|
|
|
self.assertEqual(2, len(manager.used))
|
|
self.assertIn('192.168.0.0', manager.used)
|
|
self.assertIn('192.168.0.255', manager.used)
|
|
|
|
def test_load_creates_networks(self):
|
|
manager = ip.IPManager()
|
|
manager.load('test', '192.168.0.0/24')
|
|
|
|
self.assertIn('test', manager._networks)
|
|
|
|
def test_loaded_randomly(self):
|
|
manager = ip.IPManager()
|
|
manager.load('test', '192.168.0.0/24')
|
|
|
|
self.assertNotEqual(['192.168.0.1', '192.168.0.2', '192.168.0.3'],
|
|
manager.queues['test'][0:3])
|
|
|
|
def test_getting_ip(self):
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/24'})
|
|
my_ip = manager.get('test')
|
|
|
|
self.assertTrue(my_ip.startswith('192.168.0'))
|
|
self.assertIn(my_ip, manager.used)
|
|
self.assertNotIn(my_ip, manager.queues['test'])
|
|
|
|
def test_getting_ip_from_empty_queue(self):
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/31'})
|
|
# There will only be 1 usable IP address in this range.
|
|
manager.get('test')
|
|
|
|
with self.assertRaises(ip.EmptyQueue):
|
|
manager.get('test')
|
|
|
|
def test_get_ip_from_missing_queue(self):
|
|
manager = ip.IPManager()
|
|
|
|
with self.assertRaises(ip.NoSuchQueue):
|
|
manager.get('management')
|
|
|
|
def test_release_used_ip(self):
|
|
target_ip = '192.168.0.1'
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/31'},
|
|
used_ips=[target_ip])
|
|
|
|
manager.release(target_ip)
|
|
|
|
# No broadcast address on this network, so only the network addr left
|
|
self.assertEqual(1, len(manager.used))
|
|
self.assertNotIn(target_ip, manager.used)
|
|
self.assertIn(target_ip, manager['test'])
|
|
|
|
def test_save_not_implemented(self):
|
|
manager = ip.IPManager()
|
|
|
|
with self.assertRaises(NotImplementedError):
|
|
manager.save()
|
|
|
|
def test_queue_dict_copied(self):
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/31'})
|
|
external = manager.queues
|
|
self.assertIsNot(manager.queues, external)
|
|
self.assertIsNot(manager.queues['test'], external['test'])
|
|
|
|
def test_queue_list_copied(self):
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/31'})
|
|
external = manager['test']
|
|
# test against the internal structure since .queues should
|
|
# itself be making copies
|
|
self.assertIsNot(manager._queues['test'], external)
|
|
|
|
def test_used_ips_copies(self):
|
|
manager = ip.IPManager(used_ips=['192.168.0.1'])
|
|
external = manager.used
|
|
self.assertIsNot(manager._used_ips, external)
|
|
|
|
def test_deleting_used_ips_releases_to_queues(self):
|
|
target_ip = '192.168.0.1'
|
|
manager = ip.IPManager(queues={'test': '192.168.0.0/31'},
|
|
used_ips=[target_ip])
|
|
|
|
del manager.used
|
|
|
|
self.assertIn(target_ip, manager['test'])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|