From 618d2541c834e8a28337512042016c2e674231c9 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Thu, 28 Jun 2012 19:15:26 -0700 Subject: [PATCH] CS-6840: Add status checking for site 2 site VPN --- .../api/commands/CreateVpnConnectionCmd.java | 4 +- .../api/commands/CreateVpnGatewayCmd.java | 4 +- .../cloud/network/Site2SiteVpnConnection.java | 1 - .../config/opt/cloud/bin/checks2svpn.sh | 31 ++++++++++++ .../config/opt/cloud/bin/ipsectunnel.sh | 48 +++++++++++++++++-- .../element/VpcVirtualRouterElement.java | 12 +---- .../network/vpn/Site2SiteVpnManagerImpl.java | 22 ++++----- 7 files changed, 90 insertions(+), 32 deletions(-) create mode 100755 patches/systemvm/debian/config/opt/cloud/bin/checks2svpn.sh diff --git a/api/src/com/cloud/api/commands/CreateVpnConnectionCmd.java b/api/src/com/cloud/api/commands/CreateVpnConnectionCmd.java index a3ec5c38519..228b70b3d42 100644 --- a/api/src/com/cloud/api/commands/CreateVpnConnectionCmd.java +++ b/api/src/com/cloud/api/commands/CreateVpnConnectionCmd.java @@ -126,12 +126,12 @@ public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { @Override public String getSyncObjType() { - return BaseAsyncCmd.networkSyncObject; + return BaseAsyncCmd.vpcSyncObject; } @Override public Long getSyncObjId() { - return getIp().getAssociatedWithNetworkId(); + return getIp().getVpcId(); } private IpAddress getIp() { diff --git a/api/src/com/cloud/api/commands/CreateVpnGatewayCmd.java b/api/src/com/cloud/api/commands/CreateVpnGatewayCmd.java index cb275841648..050dbdaf2ff 100644 --- a/api/src/com/cloud/api/commands/CreateVpnGatewayCmd.java +++ b/api/src/com/cloud/api/commands/CreateVpnGatewayCmd.java @@ -97,12 +97,12 @@ public class CreateVpnGatewayCmd extends BaseAsyncCmd { @Override public String getSyncObjType() { - return BaseAsyncCmd.networkSyncObject; + return BaseAsyncCmd.vpcSyncObject; } @Override public Long getSyncObjId() { - return getIp().getAssociatedWithNetworkId(); + return getIp().getVpcId(); } private IpAddress getIp() { diff --git a/api/src/com/cloud/network/Site2SiteVpnConnection.java b/api/src/com/cloud/network/Site2SiteVpnConnection.java index f700563f636..d5a615ff0b0 100644 --- a/api/src/com/cloud/network/Site2SiteVpnConnection.java +++ b/api/src/com/cloud/network/Site2SiteVpnConnection.java @@ -6,7 +6,6 @@ public interface Site2SiteVpnConnection { enum State { Pending, Connected, - Disconnecting, Disconnected, Error, } diff --git a/patches/systemvm/debian/config/opt/cloud/bin/checks2svpn.sh b/patches/systemvm/debian/config/opt/cloud/bin/checks2svpn.sh new file mode 100755 index 00000000000..3198824bc1b --- /dev/null +++ b/patches/systemvm/debian/config/opt/cloud/bin/checks2svpn.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +if [ -z $1 ] +then + echo "Fail to find VPN peer address!" + exit 1 +fi + +ipsec auto --status | grep vpn-$1 > /tmp/vpn-$1.status + +cat /tmp/vpn-$1.status | grep "ISAKMP SA established" > /dev/null +isakmpok=$? +if [ $isakmpok -ne 0 ] +then + echo "ISAKMP SA not found" + echo "Site-to-site VPN have not connected" + exit 12 +fi +echo "ISAKMP SA found" + +cat /tmp/vpn-$1.status | grep "IPsec SA established" > /dev/null +ipsecok=$? +if [ $ipsecok -ne 0 ] +then + echo "IPsec SA not found" + echo "Site-to-site VPN have not connected" + exit 11 +fi +echo "IPsec SA found" +echo "Site-to-site VPN have connected" +exit 0 diff --git a/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh b/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh index f3c5baf0108..7426d4b6166 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/ipsectunnel.sh @@ -28,6 +28,14 @@ usage() { #set -x +start_ipsec() { + service ipsec status > /dev/null + if [ $? -ne 0 ] + then + service ipsec start > /dev/null + fi +} + enable_iptable() { sudo iptables -A INPUT -i $outIf -p udp -m udp --dport 500 -j ACCEPT for net in $rightnets @@ -46,17 +54,22 @@ disable_iptable() { ipsec_tunnel_del() { disable_iptable + sudo ipsec auto --down vpn-$rightpeer + sudo ipsec auto --delete vpn-$rightpeer outIp=$leftpeer local vpnconffile=$vpnconfdir/ipsec.vpn-$rightpeer.conf local vpnsecretsfile=$vpnconfdir/ipsec.vpn-$rightpeer.secrets logger -t cloud "$(basename $0): removing configuration for ipsec tunnel to $rightpeer" sudo rm -f $vpnconffile sudo rm -f $vpnsecretsfile + sudo ipsec auto --rereadall } ipsec_tunnel_add() { - outIp=$leftpeer + #need to unify with remote access VPN + start_ipsec + outIp=$leftpeer sudo mkdir -p $vpnconfdir local vpnconffile=$vpnconfdir/ipsec.vpn-$rightpeer.conf local vpnsecretsfile=$vpnconfdir/ipsec.vpn-$rightpeer.secrets @@ -84,21 +97,43 @@ ipsec_tunnel_add() { sudo echo " dpddelay=30" >> $vpnconffile && sudo echo " dpdtimeout=120" >> $vpnconffile && sudo echo " dpdaction=restart" >> $vpnconffile && - sudo echo " auto=start" >> $vpnconffile && + sudo echo " auto=add" >> $vpnconffile && sudo echo "$leftpeer $rightpeer: PSK \"$secret\"" > $vpnsecretsfile && sudo chmod 0400 $vpnsecretsfile enable_iptable - sudo service ipsec restart + sudo ipsec auto --rereadall + sudo ipsec auto --add vpn-$rightpeer + sudo ipsec auto --up vpn-$rightpeer # Prevent NAT on "marked" VPN traffic sudo iptables -D POSTROUTING -t nat -o $outIf -j SNAT --to-source $outIp sudo iptables -D POSTROUTING -t nat -o $outIf -m mark ! --mark $vpnoutmark -j SNAT --to-source $outIp sudo iptables -A POSTROUTING -t nat -o $outIf -m mark ! --mark $vpnoutmark -j SNAT --to-source $outIp - result=$? 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} + do + logger -t cloud "$(basename $0): checking connection status..." + ./checks2svpn.sh $rightpeer + result=$? + if [ $result -eq 0 ] + then + break + fi + sleep 5 + done + if [ $result -eq 0 ] + then + logger -t cloud "$(basename $0): connect to remote successful" + else + logger -t cloud "$(basename $0): fail to connect to remote, status code: $result" + logger -t cloud "$(basename $0): would stop site-to-site VPN connection" + ipsec_tunnel_del + fi return $result } @@ -168,16 +203,19 @@ done < /tmp/iflist rightnets=${rightnets//,/ } +ret=0 #Firewall ports for one-to-one/static NAT if [ "$opflag" == "1" ] then ipsec_tunnel_add + ret=$? elif [ "$opflag" == "2" ] then ipsec_tunnel_del + ret=$? else printf "Invalid action specified, must choose -A or -D to add/del tunnels\n" >&2 unlock_exit 5 $lock $locked fi -unlock_exit 0 $lock $locked +unlock_exit $ret $lock $locked diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index b07a2b5df9e..1b5c28861e5 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -456,11 +456,7 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc return true; } - if (!_vpcRouterMgr.startSite2SiteVpn(conn, routers.get(0))) { - throw new CloudRuntimeException("Failed to apply site-to-site VPN in VPC " + ip.getVpcId()); - } - - return true; + return _vpcRouterMgr.startSite2SiteVpn(conn, routers.get(0)); } @Override @@ -485,10 +481,6 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc return true; } - if (!_vpcRouterMgr.stopSite2SiteVpn(conn, routers.get(0))) { - throw new CloudRuntimeException("Failed to apply site-to-site VPN in VPC " + ip.getVpcId()); - } - - return true; + return _vpcRouterMgr.stopSite2SiteVpn(conn, routers.get(0)); } } diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index eca1d807cd4..6c41ec8cacf 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -20,7 +20,6 @@ import com.cloud.api.commands.ListVpnCustomerGatewaysCmd; import com.cloud.api.commands.ListVpnGatewaysCmd; import com.cloud.api.commands.ResetVpnConnectionCmd; import com.cloud.api.commands.UpdateVpnCustomerGatewayCmd; -import com.cloud.domain.Domain; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; @@ -84,8 +83,6 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnService, Manager { if (ip.getVpcId() == null) { throw new InvalidParameterValueException("The VPN gateway cannot create with ip not belong to VPC"); } - Long domainId = ip.getDomainId(); - Long accountId = ip.getAccountId(); if (_vpnGatewayDao.findByIpAddrId(ipId) != null) { throw new InvalidParameterValueException("The VPN gateway with ip ID " + ipId + " already existed!"); } @@ -148,8 +145,6 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnService, Manager { + vpnGatewayId + " already existed!"); } Site2SiteVpnConnectionVO conn = new Site2SiteVpnConnectionVO(vpnGatewayId, customerGatewayId); - conn.setState(State.Pending); - _vpnConnectionDao.persist(conn); return conn; } @@ -160,6 +155,8 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnService, Manager { throw new InvalidParameterValueException("Site to site VPN connection " + id + " not in correct state(pending or disconnected) to process!"); } + conn.setState(State.Pending); + _vpnConnectionDao.persist(conn); List elements = _networkMgr.getSite2SiteVpnElements(); boolean result = true; for (Site2SiteVpnServiceProvider element : elements) { @@ -173,7 +170,7 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnService, Manager { } conn.setState(State.Error); _vpnConnectionDao.persist(conn); - return null; + throw new ResourceUnavailableException("Failed to apply site-to-site VPN", Site2SiteVpnConnection.class, id); } @Override @@ -268,22 +265,23 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnService, Manager { private void stopVpnConnection(Long id) throws ResourceUnavailableException { Site2SiteVpnConnectionVO conn = _vpnConnectionDao.findById(id); - if (conn.getState() != State.Connected) { + if (conn.getState() != State.Connected && conn.getState() != State.Error) { throw new InvalidParameterValueException("Site to site VPN connection " + id + " not in correct state(connected) to process disconnect!"); } List elements = _networkMgr.getSite2SiteVpnElements(); boolean result = true; - conn.setState(State.Disconnecting); + conn.setState(State.Disconnected); + _vpnConnectionDao.persist(conn); for (Site2SiteVpnServiceProvider element : elements) { result = result & element.stopSite2SiteVpn(conn); } - if (result) { - conn.setState(State.Disconnected); + if (!result) { + conn.setState(State.Error); _vpnConnectionDao.persist(conn); + throw new ResourceUnavailableException("Failed to apply site-to-site VPN", Site2SiteVpnConnection.class, id); } - conn.setState(State.Error); } @Override @@ -293,7 +291,7 @@ public class Site2SiteVpnManagerImpl implements Site2SiteVpnService, Manager { if (conn == null) { throw new InvalidParameterValueException("Fail to find site to site VPN connection " + id + " to reset!"); } - if (conn.getState() == State.Connected) { + if (conn.getState() == State.Connected || conn.getState() == State.Error) { stopVpnConnection(id); } startVpnConnection(id);