cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From yas...@apache.org
Subject git commit: updated refs/heads/master to 1528725
Date Fri, 25 Oct 2013 00:35:08 GMT
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 <sheng.yang@citrix.com>
Authored: Thu Oct 24 17:33:46 2013 -0700
Committer: Sheng Yang <sheng.yang@citrix.com>
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<? extends RemoteAccessVpn> 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, Long> {
     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<RemoteAccessVpnVO> findByAccount(Long accountId);
     List<RemoteAccessVpnVO> 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<RemoteAccessVpnVO, Lo
         AllFieldsSearch = createSearchBuilder();
         AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
         AllFieldsSearch.and("networkId", AllFieldsSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("vpcId", AllFieldsSearch.entity().getVpcId(), SearchCriteria.Op.EQ);
         AllFieldsSearch.and("ipAddress", AllFieldsSearch.entity().getServerAddressId(), SearchCriteria.Op.EQ);
         AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
         AllFieldsSearch.done();
@@ -60,6 +61,14 @@ public class RemoteAccessVpnDaoImpl extends GenericDaoBase<RemoteAccessVpnVO, Lo
         return findOneBy(sc);
     }
 
+    @Override
+    public RemoteAccessVpnVO findByAccountAndVpc(Long accountId, Long vpcId) {
+        SearchCriteria<RemoteAccessVpnVO> sc = AllFieldsSearch.create();
+        sc.setParameters("accountId", accountId);
+        sc.setParameters("vpcId", vpcId);
+        return findOneBy(sc);
+    }
+
 	@Override
 	public List<RemoteAccessVpnVO> findByAccount(Long accountId) {
 		SearchCriteria<RemoteAccessVpnVO> 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<? extends VpnUser> 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<DomainRouterVO> 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<DomainRouterVO> 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<DomainRouterVO> 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<? extends VpnUser> users) throws ResourceUnavailableException {
+    	if (vpn.getVpcId() == null) {
+    		return null;
+    	}
+
+    	List<DomainRouterVO> 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<DomainRouterVO> 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<DomainRouterVO> 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<VpnUserVO> 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<DomainRouterVO> 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<? extends VpnUser> 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<? extends VpnUser> 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<RemoteAccessVPNServiceProvider> _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<String, Integer> cidr = NetUtils.getCidr(network.getCidr());
+        Pair<String, Integer> 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<RemoteAccessVpn, NetworkRuleConflictException>() {
             @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<? extends FirewallRule> vpnFwRules = _rulesDao.listByIpAndPurpose(ipId, Purpose.Vpn);
-
+                
                 boolean applyFirewall = false;
                 final List<FirewallRuleVO> fwRules = new ArrayList<FirewallRuleVO>();
                 //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<? extends VpnUser> 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 <ip range for clients> -l <local ip> -p <ipsec psk> -s <public ip> -D <eth for public ip> -z < zone cidr>  \n" $(basename $0)
-  printf "Delete VPN     : %s -d -l <local ip> -s <public ip> -D <eth for public ip> -z < zone cidr> \n" $(basename $0)
-  printf "Add VPN User   : %s -u <username,password> \n" $(basename $0)
-  printf "Remote VPN User: %s -U <username \n" $(basename $0)
-}
-
-iptables_() {
-  local op=$1
-  local public_ip=$2
-
-  sudo iptables $op INPUT -i $dev -d $public_ip -p udp --dport 500 -j ACCEPT
-  sudo iptables $op INPUT -i $dev -d $public_ip -p udp --dport 4500 -j ACCEPT
-  sudo iptables $op INPUT -i $dev -d $public_ip -p udp --dport 1701 -j ACCEPT
-  sudo iptables $op INPUT -i $dev -p ah -j ACCEPT
-  sudo iptables $op INPUT -i $dev -p esp -j ACCEPT
-  sudo iptables $op FORWARD -i ppp+ -d $zcidr -j ACCEPT
-  sudo iptables $op FORWARD -i ppp+ -o ppp+ -j ACCEPT 
-  sudo iptables $op INPUT -i ppp+ -p udp --dport 53 -j ACCEPT
-  sudo iptables $op INPUT -i ppp+ -p tcp --dport 53 -j ACCEPT
-  sudo iptables -t nat $op PREROUTING -i ppp+ -p udp --dport 53 -j DNAT --to-destination $local_ip
-  sudo iptables -t nat $op PREROUTING -i ppp+ -p tcp --dport 53 -j DNAT --to-destination $local_ip
-}
-
-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
-}
-
-create_l2tp_ipsec_vpn_server() {
-  local ipsec_psk=$1
-  local public_ip=$2
-  local client_range=$3
-  local local_ip=$4
-
-  sed -i -e "s/left=.*$/left=$public_ip/" /etc/ipsec.d/l2tp.conf
-  echo ": PSK \"$ipsec_psk\"" > /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 <ip range for clients> -l <localip> -p <ipsec psk> -s <public ip> \n" $(basename $0)
-  printf "Delete VPN     : %s -d -s <public ip>\n" $(basename $0)
+  printf "Create VPN     : %s -c -r <ip range for clients> -l <local ip> -p <ipsec psk> -s <public ip> -i <eth for public ip> \n" $(basename $0)
+  printf "Delete VPN     : %s -d -l <local ip> -s <public ip> -D <eth for public ip> -C < local cidr> \n" $(basename $0)
   printf "Add VPN User   : %s -u <username,password> \n" $(basename $0)
   printf "Remote VPN User: %s -U <username \n" $(basename $0)
 }
@@ -32,25 +32,27 @@ get_intf_ip() {
   ip addr show $1 | grep -w inet | awk '{print $2}' | awk -F'/' '{print $1}'
 }
 
-
 iptables_() {
    local op=$1
    local public_ip=$2
-   local public_if="eth2"
-   local subnet_if="eth0"
-   local subnet_ip=$(get_intf_ip $subnet_if)
-
-   sudo iptables $op INPUT -i $public_if --dst $public_ip -p udp -m udp --dport 500 -j ACCEPT
-   sudo iptables $op INPUT -i $public_if --dst $public_ip -p udp -m udp --dport 4500 -j ACCEPT
-   sudo iptables $op INPUT -i $public_if --dst $public_ip -p udp -m udp --dport 1701 -j ACCEPT
-   sudo iptables $op INPUT -i eth2 -p ah -j ACCEPT
-   sudo iptables $op INPUT -i eth2 -p esp -j ACCEPT
-   sudo iptables $op FORWARD -i ppp+ -o $subnet_if -j ACCEPT 
-   sudo iptables $op FORWARD -i $subnet_if -o ppp+ -j ACCEPT 
-   sudo iptables $op FORWARD -i ppp+ -o ppp+ -j ACCEPT 
+
+   sudo iptables $op INPUT -i $dev --dst $public_ip -p udp -m udp --dport 500 -j ACCEPT
+   sudo iptables $op INPUT -i $dev --dst $public_ip -p udp -m udp --dport 4500 -j ACCEPT
+   sudo iptables $op INPUT -i $dev --dst $public_ip -p udp -m udp --dport 1701 -j ACCEPT
+   sudo iptables $op INPUT -i $dev -p ah -j ACCEPT
+   sudo iptables $op INPUT -i $dev -p esp -j ACCEPT
+   sudo iptables $op FORWARD -i ppp+ -d $cidr -j ACCEPT
+   sudo iptables $op FORWARD -s $cidr -o ppp+ -j ACCEPT
+   sudo iptables $op FORWARD -i ppp+ -o ppp+ -j ACCEPT
    sudo iptables $op INPUT -i ppp+ -m udp -p udp --dport 53 -j ACCEPT
    sudo iptables $op INPUT -i ppp+ -m tcp -p tcp --dport 53 -j ACCEPT
-   sudo iptables -t nat $op PREROUTING -i ppp+ -p tcp -m tcp --dport 53 -j  DNAT --to-destination $subnet_ip
+   sudo iptables -t nat $op PREROUTING -i ppp+ -p tcp -m tcp --dport 53 -j  DNAT --to-destination $local_ip
+   sudo iptables -t nat $op PREROUTING -i ppp+ -p udp -m udp --dport 53 -j  DNAT --to-destination $local_ip
+
+   if grep "vpcrouter" /var/cache/cloud/cmdline &> /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)


Mime
View raw message