Skip to content

Commit a28af1a

Browse files
committed
server: Return the device ids of the CD-ROMs from TemplateManager
Move the calculation of the device ids reserved for the CD-ROM and the config drive ISO to TemplateManager, as getCdromDeviceIds(). An Instance has one CD-ROM, and the config drive ISO is one more CD-ROM (device id 4) when any network of the Instance uses config drive. VolumeApiService#getReservedDeviceIds() delegates to it, and a variant with the usage of config drive is added for the cases where the networks of the Instance are not known yet (VM import and backup restore).
1 parent 594b506 commit a28af1a

9 files changed

Lines changed: 223 additions & 120 deletions

File tree

‎api/src/main/java/com/cloud/storage/VolumeApiService.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ Volume updateVolume(long volumeId, String path, String state, Long storageId,
192192
*/
193193
Set<Long> getReservedDeviceIds(VirtualMachine vm);
194194

195+
/**
196+
* Same as {@link #getReservedDeviceIds(VirtualMachine)}, with the specified usage of config drive instead of the one
197+
* of the Instance. It is useful when the networks of the Instance are not known yet, e.g. when importing it.
198+
*/
199+
Set<Long> getReservedDeviceIds(VirtualMachine vm, boolean configDriveUsed);
200+
195201
boolean validateConditionsToReplaceDiskOfferingOfVolume(Volume volume, DiskOffering newDiskOffering, StoragePool destPool);
196202

197203
Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge);

‎engine/components-api/src/main/java/com/cloud/template/TemplateManager.java‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.cloud.template;
1818

1919
import java.util.List;
20+
import java.util.Set;
2021

2122
import org.apache.cloudstack.api.BaseCmd;
2223
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@@ -37,6 +38,7 @@
3738
import com.cloud.storage.VMTemplateVO;
3839
import com.cloud.storage.VolumeVO;
3940
import com.cloud.utils.Pair;
41+
import com.cloud.vm.VirtualMachine;
4042
import com.cloud.vm.VirtualMachineProfile;
4143

4244
/**
@@ -151,6 +153,23 @@ public interface TemplateManager {
151153
*/
152154
void prepareIsoForVmProfile(VirtualMachineProfile profile, DeployDestination dest);
153155

156+
/**
157+
* Returns the device ids of the CD-ROM devices of the Instance, starting from {@link #CDROM_PRIMARY_DEVICE_SEQ}.
158+
* They cannot be used by the volumes of the Instance.
159+
* An Instance has one CD-ROM device. If it uses config drive, the config drive ISO is one more CD-ROM, which has the
160+
* device id 4.
161+
*
162+
* @param vm the Instance
163+
* @return the device ids of the CD-ROM devices, including the one of the config drive ISO if the Instance uses config drive
164+
*/
165+
Set<Long> getCdromDeviceIds(VirtualMachine vm);
166+
167+
/**
168+
* Same as {@link #getCdromDeviceIds(VirtualMachine)}, with the specified usage of config drive instead of the one of
169+
* the Instance. It is useful when the networks of the Instance are not known yet, e.g. when importing it.
170+
*/
171+
Set<Long> getCdromDeviceIds(VirtualMachine vm, boolean configDriveUsed);
172+
154173
public static final String MESSAGE_REGISTER_PUBLIC_TEMPLATE_EVENT = "Message.RegisterPublicTemplate.Event";
155174
public static final String MESSAGE_RESET_TEMPLATE_PERMISSION_EVENT = "Message.ResetTemplatePermission.Event";
156175

‎server/src/main/java/com/cloud/hypervisor/KVMGuru.java‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2828
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
2929
import com.cloud.hypervisor.kvm.dpdk.DpdkHelper;
30-
import com.cloud.network.element.ConfigDriveNetworkElement;
3130
import com.cloud.service.ServiceOfferingVO;
3231
import com.cloud.storage.DataStoreRole;
3332
import com.cloud.storage.GuestOSHypervisorVO;
@@ -54,7 +53,6 @@
5453
import java.math.BigDecimal;
5554
import java.math.RoundingMode;
5655
import java.util.ArrayList;
57-
import java.util.HashSet;
5856
import java.util.List;
5957
import java.util.Map;
6058
import java.util.Set;
@@ -367,8 +365,7 @@ public VirtualMachine importVirtualMachineFromBackup(long zoneId, long domainId,
367365
_instanceDao.update(vm.getId(), vm);
368366
}
369367
// the networks of the (possibly expunged) VM may not be available, so always keep the config drive device id free
370-
Set<Long> reservedDeviceIds = new HashSet<>(volumeApiService.getReservedDeviceIds(vm));
371-
reservedDeviceIds.add(ConfigDriveNetworkElement.CONFIGDRIVEDISKSEQ.longValue());
368+
Set<Long> reservedDeviceIds = volumeApiService.getReservedDeviceIds(vm, true);
372369
for (Backup.VolumeInfo VMVolToRestore : vm.getBackupVolumeList()) {
373370
VolumeVO volume = _volumeDao.findByUuidIncludingRemoved(VMVolToRestore.getUuid());
374371
volume.setState(Volume.State.Ready);

‎server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java‎

Lines changed: 5 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,6 @@
160160
import com.cloud.hypervisor.Hypervisor.HypervisorType;
161161
import com.cloud.hypervisor.HypervisorCapabilitiesVO;
162162
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
163-
import com.cloud.network.Network.Provider;
164-
import com.cloud.network.Network.Service;
165-
import com.cloud.network.NetworkModel;
166-
import com.cloud.network.element.ConfigDriveNetworkElement;
167163
import com.cloud.offering.DiskOffering;
168164
import com.cloud.org.Cluster;
169165
import com.cloud.org.Grouping;
@@ -223,7 +219,6 @@
223219
import com.cloud.utils.fsm.NoTransitionException;
224220
import com.cloud.utils.fsm.StateMachine2;
225221
import com.cloud.vm.DiskProfile;
226-
import com.cloud.vm.NicVO;
227222
import com.cloud.vm.VMInstanceDetailVO;
228223
import com.cloud.vm.UserVmManager;
229224
import com.cloud.vm.UserVmService;
@@ -245,7 +240,6 @@
245240
import com.cloud.vm.VmWorkResizeVolume;
246241
import com.cloud.vm.VmWorkSerializer;
247242
import com.cloud.vm.VmWorkTakeVolumeSnapshot;
248-
import com.cloud.vm.dao.NicDao;
249243
import com.cloud.vm.dao.UserVmDao;
250244
import com.cloud.vm.dao.VMInstanceDetailsDao;
251245
import com.cloud.vm.dao.VMInstanceDao;
@@ -299,10 +293,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
299293
@Inject
300294
private VMInstanceDetailsDao vmInstanceDetailsDao;
301295
@Inject
302-
private NicDao _nicDao;
303-
@Inject
304-
private NetworkModel _networkModel;
305-
@Inject
306296
private UserVmService _userVmService;
307297
@Inject
308298
private VolumeDataStoreDao _volumeStoreDao;
@@ -5047,44 +5037,14 @@ protected String getMinimumHypervisorVersionInDatacenter(long datacenterId, Hype
50475037
return StringUtils.isBlank(minHwVersion) ? defaultHypervisorVersion : minHwVersion;
50485038
}
50495039

5050-
/**
5051-
* The number of CD-ROM devices of the Instance. Each CD-ROM device occupies a device id, starting from
5052-
* {@link TemplateManager#CDROM_PRIMARY_DEVICE_SEQ}.
5053-
*/
5054-
protected int getVmCdromCount(VirtualMachine vm) {
5055-
return 1;
5056-
}
5057-
5058-
/**
5059-
* Checks if a config drive ISO is (or will be) attached to the Instance, which is the case when any of its networks
5060-
* has ConfigDrive as the provider of the Dhcp, Dns or UserData service. Checking the network providers (instead of
5061-
* only the config drive location detail, which is added when the ISO is created) also covers Instances which have
5062-
* never been started.
5063-
*/
5064-
protected boolean isConfigDriveUsed(VirtualMachine vm) {
5065-
if (vmInstanceDetailsDao.findDetail(vm.getId(), VmDetailConstants.CONFIG_DRIVE_LOCATION) != null) {
5066-
return true;
5067-
}
5068-
for (NicVO nic : _nicDao.listByVmId(vm.getId())) {
5069-
for (Service service : Arrays.asList(Service.UserData, Service.Dhcp, Service.Dns)) {
5070-
if (_networkModel.isProviderSupportServiceInNetwork(nic.getNetworkId(), service, Provider.ConfigDrive)) {
5071-
return true;
5072-
}
5073-
}
5074-
}
5075-
return false;
5040+
@Override
5041+
public Set<Long> getReservedDeviceIds(VirtualMachine vm) {
5042+
return _tmpltMgr.getCdromDeviceIds(vm);
50765043
}
50775044

50785045
@Override
5079-
public Set<Long> getReservedDeviceIds(VirtualMachine vm) {
5080-
Set<Long> reservedDeviceIds = new HashSet<>();
5081-
for (int i = 0; i < getVmCdromCount(vm); i++) {
5082-
reservedDeviceIds.add((long) TemplateManager.CDROM_PRIMARY_DEVICE_SEQ + i);
5083-
}
5084-
if (isConfigDriveUsed(vm)) {
5085-
reservedDeviceIds.add(ConfigDriveNetworkElement.CONFIGDRIVEDISKSEQ.longValue());
5086-
}
5087-
return reservedDeviceIds;
5046+
public Set<Long> getReservedDeviceIds(VirtualMachine vm, boolean configDriveUsed) {
5047+
return _tmpltMgr.getCdromDeviceIds(vm, configDriveUsed);
50885048
}
50895049

50905050
/**

‎server/src/main/java/com/cloud/template/TemplateManagerImpl.java‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@
2323
import java.util.Arrays;
2424
import java.util.Date;
2525
import java.util.HashMap;
26+
import java.util.HashSet;
2627
import java.util.List;
2728
import java.util.Map;
29+
import java.util.Set;
2830
import java.util.UUID;
2931
import java.util.concurrent.ExecutionException;
3032
import java.util.concurrent.ExecutorService;
@@ -151,6 +153,10 @@
151153
import com.cloud.hypervisor.Hypervisor.HypervisorType;
152154
import com.cloud.hypervisor.HypervisorGuru;
153155
import com.cloud.hypervisor.HypervisorGuruManager;
156+
import com.cloud.network.Network.Provider;
157+
import com.cloud.network.Network.Service;
158+
import com.cloud.network.NetworkModel;
159+
import com.cloud.network.element.ConfigDriveNetworkElement;
154160
import com.cloud.projects.Project;
155161
import com.cloud.projects.ProjectManager;
156162
import com.cloud.resourcelimit.CheckedReservation;
@@ -215,6 +221,7 @@
215221
import com.cloud.utils.db.TransactionCallbackNoReturn;
216222
import com.cloud.utils.db.TransactionStatus;
217223
import com.cloud.utils.exception.CloudRuntimeException;
224+
import com.cloud.vm.NicVO;
218225
import com.cloud.vm.UserVmManager;
219226
import com.cloud.vm.UserVmVO;
220227
import com.cloud.vm.VMInstanceVO;
@@ -223,8 +230,10 @@
223230
import com.cloud.vm.VirtualMachineProfile;
224231
import com.cloud.vm.VirtualMachineProfileImpl;
225232
import com.cloud.vm.VmDetailConstants;
233+
import com.cloud.vm.dao.NicDao;
226234
import com.cloud.vm.dao.UserVmDao;
227235
import com.cloud.vm.dao.VMInstanceDao;
236+
import com.cloud.vm.dao.VMInstanceDetailsDao;
228237
import com.google.gson.Gson;
229238
import com.google.gson.GsonBuilder;
230239

@@ -324,6 +333,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
324333
private HeuristicRuleHelper heuristicRuleHelper;
325334
@Inject
326335
private UserDataDao userDataDao;
336+
@Inject
337+
private NicDao _nicDao;
338+
@Inject
339+
private NetworkModel _networkModel;
340+
@Inject
341+
private VMInstanceDetailsDao _vmInstanceDetailsDao;
327342

328343
private List<TemplateAdapter> _adapters;
329344

@@ -730,6 +745,61 @@ public void prepareIsoForVmProfile(VirtualMachineProfile profile, DeployDestinat
730745
}
731746
}
732747

748+
@Override
749+
public Set<Long> getCdromDeviceIds(VirtualMachine vm) {
750+
if (vm.getType() != VirtualMachine.Type.User) {
751+
return getCdromDeviceIds(1);
752+
}
753+
return getCdromDeviceIds(vm, isConfigDriveUsed(vm));
754+
}
755+
756+
@Override
757+
public Set<Long> getCdromDeviceIds(VirtualMachine vm, boolean configDriveUsed) {
758+
return getCdromDeviceIds(getCdromCount(vm, configDriveUsed));
759+
}
760+
761+
private Set<Long> getCdromDeviceIds(int cdromCount) {
762+
Set<Long> deviceIds = new HashSet<>();
763+
for (int i = 0; i < cdromCount; i++) {
764+
deviceIds.add((long) CDROM_PRIMARY_DEVICE_SEQ + i);
765+
}
766+
return deviceIds;
767+
}
768+
769+
private int getCdromCount(VirtualMachine vm, boolean configDriveUsed) {
770+
// an Instance has one CD-ROM device for its ISO
771+
int cdromCount = 1;
772+
// the config drive ISO is one more CD-ROM, which has the device id of ConfigDriveNetworkElement#CONFIGDRIVEDISKSEQ
773+
if (vm.getType() == VirtualMachine.Type.User && configDriveUsed) {
774+
cdromCount += ConfigDriveNetworkElement.CONFIGDRIVEDISKSEQ - CDROM_PRIMARY_DEVICE_SEQ;
775+
}
776+
return cdromCount;
777+
}
778+
779+
/**
780+
* Checks if a config drive ISO is (or will be) attached to the Instance, which is the case when any of its networks
781+
* has ConfigDrive as the provider of the Dhcp, Dns or UserData service. Checking the network providers (instead of
782+
* only the config drive location detail, which is added when the ISO is created) also covers Instances which have
783+
* never been started.
784+
*/
785+
boolean isConfigDriveUsed(VirtualMachine vm) {
786+
if (_vmInstanceDetailsDao.findDetail(vm.getId(), VmDetailConstants.CONFIG_DRIVE_LOCATION) != null) {
787+
return true;
788+
}
789+
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
790+
if (CollectionUtils.isEmpty(nics)) {
791+
return false;
792+
}
793+
for (NicVO nic : nics) {
794+
for (Service service : Arrays.asList(Service.UserData, Service.Dhcp, Service.Dns)) {
795+
if (_networkModel.isProviderSupportServiceInNetwork(nic.getNetworkId(), service, Provider.ConfigDrive)) {
796+
return true;
797+
}
798+
}
799+
}
800+
return false;
801+
}
802+
733803
private void prepareTemplateInOneStoragePool(final VMTemplateVO template, final StoragePoolVO pool) {
734804
logger.info("Schedule to preload Template {} into primary storage {}", template, pool);
735805
if (pool.getPoolType() == Storage.StoragePoolType.DatastoreCluster) {

‎server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
import com.cloud.network.dao.NetworkDao;
7979
import com.cloud.network.dao.NetworkVO;
8080
import com.cloud.network.dao.PhysicalNetworkDao;
81-
import com.cloud.network.element.ConfigDriveNetworkElement;
8281
import com.cloud.offering.DiskOffering;
8382
import com.cloud.offering.NetworkOffering;
8483
import com.cloud.offering.ServiceOffering;
@@ -877,9 +876,7 @@ private Pair<DiskProfile, StoragePool> importDisk(UnmanagedInstanceTO.Disk disk,
877876
* and the one of the config drive ISO (always kept free, as the NICs of the Instance are not imported yet at this point).
878877
*/
879878
private Set<Long> getReservedDeviceIds(VirtualMachine vm) {
880-
Set<Long> reservedDeviceIds = new HashSet<>(volumeApiService.getReservedDeviceIds(vm));
881-
reservedDeviceIds.add(ConfigDriveNetworkElement.CONFIGDRIVEDISKSEQ.longValue());
882-
return reservedDeviceIds;
879+
return volumeApiService.getReservedDeviceIds(vm, true);
883880
}
884881

885882
private long getNextDeviceId(long deviceId, Set<Long> reservedDeviceIds) {

0 commit comments

Comments
 (0)