Merge "LBaaS: remove orphan haproxy instances on agent start"
This commit is contained in:
commit
ae4faec587
@ -113,7 +113,7 @@ class HaproxyNSDriver(agent_device_driver.AgentDeviceDriver):
|
||||
self.pool_to_port_id[pool_id] = logical_config['vip']['port']['id']
|
||||
|
||||
@n_utils.synchronized('haproxy-driver')
|
||||
def undeploy_instance(self, pool_id):
|
||||
def undeploy_instance(self, pool_id, cleanup_namespace=False):
|
||||
namespace = get_ns_name(pool_id)
|
||||
ns = ip_lib.IPWrapper(self.root_helper, namespace)
|
||||
pid_path = self._get_state_file_path(pool_id, 'pid')
|
||||
@ -125,6 +125,12 @@ class HaproxyNSDriver(agent_device_driver.AgentDeviceDriver):
|
||||
if pool_id in self.pool_to_port_id:
|
||||
self._unplug(namespace, self.pool_to_port_id[pool_id])
|
||||
|
||||
# delete all devices from namespace;
|
||||
# used when deleting orphans and port_id is not known for pool_id
|
||||
if cleanup_namespace:
|
||||
for device in ns.get_devices(exclude_loopback=True):
|
||||
self.vif_driver.unplug(device.name, namespace=namespace)
|
||||
|
||||
# remove the configuration directory
|
||||
conf_dir = os.path.dirname(self._get_state_file_path(pool_id, ''))
|
||||
if os.path.isdir(conf_dir):
|
||||
@ -326,6 +332,16 @@ class HaproxyNSDriver(agent_device_driver.AgentDeviceDriver):
|
||||
def delete_pool_health_monitor(self, health_monitor, pool_id):
|
||||
self._refresh_device(pool_id)
|
||||
|
||||
def remove_orphans(self, known_pool_ids):
|
||||
if not os.path.exists(self.state_path):
|
||||
return
|
||||
|
||||
orphans = (pool_id for pool_id in os.listdir(self.state_path)
|
||||
if pool_id not in known_pool_ids)
|
||||
for pool_id in orphans:
|
||||
if self.exists(pool_id):
|
||||
self.undeploy_instance(pool_id, cleanup_namespace=True)
|
||||
|
||||
|
||||
# NOTE (markmcclain) For compliance with interface.py which expects objects
|
||||
class Wrap(object):
|
||||
|
@ -123,6 +123,41 @@ class TestHaproxyNSDriver(base.BaseTestCase):
|
||||
mock.call().garbage_collect_namespace()
|
||||
])
|
||||
|
||||
def test_undeploy_instance_with_ns_cleanup(self):
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.driver, '_get_state_file_path'),
|
||||
mock.patch.object(self.driver, 'vif_driver'),
|
||||
mock.patch.object(namespace_driver, 'kill_pids_in_file'),
|
||||
mock.patch('neutron.agent.linux.ip_lib.IPWrapper'),
|
||||
mock.patch('os.path.isdir'),
|
||||
mock.patch('shutil.rmtree')
|
||||
) as (gsp, vif, kill, ip_wrap, isdir, rmtree):
|
||||
device = mock.Mock()
|
||||
device_name = 'port_device'
|
||||
device.name = device_name
|
||||
ip_wrap.return_value.get_devices.return_value = [device]
|
||||
|
||||
self.driver.undeploy_instance('pool_id', cleanup_namespace=True)
|
||||
vif.unplug.assert_called_once_with(device_name,
|
||||
namespace='qlbaas-pool_id')
|
||||
|
||||
def test_remove_orphans(self):
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.driver, 'exists'),
|
||||
mock.patch.object(self.driver, 'undeploy_instance'),
|
||||
mock.patch('os.listdir'),
|
||||
mock.patch('os.path.exists')
|
||||
) as (exists, undeploy, listdir, path_exists):
|
||||
known = ['known1', 'known2']
|
||||
unknown = ['unknown1', 'unknown2']
|
||||
listdir.return_value = known + unknown
|
||||
exists.side_effect = lambda x: x == 'unknown2'
|
||||
|
||||
self.driver.remove_orphans(known)
|
||||
|
||||
undeploy.assert_called_once_with('unknown2',
|
||||
cleanup_namespace=True)
|
||||
|
||||
def test_exists(self):
|
||||
with contextlib.nested(
|
||||
mock.patch.object(self.driver, '_get_state_file_path'),
|
||||
|
Loading…
Reference in New Issue
Block a user