'unrouted': constants.DOWN
}
+IPSEC_CONNS = 'ipsec_site_connections'
+
def _get_template(template_file):
global JINJA_ENV
'ipsec_site_connections': copy.deepcopy(process.connection_status)
}
+ def update_downed_connections(self, process_id, new_status):
+ """Update info to be reported, if connections just went down.
+
+ If there is no longer any information for a connection (because it
+ has been removed (e.g. due to an admin down of VPN service or IPSec
+ connection), but there was previous status information for the
+ connection, mark the connection as down for reporting purposes.
+ """
+ if process_id in self.process_status_cache:
+ for conn in self.process_status_cache[process_id][IPSEC_CONNS]:
+ if conn not in new_status[IPSEC_CONNS]:
+ new_status[IPSEC_CONNS][conn] = {
+ 'status': constants.DOWN,
+ 'updated_pending_status': True
+ }
+
def report_status(self, context):
status_changed_vpn_services = []
for process in self.processes.values():
previous_status = self.get_process_status_cache(process)
if self.is_status_updated(process, previous_status):
new_status = self.copy_process_status(process)
- self.process_status_cache[process.id] = new_status
+ self.update_downed_connections(process.id, new_status)
status_changed_vpn_services.append(new_status)
+ self.process_status_cache[process.id] = (
+ self.copy_process_status(process))
# We need unset updated_pending status after it
# is reported to the server side
self.unset_updated_pending_status(process)
ikelifetime=480m
keylife=60m
keyingtries=%forever
-{% for ipsec_site_connection in vpnservice.ipsec_site_connections
+{% for ipsec_site_connection in vpnservice.ipsec_site_connections if ipsec_site_connection.admin_state_up
%}conn {{ipsec_site_connection.id}}
# NOTE: a default route is required for %defaultroute to work...
left={{vpnservice.external_ip}}
context, old_ipsec_site_connection, ipsec_site_connection)
return ipsec_site_connection
+ def update_vpnservice(self, context, vpnservice_id, vpnservice):
+ old_vpn_service = self.get_vpnservice(context, vpnservice_id)
+ new_vpn_service = super(
+ VPNDriverPlugin, self).update_vpnservice(context, vpnservice_id,
+ vpnservice)
+ driver = self._get_driver_for_vpnservice(old_vpn_service)
+ driver.update_vpnservice(context, old_vpn_service, new_vpn_service)
+ return new_vpn_service
+
def delete_vpnservice(self, context, vpnservice_id):
vpnservice = self._get_vpnservice(context, vpnservice_id)
super(VPNDriverPlugin, self).delete_vpnservice(context, vpnservice_id)
process_id = _uuid()
self.driver.sync(context, [{'id': process_id}])
self.assertNotIn(process_id, self.driver.processes)
+
+ def test_status_updated_on_connection_admin_down(self):
+ self.driver.process_status_cache = {
+ '1': {
+ 'status': constants.ACTIVE,
+ 'id': 123,
+ 'updated_pending_status': False,
+ 'ipsec_site_connections': {
+ '10': {
+ 'status': constants.ACTIVE,
+ 'updated_pending_status': False,
+ },
+ '20': {
+ 'status': constants.ACTIVE,
+ 'updated_pending_status': False,
+ }
+ }
+ }
+ }
+ # Simulate that there is no longer status for connection '20'
+ # e.g. connection admin down
+ new_status = {
+ 'ipsec_site_connections': {
+ '10': {
+ 'status': constants.ACTIVE,
+ 'updated_pending_status': False
+ }
+ }
+ }
+ self.driver.update_downed_connections('1', new_status)
+ existing_conn = new_status['ipsec_site_connections'].get('10')
+ self.assertIsNotNone(existing_conn)
+ self.assertEqual(constants.ACTIVE, existing_conn['status'])
+ missing_conn = new_status['ipsec_site_connections'].get('20')
+ self.assertIsNotNone(missing_conn)
+ self.assertEqual(constants.DOWN, missing_conn['status'])
+
+ def test_status_updated_on_service_admin_down(self):
+ self.driver.process_status_cache = {
+ '1': {
+ 'status': constants.ACTIVE,
+ 'id': 123,
+ 'updated_pending_status': False,
+ 'ipsec_site_connections': {
+ '10': {
+ 'status': constants.ACTIVE,
+ 'updated_pending_status': False,
+ },
+ '20': {
+ 'status': constants.ACTIVE,
+ 'updated_pending_status': False,
+ }
+ }
+ }
+ }
+ # Simulate that there are no connections now
+ new_status = {
+ 'ipsec_site_connections': {}
+ }
+ self.driver.update_downed_connections('1', new_status)
+ missing_conn = new_status['ipsec_site_connections'].get('10')
+ self.assertIsNotNone(missing_conn)
+ self.assertEqual(constants.DOWN, missing_conn['status'])
+ missing_conn = new_status['ipsec_site_connections'].get('20')
+ self.assertIsNotNone(missing_conn)
+ self.assertEqual(constants.DOWN, missing_conn['status'])
self.driver.delete_vpnservice.assert_called_once_with(
mock.ANY, mock.ANY)
+ def test_update_vpnservice(self, **extras):
+ super(TestVPNDriverPlugin, self).test_update_vpnservice()
+ self.driver.update_vpnservice.assert_called_once_with(
+ mock.ANY, mock.ANY, mock.ANY)
+
@contextlib.contextmanager
def vpnservice_set(self):
"""Test case to create a ipsec_site_connection."""