You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2018/01/05 07:49:09 UTC

[GitHub] rhtyd closed pull request #2368: CLOUDSTACK-10126: Separate Subnet for SSVM and CPVM

rhtyd closed pull request #2368: CLOUDSTACK-10126: Separate Subnet for SSVM and CPVM
URL: https://github.com/apache/cloudstack/pull/2368
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 0e275b5de15..8b632be4fd5 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -125,6 +125,7 @@
     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 e5bfc07c699..f7957469cd1 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 @@
             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 String getEndIp() {
         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 acb9e7a4678..d6481846f43 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 @@
             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 String getEndIp() {
         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 c5c700ef5df..27ebf71a994 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 @@
     @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 void setEndIp(List<String> endIp) {
         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 5d51b47a994..585c7fd4992 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 70b4df16654..3d68cc3d9a8 100644
--- a/engine/schema/src/com/cloud/dc/DataCenterIpAddressVO.java
+++ b/engine/schema/src/com/cloud/dc/DataCenterIpAddressVO.java
@@ -60,6 +60,12 @@
     @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 Date getTakenAt() {
     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 4fc055e6ac8..a6cd59f1cc3 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 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 @@
 
     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 @@
 
     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 847a24730fc..385fb406155 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.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 String allocatePodVlan(long podId, long accountId) {
     }
 
     @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 void deleteVnet(long physicalNetworkId) {
     }
 
     @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 9929cc3e4b2..bb840b5adec 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 @@
 
 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 12bfdc85628..8b0a44bbbf0 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.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 @@
 
 @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 @@
     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 boolean mark(long dcId, long podId, String ip) {
 
     @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 void addIpRange(long dcId, long podId, String start, String end) {
                     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 DataCenterIpAddressDaoImpl() {
         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 DataCenterIpAddressDaoImpl() {
         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 e352198d586..49b8c150ecc 100644
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -947,6 +947,8 @@ public PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
         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 PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
 
                 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 PodResponse createPodResponse(Pod pod, Boolean showCapacities) {
         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 dfc7c372d48..36bedd5012b 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 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 void doInTransactionWithoutResult(final TransactionStatus status) {
         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 Pod createPodIpRange(final CreateManagementNetworkIpRangeCmd cmd) {
         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 Pod createPodIpRange(final CreateManagementNetworkIpRangeCmd cmd) {
                 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 void doInTransactionWithoutResult(final TransactionStatus status) {
                         }
                     }
 
-                    _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 void deletePodIpRange(final DeleteManagementNetworkIpRangeCmd cmd) throws
         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 void deletePodIpRange(final DeleteManagementNetworkIpRangeCmd cmd) throws
             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 HostPodVO createPod(final long userId, final String podName, final long z
 
         // 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 HostPodVO doInTransaction(final TransactionStatus status) {
                 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 51809589e16..dca994d6a5a 100644
--- a/server/src/com/cloud/network/IpAddressManagerImpl.java
+++ b/server/src/com/cloud/network/IpAddressManagerImpl.java
@@ -1065,7 +1065,7 @@ public AcquirePodIpCmdResponse allocatePodIp(String zoneId, String podId) throws
         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 e7600010e1d..eb80c12702d 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.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 void reserve(NicProfile nic, Network config, VirtualMachineProfile vm, De
         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 106aa9e831f..854ec136b49 100644
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -902,7 +902,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Intern
                     }
 
                     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 dcb8b456c54..8648033c9b0 100644
--- a/server/test/com/cloud/configuration/ConfigurationManagerTest.java
+++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java
@@ -891,4 +891,24 @@ public void hasSameSubnetTest() {
         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 d0e61623566..f216423d4bf 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 677448a15ab..c3fa97c8fc1 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('');


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services