This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/master by this push:
new bf4f1bb CLOUDSTACK-10126: Separate Subnet for SSVM and CPVM (#2368)
bf4f1bb is described below
commit bf4f1bbb90a7ac05c7d40b1e5667186a646a25f7
Author: Nicolas Vazquez <[email protected]>
AuthorDate: Fri Jan 5 04:49:03 2018 -0300
CLOUDSTACK-10126: Separate Subnet for SSVM and CPVM (#2368)
This extends work presented on #2048 on which the ability to extend the
management range is provided.
Aim
This PR allows separating the management network subnet on which SSVM and
CPVM are from the virtual routers management subnet.
Detailed use case
PCI compliance requires that network elements are defined as ‘in scope’ or
‘out of scope’, for compliance purposes. The SSVM and CPVM are both in scope as
they allow public HTTP or HTTPS connections. The virtual routers have been
defined as out of scope as they have been placed entirely in a firewalled
network's segment. However, all of the system VM types share management
network. As SSVM and CPVM are both in scope this would bring the virtual
routers into scope as well, requiring in [...]
Description
By this feature it is possible to dedicate a created range for SSVM and
CPVM (system vms) and provide a VLAN ID for its range.
A new boolean global configuration is added:
system.vm.management.ip.reservation.mode.strictness. If enabled, the use of
System VMs management IP reservation is strict, preferred if not. Default value
is false (preferred).
Strict reservation: System VMs should try to get a private IP from a range
marked for system vms. If not available, deployment fails
Preferred reservation: System VMS will try to get a private IP from a range
marked for system vms. If not available, IP for range not marked for system vms
is taken.
---
.../org/apache/cloudstack/api/ApiConstants.java | 1 +
.../network/CreateManagementNetworkIpRangeCmd.java | 21 ++++++++
.../network/DeleteManagementNetworkIpRangeCmd.java | 10 ++++
.../cloudstack/api/response/PodResponse.java | 24 +++++++++
.../resources/META-INF/db/schema-41000to41100.sql | 7 +++
.../src/com/cloud/dc/DataCenterIpAddressVO.java | 14 +++++
.../schema/src/com/cloud/dc/dao/DataCenterDao.java | 31 +++++++++--
.../src/com/cloud/dc/dao/DataCenterDaoImpl.java | 11 ++--
.../com/cloud/dc/dao/DataCenterIpAddressDao.java | 4 +-
.../cloud/dc/dao/DataCenterIpAddressDaoImpl.java | 37 +++++++++++--
server/src/com/cloud/api/ApiResponseHelper.java | 9 ++++
.../configuration/ConfigurationManagerImpl.java | 60 +++++++++++++++++++---
.../com/cloud/network/IpAddressManagerImpl.java | 2 +-
.../cloud/network/guru/PodBasedNetworkGuru.java | 19 ++++---
.../com/cloud/server/ConfigurationServerImpl.java | 2 +-
.../configuration/ConfigurationManagerTest.java | 20 ++++++++
ui/scripts/system.js | 24 ++++++++-
ui/scripts/ui/widgets/multiEdit.js | 25 ++++++++-
18 files changed, 288 insertions(+), 33 deletions(-)
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java
b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 41cf7d9..20a44b0 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -125,6 +125,7 @@ public class ApiConstants {
public static final String FORCED_DESTROY_LOCAL_STORAGE =
"forcedestroylocalstorage";
public static final String FORMAT = "format";
public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork";
+ public static final String FOR_SYSTEM_VMS = "forsystemvms";
public static final String GATEWAY = "gateway";
public static final String IP6_GATEWAY = "ip6gateway";
public static final String GROUP = "group";
diff --git
a/api/src/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java
b/api/src/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java
index e5bfc07..f795746 100644
---
a/api/src/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java
+++
b/api/src/org/apache/cloudstack/api/command/admin/network/CreateManagementNetworkIpRangeCmd.java
@@ -85,6 +85,16 @@ public class CreateManagementNetworkIpRangeCmd extends
BaseAsyncCmd {
description = "The ending IP address.")
private String endIp;
+ @Parameter(name = ApiConstants.FOR_SYSTEM_VMS,
+ type = CommandType.BOOLEAN,
+ description = "Specify if range is dedicated for CPVM and SSVM.")
+ private Boolean forSystemVms;
+
+ @Parameter(name = ApiConstants.VLAN,
+ type = CommandType.STRING,
+ description = "Optional. The vlan id the ip range sits on, default
to Null when it is not specificed which means you network is not on any Vlan")
+ private String vlan;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -109,6 +119,17 @@ public class CreateManagementNetworkIpRangeCmd extends
BaseAsyncCmd {
return endIp;
}
+ public Boolean isForSystemVms() {
+ return forSystemVms == null ? Boolean.FALSE : forSystemVms;
+ }
+
+ public String getVlan() {
+ if (vlan == null || vlan.isEmpty()) {
+ vlan = "untagged";
+ }
+ return vlan;
+ }
+
@Override
public String getEventType() {
return EventTypes.EVENT_MANAGEMENT_IP_RANGE_CREATE;
diff --git
a/api/src/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java
b/api/src/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java
index acb9e7a..d648184 100644
---
a/api/src/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java
+++
b/api/src/org/apache/cloudstack/api/command/admin/network/DeleteManagementNetworkIpRangeCmd.java
@@ -72,6 +72,12 @@ public class DeleteManagementNetworkIpRangeCmd extends
BaseAsyncCmd {
validations = ApiArgValidator.NotNullOrEmpty)
private String endIp;
+ @Parameter(name = ApiConstants.VLAN,
+ type = CommandType.STRING,
+ required = true,
+ description = "The vlan id the ip range sits on")
+ private String vlan;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -88,6 +94,10 @@ public class DeleteManagementNetworkIpRangeCmd extends
BaseAsyncCmd {
return endIp;
}
+ public String getVlan() {
+ return vlan;
+ }
+
@Override
public String getEventType() {
return EventTypes.EVENT_MANAGEMENT_IP_RANGE_DELETE;
diff --git a/api/src/org/apache/cloudstack/api/response/PodResponse.java
b/api/src/org/apache/cloudstack/api/response/PodResponse.java
index c5c700e..27ebf71 100644
--- a/api/src/org/apache/cloudstack/api/response/PodResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/PodResponse.java
@@ -61,6 +61,14 @@ public class PodResponse extends BaseResponse {
@Param(description = "the ending IP for the Pod")
private List<String> endIp;
+ @SerializedName("forsystemvms")
+ @Param(description = "indicates if range is dedicated for CPVM and SSVM")
+ private List<String> forSystemVms;
+
+ @SerializedName("vlanid")
+ @Param(description = "indicates Vlan ID for the range")
+ private List<String> vlanId;
+
@SerializedName("allocationstate")
@Param(description = "the allocation state of the Pod")
private String allocationState;
@@ -133,6 +141,22 @@ public class PodResponse extends BaseResponse {
this.endIp = endIp;
}
+ public void setForSystemVms(List<String> forSystemVms) {
+ this.forSystemVms = forSystemVms;
+ }
+
+ public List<String> getForSystemVms() {
+ return forSystemVms;
+ }
+
+ public List<String> getVlanId() {
+ return vlanId;
+ }
+
+ public void setVlanId(List<String> vlanId) {
+ this.vlanId = vlanId;
+ }
+
public String getAllocationState() {
return allocationState;
}
diff --git a/engine/schema/resources/META-INF/db/schema-41000to41100.sql
b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
index 5d51b47..585c7fd 100644
--- a/engine/schema/resources/META-INF/db/schema-41000to41100.sql
+++ b/engine/schema/resources/META-INF/db/schema-41000to41100.sql
@@ -516,3 +516,10 @@ UPDATE `cloud`.`vm_template` SET guest_os_id=99 WHERE id=8;
-- Network External Ids
ALTER TABLE `cloud`.`networks` ADD `external_id` varchar(255);
+
+-- Separate Subnet for CPVM and SSVM (system vms)
+ALTER TABLE `cloud`.`op_dc_ip_address_alloc`
+ADD COLUMN `forsystemvms` TINYINT(1) NOT NULL DEFAULT '0' COMMENT 'Indicates
if IP is dedicated for CPVM or SSVM';
+
+ALTER TABLE `cloud`.`op_dc_ip_address_alloc`
+ADD COLUMN `vlan` INT(10) UNSIGNED NULL COMMENT 'Vlan the management network
range is on';
diff --git a/engine/schema/src/com/cloud/dc/DataCenterIpAddressVO.java
b/engine/schema/src/com/cloud/dc/DataCenterIpAddressVO.java
index 70b4df1..3d68cc3 100644
--- a/engine/schema/src/com/cloud/dc/DataCenterIpAddressVO.java
+++ b/engine/schema/src/com/cloud/dc/DataCenterIpAddressVO.java
@@ -60,6 +60,12 @@ public class DataCenterIpAddressVO implements
InternalIdentity {
@Column(name = "mac_address")
long macAddress;
+ @Column(name = "forsystemvms")
+ private boolean forSystemVms;
+
+ @Column(name = "vlan")
+ private Integer vlan;
+
protected DataCenterIpAddressVO() {
}
@@ -113,4 +119,12 @@ public class DataCenterIpAddressVO implements
InternalIdentity {
public long getMacAddress() {
return macAddress;
}
+
+ public boolean isForSystemVms() {
+ return forSystemVms;
+ }
+
+ public Integer getVlan() {
+ return vlan;
+ }
}
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java
b/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java
index 4fc055e..a6cd59f 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java
@@ -21,10 +21,35 @@ import java.util.List;
import com.cloud.dc.DataCenterIpAddressVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.DataCenterVnetVO;
-import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericDao;
public interface DataCenterDao extends GenericDao<DataCenterVO, Long> {
+
+ class PrivateAllocationData {
+
+ private String ipAddress;
+ private Long macAddress;
+ private Integer vlan;
+
+ public PrivateAllocationData(final String ipAddress, final Long
macAddress, final Integer vlan) {
+ this.ipAddress = ipAddress;
+ this.macAddress = macAddress;
+ this.vlan = vlan;
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public Long getMacAddress() {
+ return macAddress;
+ }
+
+ public Integer getVlan() {
+ return vlan;
+ }
+ }
+
DataCenterVO findByName(String name);
/**
@@ -35,7 +60,7 @@ public interface DataCenterDao extends
GenericDao<DataCenterVO, Long> {
String[] getNextAvailableMacAddressPair(long id, long mask);
- Pair<String, Long> allocatePrivateIpAddress(long id, long podId, long
instanceId, String reservationId);
+ PrivateAllocationData allocatePrivateIpAddress(long id, long podId, long
instanceId, String reservationId, boolean forSystemVms);
DataCenterIpAddressVO allocatePrivateIpAddress(long id, String
reservationId);
@@ -57,7 +82,7 @@ public interface DataCenterDao extends
GenericDao<DataCenterVO, Long> {
boolean deleteLinkLocalIpAddressByPod(long podId);
- void addPrivateIpAddress(long dcId, long podId, String start, String end);
+ void addPrivateIpAddress(long dcId, long podId, String start, String end,
boolean forSystemVms, Integer vlan);
void addLinkLocalIpAddress(long dcId, long podId, String start, String
end);
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java
b/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java
index 847a247..385fb40 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java
@@ -38,7 +38,6 @@ import com.cloud.network.dao.AccountGuestVlanMapDao;
import com.cloud.network.dao.AccountGuestVlanMapVO;
import com.cloud.org.Grouping;
import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.Pair;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder;
@@ -247,13 +246,13 @@ public class DataCenterDaoImpl extends
GenericDaoBase<DataCenterVO, Long> implem
}
@Override
- public Pair<String, Long> allocatePrivateIpAddress(long dcId, long podId,
long instanceId, String reservationId) {
+ public PrivateAllocationData allocatePrivateIpAddress(long dcId, long
podId, long instanceId, String reservationId, boolean forSystemVms) {
_ipAllocDao.releaseIpAddress(instanceId);
- DataCenterIpAddressVO vo = _ipAllocDao.takeIpAddress(dcId, podId,
instanceId, reservationId);
+ DataCenterIpAddressVO vo = _ipAllocDao.takeIpAddress(dcId, podId,
instanceId, reservationId, forSystemVms);
if (vo == null) {
return null;
}
- return new Pair<String, Long>(vo.getIpAddress(), vo.getMacAddress());
+ return new PrivateAllocationData(vo.getIpAddress(),
vo.getMacAddress(), vo.getVlan());
}
@Override
@@ -287,8 +286,8 @@ public class DataCenterDaoImpl extends
GenericDaoBase<DataCenterVO, Long> implem
}
@Override
- public void addPrivateIpAddress(long dcId, long podId, String start,
String end) {
- _ipAllocDao.addIpRange(dcId, podId, start, end);
+ public void addPrivateIpAddress(long dcId, long podId, String start,
String end, boolean forSystemVms, Integer vlan) {
+ _ipAllocDao.addIpRange(dcId, podId, start, end, forSystemVms, vlan);
}
@Override
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java
b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java
index 9929cc3..bb840b5 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDao.java
@@ -23,11 +23,11 @@ import com.cloud.utils.db.GenericDao;
public interface DataCenterIpAddressDao extends
GenericDao<DataCenterIpAddressVO, Long> {
- DataCenterIpAddressVO takeIpAddress(long dcId, long podId, long
instanceId, String reservationId);
+ DataCenterIpAddressVO takeIpAddress(long dcId, long podId, long
instanceId, String reservationId, boolean forSystemVms);
DataCenterIpAddressVO takeDataCenterIpAddress(long dcId, String
reservationId);
- void addIpRange(long dcId, long podId, String start, String end);
+ void addIpRange(long dcId, long podId, String start, String end, boolean
forSystemVms, Integer vlan);
void releaseIpAddress(String ipAddress, long dcId, Long instanceId);
diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java
b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java
index 12bfdc8..8b0a44b 100644
--- a/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/DataCenterIpAddressDaoImpl.java
@@ -22,6 +22,8 @@ import java.util.Date;
import java.util.List;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -38,7 +40,7 @@ import com.cloud.utils.net.NetUtils;
@Component
@DB
-public class DataCenterIpAddressDaoImpl extends
GenericDaoBase<DataCenterIpAddressVO, Long> implements DataCenterIpAddressDao {
+public class DataCenterIpAddressDaoImpl extends
GenericDaoBase<DataCenterIpAddressVO, Long> implements DataCenterIpAddressDao,
Configurable {
private static final Logger s_logger =
Logger.getLogger(DataCenterIpAddressDaoImpl.class);
private final SearchBuilder<DataCenterIpAddressVO> AllFieldsSearch;
@@ -47,16 +49,26 @@ public class DataCenterIpAddressDaoImpl extends
GenericDaoBase<DataCenterIpAddre
private final GenericSearchBuilder<DataCenterIpAddressVO, Integer>
AllAllocatedIpCount;
private final GenericSearchBuilder<DataCenterIpAddressVO, Integer>
AllAllocatedIpCountForDc;
+ private static final ConfigKey<Boolean>
SystemVmManagementIpReservationModeStrictness = new
ConfigKey<Boolean>("Advanced",
+ Boolean.class,
"system.vm.management.ip.reservation.mode.strictness", "false","If enabled, the
use of System VMs management IP reservation is strict, preferred if not.",
false, ConfigKey.Scope.Global);
+
@Override
@DB
- public DataCenterIpAddressVO takeIpAddress(long dcId, long podId, long
instanceId, String reservationId) {
+ public DataCenterIpAddressVO takeIpAddress(long dcId, long podId, long
instanceId, String reservationId, boolean forSystemVms) {
SearchCriteria<DataCenterIpAddressVO> sc = AllFieldsSearch.create();
sc.setParameters("pod", podId);
sc.setParameters("taken", (Date)null);
+ sc.setParameters("forSystemVms", forSystemVms);
TransactionLegacy txn = TransactionLegacy.currentTxn();
txn.start();
DataCenterIpAddressVO vo = lockOneRandomRow(sc, true);
+
+ // If there is no explicitly created range for system vms and
reservation mode is preferred (strictness = false)
+ if (forSystemVms && vo == null &&
!SystemVmManagementIpReservationModeStrictness.value()) {
+ sc.setParameters("forSystemVms", false);
+ vo = lockOneRandomRow(sc, true);
+ }
if (vo == null) {
txn.rollback();
return null;
@@ -121,10 +133,10 @@ public class DataCenterIpAddressDaoImpl extends
GenericDaoBase<DataCenterIpAddre
@Override
@DB
- public void addIpRange(long dcId, long podId, String start, String end) {
+ public void addIpRange(long dcId, long podId, String start, String end,
boolean forSystemVms, Integer vlan) {
TransactionLegacy txn = TransactionLegacy.currentTxn();
- String insertSql = "INSERT INTO `cloud`.`op_dc_ip_address_alloc`
(ip_address, data_center_id, pod_id, mac_address) " +
- "VALUES (?, ?, ?, (select mac_address from `cloud`.`data_center`
where id=?))";
+ String insertSql = "INSERT INTO `cloud`.`op_dc_ip_address_alloc`
(ip_address, data_center_id, pod_id, mac_address, forsystemvms" + (vlan == null
? ") " : ", vlan) ") +
+ "VALUES (?, ?, ?, (select mac_address from
`cloud`.`data_center` where id=?), ?" + (vlan == null ? ")" : ", ?)");
String updateSql = "UPDATE `cloud`.`data_center` set mac_address =
mac_address+1 where id=?";
long startIP = NetUtils.ip2Long(start);
@@ -139,6 +151,10 @@ public class DataCenterIpAddressDaoImpl extends
GenericDaoBase<DataCenterIpAddre
insertPstmt.setLong(2, dcId);
insertPstmt.setLong(3, podId);
insertPstmt.setLong(4, dcId);
+ insertPstmt.setBoolean(5, forSystemVms);
+ if (vlan != null) {
+ insertPstmt.setInt(6, vlan);
+ }
insertPstmt.executeUpdate();
}
try(PreparedStatement updatePstmt =
txn.prepareStatement(updateSql);) {
@@ -285,6 +301,7 @@ public class DataCenterIpAddressDaoImpl extends
GenericDaoBase<DataCenterIpAddre
AllFieldsSearch.and("ipAddress",
AllFieldsSearch.entity().getIpAddress(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("reservation",
AllFieldsSearch.entity().getReservationId(), SearchCriteria.Op.EQ);
AllFieldsSearch.and("taken", AllFieldsSearch.entity().getTakenAt(),
SearchCriteria.Op.EQ);
+ AllFieldsSearch.and("forSystemVms",
AllFieldsSearch.entity().isForSystemVms(), SearchCriteria.Op.EQ);
AllFieldsSearch.done();
AllIpCount = createSearchBuilder(Integer.class);
@@ -309,4 +326,14 @@ public class DataCenterIpAddressDaoImpl extends
GenericDaoBase<DataCenterIpAddre
AllAllocatedIpCountForDc.and("removed",
AllAllocatedIpCountForDc.entity().getTakenAt(), SearchCriteria.Op.NNULL);
AllAllocatedIpCountForDc.done();
}
+
+ @Override
+ public String getConfigComponentName() {
+ return DataCenterIpAddressDao.class.getSimpleName();
+ }
+
+ @Override
+ public ConfigKey<?>[] getConfigKeys() {
+ return new ConfigKey<?>[]
{SystemVmManagementIpReservationModeStrictness};
+ }
}
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java
b/server/src/com/cloud/api/ApiResponseHelper.java
index e352198..49b8c15 100644
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -947,6 +947,8 @@ public class ApiResponseHelper implements ResponseGenerator
{
String[] ipRange = new String[2];
List<String> startIp = new ArrayList<String>();
List<String> endIp = new ArrayList<String>();
+ List<String> forSystemVms = new ArrayList<String>();
+ List<String> vlanIds = new ArrayList<String>();
if (pod.getDescription() != null && pod.getDescription().length() > 0)
{
final String[] existingPodIpRanges =
pod.getDescription().split(",");
@@ -956,6 +958,11 @@ public class ApiResponseHelper implements
ResponseGenerator {
startIp.add(((existingPodIpRange.length > 0) &&
(existingPodIpRange[0] != null)) ? existingPodIpRange[0] : "");
endIp.add(((existingPodIpRange.length > 1) &&
(existingPodIpRange[1] != null)) ? existingPodIpRange[1] : "");
+ forSystemVms.add((existingPodIpRange.length > 2) &&
(existingPodIpRange[2] != null) ? existingPodIpRange[2] : "0");
+ vlanIds.add((existingPodIpRange.length > 3) &&
+ (existingPodIpRange[3] != null &&
!existingPodIpRange.equals("untagged")) ?
+
BroadcastDomainType.Vlan.toUri(existingPodIpRange[3]).toString() :
+
BroadcastDomainType.Vlan.toUri(Vlan.UNTAGGED).toString());
}
}
@@ -970,6 +977,8 @@ public class ApiResponseHelper implements ResponseGenerator
{
podResponse.setNetmask(NetUtils.getCidrNetmask(pod.getCidrSize()));
podResponse.setStartIp(startIp);
podResponse.setEndIp(endIp);
+ podResponse.setForSystemVms(forSystemVms);
+ podResponse.setVlanId(vlanIds);
podResponse.setGateway(pod.getGateway());
podResponse.setAllocationState(pod.getAllocationState().toString());
if (showCapacities != null && showCapacities) {
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 9cbe305..c3e9e11 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -17,6 +17,7 @@
package com.cloud.configuration;
import java.net.URI;
+import java.net.URISyntaxException;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.util.ArrayList;
@@ -363,6 +364,9 @@ public class ConfigurationManagerImpl extends ManagerBase
implements Configurati
public static final ConfigKey<Boolean> SystemVMUseLocalStorage = new
ConfigKey<Boolean>(Boolean.class, "system.vm.use.local.storage", "Advanced",
"false",
"Indicates whether to use local storage pools or shared storage
pools for system VMs.", false, ConfigKey.Scope.Zone, null);
+ private static final String DefaultForSystemVmsForPodIpRange = "0";
+ private static final String DefaultVlanForPodIpRange =
Vlan.UNTAGGED.toString();
+
private static final Set<Provider> VPC_ONLY_PROVIDERS =
Sets.newHashSet(Provider.VPCVirtualRouter, Provider.JuniperContrailVpcRouter,
Provider.InternalLbVm);
@Override
@@ -1095,6 +1099,25 @@ public class ConfigurationManagerImpl extends
ManagerBase implements Configurati
return true;
}
+ /**
+ * Get vlan number from vlan uri
+ * @param vlan
+ * @return
+ */
+ protected String getVlanNumberFromUri(String vlan) {
+ URI uri;
+ try {
+ uri = new URI(vlan);
+ String vlanId = BroadcastDomainType.getValue(uri);
+ if (vlanId == null || !uri.getScheme().equalsIgnoreCase("vlan")) {
+ throw new CloudRuntimeException("Vlan parameter : " + vlan + "
is not in valid format");
+ }
+ return vlanId;
+ } catch (URISyntaxException e) {
+ throw new CloudRuntimeException("Invalid vlan parameter: " + vlan
+ " can't get vlan number from it due to: " + e.getMessage());
+ }
+ }
+
@Override
@DB
public Pod createPodIpRange(final CreateManagementNetworkIpRangeCmd cmd) {
@@ -1110,6 +1133,14 @@ public class ConfigurationManagerImpl extends
ManagerBase implements Configurati
final String netmask = cmd.getNetmask();
final String startIp = cmd.getStartIp();
String endIp = cmd.getEndIp();
+ final boolean forSystemVms = cmd.isForSystemVms();
+ String vlan = cmd.getVlan();
+ if (!(Strings.isNullOrEmpty(vlan) ||
vlan.startsWith(BroadcastDomainType.Vlan.scheme()))) {
+ vlan = BroadcastDomainType.Vlan.toUri(vlan).toString();
+ }
+
+ String vlanNumberFromUri = getVlanNumberFromUri(vlan);
+ final Integer vlanId =
vlanNumberFromUri.equals(Vlan.UNTAGGED.toString()) ? null :
Integer.parseInt(vlanNumberFromUri);
final HostPodVO pod = _podDao.findById(podId);
@@ -1188,10 +1219,15 @@ public class ConfigurationManagerImpl extends
ManagerBase implements Configurati
public void doInTransactionWithoutResult(final
TransactionStatus status) {
String ipRange = pod.getDescription();
+ /*
+ * POD Description is refactored to:
+ *
<START_IP>-<END_IP>-<FOR_SYSTEM_VMS>-<VLAN>,<START_IP>-<END_IP>-<FOR_SYSTEM_VMS>-<VLAN>,...
+ */
+ String range = startIp + "-" + endIpFinal + "-" +
(forSystemVms ? "1" : "0") + "-" + (vlanId == null ? DefaultVlanForPodIpRange :
vlanId);
if(ipRange != null && !ipRange.isEmpty())
- ipRange += ("," + startIp + "-" + endIpFinal);
+ ipRange += ("," + range);
else
- ipRange = (startIp + "-" + endIpFinal);
+ ipRange = (range);
pod.setDescription(ipRange);
@@ -1212,7 +1248,7 @@ public class ConfigurationManagerImpl extends ManagerBase
implements Configurati
}
}
- _zoneDao.addPrivateIpAddress(zoneId, pod.getId(), startIp,
endIpFinal);
+ _zoneDao.addPrivateIpAddress(zoneId, pod.getId(), startIp,
endIpFinal, forSystemVms, vlanId);
}
});
} catch (final Exception e) {
@@ -1229,6 +1265,12 @@ public class ConfigurationManagerImpl extends
ManagerBase implements Configurati
final long podId = cmd.getPodId();
final String startIp = cmd.getStartIp();
final String endIp = cmd.getEndIp();
+ String vlan = cmd.getVlan();
+ try {
+ vlan = BroadcastDomainType.getValue(vlan);
+ } catch (URISyntaxException e) {
+ throw new CloudRuntimeException("Incorrect vlan " + vlan);
+ }
final HostPodVO pod = _podDao.findById(podId);
@@ -1268,10 +1310,13 @@ public class ConfigurationManagerImpl extends
ManagerBase implements Configurati
final String[] existingPodIpRange = podIpRange.split("-");
if(existingPodIpRange.length > 1) {
- if (startIp.equals(existingPodIpRange[0]) &&
endIp.equals(existingPodIpRange[1])) {
+ if (startIp.equals(existingPodIpRange[0]) &&
endIp.equals(existingPodIpRange[1]) &&
+ (existingPodIpRange.length > 3 ?
vlan.equals(existingPodIpRange[3]) : vlan.equals(DefaultVlanForPodIpRange))) {
foundRange = true;
} else if (index >= 0) {
- newPodIpRanges[index--] = (existingPodIpRange[0] + "-" +
existingPodIpRange[1]);
+ newPodIpRanges[index--] = (existingPodIpRange[0] + "-" +
existingPodIpRange[1] + "-" +
+ (existingPodIpRange.length > 2 ?
existingPodIpRange[2] : DefaultForSystemVmsForPodIpRange) + "-" +
+ (existingPodIpRange.length > 3 ?
existingPodIpRange[3] : DefaultVlanForPodIpRange));
}
}
}
@@ -1495,8 +1540,9 @@ public class ConfigurationManagerImpl extends ManagerBase
implements Configurati
// Create the new pod in the database
String ipRange;
+
if (!Strings.isNullOrEmpty(startIp)) {
- ipRange = startIp + "-" + endIp;
+ ipRange = startIp + "-" + endIp + "-" +
DefaultForSystemVmsForPodIpRange + "-" + DefaultVlanForPodIpRange;
} else {
throw new InvalidParameterValueException("Start ip is required
parameter");
}
@@ -1517,7 +1563,7 @@ public class ConfigurationManagerImpl extends ManagerBase
implements Configurati
final HostPodVO pod = _podDao.persist(podFinal);
if (!Strings.isNullOrEmpty(startIp)) {
- _zoneDao.addPrivateIpAddress(zoneId, pod.getId(), startIp,
endIpFinal);
+ _zoneDao.addPrivateIpAddress(zoneId, pod.getId(), startIp,
endIpFinal, false, null);
}
final String[] linkLocalIpRanges = getLinkLocalIPRange();
diff --git a/server/src/com/cloud/network/IpAddressManagerImpl.java
b/server/src/com/cloud/network/IpAddressManagerImpl.java
index 5180958..dca994d 100644
--- a/server/src/com/cloud/network/IpAddressManagerImpl.java
+++ b/server/src/com/cloud/network/IpAddressManagerImpl.java
@@ -1065,7 +1065,7 @@ public class IpAddressManagerImpl extends ManagerBase
implements IpAddressManage
if (podvo == null)
throw new ResourceAllocationException("No sush pod exists",
ResourceType.network);
- vo = _privateIPAddressDao.takeIpAddress(zone.getId(), podvo.getId(),
0, caller.getId() + "");
+ vo = _privateIPAddressDao.takeIpAddress(zone.getId(), podvo.getId(),
0, caller.getId() + "", false);
if(vo == null)
throw new ResourceAllocationException("Unable to allocate IP from
this Pod", ResourceType.network);
if (vo.getIpAddress() == null)
diff --git a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java
b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java
index e760001..eb80c12 100644
--- a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java
+++ b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java
@@ -16,6 +16,8 @@
// under the License.
package com.cloud.network.guru;
+import com.cloud.dc.dao.DataCenterDao.PrivateAllocationData;
+import com.cloud.vm.VirtualMachine;
import java.util.Random;
import javax.inject.Inject;
@@ -39,7 +41,6 @@ import com.cloud.network.StorageNetworkManager;
import com.cloud.network.dao.NetworkVO;
import com.cloud.offering.NetworkOffering;
import com.cloud.user.Account;
-import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
@@ -119,19 +120,25 @@ public class PodBasedNetworkGuru extends AdapterBase
implements NetworkGuru {
throws InsufficientVirtualNetworkCapacityException,
InsufficientAddressCapacityException {
Pod pod = dest.getPod();
- Pair<String, Long> ip =
_dcDao.allocatePrivateIpAddress(dest.getDataCenter().getId(),
dest.getPod().getId(), nic.getId(), context.getReservationId());
- if (ip == null) {
+ boolean forSystemVms =
vm.getType().equals(VirtualMachine.Type.ConsoleProxy) ||
vm.getType().equals(VirtualMachine.Type.SecondaryStorageVm);
+ PrivateAllocationData result =
_dcDao.allocatePrivateIpAddress(dest.getDataCenter().getId(),
dest.getPod().getId(), nic.getId(), context.getReservationId(), forSystemVms);
+ if (result == null) {
throw new InsufficientAddressCapacityException("Unable to get a
management ip address", Pod.class, pod.getId());
}
+ Integer vlan = result.getVlan();
- nic.setIPv4Address(ip.first());
-
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(ip.second(),
NetworkModel.MACIdentifier.value())));
+ nic.setIPv4Address(result.getIpAddress());
+
nic.setMacAddress(NetUtils.long2Mac(NetUtils.createSequenceBasedMacAddress(result.getMacAddress(),
NetworkModel.MACIdentifier.value())));
nic.setIPv4Gateway(pod.getGateway());
nic.setFormat(AddressFormat.Ip4);
String netmask = NetUtils.getCidrNetmask(pod.getCidrSize());
nic.setIPv4Netmask(netmask);
nic.setBroadcastType(BroadcastDomainType.Native);
- nic.setBroadcastUri(null);
+ if (vlan != null) {
+ nic.setBroadcastUri(BroadcastDomainType.Native.toUri(vlan));
+ } else {
+ nic.setBroadcastUri(null);
+ }
nic.setIsolationUri(null);
s_logger.debug("Allocated a nic " + nic + " for " + vm);
diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java
b/server/src/com/cloud/server/ConfigurationServerImpl.java
index 106aa9e..854ec13 100644
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -902,7 +902,7 @@ public class ConfigurationServerImpl extends ManagerBase
implements Configuratio
}
if (startIp != null) {
- _zoneDao.addPrivateIpAddress(zoneId, pod.getId(),
startIp, endIpFinal);
+ _zoneDao.addPrivateIpAddress(zoneId, pod.getId(),
startIp, endIpFinal, false, null);
}
String ipNums = _configDao.getValue("linkLocalIp.nums");
diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java
b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
index dcb8b45..8648033 100644
--- a/server/test/com/cloud/configuration/ConfigurationManagerTest.java
+++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
@@ -891,4 +891,24 @@ public class ConfigurationManagerTest {
result = configurationMgr.hasSameSubnet(false, null, null, null, null,
null, null, true, null, null, "2001:db8:0:f101::2", "2001:db8:0:f101::a",
ipV6Network);
Assert.assertTrue(result);
}
+
+ @Test(expected = CloudRuntimeException.class)
+ public void testGetVlanNumberFromUriInvalidParameter() {
+ configurationMgr.getVlanNumberFromUri("vlan");
+ }
+
+ @Test(expected = CloudRuntimeException.class)
+ public void testGetVlanNumberFromUriInvalidSintax() {
+ configurationMgr.getVlanNumberFromUri("xxx://7");
+ }
+
+ @Test
+ public void testGetVlanNumberFromUriVlan() {
+ Assert.assertEquals("7",
configurationMgr.getVlanNumberFromUri("vlan://7"));
+ }
+
+ @Test
+ public void testGetVlanNumberFromUriUntagged() {
+ Assert.assertEquals("untagged",
configurationMgr.getVlanNumberFromUri("vlan://untagged"));
+ }
}
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index d0e6162..f216423 100755
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -974,6 +974,13 @@
edit: true,
label: 'label.netmask'
},
+ 'vlan': {
+ edit: true,
+ label: 'label.vlan',
+ validation: {
+ required: false
+ }
+ },
'startip': {
edit: true,
label: 'label.start.IP'
@@ -985,6 +992,10 @@
required: false
}
},
+ 'systemvms' : {
+ isBoolean: true,
+ label: 'label.system.vms'
+ },
'add-rule': {
label: 'label.add',
addButton: true
@@ -1003,6 +1014,13 @@
if (args.data.endip != null &&
args.data.endip.length > 0)
array1.push("&endip=" +
args.data.endip);
+ if (args.data.systemvms) {
+
array1.push("&forsystemvms=" + (args.data.systemvms == "on" ? "true" :
"false"));
+ }
+
+ if (args.data.vlan != null &&
args.data.vlan.length > 0)
+ array1.push("&vlan=" +
todb(args.data.vlan));
+
$.ajax({
url:
createURL("createManagementNetworkIpRange" + array1.join("")),
dataType: "json",
@@ -1032,6 +1050,7 @@
array1.push("&podid=" +
args.context.multiRule[0].podid);
array1.push("&startip=" +
args.context.multiRule[0].startip);
array1.push("&endip=" +
args.context.multiRule[0].endip);
+ array1.push("&vlan=" +
args.context.multiRule[0].vlan);
$.ajax({
url:
createURL('deleteManagementNetworkIpRange' + array1.join("")),
@@ -1067,12 +1086,15 @@
var pods =
json.listpodsresponse.pod;
$(pods).each(function () {
for (var i = 0; i <
this.startip.length; i++) {
+ var systemvmsValue
= this.forsystemvms[i] == "1" ? true : false;
items.push({
podid: this.id,
gateway:
this.gateway,
netmask:
this.netmask,
startip:
this.startip[i],
- endip:
this.endip[i]
+ endip:
this.endip[i],
+ systemvms:
systemvmsValue,
+ vlan:
this.vlanid[i]
});
}
});
diff --git a/ui/scripts/ui/widgets/multiEdit.js
b/ui/scripts/ui/widgets/multiEdit.js
index 677448a..c3fa97c 100755
--- a/ui/scripts/ui/widgets/multiEdit.js
+++ b/ui/scripts/ui/widgets/multiEdit.js
@@ -179,6 +179,19 @@
}
$td.attr('title', data[fieldName]);
}
+ } else if (field.isBoolean) {
+ var $checkbox = $('<input>');
+ $checkbox.attr({
+ disabled: true,
+ name: fieldName,
+ type: 'checkbox'
+ });
+ if (_s(data[fieldName])) {
+ $checkbox.attr({
+ checked: true
+ });
+ }
+ $checkbox.appendTo($td);
} else if (field.select) {
// Get matching option text
var $matchingSelect = $multi.find('select')
@@ -980,6 +993,12 @@
error: function(args) {}
}
});
+ } else if (field.isBoolean) {
+ var $input = $('<input>')
+ .attr({
+ name: fieldName,
+ type: 'checkbox'
+ }).appendTo($td);
} else if (field.edit && field.edit != 'ignore') {
if (field.range) {
var $range = $('<div>').addClass('range').appendTo($td);
@@ -1118,7 +1137,11 @@
$multi.find('input').each(function() {
var $input = $(this);
- if ($input.data('multi-default-value')) {
+ if ($input.is(":checkbox")) {
+ $input.attr({
+ checked: false
+ });
+ } else if ($input.data('multi-default-value')) {
$input.val($input.data('multi-default-value'));
} else {
$input.val('');
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].