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']
|
self.pool_to_port_id[pool_id] = logical_config['vip']['port']['id']
|
||||||
|
|
||||||
@n_utils.synchronized('haproxy-driver')
|
@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)
|
namespace = get_ns_name(pool_id)
|
||||||
ns = ip_lib.IPWrapper(self.root_helper, namespace)
|
ns = ip_lib.IPWrapper(self.root_helper, namespace)
|
||||||
pid_path = self._get_state_file_path(pool_id, 'pid')
|
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:
|
if pool_id in self.pool_to_port_id:
|
||||||
self._unplug(namespace, self.pool_to_port_id[pool_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
|
# remove the configuration directory
|
||||||
conf_dir = os.path.dirname(self._get_state_file_path(pool_id, ''))
|
conf_dir = os.path.dirname(self._get_state_file_path(pool_id, ''))
|
||||||
if os.path.isdir(conf_dir):
|
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):
|
def delete_pool_health_monitor(self, health_monitor, pool_id):
|
||||||
self._refresh_device(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
|
# NOTE (markmcclain) For compliance with interface.py which expects objects
|
||||||
class Wrap(object):
|
class Wrap(object):
|
||||||
|
@ -123,6 +123,41 @@ class TestHaproxyNSDriver(base.BaseTestCase):
|
|||||||
mock.call().garbage_collect_namespace()
|
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):
|
def test_exists(self):
|
||||||
with contextlib.nested(
|
with contextlib.nested(
|
||||||
mock.patch.object(self.driver, '_get_state_file_path'),
|
mock.patch.object(self.driver, '_get_state_file_path'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user