from neutron.common import constants as l3_constants
from neutron.i18n import _LE
from neutron.openstack.common import log as logging
-from neutron.openstack.common import periodic_task
LOG = logging.getLogger(__name__)
ha_port['mac_address'])
ri.ha_port = ha_port
- ri._init_keepalived_manager()
+ ri._init_keepalived_manager(self.process_monitor)
ri._add_keepalived_notifiers()
def process_ha_router_removed(self, ri):
ri.ha_network_removed()
-
- def get_ha_routers(self):
- return (router for router in self.router_info.values() if router.is_ha)
-
- @periodic_task.periodic_task
- def _ensure_keepalived_alive(self, context):
- # TODO(amuller): Use external_process.ProcessMonitor
- for router in self.get_ha_routers():
- router.keepalived_manager.revive()
LOG.debug('Error while reading HA state for %s', self.router_id)
return None
- def get_keepalived_manager(self):
- return keepalived.KeepalivedManager(
+ def _init_keepalived_manager(self, process_monitor):
+ self.keepalived_manager = keepalived.KeepalivedManager(
self.router['id'],
keepalived.KeepalivedConf(),
conf_path=self.agent_conf.ha_confs_path,
- namespace=self.ns_name)
-
- def _init_keepalived_manager(self):
- # TODO(Carl) This looks a bit funny, doesn't it?
- self.keepalived_manager = self.get_keepalived_manager()
+ namespace=self.ns_name,
+ process_monitor=process_monitor)
config = self.keepalived_manager.config
config.add_instance(instance)
def spawn_keepalived(self):
- self.keepalived_manager.spawn_or_restart()
+ self.keepalived_manager.spawn()
def disable_keepalived(self):
self.keepalived_manager.disable()
it manage IPv4 addresses. In order to do that, we must delete
the address first as it is autoconfigured by the kernel.
"""
- process = keepalived.KeepalivedManager.get_process(
- self.agent_conf,
- self.router_id,
- self.ns_name,
- self.agent_conf.ha_confs_path)
- if process.active:
- manager = self.get_keepalived_manager()
+ manager = self.keepalived_manager
+ if manager.get_process().active:
conf = manager.get_conf_on_disk()
managed_by_keepalived = conf and ipv6_lladdr in conf
if managed_by_keepalived:
from neutron.agent.linux import external_process
from neutron.agent.linux import utils
from neutron.common import exceptions
-from neutron.i18n import _LW
from neutron.openstack.common import log as logging
VALID_STATES = ['MASTER', 'BACKUP']
PRIMARY_VIP_RANGE_SIZE = 24
# TODO(amuller): Use L3 agent constant when new constants module is introduced.
FIP_LL_SUBNET = '169.254.30.0/23'
+KEEPALIVED_SERVICE_NAME = 'keepalived'
LOG = logging.getLogger(__name__)
"""
def __init__(self, resource_id, config, conf_path='/tmp',
- namespace=None):
+ namespace=None, process_monitor=None):
self.resource_id = resource_id
self.config = config
self.namespace = namespace
+ self.process_monitor = process_monitor
self.conf_path = conf_path
- self.conf = cfg.CONF
self.process = None
- self.spawned = False
def _output_config_file(self):
config_str = self.config.get_config_str()
def spawn(self):
config_path = self._output_config_file()
- self.process = self.get_process(self.conf,
- self.resource_id,
- self.namespace,
- self.conf_path)
-
def callback(pid_file):
cmd = ['keepalived', '-P',
'-f', config_path,
'-r', '%s-vrrp' % pid_file]
return cmd
- self.process.enable(callback, reload_cfg=True)
+ pm = self.get_process(callback=callback)
+ pm.enable(reload_cfg=True)
- self.spawned = True
- LOG.debug('Keepalived spawned with config %s', config_path)
+ self.process_monitor.register(uuid=self.resource_id,
+ service_name=KEEPALIVED_SERVICE_NAME,
+ monitored_process=pm)
- def spawn_or_restart(self):
- if self.process:
- self.restart()
- else:
- self.spawn()
-
- def restart(self):
- if self.process.active:
- self._output_config_file()
- self.process.reload_cfg()
- else:
- LOG.warn(_LW('A previous instance of keepalived seems to be dead, '
- 'unable to restart it, a new instance will be '
- 'spawned'))
- self.process.disable()
- self.spawn()
+ LOG.debug('Keepalived spawned with config %s', config_path)
def disable(self):
- if self.process:
- self.process.disable(sig='15')
- self.spawned = False
+ self.process_monitor.unregister(uuid=self.resource_id,
+ service_name=KEEPALIVED_SERVICE_NAME)
- def revive(self):
- if self.spawned and not self.process.active:
- self.restart()
+ pm = self.get_process()
+ pm.disable(sig='15')
- @classmethod
- def get_process(cls, conf, resource_id, namespace, conf_path):
+ def get_process(self, callback=None):
return external_process.ProcessManager(
- conf,
- resource_id,
- namespace,
- pids_path=conf_path)
+ cfg.CONF,
+ self.resource_id,
+ self.namespace,
+ pids_path=self.conf_path,
+ default_cmd_callback=callback)
from neutron.agent.linux import external_process
from neutron.agent.linux import keepalived
+from neutron.agent.linux import utils
from neutron.tests import base
from neutron.tests.unit.agent.linux import test_keepalived
class KeepalivedManagerTestCase(base.BaseTestCase,
test_keepalived.KeepalivedConfBaseMixin):
- def test_keepalived_spawn(self):
- expected_config = self._get_config()
- manager = keepalived.KeepalivedManager('router1', expected_config,
- conf_path=cfg.CONF.state_path)
- self.addCleanup(manager.disable)
+ def setUp(self):
+ super(KeepalivedManagerTestCase, self).setUp()
+ cfg.CONF.set_override('check_child_processes_interval', 1, 'AGENT')
+
+ self.expected_config = self._get_config()
+ self.process_monitor = external_process.ProcessMonitor(cfg.CONF,
+ 'router')
+ self.manager = keepalived.KeepalivedManager(
+ 'router1', self.expected_config, conf_path=cfg.CONF.state_path,
+ process_monitor=self.process_monitor)
+ self.addCleanup(self.manager.get_process().disable)
+ self.addCleanup(self.process_monitor.stop)
- manager.spawn()
+ def test_keepalived_spawn(self):
+ self.manager.spawn()
process = external_process.ProcessManager(
cfg.CONF,
'router1',
pids_path=cfg.CONF.state_path)
self.assertTrue(process.active)
- self.assertEqual(expected_config.get_config_str(),
- manager.get_conf_on_disk())
+ self.assertEqual(self.expected_config.get_config_str(),
+ self.manager.get_conf_on_disk())
+
+ def test_keepalived_respawns(self):
+ self.manager.spawn()
+ process = self.manager.get_process()
+ self.assertTrue(process.active)
+
+ process.disable(sig='15')
+
+ utils.wait_until_true(
+ lambda: process.active,
+ timeout=5,
+ sleep=0.01,
+ exception=RuntimeError(_("Keepalived didn't respawn")))
self._process_monitor = None
self.create_child_processes_manager('respawn')
self.addCleanup(self.cleanup_spawned_children)
+ self.addCleanup(self._process_monitor.stop)
def create_child_processes_manager(self, action):
cfg.CONF.set_override('check_child_processes_action', action, 'AGENT')
if enable_ha:
self._assert_ha_device(router)
- self.assertTrue(router.keepalived_manager.process.active)
+ self.assertTrue(router.keepalived_manager.get_process().active)
self._delete_router(self.agent, router.router_id)
self._assert_interfaces_deleted_from_ovs()
self._assert_router_does_not_exist(router)
if enable_ha:
- self.assertFalse(router.keepalived_manager.process.active)
+ self.assertFalse(router.keepalived_manager.get_process().active)
def _assert_external_device(self, router):
external_port = router.get_ex_gw_port()