mirror of https://github.com/apache/cloudstack.git
server: trim autoscale Windows VM hostname (#11327)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> Co-authored-by: Wei Zhou <weizhou@apache.org>
This commit is contained in:
parent
39d0d62fdd
commit
da1c7cebf9
|
|
@ -16,9 +16,10 @@
|
|||
// under the License.
|
||||
package com.cloud.network.as;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
|
||||
public interface AutoScaleManager extends AutoScaleService {
|
||||
|
||||
ConfigKey<Integer> AutoScaleStatsInterval = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Integer.class,
|
||||
|
|
@ -63,7 +64,5 @@ public interface AutoScaleManager extends AutoScaleService {
|
|||
|
||||
void removeVmFromVmGroup(Long vmId);
|
||||
|
||||
String getNextVmHostName(AutoScaleVmGroupVO asGroup);
|
||||
|
||||
void checkAutoScaleVmGroupName(String groupName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.network.NetworkModel;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupVO;
|
||||
import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
|
||||
|
|
@ -113,6 +112,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
|||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.Capability;
|
||||
import com.cloud.network.Network.IpAddresses;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.as.AutoScaleCounter.AutoScaleCounterParam;
|
||||
import com.cloud.network.as.dao.AutoScalePolicyConditionMapDao;
|
||||
import com.cloud.network.as.dao.AutoScalePolicyDao;
|
||||
|
|
@ -146,7 +146,9 @@ import com.cloud.projects.Project.ListProjectResourcesCriteria;
|
|||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.template.TemplateManager;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.user.Account;
|
||||
|
|
@ -280,6 +282,8 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage
|
|||
private NetworkOfferingDao networkOfferingDao;
|
||||
@Inject
|
||||
private VirtualMachineManager virtualMachineManager;
|
||||
@Inject
|
||||
GuestOSDao guestOSDao;
|
||||
|
||||
private static final String PARAM_ROOT_DISK_SIZE = "rootdisksize";
|
||||
private static final String PARAM_DISK_OFFERING_ID = "diskofferingid";
|
||||
|
|
@ -296,6 +300,10 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage
|
|||
protected static final String VM_HOSTNAME_PREFIX = "autoScaleVm-";
|
||||
protected static final int VM_HOSTNAME_RANDOM_SUFFIX_LENGTH = 6;
|
||||
|
||||
// Windows OS has a limit of 15 characters for hostname
|
||||
// https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/naming-conventions-for-computer-domain-site-ou
|
||||
protected static final String WINDOWS_VM_HOSTNAME_PREFIX = "as-WinVm-";
|
||||
|
||||
private static final Long DEFAULT_HOST_ID = -1L;
|
||||
|
||||
ExecutorService groupExecutor;
|
||||
|
|
@ -1821,13 +1829,15 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage
|
|||
List<Long> affinityGroupIdList = getVmAffinityGroupId(deployParams);
|
||||
updateVmDetails(deployParams, customParameters);
|
||||
|
||||
String vmHostName = getNextVmHostName(asGroup);
|
||||
Pair<String, String> vmHostAndDisplayName = getNextVmHostAndDisplayName(asGroup, template);
|
||||
String vmHostName = vmHostAndDisplayName.first();
|
||||
String vmDisplayName = vmHostAndDisplayName.second();
|
||||
asGroup.setNextVmSeq(asGroup.getNextVmSeq() + 1);
|
||||
autoScaleVmGroupDao.persist(asGroup);
|
||||
|
||||
if (zone.getNetworkType() == NetworkType.Basic) {
|
||||
vm = userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, null, owner, vmHostName,
|
||||
vmHostName, diskOfferingId, dataDiskSize, null, null,
|
||||
vmDisplayName, diskOfferingId, dataDiskSize, null, null,
|
||||
hypervisorType, HTTPMethod.GET, userData, userDataId, userDataDetails, sshKeyPairs,
|
||||
null, null, true, null, affinityGroupIdList, customParameters, null, null, null,
|
||||
null, true, overrideDiskOfferingId, null, null);
|
||||
|
|
@ -1835,12 +1845,12 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage
|
|||
if (networkModel.checkSecurityGroupSupportForNetwork(owner, zone, networkIds,
|
||||
Collections.emptyList())) {
|
||||
vm = userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, networkIds, null,
|
||||
owner, vmHostName,vmHostName, diskOfferingId, dataDiskSize, null, null,
|
||||
owner, vmHostName, vmDisplayName, diskOfferingId, dataDiskSize, null, null,
|
||||
hypervisorType, HTTPMethod.GET, userData, userDataId, userDataDetails, sshKeyPairs,
|
||||
null, null, true, null, affinityGroupIdList, customParameters, null, null, null,
|
||||
null, true, overrideDiskOfferingId, null, null, null);
|
||||
} else {
|
||||
vm = userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, networkIds, owner, vmHostName, vmHostName,
|
||||
vm = userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, networkIds, owner, vmHostName, vmDisplayName,
|
||||
diskOfferingId, dataDiskSize, null, null,
|
||||
hypervisorType, HTTPMethod.GET, userData, userDataId, userDataDetails, sshKeyPairs,
|
||||
null, addrs, true, null, affinityGroupIdList, customParameters, null, null, null,
|
||||
|
|
@ -1965,13 +1975,29 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNextVmHostName(AutoScaleVmGroupVO asGroup) {
|
||||
String vmHostNameSuffix = "-" + asGroup.getNextVmSeq() + "-" +
|
||||
RandomStringUtils.random(VM_HOSTNAME_RANDOM_SUFFIX_LENGTH, 0, 0, true, false, (char[])null, new SecureRandom()).toLowerCase();
|
||||
protected boolean isWindowsOs(VirtualMachineTemplate template) {
|
||||
GuestOSVO guestOSVO = guestOSDao.findById(template.getGuestOSId());
|
||||
if (guestOSVO == null) {
|
||||
return false;
|
||||
}
|
||||
String osName = StringUtils.firstNonBlank(guestOSVO.getName(), guestOSVO.getDisplayName());
|
||||
if (StringUtils.isBlank(osName)) {
|
||||
return false;
|
||||
}
|
||||
return osName.toLowerCase().contains("windows");
|
||||
}
|
||||
|
||||
protected Pair<String, String> getNextVmHostAndDisplayName(AutoScaleVmGroupVO asGroup, VirtualMachineTemplate template) {
|
||||
boolean isWindows = isWindowsOs(template);
|
||||
String winVmHostNameSuffix = RandomStringUtils.random(VM_HOSTNAME_RANDOM_SUFFIX_LENGTH, 0, 0, true, false, (char[])null, new SecureRandom()).toLowerCase();
|
||||
String vmHostNameSuffix = "-" + asGroup.getNextVmSeq() + "-" + winVmHostNameSuffix;
|
||||
// Truncate vm group name because max length of vm name is 63
|
||||
int subStringLength = Math.min(asGroup.getName().length(), 63 - VM_HOSTNAME_PREFIX.length() - vmHostNameSuffix.length());
|
||||
return VM_HOSTNAME_PREFIX + asGroup.getName().substring(0, subStringLength) + vmHostNameSuffix;
|
||||
String name = VM_HOSTNAME_PREFIX + asGroup.getName().substring(0, subStringLength) + vmHostNameSuffix;
|
||||
if (!isWindows) {
|
||||
return new Pair<>(name, name);
|
||||
}
|
||||
return new Pair<>(WINDOWS_VM_HOSTNAME_PREFIX + winVmHostNameSuffix, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -135,8 +135,10 @@ import com.cloud.server.ResourceTag;
|
|||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
|
|
@ -259,9 +261,10 @@ public class AutoScaleManagerImplTest {
|
|||
LoadBalancingRulesService loadBalancingRulesService;
|
||||
@Mock
|
||||
VMInstanceDao vmInstanceDao;
|
||||
|
||||
@Mock
|
||||
VirtualMachineManager virtualMachineManager;
|
||||
@Mock
|
||||
GuestOSDao guestOSDao;
|
||||
|
||||
AccountVO account;
|
||||
UserVO user;
|
||||
|
|
@ -420,6 +423,11 @@ public class AutoScaleManagerImplTest {
|
|||
userDataDetails.put("0", new HashMap<>() {{ put("key1", "value1"); put("key2", "value2"); }});
|
||||
Mockito.doReturn(userDataFinal).when(userVmMgr).finalizeUserData(any(), any(), any());
|
||||
Mockito.doReturn(userDataFinal).when(userDataMgr).validateUserData(eq(userDataFinal), nullable(BaseCmd.HTTPMethod.class));
|
||||
|
||||
when(templateMock.getGuestOSId()).thenReturn(100L);
|
||||
GuestOSVO guestOSMock = Mockito.mock(GuestOSVO.class);
|
||||
when(guestOSDao.findById(anyLong())).thenReturn(guestOSMock);
|
||||
when(guestOSMock.getName()).thenReturn("linux");
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
@ -2495,4 +2503,68 @@ public class AutoScaleManagerImplTest {
|
|||
|
||||
Mockito.verify(userVmMgr).expunge(eq(userVmMock));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextVmHostAndDisplayNameGeneratesCorrectHostAndDisplayNameForLinuxTemplate() {
|
||||
when(asVmGroupMock.getName()).thenReturn(vmGroupName);
|
||||
when(asVmGroupMock.getNextVmSeq()).thenReturn(1L);
|
||||
Pair<String, String> result = autoScaleManagerImplSpy.getNextVmHostAndDisplayName(asVmGroupMock, templateMock);
|
||||
String vmHostNamePattern = AutoScaleManagerImpl.VM_HOSTNAME_PREFIX + vmGroupName +
|
||||
"-" + asVmGroupMock.getNextVmSeq() + "-[a-z]{6}";
|
||||
Assert.assertTrue(result.first().matches(vmHostNamePattern));
|
||||
Assert.assertEquals(result.first(), result.second());
|
||||
}
|
||||
|
||||
private void runGetNextVmHostAndDisplayNameGeneratesCorrectHostAndDisplayNameForWindowsTemplate() {
|
||||
when(asVmGroupMock.getName()).thenReturn(vmGroupName);
|
||||
when(asVmGroupMock.getNextVmSeq()).thenReturn(1L);
|
||||
when(templateMock.getGuestOSId()).thenReturn(1L);
|
||||
Pair<String, String> result = autoScaleManagerImplSpy.getNextVmHostAndDisplayName(asVmGroupMock, templateMock);
|
||||
String vmHostNamePattern = AutoScaleManagerImpl.WINDOWS_VM_HOSTNAME_PREFIX + "[a-z]{6}";
|
||||
Assert.assertTrue(result.first().matches(vmHostNamePattern));
|
||||
Assert.assertEquals(15, result.first().length());
|
||||
String vmDisplayHostNamePattern = AutoScaleManagerImpl.VM_HOSTNAME_PREFIX + vmGroupName +
|
||||
"-" + asVmGroupMock.getNextVmSeq() + "-[a-z]{6}";
|
||||
Assert.assertTrue(result.second().matches(vmDisplayHostNamePattern));
|
||||
Assert.assertTrue(result.second().length() <= 63);
|
||||
Assert.assertTrue(result.second().endsWith(result.first().split("-")[2]));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextVmHostAndDisplayNameGeneratesCorrectHostAndDisplayNameForWindowsTemplateUsingGuestOsName() {
|
||||
GuestOSVO guestOS = Mockito.mock(GuestOSVO.class);
|
||||
when(guestOS.getName()).thenReturn("Windows Server");
|
||||
when(guestOSDao.findById(1L)).thenReturn(guestOS);
|
||||
runGetNextVmHostAndDisplayNameGeneratesCorrectHostAndDisplayNameForWindowsTemplate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextVmHostAndDisplayNameGeneratesCorrectHostAndDisplayNameForWindowsTemplateUsingGuestOsDisplayName() {
|
||||
GuestOSVO guestOS = Mockito.mock(GuestOSVO.class);
|
||||
when(guestOS.getDisplayName()).thenReturn("Windows Server");
|
||||
when(guestOSDao.findById(1L)).thenReturn(guestOS);
|
||||
runGetNextVmHostAndDisplayNameGeneratesCorrectHostAndDisplayNameForWindowsTemplate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextVmHostAndDisplayNameTruncatesGroupNameWhenExceedingMaxLength() {
|
||||
when(asVmGroupMock.getName()).thenReturn(vmGroupNameWithMaxLength);
|
||||
when(asVmGroupMock.getNextVmSeq()).thenReturn(1L);
|
||||
Pair<String, String> result = autoScaleManagerImplSpy.getNextVmHostAndDisplayName(asVmGroupMock, templateMock);
|
||||
Assert.assertTrue(result.first().length() <= 63);
|
||||
Assert.assertTrue(result.second().length() <= 63);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNextVmHostAndDisplayNameHandlesNullGuestOS() {
|
||||
when(asVmGroupMock.getName()).thenReturn(vmGroupName);
|
||||
when(asVmGroupMock.getNextVmSeq()).thenReturn(1L);
|
||||
when(templateMock.getGuestOSId()).thenReturn(1L);
|
||||
when(guestOSDao.findById(1L)).thenReturn(null);
|
||||
Pair<String, String> result = autoScaleManagerImplSpy.getNextVmHostAndDisplayName(asVmGroupMock, templateMock);
|
||||
String vmHostNamePattern = AutoScaleManagerImpl.VM_HOSTNAME_PREFIX + vmGroupName +
|
||||
"-" + asVmGroupMock.getNextVmSeq() + "-[a-z]{6}";
|
||||
Assert.assertTrue(result.first().matches(vmHostNamePattern));
|
||||
Assert.assertEquals(result.first(), result.second());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue