S2S VPN: CS-15642: Re-initiate the VPN connections after router reboot

This commit is contained in:
Sheng Yang 2012-08-02 19:39:01 -07:00
parent da9bd84e09
commit 7779097653
4 changed files with 122 additions and 61 deletions

View File

@ -142,7 +142,7 @@ ipsec_tunnel_add() {
sudo echo " esp=$esppolicy" >> $vpnconffile &&
sudo echo " salifetime=${esplifetime}s" >> $vpnconffile &&
sudo echo " pfs=$pfs" >> $vpnconffile &&
sudo echo " keyingtries=3" >> $vpnconffile &&
sudo echo " keyingtries=2" >> $vpnconffile &&
sudo echo " auto=add" >> $vpnconffile &&
sudo echo "$leftpeer $rightpeer: PSK \"$secret\"" > $vpnsecretsfile &&
sudo chmod 0400 $vpnsecretsfile
@ -162,8 +162,8 @@ ipsec_tunnel_add() {
logger -t cloud "$(basename $0): done ipsec tunnel entry for right peer=$rightpeer right networks=$rightnets"
#20 seconds for checking if it's ready
for i in {1..4}
#5 seconds for checking if it's ready
for i in {1..5}
do
logger -t cloud "$(basename $0): checking connection status..."
/opt/cloud/bin/checks2svpn.sh $rightpeer
@ -172,7 +172,7 @@ ipsec_tunnel_add() {
then
break
fi
sleep 5
sleep 1
done
if [ $result -eq 0 ]
then

View File

@ -900,6 +900,7 @@ VirtualMachineGuru<DomainRouterVO>, Listener {
}
}
@DB
protected void updateSite2SiteVpnConnectionState(List<DomainRouterVO> routers) {
for (DomainRouterVO router : routers) {
List<Site2SiteVpnConnectionVO> conns = _s2sVpnMgr.getConnectionsForRouter(router);
@ -949,26 +950,34 @@ VirtualMachineGuru<DomainRouterVO>, Listener {
continue;
}
for (Site2SiteVpnConnectionVO conn : conns) {
if (conn.getState() != Site2SiteVpnConnection.State.Connected &&
conn.getState() != Site2SiteVpnConnection.State.Disconnected) {
continue;
Site2SiteVpnConnectionVO lock = _s2sVpnConnectionDao.acquireInLockTable(conn.getId());
if (lock == null) {
throw new CloudRuntimeException("Unable to acquire lock on " + lock);
}
Site2SiteVpnConnection.State oldState = conn.getState();
Site2SiteCustomerGateway gw = _s2sCustomerGatewayDao.findById(conn.getCustomerGatewayId());
if (answer.isConnected(gw.getGatewayIp())) {
conn.setState(Site2SiteVpnConnection.State.Connected);
} else {
conn.setState(Site2SiteVpnConnection.State.Disconnected);
}
_s2sVpnConnectionDao.persist(conn);
if (oldState != conn.getState()) {
String title = "Site-to-site Vpn Connection to " + gw.getName() +
" just switch from " + oldState + " to " + conn.getState();
String context = "Site-to-site Vpn Connection to " + gw.getName() + " on router " + router.getHostName() +
"(id: " + router.getId() + ") " + " just switch from " + oldState + " to " + conn.getState();
s_logger.info(context);
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_DOMAIN_ROUTER,
router.getDataCenterIdToDeployIn(), router.getPodIdToDeployIn(), title, context);
try {
if (conn.getState() != Site2SiteVpnConnection.State.Connected &&
conn.getState() != Site2SiteVpnConnection.State.Disconnected) {
continue;
}
Site2SiteVpnConnection.State oldState = conn.getState();
Site2SiteCustomerGateway gw = _s2sCustomerGatewayDao.findById(conn.getCustomerGatewayId());
if (answer.isConnected(gw.getGatewayIp())) {
conn.setState(Site2SiteVpnConnection.State.Connected);
} else {
conn.setState(Site2SiteVpnConnection.State.Disconnected);
}
_s2sVpnConnectionDao.persist(conn);
if (oldState != conn.getState()) {
String title = "Site-to-site Vpn Connection to " + gw.getName() +
" just switch from " + oldState + " to " + conn.getState();
String context = "Site-to-site Vpn Connection to " + gw.getName() + " on router " + router.getHostName() +
"(id: " + router.getId() + ") " + " just switch from " + oldState + " to " + conn.getState();
s_logger.info(context);
_alertMgr.sendAlert(AlertManager.ALERT_TYPE_DOMAIN_ROUTER,
router.getDataCenterIdToDeployIn(), router.getPodIdToDeployIn(), title, context);
}
} finally {
_s2sVpnConnectionDao.releaseFromLockTable(lock.getId());
}
}
}
@ -2311,6 +2320,11 @@ VirtualMachineGuru<DomainRouterVO>, Listener {
ConcurrentOperationException, ResourceUnavailableException {
s_logger.debug("Starting router " + router);
if (_itMgr.start(router, params, user, caller, planToDeploy) != null) {
// We don't want the failure of VPN Connection affect the status of router, so we try to make connection only after router start successfully
Long vpcId = router.getVpcId();
if (vpcId != null) {
_s2sVpnMgr.reconnectDisconnectedVpnByVpc(vpcId);
}
return _routerDao.findById(router.getId());
} else {
return null;

View File

@ -11,4 +11,5 @@ public interface Site2SiteVpnManager extends Site2SiteVpnService {
void markDisconnectVpnConnByVpc(long vpcId);
List<Site2SiteVpnConnectionVO> getConnectionsForRouter(DomainRouterVO router);
boolean deleteCustomerGatewayByAccount(long accountId);
void reconnectDisconnectedVpnByVpc(Long vpcId);
}

View File

@ -54,6 +54,7 @@ import com.cloud.utils.IdentityProxy;
import com.cloud.utils.Ternary;
import com.cloud.utils.component.Inject;
import com.cloud.utils.component.Manager;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.JoinBuilder;
@ -251,30 +252,39 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnManager, Manager {
}
@Override
@DB
public Site2SiteVpnConnection startVpnConnection(long id) throws ResourceUnavailableException {
Site2SiteVpnConnectionVO conn = _vpnConnectionDao.findById(id);
if (conn.getState() != State.Pending && conn.getState() != State.Disconnected) {
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(conn, id, "connectionId"));
throw new InvalidParameterValueException("Site to site VPN connection with specified connectionId not in correct state(pending or disconnected) to process!", idList);
Site2SiteVpnConnectionVO conn = _vpnConnectionDao.acquireInLockTable(id);
if (conn == null) {
throw new CloudRuntimeException("Unable to acquire lock on " + conn);
}
try {
if (conn.getState() != State.Pending && conn.getState() != State.Disconnected) {
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(conn, id, "connectionId"));
throw new InvalidParameterValueException("Site to site VPN connection with specified connectionId not in correct state(pending or disconnected) to process!", idList);
}
conn.setState(State.Pending);
_vpnConnectionDao.persist(conn);
List <? extends Site2SiteVpnServiceProvider> elements = _networkMgr.getSite2SiteVpnElements();
boolean result = true;
for (Site2SiteVpnServiceProvider element : elements) {
result = result & element.startSite2SiteVpn(conn);
}
if (result) {
conn.setState(State.Connected);
conn.setState(State.Pending);
_vpnConnectionDao.persist(conn);
return conn;
List <? extends Site2SiteVpnServiceProvider> elements = _networkMgr.getSite2SiteVpnElements();
boolean result = true;
for (Site2SiteVpnServiceProvider element : elements) {
result = result & element.startSite2SiteVpn(conn);
}
if (result) {
conn.setState(State.Connected);
_vpnConnectionDao.persist(conn);
return conn;
}
conn.setState(State.Error);
_vpnConnectionDao.persist(conn);
throw new ResourceUnavailableException("Failed to apply site-to-site VPN", Site2SiteVpnConnection.class, id);
} finally {
_vpnConnectionDao.releaseFromLockTable(conn.getId());
}
conn.setState(State.Error);
_vpnConnectionDao.persist(conn);
throw new ResourceUnavailableException("Failed to apply site-to-site VPN", Site2SiteVpnConnection.class, id);
}
@Override
@ -439,26 +449,35 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnManager, Manager {
return true;
}
@DB
private void stopVpnConnection(Long id) throws ResourceUnavailableException {
Site2SiteVpnConnectionVO conn = _vpnConnectionDao.findById(id);
if (conn.getState() != State.Connected && conn.getState() != State.Error) {
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(conn, id, "vpnConnectionId"));
throw new InvalidParameterValueException("Site to site VPN connection with specified id is not in correct state(connected) to process disconnect!", idList);
Site2SiteVpnConnectionVO conn = _vpnConnectionDao.acquireInLockTable(id);
if (conn == null) {
throw new CloudRuntimeException("Unable to acquire lock on " + conn);
}
try {
if (conn.getState() != State.Connected && conn.getState() != State.Error) {
List<IdentityProxy> idList = new ArrayList<IdentityProxy>();
idList.add(new IdentityProxy(conn, id, "vpnConnectionId"));
throw new InvalidParameterValueException("Site to site VPN connection with specified id is not in correct state(connected) to process disconnect!", idList);
}
List <? extends Site2SiteVpnServiceProvider> elements = _networkMgr.getSite2SiteVpnElements();
boolean result = true;
conn.setState(State.Disconnected);
_vpnConnectionDao.persist(conn);
for (Site2SiteVpnServiceProvider element : elements) {
result = result & element.stopSite2SiteVpn(conn);
}
if (!result) {
conn.setState(State.Error);
conn.setState(State.Disconnected);
_vpnConnectionDao.persist(conn);
throw new ResourceUnavailableException("Failed to apply site-to-site VPN", Site2SiteVpnConnection.class, id);
List <? extends Site2SiteVpnServiceProvider> elements = _networkMgr.getSite2SiteVpnElements();
boolean result = true;
for (Site2SiteVpnServiceProvider element : elements) {
result = result & element.stopSite2SiteVpn(conn);
}
if (!result) {
conn.setState(State.Error);
_vpnConnectionDao.persist(conn);
throw new ResourceUnavailableException("Failed to apply site-to-site VPN", Site2SiteVpnConnection.class, id);
}
} finally {
_vpnConnectionDao.releaseFromLockTable(conn.getId());
}
}
@ -641,15 +660,24 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnManager, Manager {
}
@Override
@DB
public void markDisconnectVpnConnByVpc(long vpcId) {
List<Site2SiteVpnConnectionVO> conns = _vpnConnectionDao.listByVpcId(vpcId);
for (Site2SiteVpnConnectionVO conn : conns) {
if (conn == null) {
continue;
}
if (conn.getState() == Site2SiteVpnConnection.State.Connected) {
conn.setState(Site2SiteVpnConnection.State.Disconnected);
_vpnConnectionDao.persist(conn);
Site2SiteVpnConnectionVO lock = _vpnConnectionDao.acquireInLockTable(conn.getId());
if (lock == null) {
throw new CloudRuntimeException("Unable to acquire lock on " + conn);
}
try {
if (conn.getState() == Site2SiteVpnConnection.State.Connected) {
conn.setState(Site2SiteVpnConnection.State.Disconnected);
_vpnConnectionDao.persist(conn);
}
} finally {
_vpnConnectionDao.releaseFromLockTable(lock.getId());
}
}
}
@ -675,4 +703,22 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnManager, Manager {
}
return result;
}
@Override
public void reconnectDisconnectedVpnByVpc(Long vpcId) {
List<Site2SiteVpnConnectionVO> conns = _vpnConnectionDao.listByVpcId(vpcId);
for (Site2SiteVpnConnectionVO conn : conns) {
if (conn == null) {
continue;
}
if (conn.getState() == Site2SiteVpnConnection.State.Disconnected) {
try {
startVpnConnection(conn.getId());
} catch (ResourceUnavailableException e) {
Site2SiteCustomerGatewayVO gw = _customerGatewayDao.findById(conn.getCustomerGatewayId());
s_logger.warn("Site2SiteVpnManager: Fail to re-initiate VPN connection " + conn.getId() + " which connect to " + gw.getName());
}
}
}
}
}