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