Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EA67B10DE7 for ; Fri, 25 Oct 2013 00:35:08 +0000 (UTC) Received: (qmail 98090 invoked by uid 500); 25 Oct 2013 00:35:08 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 98069 invoked by uid 500); 25 Oct 2013 00:35:08 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 98062 invoked by uid 99); 25 Oct 2013 00:35:08 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 25 Oct 2013 00:35:08 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 7B8AE81CBB0; Fri, 25 Oct 2013 00:35:08 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: yasker@apache.org To: commits@cloudstack.apache.org Message-Id: <2c8f3023ed644351aa3c2e7900acb089@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: git commit: updated refs/heads/master to 1528725 Date: Fri, 25 Oct 2013 00:35:08 +0000 (UTC) Updated Branches: refs/heads/master d63a08d0a -> 152872594 CLOUDSTACK-754: Enable Remote Access VPN for VPC With integration smoke test case. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/15287259 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/15287259 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/15287259 Branch: refs/heads/master Commit: 152872594979f3724c1d59a27b7dc1072d4be174 Parents: d63a08d Author: Sheng Yang Authored: Thu Oct 24 17:33:46 2013 -0700 Committer: Sheng Yang Committed: Thu Oct 24 17:34:41 2013 -0700 ---------------------------------------------------------------------- api/src/com/cloud/network/RemoteAccessVpn.java | 3 +- .../network/vpn/RemoteAccessVpnService.java | 3 +- .../user/vpn/CreateRemoteAccessVpnCmd.java | 17 +- .../api/routing/RemoteAccessVpnCfgCommand.java | 35 +++- .../cloud/network/dao/RemoteAccessVpnDao.java | 3 +- .../network/dao/RemoteAccessVpnDaoImpl.java | 9 + .../cloud/network/dao/RemoteAccessVpnVO.java | 15 +- .../xen/resource/CitrixResourceBase.java | 3 +- .../ExternalFirewallDeviceManagerImpl.java | 2 +- .../network/element/VirtualRouterElement.java | 15 +- .../element/VpcVirtualRouterElement.java | 45 +++++ .../VirtualNetworkApplianceManagerImpl.java | 10 +- .../VpcVirtualNetworkApplianceManager.java | 29 +++ .../VpcVirtualNetworkApplianceManagerImpl.java | 111 ++++++++++- .../network/vpn/RemoteAccessVpnManagerImpl.java | 89 ++++++--- .../MockVpcVirtualNetworkApplianceManager.java | 22 +++ setup/db/db/schema-421to430.sql | 3 + .../debian/vpn/opt/cloud/bin/vpc_vpn_l2tp.sh | 178 ----------------- .../debian/vpn/opt/cloud/bin/vpn_l2tp.sh | 95 ++++++--- test/integration/smoke/test_vpc_vpn.py | 192 +++++++++++++++++++ 20 files changed, 614 insertions(+), 265 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/api/src/com/cloud/network/RemoteAccessVpn.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/RemoteAccessVpn.java b/api/src/com/cloud/network/RemoteAccessVpn.java index 058b2f4..4f61334 100644 --- a/api/src/com/cloud/network/RemoteAccessVpn.java +++ b/api/src/com/cloud/network/RemoteAccessVpn.java @@ -31,6 +31,7 @@ public interface RemoteAccessVpn extends ControlledEntity, InternalIdentity, Ide String getIpRange(); String getIpsecPresharedKey(); String getLocalIp(); - long getNetworkId(); + Long getNetworkId(); + Long getVpcId(); State getState(); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java ---------------------------------------------------------------------- diff --git a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java index 285e714..de7692d 100644 --- a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java +++ b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java @@ -31,7 +31,7 @@ import com.cloud.utils.Pair; public interface RemoteAccessVpnService { static final String RemoteAccessVpnClientIpRangeCK = "remote.access.vpn.client.iprange"; - RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, long networkId) + RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall) throws NetworkRuleConflictException; void destroyRemoteAccessVpnForIp(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException; @@ -47,5 +47,4 @@ public interface RemoteAccessVpnService { List listRemoteAccessVpns(long networkId); RemoteAccessVpn getRemoteAccessVpn(long vpnAddrId); - } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java index ff681a9..523101d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java @@ -126,25 +126,10 @@ public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { return EventTypes.EVENT_REMOTE_ACCESS_VPN_CREATE; } - public long getNetworkId() { - IpAddress ip = _entityMgr.findById(IpAddress.class, getPublicIpId()); - Long ntwkId = null; - - if (ip.getAssociatedWithNetworkId() != null) { - ntwkId = ip.getAssociatedWithNetworkId(); - } - - if (ntwkId == null) { - throw new InvalidParameterValueException("Unable to create remote access vpn for the ipAddress id=" + getPublicIpId() + - " as ip is not associated with any network and no networkId is passed in"); - } - return ntwkId; - } - @Override public void create() { try { - RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall(), getNetworkId()); + RemoteAccessVpn vpn = _ravService.createRemoteAccessVpn(publicIpId, ipRange, getOpenFirewall()); if (vpn != null) { this.setEntityId(vpn.getServerAddressId()); // find uuid for server ip address http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/core/src/com/cloud/agent/api/routing/RemoteAccessVpnCfgCommand.java ---------------------------------------------------------------------- diff --git a/core/src/com/cloud/agent/api/routing/RemoteAccessVpnCfgCommand.java b/core/src/com/cloud/agent/api/routing/RemoteAccessVpnCfgCommand.java index 68d7caf..37278ee 100644 --- a/core/src/com/cloud/agent/api/routing/RemoteAccessVpnCfgCommand.java +++ b/core/src/com/cloud/agent/api/routing/RemoteAccessVpnCfgCommand.java @@ -20,10 +20,13 @@ package com.cloud.agent.api.routing; public class RemoteAccessVpnCfgCommand extends NetworkElementCommand { boolean create; + private boolean vpcEnabled; String vpnServerIp; String ipRange; String presharedKey; String localIp; + private String localCidr; + private String publicInterface; protected RemoteAccessVpnCfgCommand() { this.create = false; @@ -39,12 +42,18 @@ public class RemoteAccessVpnCfgCommand extends NetworkElementCommand { } - public RemoteAccessVpnCfgCommand(boolean create, String vpnServerAddress, String localIp, String ipRange, String ipsecPresharedKey) { + public RemoteAccessVpnCfgCommand(boolean create, String vpnServerAddress, String localIp, String ipRange, String ipsecPresharedKey, boolean vpcEnabled) { this.vpnServerIp = vpnServerAddress; this.ipRange = ipRange; this.presharedKey = ipsecPresharedKey; this.localIp = localIp; this.create = create; + this.vpcEnabled = vpcEnabled; + if (vpcEnabled) { + this.setPublicInterface("eth1"); + } else { + this.setPublicInterface("eth2"); + } } public String getVpnServerIp() { @@ -75,4 +84,28 @@ public class RemoteAccessVpnCfgCommand extends NetworkElementCommand { return localIp; } + public boolean isVpcEnabled() { + return vpcEnabled; + } + + public void setVpcEnabled(boolean vpcEnabled) { + this.vpcEnabled = vpcEnabled; + } + + public String getLocalCidr() { + return localCidr; + } + + public void setLocalCidr(String localCidr) { + this.localCidr = localCidr; + } + + public String getPublicInterface() { + return publicInterface; + } + + public void setPublicInterface(String publicInterface) { + this.publicInterface = publicInterface; + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDao.java b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDao.java index 6e3b483..fd8fde7 100644 --- a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDao.java +++ b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDao.java @@ -24,7 +24,8 @@ import com.cloud.utils.db.GenericDao; public interface RemoteAccessVpnDao extends GenericDao { RemoteAccessVpnVO findByPublicIpAddress(long ipAddressId); RemoteAccessVpnVO findByPublicIpAddressAndState(long ipAddressId, RemoteAccessVpn.State state); - RemoteAccessVpnVO findByAccountAndNetwork(Long accountId, Long zoneId); + RemoteAccessVpnVO findByAccountAndNetwork(Long accountId, Long networkId); + RemoteAccessVpnVO findByAccountAndVpc(Long accountId, Long vpcId); List findByAccount(Long accountId); List listByNetworkId(Long networkId); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDaoImpl.java b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDaoImpl.java index ed732d8..2d85c15 100644 --- a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnDaoImpl.java @@ -40,6 +40,7 @@ public class RemoteAccessVpnDaoImpl extends GenericDaoBase sc = AllFieldsSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("vpcId", vpcId); + return findOneBy(sc); + } + @Override public List findByAccount(Long accountId) { SearchCriteria sc = AllFieldsSearch.create(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java index 2e8ee91..af82281 100644 --- a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java +++ b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java @@ -34,7 +34,7 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { private long accountId; @Column(name="network_id") - private long networkId; + private Long networkId; @Column(name="domain_id") private long domainId; @@ -62,11 +62,14 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { @Column(name="uuid") private String uuid; + @Column(name="vpc_id") + private Long vpcId; + public RemoteAccessVpnVO() { this.uuid = UUID.randomUUID().toString(); } - public RemoteAccessVpnVO(long accountId, long domainId, long networkId, long publicIpId, String localIp, String ipRange, String presharedKey) { + public RemoteAccessVpnVO(long accountId, long domainId, Long networkId, long publicIpId, Long vpcId, String localIp, String ipRange, String presharedKey) { this.accountId = accountId; this.serverAddressId = publicIpId; this.ipRange = ipRange; @@ -76,6 +79,7 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { this.networkId = networkId; this.state = State.Added; this.uuid = UUID.randomUUID().toString(); + this.vpcId = vpcId; } @Override @@ -126,7 +130,7 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { } @Override - public long getNetworkId() { + public Long getNetworkId() { return networkId; } @@ -139,4 +143,9 @@ public class RemoteAccessVpnVO implements RemoteAccessVpn { public String getUuid() { return uuid; } + + @Override + public Long getVpcId() { + return vpcId; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index f16a6f5..0c87e0b 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -2184,11 +2184,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe args += " -s " + cmd.getVpnServerIp(); args += " -l " + cmd.getLocalIp(); args += " -c "; - } else { args += " -d "; args += " -s " + cmd.getVpnServerIp(); } + args += " -C " + cmd.getLocalCidr(); + args += " -i " + cmd.getPublicInterface(); String result = callHostPlugin(conn, "vmops", "routerProxy", "args", args); if (result == null || result.isEmpty()) { return new Answer(cmd, false, "Configure VPN failed"); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java index 32744ef..fa171ab 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java @@ -669,7 +669,7 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl String maskedIpRange = ipRange[0] + "-" + ipRange[1]; - RemoteAccessVpnCfgCommand createVpnCmd = new RemoteAccessVpnCfgCommand(create, ip.getAddress().addr(), vpn.getLocalIp(), maskedIpRange, vpn.getIpsecPresharedKey()); + RemoteAccessVpnCfgCommand createVpnCmd = new RemoteAccessVpnCfgCommand(create, ip.getAddress().addr(), vpn.getLocalIp(), maskedIpRange, vpn.getIpsecPresharedKey(), false); createVpnCmd.setAccessDetail(NetworkElementCommand.ACCOUNT_ID, String.valueOf(network.getAccountId())); createVpnCmd.setAccessDetail(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); Answer answer = _agentMgr.easySend(externalFirewall.getId(), createVpnCmd); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/src/com/cloud/network/element/VirtualRouterElement.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 503ce74..28bfb6f 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -387,8 +387,11 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl @Override public String[] applyVpnUsers(RemoteAccessVpn vpn, List users) throws ResourceUnavailableException { - Network network = _networksDao.findById(vpn.getNetworkId()); + if (vpn.getNetworkId() == null) { + return null; + } + Network network = _networksDao.findById(vpn.getNetworkId()); if (canHandle(network, Service.Vpn)) { List routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); if (routers == null || routers.isEmpty()) { @@ -405,8 +408,11 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl @Override public boolean startVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException { - Network network = _networksDao.findById(vpn.getNetworkId()); + if (vpn.getNetworkId() == null) { + return false; + } + Network network = _networksDao.findById(vpn.getNetworkId()); if (canHandle(network, Service.Vpn)) { List routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); if (routers == null || routers.isEmpty()) { @@ -423,8 +429,11 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl @Override public boolean stopVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException { - Network network = _networksDao.findById(vpn.getNetworkId()); + if (vpn.getNetworkId() == null) { + return false; + } + Network network = _networksDao.findById(vpn.getNetworkId()); if (canHandle(network, Service.Vpn)) { List routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); if (routers == null || routers.isEmpty()) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/src/com/cloud/network/element/VpcVirtualRouterElement.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index b8a8246..1f5846b 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -39,9 +39,11 @@ import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.NetworkModel; import com.cloud.network.PublicIpAddress; +import com.cloud.network.RemoteAccessVpn; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnGateway; import com.cloud.network.VirtualRouterProvider.Type; +import com.cloud.network.VpnUser; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.Site2SiteVpnGatewayDao; @@ -531,4 +533,47 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc return _vpcRouterMgr.stopSite2SiteVpn(conn, routers.get(0)); } + + @Override + public String[] applyVpnUsers(RemoteAccessVpn vpn, List users) throws ResourceUnavailableException { + if (vpn.getVpcId() == null) { + return null; + } + + List routers = _vpcRouterMgr.getVpcRouters(vpn.getVpcId()); + if (routers == null || routers.size() != 1) { + s_logger.debug("Cannot apply vpn users on the backend; virtual router doesn't exist in the network " + vpn.getVpcId()); + return null; + } + return _vpcRouterMgr.applyVpnUsers(vpn, users, routers.get(0)); + } + + @Override + public boolean startVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException { + if (vpn.getVpcId() == null) { + return false; + } + + List routers = _vpcRouterMgr.getVpcRouters(vpn.getVpcId()); + if (routers == null || routers.size() != 1) { + s_logger.debug("Cannot apply vpn users on the backend; virtual router doesn't exist in the network " + vpn.getVpcId()); + return true; + } + return _vpcRouterMgr.startRemoteAccessVpn(vpn, routers.get(0)); + } + + @Override + public boolean stopVpn(RemoteAccessVpn vpn) throws ResourceUnavailableException { + if (vpn.getVpcId() == null) { + return false; + } + + List routers = _vpcRouterMgr.getVpcRouters(vpn.getVpcId()); + if (routers == null || routers.size() != 1) { + s_logger.debug("Cannot apply vpn users on the backend; virtual router doesn't exist in the network " + vpn.getVpcId()); + return true; + } + return _vpcRouterMgr.stopRemoteAccessVpn(vpn, routers.get(0)); + } + } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 5b9d84e..ee4c6f4 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -3342,6 +3342,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } + protected String getVpnCidr(RemoteAccessVpn vpn) + { + Network network = _networkDao.findById(vpn.getNetworkId()); + return network.getCidr(); + } + protected void createApplyVpnCommands(boolean isCreate, RemoteAccessVpn vpn, VirtualRouter router, Commands cmds) { List vpnUsers = _vpnUsersDao.listByAccount(vpn.getAccountId()); @@ -3349,8 +3355,10 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V IpAddress ip = _networkModel.getIp(vpn.getServerAddressId()); + String cidr = getVpnCidr(vpn); RemoteAccessVpnCfgCommand startVpnCmd = new RemoteAccessVpnCfgCommand(isCreate, ip.getAddress().addr(), - vpn.getLocalIp(), vpn.getIpRange(), vpn.getIpsecPresharedKey()); + vpn.getLocalIp(), vpn.getIpRange(), vpn.getIpsecPresharedKey(), (vpn.getVpcId() != null)); + startVpnCmd.setLocalCidr(cidr); startVpnCmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); startVpnCmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java index d12280a..fa34b0d 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManager.java @@ -23,8 +23,10 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; +import com.cloud.network.RemoteAccessVpn; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.VpcVirtualNetworkApplianceService; +import com.cloud.network.VpnUser; import com.cloud.network.vpc.*; import com.cloud.user.Account; import com.cloud.vm.DomainRouterVO; @@ -106,4 +108,31 @@ public interface VpcVirtualNetworkApplianceManager extends VirtualNetworkApplian * @return */ List getVpcRouters(long vpcId); + + /** + * @param vpn + * @param router + * @return + * @throws ResourceUnavailableException + */ + boolean startRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) + throws ResourceUnavailableException; + + /** + * @param vpn + * @param router + * @return + * @throws ResourceUnavailableException + */ + boolean stopRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) + throws ResourceUnavailableException; + + /** + * @param vpn + * @param users + * @param routers + * @return + * @throws ResourceUnavailableException + */ + String[] applyVpnUsers(RemoteAccessVpn vpn, List users, VirtualRouter router) throws ResourceUnavailableException; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 12d90ef..2e0f411 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -39,10 +39,12 @@ import com.cloud.agent.api.SetupGuestNetworkAnswer; import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand; import com.cloud.agent.api.routing.SetNetworkACLCommand; import com.cloud.agent.api.routing.SetSourceNatCommand; import com.cloud.agent.api.routing.SetStaticRouteCommand; import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; +import com.cloud.agent.api.routing.VpnUsersCfgCommand; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.NetworkACLTO; import com.cloud.agent.api.to.NicTO; @@ -52,10 +54,12 @@ import com.cloud.dc.DataCenterVO; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; +import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; import com.cloud.network.IpAddress; @@ -70,15 +74,18 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetwork; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.PublicIpAddress; +import com.cloud.network.RemoteAccessVpn; import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.VirtualRouterProvider; import com.cloud.network.VirtualRouterProvider.Type; import com.cloud.network.VpcVirtualNetworkApplianceService; +import com.cloud.network.VpnUser; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.RemoteAccessVpnVO; import com.cloud.network.dao.Site2SiteCustomerGatewayVO; import com.cloud.network.dao.Site2SiteVpnConnectionDao; import com.cloud.network.dao.Site2SiteVpnGatewayDao; @@ -839,7 +846,13 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian createStaticRouteCommands(staticRouteProfiles, router, cmds); } - //5) REPROGRAM GUEST NETWORK + //5) RE-APPLY ALL REMOTE ACCESS VPNs + RemoteAccessVpnVO vpn = _vpnDao.findByAccountAndVpc(router.getAccountId(), router.getVpcId()); + if (vpn != null) { + createApplyVpnCommands(true, vpn, router, cmds); + } + + //6) REPROGRAM GUEST NETWORK boolean reprogramGuestNtwks = true; if (profile.getParameter(Param.ReProgramGuestNetworks) != null && (Boolean) profile.getParameter(Param.ReProgramGuestNetworks) == false) { @@ -1342,4 +1355,100 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return _routerDao.listByVpcId(vpcId); } + @Override + public String[] applyVpnUsers(RemoteAccessVpn vpn, List users, VirtualRouter router) throws ResourceUnavailableException { + Vpc vpc = _vpcDao.findById(vpn.getVpcId()); + + if (router.getState() != State.Running) { + s_logger.warn("Failed to add/remove Remote Access VPN users: router not in running state"); + throw new ResourceUnavailableException("Failed to add/remove Remote Access VPN users: router not in running state: " + + router.getState(), DataCenter.class, vpc.getZoneId()); + } + + Commands cmds = new Commands(Command.OnError.Continue); + + createApplyVpnUsersCommand(users, router, cmds); + + // Currently we receive just one answer from the agent. In the future we have to parse individual answers and set + // results accordingly + boolean agentResult = sendCommandsToRouter(router, cmds); + + String[] result = new String[users.size()]; + for (int i = 0; i < result.length; i++) { + if (agentResult) { + result[i] = null; + } else { + result[i] = String.valueOf(agentResult); + } + } + + return result; + } + + protected String getVpnCidr(RemoteAccessVpn vpn) + { + if (vpn.getVpcId() == null) { + return super.getVpnCidr(vpn); + } + Vpc vpc = _vpcDao.findById(vpn.getVpcId()); + return vpc.getCidr(); + } + + @Override + public boolean startRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) throws ResourceUnavailableException { + if (router.getState() != State.Running) { + s_logger.warn("Unable to apply remote access VPN configuration, virtual router is not in the right state " + router.getState()); + throw new ResourceUnavailableException("Unable to apply remote access VPN configuration," + + " virtual router is not in the right state", DataCenter.class, router.getDataCenterId()); + } + + Commands cmds = new Commands(Command.OnError.Stop); + createApplyVpnCommands(true, vpn, router, cmds); + + try { + _agentMgr.send(router.getHostId(), cmds); + } catch (OperationTimedoutException e) { + s_logger.debug("Failed to start remote access VPN: ", e); + throw new AgentUnavailableException("Unable to send commands to virtual router ", router.getHostId(), e); + } + Answer answer = cmds.getAnswer("users"); + if (!answer.getResult()) { + s_logger.error("Unable to start vpn: unable add users to vpn in zone " + router.getDataCenterId() + + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + + " due to " + answer.getDetails()); + throw new ResourceUnavailableException("Unable to start vpn: Unable to add users to vpn in zone " + + router.getDataCenterId() + " for account " + vpn.getAccountId() + " on domR: " + + router.getInstanceName() + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId()); + } + answer = cmds.getAnswer("startVpn"); + if (!answer.getResult()) { + s_logger.error("Unable to start vpn in zone " + router.getDataCenterId() + " for account " + + vpn.getAccountId() + " on domR: " + router.getInstanceName() + " due to " + + answer.getDetails()); + throw new ResourceUnavailableException("Unable to start vpn in zone " + router.getDataCenterId() + + " for account " + vpn.getAccountId() + " on domR: " + router.getInstanceName() + + " due to " + answer.getDetails(), DataCenter.class, router.getDataCenterId()); + } + + return true; + } + + @Override + public boolean stopRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) throws ResourceUnavailableException { + boolean result = true; + + if (router.getState() == State.Running) { + Commands cmds = new Commands(Command.OnError.Continue); + createApplyVpnCommands(false, vpn, router, cmds); + result = result && sendCommandsToRouter(router, cmds); + } else if (router.getState() == State.Stopped) { + s_logger.debug("Router " + router + " is in Stopped state, not sending deleteRemoteAccessVpn command to it"); + } else { + s_logger.warn("Failed to delete remote access VPN: domR " + router + " is not in right state " + router.getState()); + throw new ResourceUnavailableException("Failed to delete remote access VPN: domR is not in right state " + + router.getState(), DataCenter.class, router.getDataCenterId()); + } + + return true; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 831223b..504e5e8 100755 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -63,6 +63,8 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.RulesManager; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.dao.VpcDao; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.server.ConfigurationServer; import com.cloud.user.Account; @@ -109,7 +111,7 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc @Inject ConfigurationDao _configDao; @Inject List _vpnServiceProviders; @Inject ConfigurationServer _configServer; - + @Inject VpcDao _vpcDao; int _userLimit; int _pskLength; @@ -117,11 +119,13 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc @Override @DB - public RemoteAccessVpn createRemoteAccessVpn(final long publicIpId, String ipRange, final boolean openFirewall, long networkId) + public RemoteAccessVpn createRemoteAccessVpn(final long publicIpId, String ipRange, boolean openFirewall) throws NetworkRuleConflictException { CallContext ctx = CallContext.current(); final Account caller = ctx.getCallingAccount(); + Long networkId = null; + // make sure ip address exists final PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId); if (ipAddr == null) { @@ -135,32 +139,35 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc } IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId); - _networkMgr.checkIpForService(ipAddress, Service.Vpn, null); - RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId); + networkId = ipAddress.getAssociatedWithNetworkId(); + if (networkId != null) { + _networkMgr.checkIpForService(ipAddress, Service.Vpn, null); + } + + final Long vpcId = ipAddress.getVpcId(); + /* IP Address used for VPC must be the source NAT IP of whole VPC */ + if (vpcId != null && ipAddress.isSourceNat()) { + assert networkId == null; + // No firewall setting for VPC, it would be open internally + openFirewall = false; + } - if (vpnVO != null) { - //if vpn is in Added state, return it to the api - if (vpnVO.getState() == RemoteAccessVpn.State.Added) { - return vpnVO; - } - throw new InvalidParameterValueException("A Remote Access VPN already exists for this public Ip address"); + final boolean openFirewallFinal = openFirewall; + + if (networkId == null && vpcId == null) { + throw new InvalidParameterValueException("Unable to create remote access vpn for the ipAddress: " + ipAddr.getAddress().addr() + + " as ip is not associated with any network or VPC"); } - // TODO: assumes one virtual network / domr per account per zone - vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId); + RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId); + if (vpnVO != null) { //if vpn is in Added state, return it to the api if (vpnVO.getState() == RemoteAccessVpn.State.Added) { return vpnVO; } - throw new InvalidParameterValueException("A Remote Access VPN already exists for this account"); - } - - //Verify that vpn service is enabled for the network - Network network = _networkMgr.getNetwork(networkId); - if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) { - throw new InvalidParameterValueException("Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId()); + throw new InvalidParameterValueException("A Remote Access VPN already exists for this public Ip address"); } if (ipRange == null) { @@ -177,7 +184,28 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc throw new InvalidParameterValueException("Invalid ip range " + ipRange); } - Pair cidr = NetUtils.getCidr(network.getCidr()); + Pair cidr = null; + + // TODO: assumes one virtual network / domr per account per zone + if (networkId != null) { + vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId); + if (vpnVO != null) { + //if vpn is in Added state, return it to the api + if (vpnVO.getState() == RemoteAccessVpn.State.Added) { + return vpnVO; + } + throw new InvalidParameterValueException("A Remote Access VPN already exists for this account"); + } + //Verify that vpn service is enabled for the network + Network network = _networkMgr.getNetwork(networkId); + if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) { + throw new InvalidParameterValueException("Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId()); + } + cidr = NetUtils.getCidr(network.getCidr()); + } else { // Don't need to check VPC because there is only one IP(source NAT IP) available for VPN + Vpc vpc = _vpcDao.findById(vpcId); + cidr = NetUtils.getCidr(vpc.getCidr()); + } // FIXME: This check won't work for the case where the guest ip range // changes depending on the vlan allocated. @@ -192,13 +220,15 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc long startIp = NetUtils.ip2Long(range[0]); final String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1]; final String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength); - + return Transaction.execute(new TransactionCallbackWithException() { @Override public RemoteAccessVpn doInTransaction(TransactionStatus status) throws NetworkRuleConflictException { - _rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewall, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT); + if (vpcId == null) { + _rulesMgr.reservePorts(ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewallFinal, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT); + } RemoteAccessVpnVO vpnVO = new RemoteAccessVpnVO(ipAddr.getAccountId(), ipAddr.getDomainId(), ipAddr.getAssociatedWithNetworkId(), - publicIpId, range[0], newIpRange, sharedSecret); + publicIpId, vpcId, range[0], newIpRange, sharedSecret); return _remoteAccessVpnDao.persist(vpnVO); } }); @@ -240,12 +270,9 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc _accountMgr.checkAccess(caller, null, true, vpn); - Network network = _networkMgr.getNetwork(vpn.getNetworkId()); - vpn.setState(RemoteAccessVpn.State.Removed); _remoteAccessVpnDao.update(vpn.getId(), vpn); - boolean success = false; try { for (RemoteAccessVPNServiceProvider element : _vpnServiceProviders) { @@ -258,11 +285,11 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc if (success) { //Cleanup corresponding ports final List vpnFwRules = _rulesDao.listByIpAndPurpose(ipId, Purpose.Vpn); - + boolean applyFirewall = false; final List fwRules = new ArrayList(); //if related firewall rule is created for the first vpn port, it would be created for the 2 other ports as well, so need to cleanup the backend - if (_rulesDao.findByRelatedId(vpnFwRules.get(0).getId()) != null) { + if (vpnFwRules.size() != 0 && _rulesDao.findByRelatedId(vpnFwRules.get(0).getId()) != null) { applyFirewall = true; } @@ -395,11 +422,13 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc if (vpn == null) { throw new InvalidParameterValueException("Unable to find your vpn: " + ipAddressId); } + + if (vpn.getVpcId() != null) { + openFirewall = false; + } _accountMgr.checkAccess(caller, null, true, vpn); - Network network = _networkMgr.getNetwork(vpn.getNetworkId()); - boolean started = false; try { boolean firewallOpened = true; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java index 7f1048f..acdd9dc 100644 --- a/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java +++ b/server/test/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java @@ -426,4 +426,26 @@ VpcVirtualNetworkApplianceService { // TODO Auto-generated method stub return false; } + + @Override + public boolean startRemoteAccessVpn(RemoteAccessVpn vpn, + VirtualRouter router) throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean stopRemoteAccessVpn(RemoteAccessVpn vpn, VirtualRouter router) + throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } + + @Override + public String[] applyVpnUsers(RemoteAccessVpn vpn, + List users, VirtualRouter router) + throws ResourceUnavailableException { + // TODO Auto-generated method stub + return null; + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/setup/db/db/schema-421to430.sql ---------------------------------------------------------------------- diff --git a/setup/db/db/schema-421to430.sql b/setup/db/db/schema-421to430.sql index aaebf96..2a75483 100644 --- a/setup/db/db/schema-421to430.sql +++ b/setup/db/db/schema-421to430.sql @@ -107,6 +107,9 @@ UPDATE `cloud`.`vm_template` SET `state`='Inactive' WHERE `removed` IS NOT NULL; UPDATE `cloud`.`vm_template` SET `state`='Active' WHERE `removed` IS NULL; UPDATE `cloud`.`vm_template` SET `removed`=NULL; +ALTER TABLE `cloud`.`remote_access_vpn` MODIFY COLUMN `network_id` bigint unsigned; +ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `vpc_id` bigint unsigned default NULL; + DROP VIEW IF EXISTS `cloud`.`disk_offering_view`; CREATE VIEW `cloud`.`disk_offering_view` AS select http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/systemvm/patches/debian/vpn/opt/cloud/bin/vpc_vpn_l2tp.sh ---------------------------------------------------------------------- diff --git a/systemvm/patches/debian/vpn/opt/cloud/bin/vpc_vpn_l2tp.sh b/systemvm/patches/debian/vpn/opt/cloud/bin/vpc_vpn_l2tp.sh deleted file mode 100755 index 0595869..0000000 --- a/systemvm/patches/debian/vpn/opt/cloud/bin/vpc_vpn_l2tp.sh +++ /dev/null @@ -1,178 +0,0 @@ -#!/bin/bash -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - - - -#set -x -usage() { - printf "Usage:\n" - printf "Create VPN : %s -c -r -l -p -s -D -z < zone cidr> \n" $(basename $0) - printf "Delete VPN : %s -d -l -s -D -z < zone cidr> \n" $(basename $0) - printf "Add VPN User : %s -u \n" $(basename $0) - printf "Remote VPN User: %s -U /etc/ipsec.d/ipsec.any.secrets - sed -i -e "s/^ip range = .*$/ip range = $client_range/" /etc/xl2tpd/xl2tpd.conf - sed -i -e "s/^local ip = .*$/local ip = $local_ip/" /etc/xl2tpd/xl2tpd.conf - - sed -i -e "s/^ms-dns.*$/ms-dns $local_ip/" /etc/ppp/options.xl2tpd - - iptables_ "-D" $public_ip - iptables_ "-I" $public_ip - - ipsec_server "restart" - - ipsec auto --rereadsecrets - ipsec auto --replace L2TP-PSK -} - -destroy_l2tp_ipsec_vpn_server() { - local public_ip=$1 - - ipsec auto --down L2TP-PSK - - iptables_ "-D" $public_ip - - ipsec_server "stop" -} - -remove_l2tp_ipsec_user() { - local u=$1 - sed -i -e "/^$u .*$/d" /etc/ppp/chap-secrets - if [ -x /usr/bin/tdbdump ]; then - pid=$(tdbdump /var/run/pppd2.tdb | grep -w $u | awk -F';' '{print $4}' | awk -F= '{print $2}') - [ "$pid" != "" ] && kill -9 $pid - fi - return 0 -} - -add_l2tp_ipsec_user() { - local u=$1 - local passwd=$2 - - remove_l2tp_ipsec_user $u - echo "$u * $passwd *" >> /etc/ppp/chap-secrets -} - -rflag= -pflag= -lflag= -sflag= -create= -destroy= -useradd= -userdel= - -while getopts 'cdl:p:r:s:u:U:D:z' OPTION -do - case $OPTION in - c) create=1 - ;; - d) destroy=1 - ;; - u) useradd=1 - user_pwd="$OPTARG" - ;; - U) userdel=1 - user="$OPTARG" - ;; - r) rflag=1 - client_range="$OPTARG" - ;; - p) pflag=1 - ipsec_psk="$OPTARG" - ;; - l) lflag=1 - local_ip="$OPTARG" - ;; - s) sflag=1 - server_ip="$OPTARG" - ;; - D) dev="$OPTARG" - ;; - z) zcidr="$OPTARG" - ;; - ?) usage - exit 2 - ;; - esac -done - -[ "$create$destroy" == "11" ] || [ "$create$destroy$useradd$userdel" == "" ] && usage && exit 2 -[ "$create" == "1" ] && [ "$lflag$pflag$rflag$sflag" != "1111" ] && usage && exit 2 - -if [ "$create" == "1" ]; then - create_l2tp_ipsec_vpn_server $ipsec_psk $server_ip $client_range $local_ip - exit $? -fi - -if [ "$destroy" == "1" ]; then - destroy_l2tp_ipsec_vpn_server $server_ip - exit $? -fi - -if [ "$useradd" == "1" ]; then - u=$(echo $user_pwd | awk -F',' '{print $1}') - pwd=$(echo $user_pwd | awk -F',' '{print $2}') - add_l2tp_ipsec_user $u $pwd - exit $? -fi -if [ "$userdel" == "1" ]; then - remove_l2tp_ipsec_user $user - exit $? -fi http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/systemvm/patches/debian/vpn/opt/cloud/bin/vpn_l2tp.sh ---------------------------------------------------------------------- diff --git a/systemvm/patches/debian/vpn/opt/cloud/bin/vpn_l2tp.sh b/systemvm/patches/debian/vpn/opt/cloud/bin/vpn_l2tp.sh index 79661c8..86148a3 100755 --- a/systemvm/patches/debian/vpn/opt/cloud/bin/vpn_l2tp.sh +++ b/systemvm/patches/debian/vpn/opt/cloud/bin/vpn_l2tp.sh @@ -22,8 +22,8 @@ #set -x usage() { printf "Usage:\n" - printf "Create VPN : %s -c -r -l -p -s \n" $(basename $0) - printf "Delete VPN : %s -d -s \n" $(basename $0) + printf "Create VPN : %s -c -r -l -p -s -i \n" $(basename $0) + printf "Delete VPN : %s -d -l -s -D -C < local cidr> \n" $(basename $0) printf "Add VPN User : %s -u \n" $(basename $0) printf "Remote VPN User: %s -U /dev/null + then + return + fi if sudo iptables -t mangle -N VPN_$public_ip &> /dev/null then @@ -64,17 +66,42 @@ iptables_() { sudo iptables -t mangle $op VPN_$public_ip -p esp -j ACCEPT } +start_ipsec() { + service ipsec status > /dev/null + if [ $? -ne 0 ] + then + service ipsec start > /dev/null + #Wait until ipsec started, 5 seconds at most + for i in {1..5} + do + logger -t cloud "$(basename $0): waiting ipsec start..." + service ipsec status > /dev/null + result=$? + if [ $result -eq 0 ] + then + break + fi + sleep 1 + done + fi + service ipsec status > /dev/null + return $? +} + ipsec_server() { local op=$1 - if [ "$op" == "restart" ]; then - service ipsec stop - service xl2tpd stop - service ipsec start - service xl2tpd start - return $? - fi - service ipsec $op - service xl2tpd $op + case $op in + "start") start_ipsec + sudo service xl2tpd start + ;; + "stop") sudo service xl2tpd stop + ;; + "restart") start_ipsec + sudo ipsec auto --rereadall + service xl2tpd stop + service xl2tpd start + ;; + esac } create_l2tp_ipsec_vpn_server() { @@ -135,8 +162,10 @@ create= destroy= useradd= userdel= +dev= +cidr= -while getopts 'cdl:p:r:s:u:U:' OPTION +while getopts 'cdl:p:r:s:u:U:i:C:' OPTION do case $OPTION in c) create=1 @@ -161,12 +190,26 @@ do s) sflag=1 server_ip="$OPTARG" ;; + i) dev="$OPTARG" + ;; + C) cidr="$OPTARG" + ;; ?) usage exit 2 ;; esac done +if [ "$dev" == "" ] +then + $dev="eth2" +fi + +if [ "$cidr" == "" ] +then + $cidr=$(get_intf_ip "eth0") +fi + [ "$create$destroy" == "11" ] || [ "$create$destroy$useradd$userdel" == "" ] && usage && exit 2 [ "$create" == "1" ] && [ "$lflag$pflag$rflag$sflag" != "1111" ] && usage && exit 2 http://git-wip-us.apache.org/repos/asf/cloudstack/blob/15287259/test/integration/smoke/test_vpc_vpn.py ---------------------------------------------------------------------- diff --git a/test/integration/smoke/test_vpc_vpn.py b/test/integration/smoke/test_vpc_vpn.py new file mode 100644 index 0000000..c360884 --- /dev/null +++ b/test/integration/smoke/test_vpc_vpn.py @@ -0,0 +1,192 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" Tests for VPN in VPC +""" +#Import Local Modules +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from nose.plugins.attrib import attr + +class Services: + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + "network_offering": { + "name": "Network offering for internal vpc", + "displaytext": "Network offering for internal vpc", + "guestiptype": "Isolated", + "traffictype": "Guest", + "supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL", + "serviceProviderList": { + "Dhcp": "VpcVirtualRouter", + "Dns": "VpcVirtualRouter", + "Vpn": "VpcVirtualRouter", + "UserData": "VpcVirtualRouter", + "Lb": "InternalLbVM", + "SourceNat": "VpcVirtualRouter", + "StaticNat": "VpcVirtualRouter", + "PortForwarding": "VpcVirtualRouter", + "NetworkACL": "VpcVirtualRouter", + }, + "serviceCapabilityList": { + "SourceNat": {"SupportedSourceNatTypes": "peraccount"}, + "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"} + } + }, + "vpn_user": { + "username": "test", + "password": "password", + } + } + + +class TestVpcVpn(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.apiclient = super(TestVpcVpn, cls).getClsTestClient().getApiClient() + cls.services = Services().services + cls.zone = get_zone(cls.apiclient, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offering"] + ) + cls.account = Account.create(cls.apiclient, services=cls.services["account"]) + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + cls.cleanup = [cls.account] + + @attr(tags=["advanced"]) + def test_vpc_vpn(self): + """Test VPN in VPC""" + + # 0) Get the default network offering for VPC + networkOffering = NetworkOffering.list(self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks") + self.assert_(networkOffering is not None and len(networkOffering) > 0, "No VPC based network offering") + + # 1) Create VPC + vpcOffering = VpcOffering.list(self.apiclient,isdefault=True) + self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found") + self.services["vpc"] = {} + self.services["vpc"]["name"] = "vpc-vpn" + self.services["vpc"]["displaytext"] = "vpc-vpn" + self.services["vpc"]["cidr"] = "10.1.1.0/24" + vpc = VPC.create( + apiclient=self.apiclient, + services=self.services["vpc"], + networkDomain="vpc.vpn", + vpcofferingid=vpcOffering[0].id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.domain.id + ) + self.assert_(vpc is not None, "VPC creation failed") + + # 2) Create network in VPC + self.services["vpcnetwork"] = {} + self.services["vpcnetwork"]["name"] = "vpcntwk" + self.services["vpcnetwork"]["displaytext"] = "vpcntwk" + ntwk = Network.create( + apiclient=self.apiclient, + services=self.services["vpcnetwork"], + accountid=self.account.name, + domainid=self.domain.id, + networkofferingid=networkOffering[0].id, + zoneid=self.zone.id, + vpcid=vpc.id, + gateway="10.1.1.1", + netmask="255.255.255.192" + ) + self.assertIsNotNone(ntwk, "Network failed to create") + self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id)) + + # 3) Deploy a vm + self.services["virtual_machine"]["networkids"] = ntwk.id + vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"], + templateid=self.template.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid= self.domain.id, + serviceofferingid=self.service_offering.id, + ) + self.assert_(vm is not None, "VM failed to deploy") + self.assert_(vm.state == 'Running', "VM is not running") + self.debug("VM %s deployed in VPC %s" %(vm.id, vpc.id)) + + # 4) Enable VPN for VPC + + src_nat_list = PublicIPAddress.list( + self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + listall=True, + issourcenat=True, + vpcid=vpc.id + ) + ip = src_nat_list[0] + vpn = Vpn.create(self.apiclient, + publicipid=ip.id, + account=self.account.name, + domainid=self.account.domainid) + + # 5) Add VPN user for VPC + vpnUser = VpnUser.create(self.apiclient, + account=self.account.name, + domainid=self.account.domainid, + username=self.services["vpn_user"]["username"], + password=self.services["vpn_user"]["password"]) + + # 6) Disable VPN for VPC + vpn.delete(self.apiclient) + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.apiclient, cls.cleanup) + except Exception, e: + raise Exception("Cleanup failed with %s" % e)