Skip to content

Commit 553630b

Browse files
author
Mike Tutkowski
committed
CLOUDSTACK-6170 (VMware root-disk support for managed storage)
1 parent 9493b4d commit 553630b

3 files changed

Lines changed: 149 additions & 20 deletions

File tree

plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,16 @@
2929

3030
import org.apache.log4j.Logger;
3131

32+
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
33+
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
34+
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
3235
import org.apache.cloudstack.framework.config.ConfigKey;
3336
import org.apache.cloudstack.framework.config.Configurable;
3437
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
3538
import org.apache.cloudstack.storage.command.CopyCommand;
39+
import org.apache.cloudstack.storage.command.DeleteCommand;
40+
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
41+
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
3642
import org.apache.cloudstack.storage.to.VolumeObjectTO;
3743

3844
import com.cloud.agent.api.BackupSnapshotCommand;
@@ -48,6 +54,7 @@
4854
import com.cloud.agent.api.to.DataObjectType;
4955
import com.cloud.agent.api.to.DataStoreTO;
5056
import com.cloud.agent.api.to.DataTO;
57+
import com.cloud.agent.api.to.DiskTO;
5158
import com.cloud.agent.api.to.NicTO;
5259
import com.cloud.agent.api.to.VirtualMachineTO;
5360
import com.cloud.cluster.ClusterManager;
@@ -76,7 +83,10 @@
7683
import com.cloud.storage.DataStoreRole;
7784
import com.cloud.storage.GuestOSVO;
7885
import com.cloud.storage.Storage;
86+
import com.cloud.storage.Volume;
87+
import com.cloud.storage.VolumeVO;
7988
import com.cloud.storage.dao.GuestOSDao;
89+
import com.cloud.storage.dao.VolumeDao;
8090
import com.cloud.storage.secondary.SecondaryStorageVmManager;
8191
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
8292
import com.cloud.utils.Pair;
@@ -123,6 +133,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
123133
private VMInstanceDao _vmDao;
124134
@Inject
125135
private ClusterManager _clusterMgr;
136+
@Inject
137+
VolumeDao _volumeDao;
138+
@Inject
139+
PrimaryDataStoreDao _storagePoolDao;
140+
@Inject
141+
VolumeDataFactory _volFactory;
126142

127143
protected VMwareGuru() {
128144
super();
@@ -476,4 +492,43 @@ public String getConfigComponentName() {
476492
public ConfigKey<?>[] getConfigKeys() {
477493
return new ConfigKey<?>[] {VmwareReserveCpu, VmwareReserveMemory};
478494
}
495+
496+
@Override
497+
public List<Command> finalizeExpungeVolumes(VirtualMachine vm) {
498+
List<Command> commands = new ArrayList<Command>();
499+
500+
List<VolumeVO> volumes = _volumeDao.findByInstance(vm.getId());
501+
502+
if (volumes != null) {
503+
for (VolumeVO volume : volumes) {
504+
StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
505+
506+
// storagePool should be null if we are expunging a volume that was never
507+
// attached to a VM that was started (the "trick" for storagePool to be null
508+
// is that none of the VMs this volume may have been attached to were ever started,
509+
// so the volume was never assigned to a storage pool)
510+
if (storagePool != null && storagePool.isManaged() && volume.getVolumeType() == Volume.Type.ROOT) {
511+
VolumeInfo volumeInfo = _volFactory.getVolume(volume.getId());
512+
PrimaryDataStore primaryDataStore = (PrimaryDataStore)volumeInfo.getDataStore();
513+
Map<String, String> details = primaryDataStore.getDetails();
514+
515+
if (details == null) {
516+
details = new HashMap<String, String>();
517+
518+
primaryDataStore.setDetails(details);
519+
}
520+
521+
details.put(DiskTO.MANAGED, Boolean.TRUE.toString());
522+
523+
DeleteCommand cmd = new DeleteCommand(volumeInfo.getTO());
524+
525+
commands.add(cmd);
526+
527+
break;
528+
}
529+
}
530+
}
531+
532+
return commands;
533+
}
479534
}

plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,9 +1412,8 @@ protected StartAnswer execute(StartCommand cmd) {
14121412
DiskTO[] disks = validateDisks(vmSpec.getDisks());
14131413
assert (disks.length > 0);
14141414
NicTO[] nics = vmSpec.getNics();
1415-
Map<String, String> iqnToPath = new HashMap<String, String>();
14161415

1417-
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks, iqnToPath, cmd);
1416+
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks, cmd);
14181417
if ((dataStoresDetails == null) || (dataStoresDetails.isEmpty())) {
14191418
String msg = "Unable to locate datastore details of the volumes to be attached";
14201419
s_logger.error(msg);
@@ -1471,9 +1470,23 @@ protected StartAnswer execute(StartCommand cmd) {
14711470
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
14721471
for (DiskTO vol : disks) {
14731472
if (vol.getType() == Volume.Type.ROOT) {
1474-
DataStoreTO primaryStore = vol.getData().getDataStore();
1475-
/** @todo Mike T. update this in 4.4 to support root disks on managed storage */
1476-
rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
1473+
Map<String, String> details = vol.getDetails();
1474+
boolean managed = false;
1475+
1476+
if (details != null) {
1477+
managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
1478+
}
1479+
1480+
if (managed) {
1481+
String datastoreName = VmwareResource.getDatastoreName(details.get(DiskTO.IQN));
1482+
1483+
rootDiskDataStoreDetails = dataStoresDetails.get(datastoreName);
1484+
}
1485+
else {
1486+
DataStoreTO primaryStore = vol.getData().getDataStore();
1487+
1488+
rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
1489+
}
14771490
}
14781491
}
14791492

@@ -1759,7 +1772,10 @@ protected StartAnswer execute(StartCommand cmd) {
17591772

17601773
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask));
17611774
postNvpConfigBeforeStart(vmMo, vmSpec);
1762-
postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey);
1775+
1776+
Map<String, String> iqnToPath = new HashMap<String, String>();
1777+
1778+
postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey, iqnToPath);
17631779

17641780
//
17651781
// Power-on VM
@@ -1891,7 +1907,12 @@ private String[] syncDiskChain(DatacenterMO dcMo, VirtualMachineMO vmMo, Virtual
18911907
final String datastoreDiskPath;
18921908

18931909
if (isManaged) {
1894-
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
1910+
if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
1911+
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, dsMo.getName());
1912+
}
1913+
else {
1914+
datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
1915+
}
18951916
} else {
18961917
datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
18971918
}
@@ -2177,9 +2198,8 @@ private int getDiskController(VirtualMachineDiskInfo matchingExistingDisk, DiskT
21772198
return controllerKey;
21782199
}
21792200

2180-
private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey, int scsiControllerKey)
2181-
throws Exception {
2182-
2201+
private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey,
2202+
int scsiControllerKey, Map<String, String> iqnToPath) throws Exception {
21832203
VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
21842204

21852205
for (DiskTO vol : sortedDisks) {
@@ -2194,14 +2214,45 @@ private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO v
21942214
String[] diskChain = diskInfo.getDiskChain();
21952215
assert (diskChain.length > 0);
21962216

2217+
Map<String, String> details = vol.getDetails();
2218+
boolean managed = false;
2219+
2220+
if (details != null) {
2221+
managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
2222+
}
2223+
21972224
DatastoreFile file = new DatastoreFile(diskChain[0]);
2198-
if (!file.getFileBaseName().equalsIgnoreCase(volumeTO.getPath())) {
2199-
if (s_logger.isInfoEnabled())
2200-
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + file.getFileBaseName());
2225+
2226+
if (managed) {
2227+
DatastoreFile originalFile = new DatastoreFile(volumeTO.getPath());
2228+
2229+
if (!file.getFileBaseName().equalsIgnoreCase(originalFile.getFileBaseName())) {
2230+
if (s_logger.isInfoEnabled())
2231+
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + diskChain[0]);
2232+
}
2233+
}
2234+
else {
2235+
if (!file.getFileBaseName().equalsIgnoreCase(volumeTO.getPath())) {
2236+
if (s_logger.isInfoEnabled())
2237+
s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + file.getFileBaseName());
2238+
}
22012239
}
22022240

22032241
VolumeObjectTO volInSpec = getVolumeInSpec(vmSpec, volumeTO);
2204-
volInSpec.setPath(file.getFileBaseName());
2242+
2243+
if (managed) {
2244+
String datastoreVolumePath = diskChain[0];
2245+
2246+
iqnToPath.put(details.get(DiskTO.IQN), datastoreVolumePath);
2247+
2248+
vol.setPath(datastoreVolumePath);
2249+
volumeTO.setPath(datastoreVolumePath);
2250+
volInSpec.setPath(datastoreVolumePath);
2251+
}
2252+
else {
2253+
volInSpec.setPath(file.getFileBaseName());
2254+
}
2255+
22052256
volInSpec.setChainInfo(_gson.toJson(diskInfo));
22062257
}
22072258
}
@@ -2263,7 +2314,7 @@ public int compare(DiskTO arg0, DiskTO arg1) {
22632314
}
22642315

22652316
private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context,
2266-
DiskTO[] disks, Map<String, String> iqnToPath, Command cmd) throws Exception {
2317+
DiskTO[] disks, Command cmd) throws Exception {
22672318
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> mapIdToMors = new HashMap<String, Pair<ManagedObjectReference, DatastoreMO>>();
22682319

22692320
assert (hyperHost != null) && (context != null);
@@ -2299,8 +2350,6 @@ private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastor
22992350
DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDatastore);
23002351
String datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
23012352

2302-
iqnToPath.put(iScsiName, datastoreVolumePath);
2303-
23042353
volumeTO.setPath(datastoreVolumePath);
23052354
vol.setPath(datastoreVolumePath);
23062355
}
@@ -3462,6 +3511,8 @@ public void removeManagedTargetsFromCluster(List<String> iqns) throws Exception
34623511
}
34633512

34643513
addRemoveInternetScsiTargetsToAllHosts(false, lstManagedTargets, lstHosts);
3514+
3515+
rescanAllHosts(lstHosts);
34653516
}
34663517

34673518
private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets,
@@ -4281,7 +4332,7 @@ protected Answer execute(UnregisterNicCommand cmd) {
42814332

42824333
public Answer execute(DeleteCommand cmd) {
42834334
if (s_logger.isInfoEnabled()) {
4284-
s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
4335+
s_logger.info("Executing resource DeleteCommand: " + _gson.toJson(cmd));
42854336
}
42864337

42874338
/*

plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.apache.cloudstack.storage.command.DettachCommand;
4747
import org.apache.cloudstack.storage.command.ForgetObjectCmd;
4848
import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
49+
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
4950
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
5051
import org.apache.cloudstack.storage.to.TemplateObjectTO;
5152
import org.apache.cloudstack.storage.to.VolumeObjectTO;
@@ -1420,19 +1421,41 @@ public Answer createSnapshot(CreateObjectCommand cmd) {
14201421
return new CreateObjectAnswer(newSnapshot);
14211422
}
14221423

1424+
// format: [datastore_name] file_name.vmdk (the '[' and ']' chars should only be used to denote the datastore)
1425+
private String getManagedDatastoreNameFromPath(String path) {
1426+
int lastIndexOf = path.lastIndexOf("]");
1427+
1428+
return path.substring(1, lastIndexOf);
1429+
}
1430+
14231431
@Override
14241432
public Answer deleteVolume(DeleteCommand cmd) {
14251433
if (s_logger.isInfoEnabled()) {
1426-
s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
1434+
s_logger.info("Executing resource DeleteCommand: " + _gson.toJson(cmd));
14271435
}
14281436

14291437
try {
14301438
VmwareContext context = hostService.getServiceContext(null);
14311439
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
14321440
VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
14331441
DataStoreTO store = vol.getDataStore();
1442+
PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO)store;
1443+
1444+
Map<String, String> details = primaryDataStoreTO.getDetails();
1445+
boolean isManaged = false;
1446+
String managedDatastoreName = null;
1447+
1448+
if (details != null) {
1449+
isManaged = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED));
1450+
1451+
if (isManaged) {
1452+
managedDatastoreName = getManagedDatastoreNameFromPath(vol.getPath());
1453+
}
1454+
}
1455+
1456+
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost,
1457+
isManaged ? managedDatastoreName : store.getUuid());
14341458

1435-
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
14361459
if (morDs == null) {
14371460
String msg = "Unable to find datastore based on volume mount point " + store.getUuid();
14381461
s_logger.error(msg);

0 commit comments

Comments
 (0)