def __init__(self, conf, logger, servers_per_port): self.conf = conf self.logger = logger self.servers_per_port = servers_per_port self.swift_dir = conf.get('swift_dir', '/etc/swift') self.ring_check_interval = int(conf.get('ring_check_interval', 15)) self.port_pid_state = PortPidState(servers_per_port, logger) bind_ip = conf.get('bind_ip', '0.0.0.0') self.cache = BindPortsCache(self.swift_dir, bind_ip)
def test_bind_ports_cache(self): test_policies = [ StoragePolicy(0, 'aay', True), StoragePolicy(1, 'bee', False), StoragePolicy(2, 'cee', False) ] my_ips = ['1.2.3.4', '2.3.4.5'] other_ips = ['3.4.5.6', '4.5.6.7'] bind_ip = my_ips[1] devs_by_ring_name1 = { 'object': [ # 'aay' { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[0], 'port': 6006 }, { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[0], 'port': 6007 }, { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[1], 'port': 6008 }, None, { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[1], 'port': 6009 } ], 'object-1': [ # 'bee' { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[1], 'port': 6006 }, # dupe { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[0], 'port': 6010 }, { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[1], 'port': 6011 }, { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[1], 'port': 6012 } ], 'object-2': [ # 'cee' { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[0], 'port': 6010 }, # on our IP and a not-us IP { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[0], 'port': 6013 }, None, { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[1], 'port': 6014 }, { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[1], 'port': 6015 } ], } devs_by_ring_name2 = { 'object': [ # 'aay' { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[0], 'port': 6016 }, { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[1], 'port': 6019 } ], 'object-1': [ # 'bee' { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[1], 'port': 6016 }, # dupe { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[1], 'port': 6022 } ], 'object-2': [ # 'cee' { 'id': 0, 'zone': 0, 'region': 1, 'ip': my_ips[0], 'port': 6020 }, { 'id': 0, 'zone': 0, 'region': 1, 'ip': other_ips[1], 'port': 6025 } ], } ring_files = [ ring_name + '.ring.gz' for ring_name in sorted(devs_by_ring_name1) ] def _fake_load(gz_path, stub_objs, metadata_only=False): return RingData(devs=stub_objs[os.path.basename(gz_path)[:-8]], replica2part2dev_id=[], part_shift=24) with mock.patch( 'swift.common.storage_policy.RingData.load' ) as mock_ld, \ patch_policies(test_policies), \ mock.patch('swift.common.storage_policy.whataremyips') \ as mock_whataremyips, \ temptree(ring_files) as tempdir: mock_whataremyips.return_value = my_ips cache = BindPortsCache(tempdir, bind_ip) self.assertEqual([ mock.call(bind_ip), ], mock_whataremyips.mock_calls) mock_whataremyips.reset_mock() mock_ld.side_effect = partial(_fake_load, stub_objs=devs_by_ring_name1) self.assertEqual(set([ 6006, 6008, 6011, 6010, 6014, ]), cache.all_bind_ports_for_node()) self.assertEqual([ mock.call(os.path.join(tempdir, ring_files[0]), metadata_only=True), mock.call(os.path.join(tempdir, ring_files[1]), metadata_only=True), mock.call(os.path.join(tempdir, ring_files[2]), metadata_only=True), ], mock_ld.mock_calls) mock_ld.reset_mock() mock_ld.side_effect = partial(_fake_load, stub_objs=devs_by_ring_name2) self.assertEqual(set([ 6006, 6008, 6011, 6010, 6014, ]), cache.all_bind_ports_for_node()) self.assertEqual([], mock_ld.mock_calls) # but when all the file mtimes are made different, it'll # reload for gz_file in [os.path.join(tempdir, n) for n in ring_files]: os.utime(gz_file, (88, 88)) self.assertEqual(set([ 6016, 6020, ]), cache.all_bind_ports_for_node()) self.assertEqual([ mock.call(os.path.join(tempdir, ring_files[0]), metadata_only=True), mock.call(os.path.join(tempdir, ring_files[1]), metadata_only=True), mock.call(os.path.join(tempdir, ring_files[2]), metadata_only=True), ], mock_ld.mock_calls) mock_ld.reset_mock() # Don't do something stupid like crash if a ring file is missing. os.unlink(os.path.join(tempdir, 'object-2.ring.gz')) self.assertEqual(set([ 6016, 6020, ]), cache.all_bind_ports_for_node()) self.assertEqual([], mock_ld.mock_calls) # whataremyips() is only called in the constructor self.assertEqual([], mock_whataremyips.mock_calls)