Skip to content

Commit 381f3d9

Browse files
committed
Refactor VM import
1 parent c22b3be commit 381f3d9

File tree

5 files changed

+177
-65
lines changed

5 files changed

+177
-65
lines changed

engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,6 @@ List<ServiceOfferingVO> createSystemServiceOfferings(String name, String uniqueN
5757
ServiceOfferingVO getcomputeOffering(ServiceOfferingVO serviceOffering, Map<String, String> customParameters);
5858

5959
ServiceOfferingVO findDefaultSystemOffering(String offeringName, Boolean useLocalStorage);
60+
61+
List<ServiceOfferingVO> listPublicByCpuAndMemory(Integer cpus, Integer memory);
6062
}

engine/schema/src/main/java/com/cloud/service/dao/ServiceOfferingDaoImpl.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class ServiceOfferingDaoImpl extends GenericDaoBase<ServiceOfferingVO, Lo
5454
protected final SearchBuilder<ServiceOfferingVO> SystemServiceOffering;
5555
protected final SearchBuilder<ServiceOfferingVO> ServiceOfferingsByKeywordSearch;
5656
protected final SearchBuilder<ServiceOfferingVO> PublicServiceOfferingSearch;
57+
protected final SearchBuilder<ServiceOfferingVO> PublicCpuRamSearch;
5758

5859
public ServiceOfferingDaoImpl() {
5960
super();
@@ -84,6 +85,12 @@ public ServiceOfferingDaoImpl() {
8485
ServiceOfferingsByKeywordSearch.or("name", ServiceOfferingsByKeywordSearch.entity().getName(), SearchCriteria.Op.EQ);
8586
ServiceOfferingsByKeywordSearch.or("displayText", ServiceOfferingsByKeywordSearch.entity().getDisplayText(), SearchCriteria.Op.EQ);
8687
ServiceOfferingsByKeywordSearch.done();
88+
89+
PublicCpuRamSearch = createSearchBuilder();
90+
PublicCpuRamSearch.and("cpu", PublicCpuRamSearch.entity().getCpu(), SearchCriteria.Op.EQ);
91+
PublicCpuRamSearch.and("ram", PublicCpuRamSearch.entity().getRamSize(), SearchCriteria.Op.EQ);
92+
PublicCpuRamSearch.and("system_use", PublicCpuRamSearch.entity().getSystemUse(), SearchCriteria.Op.EQ);
93+
PublicCpuRamSearch.done();
8794
}
8895

8996
@Override
@@ -289,4 +296,13 @@ public ServiceOfferingVO findDefaultSystemOffering(String offeringName, Boolean
289296
}
290297
return serviceOffering;
291298
}
299+
300+
@Override
301+
public List<ServiceOfferingVO> listPublicByCpuAndMemory(Integer cpus, Integer memory) {
302+
SearchCriteria<ServiceOfferingVO> sc = PublicCpuRamSearch.create();
303+
sc.setParameters("cpu", cpus);
304+
sc.setParameters("ram", memory);
305+
sc.setParameters("system_use", false);
306+
return listBy(sc);
307+
}
292308
}

plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java

Lines changed: 142 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@
7676
import com.cloud.org.Cluster.ClusterType;
7777
import com.cloud.secstorage.CommandExecLogDao;
7878
import com.cloud.server.ConfigurationServer;
79+
import com.cloud.service.ServiceOfferingVO;
7980
import com.cloud.service.dao.ServiceOfferingDao;
81+
import com.cloud.storage.GuestOSVO;
8082
import com.cloud.storage.ImageStoreDetailsUtil;
8183
import com.cloud.storage.JavaStorageLayer;
8284
import com.cloud.storage.Storage;
@@ -85,6 +87,7 @@
8587
import com.cloud.storage.VMTemplateStoragePoolVO;
8688
import com.cloud.storage.Volume;
8789
import com.cloud.storage.VolumeVO;
90+
import com.cloud.storage.dao.GuestOSDao;
8891
import com.cloud.storage.dao.VMTemplatePoolDao;
8992
import com.cloud.storage.dao.VolumeDao;
9093
import com.cloud.template.TemplateManager;
@@ -103,7 +106,10 @@
103106
import com.cloud.utils.script.Script;
104107
import com.cloud.utils.ssh.SshHelper;
105108
import com.cloud.vm.DomainRouterVO;
109+
import com.cloud.vm.UserVmVO;
110+
import com.cloud.vm.VMInstanceVO;
106111
import com.cloud.vm.dao.UserVmCloneSettingDao;
112+
import com.cloud.vm.dao.UserVmDao;
107113
import com.cloud.vm.dao.VMInstanceDao;
108114
import com.vmware.vim25.AboutInfo;
109115
import com.vmware.vim25.ManagedObjectReference;
@@ -126,6 +132,7 @@
126132
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
127133
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
128134
import org.apache.cloudstack.utils.identity.ManagementServerNode;
135+
import org.apache.commons.collections.CollectionUtils;
129136
import org.apache.commons.lang.BooleanUtils;
130137
import org.apache.commons.lang.StringUtils;
131138
import org.apache.log4j.Logger;
@@ -214,6 +221,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
214221
private VolumeDao volumeDao;
215222
@Inject
216223
private ServiceOfferingDao serviceOfferingDao;
224+
@Inject
225+
private GuestOSDao guestOSDao;
226+
@Inject
227+
private UserVmDao userVmDao;
217228

218229
private String _mountParent;
219230
private StorageLayer _storage;
@@ -1317,8 +1328,13 @@ public boolean importVmwareVM(String vmInternalName, Long zoneId) {
13171328

13181329
s_logger.debug("VM " + vmInternalName + " found on datacenter " + datacenterName + ", trying to import it...");
13191330

1320-
importVMAndServiceOffering(configSummary);
1321-
importVMVolumes(virtualDisks, zoneId);
1331+
Long guestOsId = importVMGuestOs(configSummary);
1332+
Long serviceOfferingId = importVMServiceOffering(configSummary);
1333+
Long poolId = getPoolId(virtualDisks);
1334+
Long templateId = importVMTemplate(virtualDisks, poolId);
1335+
VMInstanceVO vmInstanceVO = createVMRecord(vmInternalName, poolId, templateId, guestOsId, serviceOfferingId);
1336+
1337+
importVMVolumes(vmInstanceVO, poolId, templateId, guestOsId, virtualDisks, zoneId);
13221338
importVMNetworks(networks, networksWithDetails, nicDevices);
13231339
//Continue importing
13241340
} catch (Exception e) {
@@ -1327,70 +1343,141 @@ public boolean importVmwareVM(String vmInternalName, Long zoneId) {
13271343
return true;
13281344
}
13291345

1330-
private void importVMAndServiceOffering(VirtualMachineConfigSummary configSummary) {
1331-
Integer numCpu = configSummary.getNumCpu();
1332-
String internalName = configSummary.getName();
1333-
Integer memorySizeMB = configSummary.getMemorySizeMB();
1346+
private void checkBackingInfo(VirtualDeviceBackingInfo backingInfo) {
1347+
if (! (backingInfo instanceof VirtualDiskFlatVer2BackingInfo)) {
1348+
throw new CloudRuntimeException("Unsopported backing, expected " + VirtualDiskFlatVer2BackingInfo.class.getSimpleName());
1349+
}
13341350
}
13351351

1336-
private void importVMNetworks(String[] networks, List<NetworkDetails> networksWithDetails, VirtualDevice[] nicDevices) {
1352+
private boolean isRootDisk(VirtualDisk disk) {
1353+
VirtualDeviceBackingInfo backing = disk.getBacking();
1354+
checkBackingInfo(backing);
1355+
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
1356+
return info.getFileName().contains("ROOT");
1357+
}
1358+
1359+
private Long getPoolId(VirtualDisk disk) {
1360+
VirtualDeviceBackingInfo backing = disk.getBacking();
1361+
checkBackingInfo(backing);
1362+
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
1363+
String[] fileNameParts = info.getFileName().split(" ");
1364+
String datastoreUuid = StringUtils.substringBetween(fileNameParts[0], "[", "]");
1365+
String poolUuid = UuidUtils.normalize(datastoreUuid);
1366+
StoragePoolVO pool = primaryStorageDao.findByUuid(poolUuid);
1367+
if (pool == null) {
1368+
throw new CloudRuntimeException("Couldn't find storage pool " + poolUuid);
1369+
}
1370+
return pool.getId();
1371+
}
1372+
1373+
private Long getPoolId(List<VirtualDisk> disks) {
1374+
for (VirtualDisk disk : disks) {
1375+
if (isRootDisk(disk)) {
1376+
return getPoolId(disk);
1377+
}
1378+
}
1379+
return null;
1380+
}
1381+
1382+
private String getVolumeNameFromFileName(String fileName) {
1383+
String[] fileNameParts = fileName.split(" ");
1384+
String volumePath = fileNameParts[1];
1385+
return volumePath.split("/")[1].replaceFirst(".vmdk", "");
13371386
}
13381387

1339-
private void importVMVolumes(List<VirtualDisk> virtualDisks, Long zoneId) {
1388+
private String getVolumeName(VirtualDisk disk) {
1389+
VirtualDeviceBackingInfo backing = disk.getBacking();
1390+
checkBackingInfo(backing);
1391+
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
1392+
return getVolumeNameFromFileName(info.getFileName());
1393+
}
1394+
1395+
private String getTemplatePath(VirtualDisk rootDisk) {
1396+
VirtualDeviceBackingInfo backing = rootDisk.getBacking();
1397+
checkBackingInfo(backing);
1398+
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
1399+
VirtualDiskFlatVer2BackingInfo parent = info.getParent();
1400+
return getVolumeNameFromFileName(parent.getFileName());
1401+
}
1402+
1403+
private Long importVMTemplate(List<VirtualDisk> virtualDisks, Long poolId) {
13401404
for (VirtualDisk disk : virtualDisks) {
1341-
Long size = disk.getCapacityInBytes();
1342-
VirtualDeviceBackingInfo backing = disk.getBacking();
1343-
if (backing instanceof VirtualDiskFlatVer2BackingInfo) {
1344-
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
1345-
String fileName = info.getFileName();
1346-
String[] fileNameParts = fileName.split(" ");
1347-
String volumeName = fileNameParts[1];
1348-
Storage.ProvisioningType provisioningType = null;
1349-
Boolean thinProvisioned = info.isThinProvisioned();
1350-
if (BooleanUtils.isTrue(thinProvisioned)) {
1351-
provisioningType = Storage.ProvisioningType.THIN;
1352-
}
1353-
VirtualDiskFlatVer2BackingInfo parent = info.getParent();
1354-
Pair<Long, Long> pair = getPoolAndTemplateIds(parent);
1355-
VolumeVO volumeVO = null;
1356-
if (volumeName.contains("ROOT")) {
1357-
String name = volumeName.split("/")[1].replaceFirst(".vmdk", "");
1358-
volumeVO = new VolumeVO(Volume.Type.ROOT, name, zoneId, 1L, 2L, 1L,
1359-
provisioningType, size, null, null, null);
1360-
volumeVO.setFormat(Storage.ImageFormat.OVA);
1361-
volumeVO.setPath(name);
1362-
//volumeVO.setInstanceId(null);
1363-
//volumeVO.setChainInfo(CHAIN_INFO);
1405+
if (isRootDisk(disk)) {
1406+
String templatePath = getTemplatePath(disk);
1407+
VMTemplateStoragePoolVO templateRef = templateDataStoreDao.findByPoolPath(poolId, templatePath);
1408+
if (templateRef == null) {
1409+
//TODO: Create template and add ref
1410+
return 0L;
1411+
} else {
1412+
return templateRef.getTemplateId();
13641413
}
1365-
volumeVO.setPoolId(pair.first());
1366-
volumeVO.setTemplateId(pair.second());
1367-
volumeVO.setState(Volume.State.Ready);
1368-
VolumeVO persist = volumeDao.persist(volumeVO);
13691414
}
13701415
}
1416+
return null;
13711417
}
13721418

1373-
private Pair<Long, Long> getPoolAndTemplateIds(VirtualDiskFlatVer2BackingInfo parent) {
1374-
String fileName = parent.getFileName();
1375-
String[] fileNameParts = fileName.split(" ");
1376-
if (fileNameParts.length != 2) {
1377-
throw new CloudRuntimeException("Error parsing template");
1378-
}
1379-
String storagePoolUuid = StringUtils.substringBetween(fileNameParts[0], "[", "]");
1380-
String poolUuid = UuidUtils.fromNoHyphenUuid(storagePoolUuid);
1381-
StoragePoolVO storagePoolVO = primaryStorageDao.findByUuid(poolUuid);
1382-
if (storagePoolVO == null) {
1383-
throw new CloudRuntimeException("Could not find primary storage: " + storagePoolUuid);
1384-
}
1385-
String path = fileNameParts[1];
1386-
String[] pathParts = path.split("/");
1387-
String parentUuid = pathParts[0];
1388-
VMTemplateStoragePoolVO ref = templateDataStoreDao.findByPoolPath(storagePoolVO.getId(), parentUuid);
1389-
if (ref == null) {
1390-
//TODO: CREATE TEMPLATE
1391-
return new Pair<>(storagePoolVO.getId(), 0L);
1419+
private VMInstanceVO createVMRecord(String vmInternalName, Long poolId, Long templateId, Long guestOsId, Long serviceOfferingId) {
1420+
long id = userVmDao.getNextInSequence(Long.class, "id");
1421+
UserVmVO vmInstanceVO = new UserVmVO(id, vmInternalName, vmInternalName, templateId, HypervisorType.VMware,
1422+
guestOsId, false, false, 1L, 1L, 1L, serviceOfferingId,
1423+
null, vmInternalName, null);
1424+
return userVmDao.persist(vmInstanceVO);
1425+
}
1426+
1427+
private Long importVMGuestOs(VirtualMachineConfigSummary configSummary) {
1428+
String guestFullName = configSummary.getGuestFullName();
1429+
GuestOSVO os = guestOSDao.listByDisplayName(guestFullName);
1430+
if (os == null) {
1431+
//TODO: Set it to default?
1432+
return 0L;
1433+
} else {
1434+
return os.getId();
1435+
}
1436+
}
1437+
1438+
private Long importVMServiceOffering(VirtualMachineConfigSummary configSummary) {
1439+
Integer numCpu = configSummary.getNumCpu();
1440+
Integer memorySizeMB = configSummary.getMemorySizeMB();
1441+
configSummary.getCpuReservation();
1442+
List<ServiceOfferingVO> offerings = serviceOfferingDao.listPublicByCpuAndMemory(numCpu, memorySizeMB);
1443+
if (CollectionUtils.isEmpty(offerings)) {
1444+
//TODO: Create service offering
1445+
return 0L;
13921446
} else {
1393-
return new Pair<>(storagePoolVO.getId(), ref.getTemplateId());
1447+
return offerings.get(0).getId();
1448+
}
1449+
}
1450+
1451+
private void importVMNetworks(String[] networks, List<NetworkDetails> networksWithDetails, VirtualDevice[] nicDevices) {
1452+
}
1453+
1454+
private Storage.ProvisioningType getProvisioningType(VirtualDiskFlatVer2BackingInfo backing) {
1455+
Boolean thinProvisioned = backing.isThinProvisioned();
1456+
if (BooleanUtils.isTrue(thinProvisioned)) {
1457+
return Storage.ProvisioningType.THIN;
1458+
}
1459+
return Storage.ProvisioningType.SPARSE;
1460+
}
1461+
1462+
private void importVMVolumes(VMInstanceVO vmInstanceVO, Long poolId, Long templateId, Long guestOsId, List<VirtualDisk> virtualDisks, Long zoneId) {
1463+
for (VirtualDisk disk : virtualDisks) {
1464+
Long size = disk.getCapacityInBytes();
1465+
VirtualDeviceBackingInfo backing = disk.getBacking();
1466+
checkBackingInfo(backing);
1467+
VirtualDiskFlatVer2BackingInfo info = (VirtualDiskFlatVer2BackingInfo) backing;
1468+
String volumeName = getVolumeName(disk);
1469+
Storage.ProvisioningType provisioningType = getProvisioningType(info);
1470+
Volume.Type type = isRootDisk(disk) ? Volume.Type.ROOT : Volume.Type.DATADISK;
1471+
1472+
VolumeVO volumeVO = new VolumeVO(type, volumeName, zoneId, 1L, 2L, 1L,
1473+
provisioningType, size, null, null, null);
1474+
volumeVO.setFormat(Storage.ImageFormat.OVA);
1475+
volumeVO.setPath(volumeName);
1476+
volumeVO.setState(Volume.State.Ready);
1477+
volumeVO.setInstanceId(vmInstanceVO.getId());
1478+
volumeVO.setPoolId(poolId);
1479+
volumeVO.setTemplateId(templateId);
1480+
volumeDao.persist(volumeVO);
13941481
}
13951482
}
13961483

plugins/hypervisors/vmware/src/test/java/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.cloud.server.ConfigurationServer;
5151
import com.cloud.service.dao.ServiceOfferingDao;
5252
import com.cloud.storage.ImageStoreDetailsUtil;
53+
import com.cloud.storage.dao.GuestOSDao;
5354
import com.cloud.storage.dao.VMTemplatePoolDao;
5455
import com.cloud.storage.dao.VolumeDao;
5556
import com.cloud.template.TemplateManager;
@@ -492,6 +493,16 @@ public ServiceOfferingDao serviceOfferingDao() {
492493
return Mockito.mock(ServiceOfferingDao.class);
493494
}
494495

496+
@Bean
497+
public GuestOSDao guestOSDao() {
498+
return Mockito.mock(GuestOSDao.class);
499+
}
500+
501+
@Bean
502+
public UserVmDao userVmDao() {
503+
return Mockito.mock(UserVmDao.class);
504+
}
505+
495506
public static class Library implements TypeFilter {
496507

497508
@Override

utils/src/main/java/com/cloud/utils/UuidUtils.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,16 @@ public static boolean validateUUID(String uuid) {
3737
* Returns a valid UUID in string format from a 32 digit UUID string without hyphens.
3838
* Example: 24abcb8f4211374fa2e1e5c0b7e88a2d -> 24abcb8f-4211-374f-a2e1-e5c0b7e88a2d
3939
*/
40-
public static String fromNoHyphenUuid(String noHyphen) {
40+
public static String normalize(String noHyphen) {
4141
if (noHyphen.length() != 32 || noHyphen.contains("-")) {
4242
throw new CloudRuntimeException("Invalid string format");
4343
}
4444
StringBuilder stringBuilder = new StringBuilder();
45-
stringBuilder.append(noHyphen.substring(0, 8));
46-
stringBuilder.append("-");
47-
stringBuilder.append(noHyphen.substring(8, 12));
48-
stringBuilder.append("-");
49-
stringBuilder.append(noHyphen.substring(12, 16));
50-
stringBuilder.append("-");
51-
stringBuilder.append(noHyphen.substring(16, 20));
52-
stringBuilder.append("-");
53-
stringBuilder.append(noHyphen.substring(20, 32));
45+
stringBuilder.append(noHyphen.substring(0, 8)).append("-")
46+
.append(noHyphen.substring(8, 12)).append("-")
47+
.append(noHyphen.substring(12, 16)).append("-")
48+
.append(noHyphen.substring(16, 20)).append("-")
49+
.append(noHyphen.substring(20, 32));
5450
String uuid = stringBuilder.toString();
5551
if (!validateUUID(uuid)) {
5652
throw new CloudRuntimeException("Error generating UUID");

0 commit comments

Comments
 (0)