From ab0d7669d614cd0dbfc47531753f24b05145b86b Mon Sep 17 00:00:00 2001 From: Greg Goodrich Date: Wed, 18 Mar 2020 10:15:20 -0500 Subject: [PATCH] AC-59, AC-60 Adding VPN options for IKE version and IKE split connections. IKE version allows selecting ike (autoselect), ikev1, or ikev2. Split connections gives an option of separating the first right subnet from the rest, and kicking out individual statements for each right subnet for better cross-compatibility. VPN Connections will now get reset when an update is made to a customer gateway. --- .../network/Site2SiteCustomerGateway.java | 4 ++ .../apache/cloudstack/api/ApiConstants.java | 2 + .../user/vpn/CreateVpnCustomerGatewayCmd.java | 14 ++++ .../user/vpn/UpdateVpnCustomerGatewayCmd.java | 14 ++++ .../Site2SiteCustomerGatewayResponse.java | 16 +++++ .../Site2SiteVpnConnectionResponse.java | 16 +++++ .../api/routing/Site2SiteVpnCfgCommand.java | 23 ++++++- .../facade/Site2SiteVpnConfigItem.java | 2 +- .../virtualnetwork/model/Site2SiteVpn.java | 24 ++++++- .../VirtualRoutingResourceTest.java | 6 +- .../dao/Site2SiteCustomerGatewayVO.java | 28 +++++++- .../src/com/cloud/api/ApiResponseHelper.java | 4 ++ .../network/router/CommandSetupHelper.java | 4 +- .../network/vpn/Site2SiteVpnManagerImpl.java | 62 ++++++++++++++--- ...irtualNetworkApplianceManagerImplTest.java | 2 +- setup/db/create-schema.sql | 2 + systemvm/debian/opt/cloud/bin/configure.py | 35 ++++++++-- systemvm/debian/opt/cloud/bin/ipsectunnel.sh | 35 ++++++++-- ui/l10n/ar.js | 2 + ui/l10n/ca.js | 2 + ui/l10n/de_DE.js | 2 + ui/l10n/en.js | 2 + ui/l10n/es.js | 2 + ui/l10n/fr_FR.js | 2 + ui/l10n/hu.js | 2 + ui/l10n/it_IT.js | 2 + ui/l10n/ja_JP.js | 2 + ui/l10n/ko_KR.js | 2 + ui/l10n/nb_NO.js | 2 + ui/l10n/nl_NL.js | 2 + ui/l10n/pl.js | 2 + ui/l10n/pt_BR.js | 2 + ui/l10n/ru_RU.js | 2 + ui/l10n/zh_CN.js | 2 + ui/scripts/docs.js | 8 +++ ui/scripts/network.js | 67 ++++++++++++++++++- 36 files changed, 369 insertions(+), 31 deletions(-) diff --git a/api/src/com/cloud/network/Site2SiteCustomerGateway.java b/api/src/com/cloud/network/Site2SiteCustomerGateway.java index f9a88bdd8453..de83fddf8132 100644 --- a/api/src/com/cloud/network/Site2SiteCustomerGateway.java +++ b/api/src/com/cloud/network/Site2SiteCustomerGateway.java @@ -43,5 +43,9 @@ public interface Site2SiteCustomerGateway extends ControlledEntity, Identity, In public Date getRemoved(); + public Boolean getSplitConnections(); + + public String getIkeVersion(); + String getName(); } diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 03ee7fc1b20b..cf2172e1c7b1 100644 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -543,12 +543,14 @@ public class ApiConstants { public static final String IPSEC_PSK = "ipsecpsk"; public static final String GUEST_IP = "guestip"; public static final String REMOVED = "removed"; + public static final String IKE_VERSION = "ikeversion"; public static final String IKE_POLICY = "ikepolicy"; public static final String ESP_POLICY = "esppolicy"; public static final String IKE_LIFETIME = "ikelifetime"; public static final String ESP_LIFETIME = "esplifetime"; public static final String DPD = "dpd"; public static final String FORCE_ENCAP = "forceencap"; + public static final String SPLIT_CONNECTIONS = "splitconnections"; public static final String FOR_VPC = "forvpc"; public static final String SHRINK_OK = "shrinkok"; public static final String NICIRA_NVP_DEVICE_ID = "nvpdeviceid"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java index 5c2cbfe11288..ff616c419366 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java @@ -92,6 +92,12 @@ public class CreateVpnCustomerGatewayCmd extends BaseAsyncCmd { description = "create site-to-site VPN customer gateway for the project", since = "4.6") private Long projectId; + @Parameter(name = ApiConstants.SPLIT_CONNECTIONS, type = CommandType.BOOLEAN, required = false, description = "For IKEv2, whether to split multiple right subnet cidrs into multiple connection statements.") + private Boolean splitConnections; + + @Parameter(name = ApiConstants.IKE_VERSION, type = CommandType.STRING, required = false, description = "Which IKE Version to use, one of ike (autoselect), ikev1, or ikev2. Defaults to ike") + private String ikeVersion; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -146,6 +152,14 @@ public Long getProjectId() { return projectId; } + public Boolean getSplitConnections() { + return splitConnections; + } + + public String getIkeVersion() { + return ikeVersion; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java index bb5914111b4d..5edbda1a1b0c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java @@ -94,6 +94,12 @@ public class UpdateVpnCustomerGatewayCmd extends BaseAsyncCmd { + "gateway associated with the account for the specified domain.") private Long domainId; + @Parameter(name = ApiConstants.SPLIT_CONNECTIONS, type = CommandType.BOOLEAN, required = false, description = "For IKEv2, whether to split multiple right subnet cidrs into multiple connection statements.") + private Boolean splitConnections; + + @Parameter(name = ApiConstants.IKE_VERSION, type = CommandType.STRING, required = false, description = "Which IKE Version to use, one of ike (autoselect), ikev1, or ikev2. Defaults to ike") + private String ikeVersion; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -140,6 +146,14 @@ public Boolean getDpd() { public Boolean getEncap() { return encap; } + public boolean getSplitConnections() { + return splitConnections; + } + + public String getIkeVersion() { + return ikeVersion; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/response/Site2SiteCustomerGatewayResponse.java b/api/src/org/apache/cloudstack/api/response/Site2SiteCustomerGatewayResponse.java index 232c3f21261c..9e2ddc14f26c 100644 --- a/api/src/org/apache/cloudstack/api/response/Site2SiteCustomerGatewayResponse.java +++ b/api/src/org/apache/cloudstack/api/response/Site2SiteCustomerGatewayResponse.java @@ -102,6 +102,14 @@ public class Site2SiteCustomerGatewayResponse extends BaseResponse implements Co @Param(description = "the date and time the host was removed") private Date removed; + @SerializedName(ApiConstants.SPLIT_CONNECTIONS) + @Param(description = "For IKEv2, whether to split multiple right subnet cidrs into multiple connection statements.") + private Boolean splitConnections; + + @SerializedName(ApiConstants.IKE_VERSION) + @Param(description = "Which IKE Version to use, one of ike (autoselect), ikev1, or ikev2. Defaults to ike") + private String ikeVersion; + public void setId(String id) { this.id = id; } @@ -148,6 +156,14 @@ public void setDpd(Boolean dpd) { public void setEncap(Boolean encap) { this.encap = encap; } + public void setSplitConnections(Boolean splitConnections) { + this.splitConnections = splitConnections; + } + + public void setIkeVersion(String ikeVersion) { + this.ikeVersion = ikeVersion; + } + public void setRemoved(Date removed) { this.removed = removed; } diff --git a/api/src/org/apache/cloudstack/api/response/Site2SiteVpnConnectionResponse.java b/api/src/org/apache/cloudstack/api/response/Site2SiteVpnConnectionResponse.java index c5450a696071..5587d3c55ee4 100644 --- a/api/src/org/apache/cloudstack/api/response/Site2SiteVpnConnectionResponse.java +++ b/api/src/org/apache/cloudstack/api/response/Site2SiteVpnConnectionResponse.java @@ -132,6 +132,14 @@ public class Site2SiteVpnConnectionResponse extends BaseResponse implements Cont @Param(description = "is connection for display to the regular user", since = "4.4", authorized = {RoleType.Admin}) private Boolean forDisplay; + @SerializedName(ApiConstants.SPLIT_CONNECTIONS) + @Param(description = "Split multiple remote networks into multiple phase 2 SAs. Often used with Cisco some products.") + private Boolean splitConnections; + + @SerializedName(ApiConstants.IKE_VERSION) + @Param(description = "Which IKE Version to use, one of ike (autoselect), ikev1, or ikev2. Defaults to ike") + private String ikeVersion; + public void setId(String id) { this.id = id; } @@ -200,6 +208,14 @@ public void setRemoved(Date removed) { this.removed = removed; } + public void setSplitConnections(Boolean splitConnections) { + this.splitConnections = splitConnections; + } + + public void setIkeVersion(String ikeVersion) { + this.ikeVersion = ikeVersion; + } + @Override public void setAccountName(String accountName) { this.accountName = accountName; diff --git a/core/src/com/cloud/agent/api/routing/Site2SiteVpnCfgCommand.java b/core/src/com/cloud/agent/api/routing/Site2SiteVpnCfgCommand.java index 685cf4049c79..f679b75d155d 100644 --- a/core/src/com/cloud/agent/api/routing/Site2SiteVpnCfgCommand.java +++ b/core/src/com/cloud/agent/api/routing/Site2SiteVpnCfgCommand.java @@ -35,6 +35,8 @@ public class Site2SiteVpnCfgCommand extends NetworkElementCommand { private boolean dpd; private boolean passive; private boolean encap; + private boolean splitConnections; + private String ikeVersion; @Override public boolean executeInSequence() { @@ -46,7 +48,8 @@ public Site2SiteVpnCfgCommand() { } public Site2SiteVpnCfgCommand(boolean create, String localPublicIp, String localPublicGateway, String localGuestCidr, String peerGatewayIp, String peerGuestCidrList, - String ikePolicy, String espPolicy, String ipsecPsk, Long ikeLifetime, Long espLifetime, Boolean dpd, boolean passive, boolean encap) { + String ikePolicy, String espPolicy, String ipsecPsk, Long ikeLifetime, Long espLifetime, Boolean dpd, boolean passive, boolean encap, + boolean splitConnections, String ikeVersion) { this.create = create; this.setLocalPublicIp(localPublicIp); this.setLocalPublicGateway(localPublicGateway); @@ -61,6 +64,8 @@ public Site2SiteVpnCfgCommand(boolean create, String localPublicIp, String local this.dpd = dpd; this.passive = passive; this.encap = encap; + this.splitConnections = splitConnections; + this.ikeVersion = ikeVersion; } public boolean isCreate() { @@ -174,4 +179,20 @@ public boolean isPassive() { public void setPassive(boolean passive) { this.passive = passive; } + + public boolean getSplitConnections() { + return splitConnections; + } + + public void setSplitConnections(boolean splitConnections) { + this.splitConnections = splitConnections; + } + + public String getIkeVersion() { + return ikeVersion; + } + + public void setIkeVersion(String ikeVersion) { + this.ikeVersion = ikeVersion; + } } diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/facade/Site2SiteVpnConfigItem.java b/core/src/com/cloud/agent/resource/virtualnetwork/facade/Site2SiteVpnConfigItem.java index 5bb466c59352..badd0d376d12 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/facade/Site2SiteVpnConfigItem.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/facade/Site2SiteVpnConfigItem.java @@ -36,7 +36,7 @@ public List generateConfig(final NetworkElementCommand cmd) { final Site2SiteVpn site2siteVpn = new Site2SiteVpn(command.getLocalPublicIp(), command.getLocalGuestCidr(), command.getLocalPublicGateway(), command.getPeerGatewayIp(), command.getPeerGuestCidrList(), command.getEspPolicy(), command.getIkePolicy(), command.getIpsecPsk(), command.getIkeLifetime(), command.getEspLifetime(), command.isCreate(), command.getDpd(), - command.isPassive(), command.getEncap()); + command.isPassive(), command.getEncap(), command.getSplitConnections(), command.getIkeVersion()); return generateConfigItems(site2siteVpn); } diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/model/Site2SiteVpn.java b/core/src/com/cloud/agent/resource/virtualnetwork/model/Site2SiteVpn.java index 232e99f099ac..9057bf4f2936 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/model/Site2SiteVpn.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/model/Site2SiteVpn.java @@ -21,9 +21,9 @@ public class Site2SiteVpn extends ConfigBase { - private String localPublicIp, localGuestCidr, localPublicGateway, peerGatewayIp, peerGuestCidrList, espPolicy, ikePolicy, ipsecPsk; + private String localPublicIp, localGuestCidr, localPublicGateway, peerGatewayIp, peerGuestCidrList, espPolicy, ikePolicy, ipsecPsk, ikeVersion; private Long ikeLifetime, espLifetime; - private boolean create, dpd, passive, encap; + private boolean create, dpd, passive, encap, splitConnections; public Site2SiteVpn() { super(ConfigBase.SITE2SITEVPN); @@ -31,7 +31,7 @@ public Site2SiteVpn() { public Site2SiteVpn(String localPublicIp, String localGuestCidr, String localPublicGateway, String peerGatewayIp, String peerGuestCidrList, String espPolicy, String ikePolicy, - String ipsecPsk, Long ikeLifetime, Long espLifetime, boolean create, Boolean dpd, boolean passive, boolean encap) { + String ipsecPsk, Long ikeLifetime, Long espLifetime, boolean create, Boolean dpd, boolean passive, boolean encap, boolean splitConnections, String ikeVersion) { super(ConfigBase.SITE2SITEVPN); this.localPublicIp = localPublicIp; this.localGuestCidr = localGuestCidr; @@ -47,6 +47,8 @@ public Site2SiteVpn(String localPublicIp, String localGuestCidr, String localPub this.dpd = dpd; this.passive = passive; this.encap = encap; + this.splitConnections = splitConnections; + this.ikeVersion = ikeVersion; } public String getLocalPublicIp() { @@ -161,4 +163,20 @@ public void setEncap(boolean encap) { this.encap = encap; } + public boolean getSplitConnections() { + return splitConnections; + } + + public void setSplitConnections(boolean splitConnections) { + this.splitConnections = splitConnections; + } + + public String getIkeVersion() { + return ikeVersion; + } + + public void setIkeVersion(String ikeVersion) { + this.ikeVersion = ikeVersion; + } + } diff --git a/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java b/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java index 200f266b9251..6eb30aeeed9e 100644 --- a/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java +++ b/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java @@ -495,17 +495,17 @@ private void verifyArgs(final SetMonitorServiceCommand cmd, final String script, public void testSite2SiteVpnCfgCommand() { _count = 0; - Site2SiteVpnCfgCommand cmd = new Site2SiteVpnCfgCommand(true, "64.10.1.10", "64.10.1.1", "192.168.1.1/16", "124.10.1.10", "192.168.100.1/24", "3des-sha1,aes128-sha1;modp1536", "3des-sha1,aes128-md5", "psk", Long.valueOf(1800), Long.valueOf(1800), true, false, false); + Site2SiteVpnCfgCommand cmd = new Site2SiteVpnCfgCommand(true, "64.10.1.10", "64.10.1.1", "192.168.1.1/16", "124.10.1.10", "192.168.100.1/24", "3des-sha1,aes128-sha1;modp1536", "3des-sha1,aes128-md5", "psk", Long.valueOf(1800), Long.valueOf(1800), true, false, false, false, "ike"); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, ROUTERNAME); Answer answer = _resource.executeRequest(cmd); assertTrue(answer.getResult()); - cmd = new Site2SiteVpnCfgCommand(true, "64.10.1.10", "64.10.1.1", "192.168.1.1/16", "124.10.1.10", "192.168.100.1/24", "3des-sha1,aes128-sha1;modp1536", "3des-sha1,aes128-md5", "psk", Long.valueOf(1800), Long.valueOf(1800), false, true, false); + cmd = new Site2SiteVpnCfgCommand(true, "64.10.1.10", "64.10.1.1", "192.168.1.1/16", "124.10.1.10", "192.168.100.1/24", "3des-sha1,aes128-sha1;modp1536", "3des-sha1,aes128-md5", "psk", Long.valueOf(1800), Long.valueOf(1800), false, true, false, false, "ike"); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, ROUTERNAME); answer = _resource.executeRequest(cmd); assertTrue(answer.getResult()); - cmd = new Site2SiteVpnCfgCommand(false, "64.10.1.10", "64.10.1.1", "192.168.1.1/16", "124.10.1.10", "192.168.100.1/24", "3des-sha1,aes128-sha1;modp1536", "3des-sha1,aes128-md5", "psk", Long.valueOf(1800), Long.valueOf(1800), false, true, false); + cmd = new Site2SiteVpnCfgCommand(false, "64.10.1.10", "64.10.1.1", "192.168.1.1/16", "124.10.1.10", "192.168.100.1/24", "3des-sha1,aes128-sha1;modp1536", "3des-sha1,aes128-md5", "psk", Long.valueOf(1800), Long.valueOf(1800), false, true, false, false, "ike"); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, ROUTERNAME); answer = _resource.executeRequest(cmd); assertTrue(answer.getResult()); diff --git a/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java b/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java index f1d3ef32712d..c8241518d63e 100644 --- a/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java +++ b/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java @@ -79,6 +79,12 @@ public class Site2SiteCustomerGatewayVO implements Site2SiteCustomerGateway { @Column(name = "account_id") private Long accountId; + @Column(name = "split_connections") + private boolean splitConnections; + + @Column(name = "ike_version") + private String ikeVersion; + @Column(name = GenericDao.REMOVED_COLUMN) private Date removed; @@ -86,7 +92,7 @@ public Site2SiteCustomerGatewayVO() { } public Site2SiteCustomerGatewayVO(String name, long accountId, long domainId, String gatewayIp, String guestCidrList, String ipsecPsk, String ikePolicy, - String espPolicy, long ikeLifetime, long espLifetime, boolean dpd, boolean encap) { + String espPolicy, long ikeLifetime, long espLifetime, boolean dpd, boolean encap, boolean splitConnections, String ikeVersion) { this.name = name; this.gatewayIp = gatewayIp; this.guestCidrList = guestCidrList; @@ -100,6 +106,8 @@ public Site2SiteCustomerGatewayVO(String name, long accountId, long domainId, St uuid = UUID.randomUUID().toString(); this.accountId = accountId; this.domainId = domainId; + this.splitConnections = splitConnections; + this.ikeVersion = ikeVersion; } @Override @@ -221,6 +229,24 @@ public long getAccountId() { return accountId; } + @Override + public Boolean getSplitConnections() { + return splitConnections; + } + + public void setSplitConnections(Boolean splitConnections) { + this.splitConnections = splitConnections; + } + + @Override + public String getIkeVersion() { + return ikeVersion; + } + + public void setIkeVersion(String ikeVersion) { + this.ikeVersion = ikeVersion; + } + @Override public Class getEntityType() { return Site2SiteCustomerGateway.class; diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index c10e25983862..af6ddb74b414 100644 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -3146,6 +3146,8 @@ public Site2SiteCustomerGatewayResponse createSite2SiteCustomerGatewayResponse(S response.setDpd(result.getDpd()); response.setEncap(result.getEncap()); response.setRemoved(result.getRemoved()); + response.setIkeVersion(result.getIkeVersion()); + response.setSplitConnections(result.getSplitConnections()); response.setObjectName("vpncustomergateway"); populateAccount(response, result.getAccountId()); @@ -3185,6 +3187,8 @@ public Site2SiteVpnConnectionResponse createSite2SiteVpnConnectionResponse(Site2 response.setEspLifetime(customerGateway.getEspLifetime()); response.setDpd(customerGateway.getDpd()); response.setEncap(customerGateway.getEncap()); + response.setIkeVersion(customerGateway.getIkeVersion()); + response.setSplitConnections(customerGateway.getSplitConnections()); } } diff --git a/server/src/com/cloud/network/router/CommandSetupHelper.java b/server/src/com/cloud/network/router/CommandSetupHelper.java index fe231c3f8c6e..c0ee0792bcdb 100644 --- a/server/src/com/cloud/network/router/CommandSetupHelper.java +++ b/server/src/com/cloud/network/router/CommandSetupHelper.java @@ -911,9 +911,11 @@ public void createSite2SiteVpnCfgCommands(final Site2SiteVpnConnection conn, fin final Long espLifetime = gw.getEspLifetime(); final Boolean dpd = gw.getDpd(); final Boolean encap = gw.getEncap(); + final Boolean splitConnections = gw.getSplitConnections(); + final String ikeVersion = gw.getIkeVersion(); final Site2SiteVpnCfgCommand cmd = new Site2SiteVpnCfgCommand(isCreate, localPublicIp, localPublicGateway, localGuestCidr, peerGatewayIp, peerGuestCidrList, ikePolicy, - espPolicy, ipsecPsk, ikeLifetime, espLifetime, dpd, conn.isPassive(), encap); + espPolicy, ipsecPsk, ikeLifetime, espLifetime, dpd, conn.isPassive(), encap, splitConnections, ikeVersion); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index aebc87174850..a80eff1e5e66 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -45,6 +45,7 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.network.Site2SiteVpnConnection; @@ -229,10 +230,20 @@ public Site2SiteCustomerGateway createCustomerGateway(CreateVpnCustomerGatewayCm throw new InvalidParameterValueException("The customer gateway with name " + name + " already existed!"); } + Boolean splitConnections = cmd.getSplitConnections(); + if (splitConnections == null) { + splitConnections = false; + } + + String ikeVersion = cmd.getIkeVersion(); + if (ikeVersion == null) { + ikeVersion = "ike"; + } + checkCustomerGatewayCidrList(peerCidrList); Site2SiteCustomerGatewayVO gw = - new Site2SiteCustomerGatewayVO(name, accountId, owner.getDomainId(), gatewayIp, peerCidrList, ipsecPsk, ikePolicy, espPolicy, ikeLifetime, espLifetime, dpd, encap); + new Site2SiteCustomerGatewayVO(name, accountId, owner.getDomainId(), gatewayIp, peerCidrList, ipsecPsk, ikePolicy, espPolicy, ikeLifetime, espLifetime, dpd, encap, splitConnections, ikeVersion); _customerGatewayDao.persist(gw); return gw; } @@ -419,14 +430,6 @@ public Site2SiteCustomerGateway updateCustomerGateway(UpdateVpnCustomerGatewayCm } _accountMgr.checkAccess(caller, null, false, gw); - List conns = _vpnConnectionDao.listByCustomerGatewayId(id); - if (conns != null) { - for (Site2SiteVpnConnection conn : conns) { - if (conn.getState() != State.Error) { - throw new InvalidParameterValueException("Unable to update customer gateway with connections in non-Error state!"); - } - } - } String name = cmd.getName(); String gatewayIp = cmd.getGatewayIp(); @@ -476,6 +479,16 @@ public Site2SiteCustomerGateway updateCustomerGateway(UpdateVpnCustomerGatewayCm encap = false; } + Boolean splitConnections = cmd.getSplitConnections(); + if (splitConnections == null) { + splitConnections = false; + } + + String ikeVersion = cmd.getIkeVersion(); + if (ikeVersion == null) { + ikeVersion = "ike"; + } + checkCustomerGatewayCidrList(guestCidrList); long accountId = gw.getAccountId(); @@ -494,7 +507,38 @@ public Site2SiteCustomerGateway updateCustomerGateway(UpdateVpnCustomerGatewayCm gw.setEspLifetime(espLifetime); gw.setDpd(dpd); gw.setEncap(encap); + gw.setSplitConnections(splitConnections); + gw.setIkeVersion(ikeVersion); _customerGatewayDao.persist(gw); + + List conns = _vpnConnectionDao.listByCustomerGatewayId(id); + if (conns != null) { + for (Site2SiteVpnConnection conn : conns) { + try { + _accountMgr.checkAccess(caller, null, false, conn); + } catch (PermissionDeniedException e) { + // Just don't restart this connection, as the user has no rights to it + // Maybe should issue a notification to the system? + s_logger.info("Site2SiteVpnManager:updateCustomerGateway() Not resetting VPN connection " + conn.getId() + " as user lacks permission"); + continue; + } + + if (conn.getState() == State.Pending) { + // Vpn connection cannot be reset when the state is Pending + continue; + } + try { + if (conn.getState() == State.Connected || conn.getState() == State.Error) { + stopVpnConnection(conn.getId()); + } + startVpnConnection(conn.getId()); + } catch (ResourceUnavailableException e) { + // Should never get here, as we are looping on the actual connections, but we must handle it regardless + continue; + } + } + } + return gw; } diff --git a/server/test/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java b/server/test/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java index f87b009c79b5..178514310af3 100644 --- a/server/test/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java +++ b/server/test/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java @@ -275,7 +275,7 @@ public void testUpdateSite2SiteVpnConnectionState() throws Exception{ conns.add(conn); conns.add(conn1); - Site2SiteCustomerGatewayVO gw = new Site2SiteCustomerGatewayVO("Testing gateway", 1L, 1L, "192.168.50.15", "Guest List", "ipsecPsk", "ikePolicy", "espPolicy", 1L, 1L, true, true); + Site2SiteCustomerGatewayVO gw = new Site2SiteCustomerGatewayVO("Testing gateway", 1L, 1L, "192.168.50.15", "Guest List", "ipsecPsk", "ikePolicy", "espPolicy", 1L, 1L, true, true, false, "ike"); HostVO hostVo = new HostVO(1L, "Testing host", Host.Type.Routing, "192.168.50.15", "privateNetmask", "privateMacAddress", "publicIpAddress", "publicNetmask", "publicMacAddress", "storageIpAddress", "storageNetmask", "storageMacAddress", "deuxStorageIpAddress", "duxStorageNetmask", "deuxStorageMacAddress", "guid", Status.Up, "version", "iqn", new Date() , 1L, 1L, 1L, 1L, "parent", 20L, Storage.StoragePoolType.Gluster); hostVo.setManagementServerId(ManagementServerNode.getManagementServerId()); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 7665aec0eeae..3cd09ff58cd3 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -2283,6 +2283,8 @@ CREATE TABLE `cloud`.`s2s_customer_gateway` ( `domain_id` bigint unsigned NOT NULL, `account_id` bigint unsigned NOT NULL, `removed` datetime COMMENT 'date removed if not null', + `ike_version` varchar(5) NOT NULL DEFAULT 'ike' COMMENT 'one of ike, ikev1, ikev2', + `split_connections` int(1) NOT NULL DEFAULT 0, PRIMARY KEY (`id`), CONSTRAINT `fk_s2s_customer_gateway__account_id` FOREIGN KEY (`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_s2s_customer_gateway__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain`(`id`) ON DELETE CASCADE, diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py index a7f297edbb20..80c11a896c34 100755 --- a/systemvm/debian/opt/cloud/bin/configure.py +++ b/systemvm/debian/opt/cloud/bin/configure.py @@ -538,10 +538,18 @@ def configure_ipsec(self, obj): vpnsecretsfile = "%s/ipsec.vpn-%s.secrets" % (self.VPNCONFDIR, rightpeer) ikepolicy = obj['ike_policy'].replace(';', '-') esppolicy = obj['esp_policy'].replace(';', '-') + splitconnections = obj['split_connections'] if 'split_connections' in obj else False + ikeversion = obj['ike_version'] if 'ike_version' in obj and obj['ike_version'].lower() in ('ike', 'ikev1', 'ikev2') else 'ike' + + peerlistarr = peerlist.split(',') + if splitconnections: + logging.debug('Splitting rightsubnets %s' % peerlistarr) + peerlist = peerlistarr[0] if rightpeer in self.confips: self.confips.remove(rightpeer) file = CsFile(vpnconffile) + file.repopulate() # This avoids issues when switching off split_connections or removing subnets with split_connections == true file.add("#conn for vpn-%s" % rightpeer, 0) file.search("conn ", "conn vpn-%s" % rightpeer) file.addeq(" left=%s" % leftpeer) @@ -550,7 +558,7 @@ def configure_ipsec(self, obj): file.addeq(" rightsubnet=%s" % peerlist) file.addeq(" type=tunnel") file.addeq(" authby=secret") - file.addeq(" keyexchange=ike") + file.addeq(" keyexchange=%s" % ikeversion) file.addeq(" ike=%s" % ikepolicy) file.addeq(" ikelifetime=%s" % self.convert_sec_to_h(obj['ike_lifetime'])) file.addeq(" esp=%s" % esppolicy) @@ -564,6 +572,14 @@ def configure_ipsec(self, obj): file.addeq(" dpddelay=30") file.addeq(" dpdtimeout=120") file.addeq(" dpdaction=restart") + if splitconnections and peerlistarr.count > 1: + logging.debug('Splitting connections for rightsubnets %s' % peerlistarr) + for peeridx in range(1, len(peerlistarr)): + logging.debug('Adding split connection -%d for subnet %s' % (peeridx + 1, peerlistarr[peeridx])) + file.append('') + file.search('conn vpn-.*-%d' % (peeridx + 1), "conn vpn-%s-%d" % (rightpeer, peeridx + 1)) + file.append(' also=vpn-%s' % rightpeer) + file.append(' rightsubnet=%s' % peerlistarr[peeridx]) secret = CsFile(vpnsecretsfile) secret.search("%s " % leftpeer, "%s %s : PSK \"%s\"" % (leftpeer, rightpeer, obj['ipsec_psk'])) if secret.is_changed() or file.is_changed(): @@ -577,14 +593,25 @@ def configure_ipsec(self, obj): os.chmod(vpnsecretsfile, 0400) for i in xrange(3): - result = CsHelper.execute('ipsec status vpn-%s | grep "%s"' % (rightpeer, peerlist.split(",", 1)[0])) - if len(result) > 0: + done = True + for peeridx in range(0, len(peerlistarr)): + # Check for the proper connection and subnet + conn = rightpeer if not splitconnections else rightpeer if peeridx == 0 else '%s-%d' % (rightpeer, peeridx + 1) + result = CsHelper.execute('ipsec status vpn-%s | grep "%s"' % (conn, peerlistarr[peeridx])) + # If any of the peers hasn't yet finished, continue the outer loop + if len(result) == 0: + done = False + if done: break time.sleep(1) # With 'auto=route', connections are established on an attempt to # communicate over the S2S VPN. This uses ping to initialize the connection. - CsHelper.execute("timeout 5 ping -c 3 %s" % (peerlist.split("/", 1)[0].replace(".0", ".1"))) + for peer in peerlistarr: + octets = peer.split('/', 1)[0].split('.') + octets[3] = str((int(octets[3]) + 1)) + ipinsubnet = '.'.join(octets) + CsHelper.execute("timeout 5 ping -c 3 %s" % ipinsubnet) def convert_sec_to_h(self, val): hrs = int(val) / 3600 diff --git a/systemvm/debian/opt/cloud/bin/ipsectunnel.sh b/systemvm/debian/opt/cloud/bin/ipsectunnel.sh index c42650f8d1de..ad12efddbdb6 100755 --- a/systemvm/debian/opt/cloud/bin/ipsectunnel.sh +++ b/systemvm/debian/opt/cloud/bin/ipsectunnel.sh @@ -23,7 +23,7 @@ vpnoutmark="0x525" vpninmark="0x524" usage() { - printf "Usage: %s: (-A|-D) -l -n -g -r -N -e -i -t -T -s -d [ -p -c -S ]\n" $(basename $0) >&2 + printf "Usage: %s: (-A|-D) -l -n -g -r -N -e -i -t -T -s -d [ -p -c -S -C -v ]\n" $(basename $0) >&2 } #set -x @@ -139,14 +139,21 @@ ipsec_tunnel_add() { check_and_enable_iptables + rsubnets=" rightsubnets={$rightnets}" + if [ $splitconnections -eq 1 ] + then + rsubnetarr=(${rightnets}) + rsubnets=" rightsubnet=${rsubnetarr[0]}" + fi + sudo echo "conn vpn-$rightpeer" > $vpnconffile && sudo echo " left=$leftpeer" >> $vpnconffile && sudo echo " leftsubnet=$leftnet" >> $vpnconffile && sudo echo " right=$rightpeer" >> $vpnconffile && - sudo echo " rightsubnets={$rightnets}" >> $vpnconffile && + sudo echo $rsubnets >> $vpnconffile && sudo echo " type=tunnel" >> $vpnconffile && sudo echo " authby=secret" >> $vpnconffile && - sudo echo " keyexchange=ike" >> $vpnconffile && + sudo echo " keyexchange=${ikeversion:-ike}" >> $vpnconffile && sudo echo " ike=$ikepolicy" >> $vpnconffile && sudo echo " ikelifetime=${ikelifetime}s" >> $vpnconffile && sudo echo " esp=$esppolicy" >> $vpnconffile && @@ -163,6 +170,20 @@ ipsec_tunnel_add() { sudo echo " dpdaction=restart" >> $vpnconffile fi + if [ $splitconnections -eq 1 ] + then + # Split out all but the first right subnet into their own statements + subnetidx=2 + for rsubnet in ${rsubnetarr[@]:1}; do + sudo echo "" >> $vpnconffile && + sudo echo "conn vpn-$rightpeer-$subnetidx" >> $vpnconffile && + sudo echo " also=vpn-$rightpeer" >> $vpnconffile && + sudo echo " auto=route" >> $vpnconffile && + sudo echo " rightsubnet=$rsubnet" >> $vpnconffile + ((++subnetidx)) + done + fi + enable_iptables_subnets sudo ipsec auto --rereadall @@ -215,8 +236,10 @@ passive=0 op="" checkup=0 secure=1 +ikeversion="ike" +splitconnections=0 -while getopts 'ADSpcl:n:g:r:N:e:i:t:T:s:d:' OPTION +while getopts 'ACDSpcl:n:g:r:N:e:i:t:T:s:d:v:' OPTION do case $OPTION in A) opflag=1 @@ -243,6 +266,8 @@ do e) eflag=1 esppolicy="$OPTARG" ;; + v) ikeversion="$OPTARG" + ;; i) iflag=1 ikepolicy="$OPTARG" ;; @@ -264,6 +289,8 @@ do ;; S) secure=0 ;; + C) splitconnections=1 + ;; ?) usage exit 2 ;; diff --git a/ui/l10n/ar.js b/ui/l10n/ar.js index 3b560a86e728..70569bd1517d 100644 --- a/ui/l10n/ar.js +++ b/ui/l10n/ar.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "عمر ESP (ثانية)", "label.ESP.policy": "سياسة ESP", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE الإصدار", + "label.IPsec.splitconnections": "انقسام الاتصالات", "label.IKE.encryption": "IKE Encryption", "label.IKE.hash": "IKE Hash", "label.IKE.lifetime": "عمر IKE (ثانية)", diff --git a/ui/l10n/ca.js b/ui/l10n/ca.js index f6ae80f81f3c..aa7a856af60c 100644 --- a/ui/l10n/ca.js +++ b/ui/l10n/ca.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP Lifetime (second)", "label.ESP.policy": "ESP policy", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE Version", + "label.IPsec.splitconnections": "Split Connections", "label.IKE.encryption": "IKE Encryption", "label.IKE.hash": "IKE Hash", "label.IKE.lifetime": "IKE lifetime (second)", diff --git a/ui/l10n/de_DE.js b/ui/l10n/de_DE.js index 934f8f98c09d..4dfea163407c 100644 --- a/ui/l10n/de_DE.js +++ b/ui/l10n/de_DE.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP-Lebensdauer (Sekunde)", "label.ESP.policy": "ESP-Richtlinie", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE Ausführung", + "label.IPsec.splitconnections": "geteilte Verbindungen", "label.IKE.encryption": "IKE-Verschlüsselung", "label.IKE.hash": "IKE-Prüfsumme", "label.IKE.lifetime": "IKE-Lebensdauer (Sekunde)", diff --git a/ui/l10n/en.js b/ui/l10n/en.js index b9f36822b7ae..12b2994c35a7 100644 --- a/ui/l10n/en.js +++ b/ui/l10n/en.js @@ -56,6 +56,8 @@ var dictionary = {"ICMP.code":"ICMP Code", "label.ESP.lifetime":"ESP Lifetime (second)", "label.ESP.policy":"ESP policy", "label.IKE.DH":"IKE DH", +"label.IKE.version": "IKE Version", +"label.IPsec.splitconnections": "Split Connections", "label.IKE.encryption":"IKE Encryption", "label.IKE.hash":"IKE Hash", "label.IKE.lifetime":"IKE lifetime (second)", diff --git a/ui/l10n/es.js b/ui/l10n/es.js index 35257d479898..26ba97262006 100644 --- a/ui/l10n/es.js +++ b/ui/l10n/es.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "Tiempo de vida ESP (en segundos)", "label.ESP.policy": "Política ESP", "label.IKE.DH": "IKE DH", + "label.IKE.version": "Versión IKE", + "label.IPsec.splitconnections": "Conexiones Divididas", "label.IKE.encryption": "Encriptación IKE", "label.IKE.hash": "Hash IKE", "label.IKE.lifetime": "Tiempo de vida IKE (segundos)", diff --git a/ui/l10n/fr_FR.js b/ui/l10n/fr_FR.js index 9935a818021e..d5f7594243c1 100644 --- a/ui/l10n/fr_FR.js +++ b/ui/l10n/fr_FR.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "Durée de vie ESP (secondes)", "label.ESP.policy": "Mode ESP", "label.IKE.DH": "DH IKE", + "label.IKE.version": "Version IKE", + "label.IPsec.splitconnections": "Connexions Séparées", "label.IKE.encryption": "Chiffrement IKE", "label.IKE.hash": "Empreinte IKE", "label.IKE.lifetime": "Durée de vie IKE (secondes)", diff --git a/ui/l10n/hu.js b/ui/l10n/hu.js index 912ecf9a49da..4e3d2e490deb 100644 --- a/ui/l10n/hu.js +++ b/ui/l10n/hu.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP élettartam (mp)", "label.ESP.policy": "ESP szabályzat", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE Változat", + "label.IPsec.splitconnections": "Megosztott Kapcsolatok", "label.IKE.encryption": "IKE titkosítás", "label.IKE.hash": "IKE Hash", "label.IKE.lifetime": "IKE élettartam (mp)", diff --git a/ui/l10n/it_IT.js b/ui/l10n/it_IT.js index f725584e08bb..e2d0553452ac 100644 --- a/ui/l10n/it_IT.js +++ b/ui/l10n/it_IT.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP Lifetime (second)", "label.ESP.policy": "Policy di ESP", "label.IKE.DH": "DH di IKE", + "label.IKE.version": "Versione di IKE", + "label.IPsec.splitconnections": "Connessioni Divise", "label.IKE.encryption": "Encryption di IKE", "label.IKE.hash": "Hash di IKE", "label.IKE.lifetime": "IKE lifetime (second)", diff --git a/ui/l10n/ja_JP.js b/ui/l10n/ja_JP.js index 40cf38fd8570..550a7cceca7f 100644 --- a/ui/l10n/ja_JP.js +++ b/ui/l10n/ja_JP.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP 有効期間 (秒)", "label.ESP.policy": "ESP ポリシー", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE バージョン", + "label.IPsec.splitconnections": "スプリット接続", "label.IKE.encryption": "IKE 暗号化", "label.IKE.hash": "IKE ハッシュ", "label.IKE.lifetime": "IKE 有効期間 (秒)", diff --git a/ui/l10n/ko_KR.js b/ui/l10n/ko_KR.js index f6980bc067e1..c2b394de7861 100644 --- a/ui/l10n/ko_KR.js +++ b/ui/l10n/ko_KR.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP 유효기간(초)", "label.ESP.policy": "ESP 정책", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE 버전", + "label.IPsec.splitconnections": "분할 연결", "label.IKE.encryption": "IKE 암호화", "label.IKE.hash": "IKE 해시", "label.IKE.lifetime": "IKE 유효기간(초)", diff --git a/ui/l10n/nb_NO.js b/ui/l10n/nb_NO.js index 28cd09c3b9ab..8f2aec361952 100644 --- a/ui/l10n/nb_NO.js +++ b/ui/l10n/nb_NO.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP levetid (sekund)", "label.ESP.policy": "ESP policy", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE versjon", + "label.IPsec.splitconnections": "delte forbindelser", "label.IKE.encryption": "IKE kryptering", "label.IKE.hash": "IKE Hash", "label.IKE.lifetime": "IKE livstid (sekunder)", diff --git a/ui/l10n/nl_NL.js b/ui/l10n/nl_NL.js index 4508241ad307..2c15d5e35806 100644 --- a/ui/l10n/nl_NL.js +++ b/ui/l10n/nl_NL.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP Lifetime (secondes)", "label.ESP.policy": "ESP policy", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE Versie", + "label.IPsec.splitconnections": "Gesplitste Verbindingen", "label.IKE.encryption": "IKE Encryptie", "label.IKE.hash": "IKE Hash", "label.IKE.lifetime": "IKE lifetime (secondes)", diff --git a/ui/l10n/pl.js b/ui/l10n/pl.js index 30c04b9ff75b..c0dd020bc9a9 100644 --- a/ui/l10n/pl.js +++ b/ui/l10n/pl.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP Lifetime (second)", "label.ESP.policy": "ESP policy", "label.IKE.DH": "IKE DH", + "label.IKE.version": "IKE Version", + "label.IPsec.splitconnections": "Split Connections", "label.IKE.encryption": "IKE Encryption", "label.IKE.hash": "IKE Hash", "label.IKE.lifetime": "IKE lifetime (second)", diff --git a/ui/l10n/pt_BR.js b/ui/l10n/pt_BR.js index ccfa59ae7d35..7ea6c2ed734c 100644 --- a/ui/l10n/pt_BR.js +++ b/ui/l10n/pt_BR.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "Tempo de vida do ESP (segundos)", "label.ESP.policy": "Política ESP", "label.IKE.DH": "DH IKE", + "label.IKE.version": "Versão IKE", + "label.IPsec.splitconnections": "Conexões Divididas", "label.IKE.encryption": "Encriptação IKE", "label.IKE.hash": "Hash IKE", "label.IKE.lifetime": "Tempo de vida IKE (segundos)", diff --git a/ui/l10n/ru_RU.js b/ui/l10n/ru_RU.js index 6a11b38a0f70..0fc5a7fb2e48 100644 --- a/ui/l10n/ru_RU.js +++ b/ui/l10n/ru_RU.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "Время жизни ESP (в секундах)", "label.ESP.policy": "Политика ESP", "label.IKE.DH": "IKE DH", + "label.IKE.version": "версия IKE", + "label.IPsec.splitconnections": "разделить соединения", "label.IKE.encryption": "Шифрование IKE", "label.IKE.hash": "IKE Hash", "label.IKE.lifetime": "IKE lifetime (second)", diff --git a/ui/l10n/zh_CN.js b/ui/l10n/zh_CN.js index dc44fdb9a96a..19473ab0c16d 100644 --- a/ui/l10n/zh_CN.js +++ b/ui/l10n/zh_CN.js @@ -56,6 +56,8 @@ var dictionary = { "label.ESP.lifetime": "ESP 使用期限(第二阶段)", "label.ESP.policy": "ESP 策略", "label.IKE.DH": "IKE DH 算法", + "label.IKE.version": "IKE 版", + "label.IPsec.splitconnections": "分割连接", "label.IKE.encryption": "IKE 加密算法", "label.IKE.hash": "IKE 哈希算法", "label.IKE.lifetime": "IKE 使用期限(第二阶段)", diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js index bbe8f3e64b49..b3fe0e2fe3ba 100755 --- a/ui/scripts/docs.js +++ b/ui/scripts/docs.js @@ -1090,6 +1090,14 @@ cloudStack.docs = { desc: 'Enter a secret key value. The endpoints of the VPN share a secret key. This is used to authenticate the customer gateway and the VPC VPN gateway to each other.', externalLink: '' }, + helpVPNGatewayIKEVersion: { + desc: 'Enter ike, ikev1, or ikev2 to specify which Internet Key Exchange (IKE) version to use for the key exchange. Using ike will negotiate the version.', + externalLink: '' + }, + helpVPNGatewaySplitConnections: { + desc: 'Split multiple remote networks into multiple phase 2 SAs. Often used with Cisco some products.', + externalLink: '' + }, helpVPNGatewayIKEEncryption: { desc: 'Enter AES128, AES192, AES256, or 3DES to specify the Internet Key Exchange (IKE) policy for phase-1. Authentication is accomplished with Preshared Keys.', externalLink: '' diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 34b68f246870..047652d70816 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -5885,6 +5885,28 @@ } }, + ikeversion: { + label: 'label.IKE.version', + docID: 'helpVPNGatewayIKEVersion', + select: function(args) { + var items = []; + items.push({ + id: 'ike', + description: 'ike' + }); + items.push({ + id: 'ikev1', + description: 'ikev1' + }); + items.push({ + id: 'ikev2', + description: 'ikev2' + }); + args.response.success({ + data: items + }); + } + }, //IKE Policy ikeEncryption: { label: 'label.IKE.encryption', @@ -6110,7 +6132,13 @@ forceencap: { label: 'label.vpn.force.encapsulation', docID: 'helpVPNGatewayForceEncapsulation', - docID: 'helpVPNGatewayForceEncapsulation', + isBoolean: true, + isChecked: false + }, + + splitconnections: { + label: 'label.IPsec.splitconnections', + docID: 'helpVPNGatewaySplitConnections', isBoolean: true, isChecked: false } @@ -6122,10 +6150,12 @@ gateway: args.data.gateway, cidrlist: args.data.cidrlist, ipsecpsk: args.data.ipsecpsk, + ikeversion: args.data.ikeversion, ikelifetime: args.data.ikelifetime, esplifetime: args.data.esplifetime, dpd: (args.data.dpd == "on"), - forceencap: (args.data.forceencap == "on") + forceencap: (args.data.forceencap == "on"), + splitconnections: (args.data.splitconnections == "on") }; var ikepolicy = args.data.ikeEncryption + '-' + args.data.ikeHash; @@ -6179,10 +6209,12 @@ gateway: args.data.gateway, cidrlist: args.data.cidrlist, ipsecpsk: args.data.ipsecpsk, + ikeversion: args.data.ikeversion, ikelifetime: args.data.ikelifetime, esplifetime: args.data.esplifetime, dpd: (args.data.dpd == "on"), - forceencap: (args.data.forceencap == "on") + forceencap: (args.data.forceencap == "on"), + splitconnections: (args.data.splitconnections == "on") }; var ikepolicy = args.data.ikeEncryption + '-' + args.data.ikeHash; @@ -6294,6 +6326,28 @@ } }, + ikeversion: { + label: 'label.IKE.version', + isEditable: true, + select: function(args) { + var items = []; + items.push({ + id: 'ike', + description: 'ike' + }); + items.push({ + id: 'ikev1', + description: 'ikev1' + }); + items.push({ + id: 'ikev2', + description: 'ikev2' + }); + args.response.success({ + data: items + }); + } + }, //IKE Policy ikeEncryption: { label: 'label.IKE.encryption', @@ -6461,6 +6515,13 @@ converter: cloudStack.converters.toBooleanText }, + splitconnections: { + label: 'label.IPsec.splitconnections', + isBoolean: true, + isEditable: true, + converter: cloudStack.converters.toBooleanText + }, + id: { label: 'label.id' },