mirror of https://github.com/apache/cloudstack.git
Merge bbe7804230 into b7d4df0a11
This commit is contained in:
commit
67ac1184af
|
|
@ -3083,10 +3083,11 @@ public class ManagementServerImpl extends MutualExclusiveIdsManagerBase implemen
|
|||
|
||||
if (osDisplayName != null) {
|
||||
List<GuestOSVO> guestOSVOS = _guestOSDao.listLikeDisplayName(osDisplayName);
|
||||
if (CollectionUtils.isNotEmpty(guestOSVOS)) {
|
||||
List<Long> guestOSids = guestOSVOS.stream().map(mo -> mo.getId()).collect(Collectors.toList());
|
||||
sc.addAnd(guestOsId, SearchCriteria.Op.IN, guestOSids.toArray());
|
||||
if (CollectionUtils.isEmpty(guestOSVOS)) {
|
||||
return new Pair<>(Collections.emptyList(), 0);
|
||||
}
|
||||
List<Long> guestOSids = guestOSVOS.stream().map(mo -> mo.getId()).collect(Collectors.toList());
|
||||
sc.addAnd(guestOsId, SearchCriteria.Op.IN, guestOSids.toArray());
|
||||
}
|
||||
|
||||
final Pair<List<GuestOSHypervisorVO>, Integer> result = _guestOSHypervisorDao.searchAndCount(sc, searchFilter);
|
||||
|
|
|
|||
|
|
@ -1732,11 +1732,12 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
Pair<UnmanagedInstanceTO, Boolean> sourceInstanceDetails = getSourceVmwareUnmanagedInstance(vcenter, datacenterName, username, password, clusterName, sourceHostName, sourceVMName, serviceOffering);
|
||||
sourceVMwareInstance = sourceInstanceDetails.first();
|
||||
isClonedInstance = sourceInstanceDetails.second();
|
||||
guestOsId = resolveVmwareToKvmImportGuestOsId(guestOsId, sourceVMwareInstance);
|
||||
|
||||
// Ensure that the configured resource limits will not be exceeded before beginning the conversion process
|
||||
checkVmResourceLimitsForUnmanagedInstanceImport(owner, sourceVMwareInstance, serviceOffering, template, reservations);
|
||||
|
||||
boolean isWindowsVm = sourceVMwareInstance.getOperatingSystem().toLowerCase().contains("windows");
|
||||
boolean isWindowsVm = StringUtils.containsIgnoreCase(sourceVMwareInstance.getOperatingSystem(), "windows");
|
||||
if (isWindowsVm) {
|
||||
checkConversionSupportOnHost(convertHost, sourceVMName, true, useVddk, details);
|
||||
}
|
||||
|
|
@ -1792,6 +1793,104 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
|||
}
|
||||
}
|
||||
|
||||
protected Long resolveVmwareToKvmImportGuestOsId(Long requestedGuestOsId, UnmanagedInstanceTO sourceVMwareInstance) {
|
||||
if (requestedGuestOsId != null || sourceVMwareInstance == null) {
|
||||
return requestedGuestOsId;
|
||||
}
|
||||
|
||||
String osDisplayName = sourceVMwareInstance.getOperatingSystem();
|
||||
String osNameForHypervisor = sourceVMwareInstance.getOperatingSystemId();
|
||||
String sourceHypervisorVersion = sourceVMwareInstance.getHostHypervisorVersion();
|
||||
|
||||
GuestOSHypervisor guestOSHypervisor = findVmwareGuestOsMappingByDisplayName(osDisplayName, sourceHypervisorVersion);
|
||||
if (guestOSHypervisor == null) {
|
||||
guestOSHypervisor = findVmwareGuestOsMappingByOsName(osNameForHypervisor, sourceHypervisorVersion);
|
||||
}
|
||||
if (guestOSHypervisor == null) {
|
||||
guestOSHypervisor = findVmwareGuestOsMappingByDisplayName(osDisplayName, null);
|
||||
}
|
||||
if (guestOSHypervisor == null) {
|
||||
guestOSHypervisor = findVmwareGuestOsMappingByOsName(osNameForHypervisor, null);
|
||||
}
|
||||
if (guestOSHypervisor != null) {
|
||||
return guestOSHypervisor.getGuestOsId();
|
||||
}
|
||||
|
||||
GuestOS guestOS = findVmwareGuestOsByDisplayName(osDisplayName);
|
||||
return guestOS != null ? guestOS.getId() : null;
|
||||
}
|
||||
|
||||
private GuestOSHypervisor findVmwareGuestOsMappingByDisplayName(String osDisplayName, String hypervisorVersion) {
|
||||
List<GuestOS> guestOSes = listStrongMatchingGuestOses(osDisplayName);
|
||||
for (GuestOS guestOS : guestOSes) {
|
||||
GuestOSHypervisor guestOSHypervisor = guestOSHypervisorDao.findByOsIdAndHypervisor(
|
||||
guestOS.getId(), Hypervisor.HypervisorType.VMware.toString(), hypervisorVersion);
|
||||
if (guestOSHypervisor != null) {
|
||||
return guestOSHypervisor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private GuestOSHypervisor findVmwareGuestOsMappingByOsName(String osNameForHypervisor, String hypervisorVersion) {
|
||||
if (StringUtils.isBlank(osNameForHypervisor)) {
|
||||
return null;
|
||||
}
|
||||
return guestOSHypervisorDao.findByOsNameAndHypervisor(
|
||||
osNameForHypervisor, Hypervisor.HypervisorType.VMware.toString(), hypervisorVersion);
|
||||
}
|
||||
|
||||
private GuestOS findVmwareGuestOsByDisplayName(String osDisplayName) {
|
||||
List<GuestOS> guestOSes = listStrongMatchingGuestOses(osDisplayName);
|
||||
return CollectionUtils.isNotEmpty(guestOSes) ? guestOSes.get(0) : null;
|
||||
}
|
||||
|
||||
private List<GuestOS> listStrongMatchingGuestOses(String osDisplayName) {
|
||||
List<GuestOS> guestOSes = new ArrayList<>();
|
||||
if (StringUtils.isBlank(osDisplayName)) {
|
||||
return guestOSes;
|
||||
}
|
||||
|
||||
GuestOS exactMatch = guestOSDao.findOneByDisplayName(osDisplayName);
|
||||
if (exactMatch != null) {
|
||||
guestOSes.add(exactMatch);
|
||||
}
|
||||
|
||||
List<? extends GuestOS> candidates = guestOSDao.listLikeDisplayName(osDisplayName);
|
||||
if (CollectionUtils.isEmpty(candidates)) {
|
||||
return guestOSes;
|
||||
}
|
||||
|
||||
for (GuestOS candidate : candidates) {
|
||||
if (candidate == null || exactMatch != null && candidate.getId() == exactMatch.getId()) {
|
||||
continue;
|
||||
}
|
||||
if (isStrongGuestOsNameMatch(candidate.getDisplayName(), osDisplayName)) {
|
||||
guestOSes.add(candidate);
|
||||
}
|
||||
}
|
||||
return guestOSes;
|
||||
}
|
||||
|
||||
private boolean isStrongGuestOsNameMatch(String candidateName, String sourceName) {
|
||||
String candidate = normalizeGuestOsName(candidateName);
|
||||
String source = normalizeGuestOsName(sourceName);
|
||||
if (StringUtils.isAnyBlank(candidate, source)) {
|
||||
return false;
|
||||
}
|
||||
if (candidate.equals(source)) {
|
||||
return true;
|
||||
}
|
||||
if (Math.min(candidate.length(), source.length()) < 8) {
|
||||
return false;
|
||||
}
|
||||
return candidate.contains(source) || source.contains(candidate);
|
||||
}
|
||||
|
||||
private String normalizeGuestOsName(String name) {
|
||||
return StringUtils.defaultString(name).toLowerCase().replaceAll("[^a-z0-9]+", " ").trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the conversion storage pool exists and is suitable for the conversion or not.
|
||||
* Secondary storage is only allowed when forceConvertToPool is false.
|
||||
|
|
|
|||
|
|
@ -135,6 +135,8 @@ import com.cloud.service.ServiceOfferingVO;
|
|||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.GuestOSHypervisorVO;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.ScopeType;
|
||||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
|
|
@ -147,6 +149,8 @@ import com.cloud.storage.Volume;
|
|||
import com.cloud.storage.VolumeApiService;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.storage.dao.GuestOSHypervisorDao;
|
||||
import com.cloud.storage.dao.SnapshotDao;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
|
|
@ -249,6 +253,10 @@ public class UnmanagedVMsManagerImplTest {
|
|||
private ImportVmTasksManager importVmTasksManager;
|
||||
@Mock
|
||||
private SnapshotDao snapshotDao;
|
||||
@Mock
|
||||
private GuestOSDao guestOSDao;
|
||||
@Mock
|
||||
private GuestOSHypervisorDao guestOSHypervisorDao;
|
||||
|
||||
@Mock
|
||||
private VMInstanceVO virtualMachine;
|
||||
|
|
@ -730,6 +738,88 @@ public class UnmanagedVMsManagerImplTest {
|
|||
Assert.assertEquals(defaultTemplateName, templateForImportInstance.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveVmwareToKvmImportGuestOsIdKeepsRequestedGuestOsId() {
|
||||
Long resolvedGuestOsId = unmanagedVMsManager.resolveVmwareToKvmImportGuestOsId(1L, instance);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(1L), resolvedGuestOsId);
|
||||
Mockito.verifyNoInteractions(guestOSDao, guestOSHypervisorDao);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveVmwareToKvmImportGuestOsIdPrefersDisplayNameMapping() {
|
||||
String osDisplayName = "Debian GNU/Linux 11 (64-bit)";
|
||||
instance.setOperatingSystem(osDisplayName);
|
||||
instance.setOperatingSystemId("otherLinux64Guest");
|
||||
instance.setHostHypervisorVersion("8.0.3");
|
||||
|
||||
GuestOSVO guestOS = mock(GuestOSVO.class);
|
||||
when(guestOS.getId()).thenReturn(10L);
|
||||
when(guestOSDao.findOneByDisplayName(osDisplayName)).thenReturn(guestOS);
|
||||
when(guestOSDao.listLikeDisplayName(osDisplayName)).thenReturn(List.of(guestOS));
|
||||
|
||||
GuestOSHypervisorVO guestOSHypervisor = mock(GuestOSHypervisorVO.class);
|
||||
when(guestOSHypervisor.getGuestOsId()).thenReturn(20L);
|
||||
when(guestOSHypervisorDao.findByOsIdAndHypervisor(10L, Hypervisor.HypervisorType.VMware.toString(), "8.0.3")).thenReturn(guestOSHypervisor);
|
||||
|
||||
Long resolvedGuestOsId = unmanagedVMsManager.resolveVmwareToKvmImportGuestOsId(null, instance);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(20L), resolvedGuestOsId);
|
||||
Mockito.verify(guestOSHypervisorDao, Mockito.never()).findByOsNameAndHypervisor(anyString(), anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveVmwareToKvmImportGuestOsIdFallsBackToConfiguredGuestOsIdentifier() {
|
||||
String osDisplayName = "Unmatched Runtime OS";
|
||||
instance.setOperatingSystem(osDisplayName);
|
||||
instance.setOperatingSystemId("ubuntu64Guest");
|
||||
instance.setHostHypervisorVersion("8.0.3");
|
||||
when(guestOSDao.findOneByDisplayName(osDisplayName)).thenReturn(null);
|
||||
when(guestOSDao.listLikeDisplayName(osDisplayName)).thenReturn(Collections.emptyList());
|
||||
|
||||
GuestOSHypervisorVO guestOSHypervisor = mock(GuestOSHypervisorVO.class);
|
||||
when(guestOSHypervisor.getGuestOsId()).thenReturn(30L);
|
||||
when(guestOSHypervisorDao.findByOsNameAndHypervisor("ubuntu64Guest", Hypervisor.HypervisorType.VMware.toString(), "8.0.3")).thenReturn(guestOSHypervisor);
|
||||
|
||||
Long resolvedGuestOsId = unmanagedVMsManager.resolveVmwareToKvmImportGuestOsId(null, instance);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(30L), resolvedGuestOsId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveVmwareToKvmImportGuestOsIdFallsBackToGuestOsTypeMatch() {
|
||||
String osDisplayName = "Debian GNU/Linux 11 (64-bit)";
|
||||
instance.setOperatingSystem(osDisplayName);
|
||||
instance.setOperatingSystemId("otherLinux64Guest");
|
||||
instance.setHostHypervisorVersion("8.0.3");
|
||||
|
||||
GuestOSVO guestOS = mock(GuestOSVO.class);
|
||||
when(guestOS.getId()).thenReturn(40L);
|
||||
when(guestOSDao.findOneByDisplayName(osDisplayName)).thenReturn(guestOS);
|
||||
when(guestOSDao.listLikeDisplayName(osDisplayName)).thenReturn(List.of(guestOS));
|
||||
|
||||
Long resolvedGuestOsId = unmanagedVMsManager.resolveVmwareToKvmImportGuestOsId(null, instance);
|
||||
|
||||
Assert.assertEquals(Long.valueOf(40L), resolvedGuestOsId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveVmwareToKvmImportGuestOsIdAvoidsWeakGuestOsTypeMatch() {
|
||||
String osDisplayName = "Linux";
|
||||
instance.setOperatingSystem(osDisplayName);
|
||||
instance.setOperatingSystemId(null);
|
||||
instance.setHostHypervisorVersion("8.0.3");
|
||||
|
||||
GuestOSVO guestOS = mock(GuestOSVO.class);
|
||||
when(guestOS.getDisplayName()).thenReturn("Other Linux (64-bit)");
|
||||
when(guestOSDao.findOneByDisplayName(osDisplayName)).thenReturn(null);
|
||||
when(guestOSDao.listLikeDisplayName(osDisplayName)).thenReturn(List.of(guestOS));
|
||||
|
||||
Long resolvedGuestOsId = unmanagedVMsManager.resolveVmwareToKvmImportGuestOsId(null, instance);
|
||||
|
||||
Assert.assertNull(resolvedGuestOsId);
|
||||
}
|
||||
|
||||
private enum VcenterParameter {
|
||||
EXISTING,
|
||||
EXTERNAL,
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@
|
|||
:filterOption="(input, option) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}">
|
||||
<a-select-option v-for="mapping in resource.guestOsMappings" :key="mapping.ostypeid" :label="mapping.osdisplayname">
|
||||
<a-select-option v-for="mapping in resource.guestOsMappings" :key="mapping.ostypeid" :value="mapping.ostypeid" :label="mapping.osdisplayname">
|
||||
<span>
|
||||
{{ mapping.osdisplayname }}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1379,11 +1379,7 @@ export default {
|
|||
this.fetchInstances()
|
||||
}
|
||||
},
|
||||
async fetchGuestOsMappings (osIdentifier, hypervisorVersion) {
|
||||
const params = {}
|
||||
params.hypervisor = 'VMware'
|
||||
params.hypervisorversion = hypervisorVersion
|
||||
params.osnameforhypervisor = osIdentifier
|
||||
async fetchGuestOsMappingsByParams (params) {
|
||||
return await getAPI('listGuestOsMapping', params).then(json => {
|
||||
return json.listguestosmappingresponse?.guestosmapping || []
|
||||
}).catch(error => {
|
||||
|
|
@ -1391,6 +1387,113 @@ export default {
|
|||
return []
|
||||
})
|
||||
},
|
||||
normalizeGuestOsName (name) {
|
||||
return (name || '')
|
||||
.toLowerCase()
|
||||
.replace(/^microsoft\s+/, '')
|
||||
.replace(/[^a-z0-9]+/g, ' ')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
},
|
||||
isStrongGuestOsNameMatch (osType, osDisplayName) {
|
||||
const candidate = this.normalizeGuestOsName(osType.description || osType.osdisplayname)
|
||||
const source = this.normalizeGuestOsName(osDisplayName)
|
||||
if (!candidate || !source) {
|
||||
return false
|
||||
}
|
||||
if (candidate === source) {
|
||||
return true
|
||||
}
|
||||
if (Math.min(candidate.length, source.length) < 8) {
|
||||
return false
|
||||
}
|
||||
return candidate.includes(source) || source.includes(candidate)
|
||||
},
|
||||
async fetchGuestOsTypeFallbackMappings (osDisplayName) {
|
||||
if (!osDisplayName || !('listOsTypes' in this.$store.getters.apis)) {
|
||||
return []
|
||||
}
|
||||
return await getAPI('listOsTypes', {
|
||||
description: osDisplayName
|
||||
}).then(json => {
|
||||
const osTypes = json.listostypesresponse?.ostype || []
|
||||
return osTypes
|
||||
.filter(osType => this.isStrongGuestOsNameMatch(osType, osDisplayName))
|
||||
.map(osType => {
|
||||
return {
|
||||
ostypeid: osType.id,
|
||||
osdisplayname: osType.description || osType.osdisplayname
|
||||
}
|
||||
})
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
return []
|
||||
})
|
||||
},
|
||||
filterGuestOsMappings (mappings, params, osDisplayName) {
|
||||
if (!mappings || mappings.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const osNameForHypervisor = (params.osnameforhypervisor || '').toLowerCase()
|
||||
let filteredMappings = mappings
|
||||
if (osNameForHypervisor) {
|
||||
filteredMappings = mappings.filter(mapping => (mapping.osnameforhypervisor || '').toLowerCase() === osNameForHypervisor)
|
||||
}
|
||||
|
||||
if (osDisplayName) {
|
||||
const displayNameMatches = filteredMappings.filter(mapping => this.isStrongGuestOsNameMatch(mapping, osDisplayName))
|
||||
if (displayNameMatches.length > 0) {
|
||||
return displayNameMatches
|
||||
}
|
||||
if (params.osdisplayname) {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
return filteredMappings
|
||||
},
|
||||
async fetchGuestOsMappings (osIdentifier, osDisplayName, hypervisorVersion) {
|
||||
const lookups = []
|
||||
if (osIdentifier) {
|
||||
lookups.push({
|
||||
hypervisor: 'VMware',
|
||||
hypervisorversion: hypervisorVersion,
|
||||
osnameforhypervisor: osIdentifier
|
||||
})
|
||||
}
|
||||
if (osIdentifier) {
|
||||
lookups.push({
|
||||
hypervisor: 'VMware',
|
||||
osnameforhypervisor: osIdentifier
|
||||
})
|
||||
}
|
||||
if (osDisplayName) {
|
||||
lookups.push({
|
||||
hypervisor: 'VMware',
|
||||
hypervisorversion: hypervisorVersion,
|
||||
osdisplayname: osDisplayName
|
||||
})
|
||||
}
|
||||
if (osDisplayName) {
|
||||
lookups.push({
|
||||
hypervisor: 'VMware',
|
||||
osdisplayname: osDisplayName
|
||||
})
|
||||
}
|
||||
|
||||
for (const params of lookups) {
|
||||
if (!params.hypervisorversion) {
|
||||
delete params.hypervisorversion
|
||||
}
|
||||
const mappings = await this.fetchGuestOsMappingsByParams(params)
|
||||
const filteredMappings = this.filterGuestOsMappings(mappings, params, osDisplayName)
|
||||
if (filteredMappings.length > 0) {
|
||||
return filteredMappings
|
||||
}
|
||||
}
|
||||
return await this.fetchGuestOsTypeFallbackMappings(osDisplayName)
|
||||
},
|
||||
fetchVmwareInstanceForKVMMigration (vmname, hostname) {
|
||||
const params = {}
|
||||
this.loadingGuestOsMappings = true
|
||||
|
|
@ -1411,7 +1514,10 @@ export default {
|
|||
this.selectedUnmanagedInstance = response.unmanagedinstance[0]
|
||||
this.selectedUnmanagedInstance.ostypename = this.selectedUnmanagedInstance.osdisplayname
|
||||
this.selectedUnmanagedInstance.state = this.selectedUnmanagedInstance.powerstate
|
||||
this.selectedUnmanagedInstance.guestOsMappings = await this.fetchGuestOsMappings(this.selectedUnmanagedInstance.osid, this.selectedUnmanagedInstance.hypervisorversion)
|
||||
this.selectedUnmanagedInstance.guestOsMappings = await this.fetchGuestOsMappings(
|
||||
this.selectedUnmanagedInstance.osid,
|
||||
this.selectedUnmanagedInstance.osdisplayname,
|
||||
this.selectedUnmanagedInstance.hypervisorversion)
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue