CLOUDSTACK-9134: set device_id as the first device_id not in use instead of nic count
when we restart vpc tiers, the old nics will be removed, and create a new nic.
however, the device_id was set to the nic count, which may be already used.
this commit get the first device_id not in use as the device_id of new nic.
This issue also happen when we add multiple networks to a vm and remove them.
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
index a3ae526..21699a3 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java
@@ -3150,7 +3150,7 @@
//1) allocate nic (if needed) Always allocate if it is a user vm
if (nic == null || (vmProfile.getType() == VirtualMachine.Type.User)) {
- int deviceId = _nicDao.countNics(vm.getId());
+ int deviceId = _nicDao.getFreeDeviceId(vm.getId());
nic = allocateNic(requested, network, false, deviceId, vmProfile).first();
diff --git a/engine/schema/src/com/cloud/vm/dao/NicDao.java b/engine/schema/src/com/cloud/vm/dao/NicDao.java
index a7ad016..2c7895a 100644
--- a/engine/schema/src/com/cloud/vm/dao/NicDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/NicDao.java
@@ -55,7 +55,7 @@
String getIpAddress(long networkId, long instanceId);
- int countNics(long instanceId);
+ int getFreeDeviceId(long instanceId);
NicVO findByNetworkIdInstanceIdAndBroadcastUri(long networkId, long instanceId, String broadcastUri);
diff --git a/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java
index da89b2c..f1299b3 100644
--- a/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/NicDaoImpl.java
@@ -25,6 +25,7 @@
import org.springframework.stereotype.Component;
+import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
@@ -44,7 +45,7 @@
private SearchBuilder<NicVO> AllFieldsSearch;
private GenericSearchBuilder<NicVO, String> IpSearch;
private SearchBuilder<NicVO> NonReleasedSearch;
- private GenericSearchBuilder<NicVO, Integer> CountBy;
+ private GenericSearchBuilder<NicVO, Integer> deviceIdSearch;
private GenericSearchBuilder<NicVO, Integer> CountByForStartingVms;
@Inject
@@ -81,11 +82,10 @@
NonReleasedSearch.and("state", NonReleasedSearch.entity().getState(), Op.NOTIN);
NonReleasedSearch.done();
- CountBy = createSearchBuilder(Integer.class);
- CountBy.select(null, Func.COUNT, CountBy.entity().getId());
- CountBy.and("vmId", CountBy.entity().getInstanceId(), Op.EQ);
- CountBy.and("removed", CountBy.entity().getRemoved(), Op.NULL);
- CountBy.done();
+ deviceIdSearch = createSearchBuilder(Integer.class);
+ deviceIdSearch.select(null, Func.DISTINCT, deviceIdSearch.entity().getDeviceId());
+ deviceIdSearch.and("instance", deviceIdSearch.entity().getInstanceId(), Op.EQ);
+ deviceIdSearch.done();
CountByForStartingVms = createSearchBuilder(Integer.class);
CountByForStartingVms.select(null, Func.COUNT, CountByForStartingVms.entity().getId());
@@ -222,11 +222,20 @@
}
@Override
- public int countNics(long instanceId) {
- SearchCriteria<Integer> sc = CountBy.create();
- sc.setParameters("vmId", instanceId);
- List<Integer> results = customSearch(sc, null);
- return results.get(0);
+ public int getFreeDeviceId(long instanceId) {
+ Filter searchFilter = new Filter(NicVO.class, "deviceId", true, null, null);
+ SearchCriteria<Integer> sc = deviceIdSearch.create();
+ sc.setParameters("instance", instanceId);
+ List<Integer> deviceIds = customSearch(sc, searchFilter);
+
+ int freeDeviceId = 0;
+ for (int deviceId : deviceIds) {
+ if (deviceId > freeDeviceId)
+ break;
+ freeDeviceId ++;
+ }
+
+ return freeDeviceId;
}
@Override