mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fixes for KVM unmanaged instances import on advanced network and VNC password (#8492)
This PR fixes a regression caused by #8465 on advanced zones, import fails with: 2024-01-10 12:13:33,234 DEBUG [o.a.c.e.o.NetworkOrchestrator] (API-Job-Executor-3:ctx-991bbe9f job-128 ctx-f49517d4) (logid:d7b8e716) Allocating nic for vm 142272e8-9e2e-407b-9d7e-e9a03b81653c in network Network {"id": 204, "name": "Isolated", "uuid": "9679fac5-e3ac-4694-a57b-beb635340f39", "networkofferingid": 10} during import 2024-01-10 12:13:33,239 ERROR [o.a.c.v.UnmanagedVMsManagerImpl] (API-Job-Executor-3:ctx-991bbe9f job-128 ctx-f49517d4) (logid:d7b8e716) Failed to import NICs while importing vm: i-2-31-VM com.cloud.exception.InsufficientVirtualNetworkCapacityException: Unable to acquire Guest IP address for network Network {"id": 204, "name": "Isolated", "uuid": "9679fac5-e3ac-4694-a57b-beb635340f39", "networkofferingid": 10}Scope=interface com.cloud.dc.DataCenter; id=1 at org.apache.cloudstack.engine.orchestration.NetworkOrchestrator.importNic(NetworkOrchestrator.java:4582) at org.apache.cloudstack.vm.UnmanagedVMsManagerImpl.importNic(UnmanagedVMsManagerImpl.java:859) at org.apache.cloudstack.vm.UnmanagedVMsManagerImpl.importVirtualMachineInternal(UnmanagedVMsManagerImpl.java:1198) at org.apache.cloudstack.vm.UnmanagedVMsManagerImpl.importUnmanagedInstanceFromHypervisor(UnmanagedVMsManagerImpl.java:1511) at org.apache.cloudstack.vm.UnmanagedVMsManagerImpl.baseImportInstance(UnmanagedVMsManagerImpl.java:1342) at org.apache.cloudstack.vm.UnmanagedVMsManagerImpl.importUnmanagedInstance(UnmanagedVMsManagerImpl.java:1282) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) Also, addresses the VNC password field set instead of a fixed string
This commit is contained in:
parent
59e78cbc45
commit
a3a4833c3e
@ -4567,23 +4567,18 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
||||
public Pair<NicProfile, Integer> importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses, final DataCenter dataCenter, final boolean forced)
|
||||
throws ConcurrentOperationException, InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
|
||||
s_logger.debug("Allocating nic for vm " + vm.getUuid() + " in network " + network + " during import");
|
||||
String guestIp = null;
|
||||
IPAddressVO freeIpAddress = null;
|
||||
String selectedIp = null;
|
||||
if (ipAddresses != null && StringUtils.isNotEmpty(ipAddresses.getIp4Address())) {
|
||||
if (ipAddresses.getIp4Address().equals("auto")) {
|
||||
ipAddresses.setIp4Address(null);
|
||||
}
|
||||
freeIpAddress = getGuestIpForNicImport(network, dataCenter, ipAddresses);
|
||||
if (freeIpAddress != null && freeIpAddress.getAddress() != null) {
|
||||
guestIp = freeIpAddress.getAddress().addr();
|
||||
}
|
||||
if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
|
||||
selectedIp = getSelectedIpForNicImport(network, dataCenter, ipAddresses);
|
||||
if (selectedIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
|
||||
throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class,
|
||||
network.getDataCenterId());
|
||||
}
|
||||
}
|
||||
final String finalGuestIp = guestIp;
|
||||
final IPAddressVO freeIp = freeIpAddress;
|
||||
final String finalSelectedIp = selectedIp;
|
||||
final NicVO vo = Transaction.execute(new TransactionCallback<NicVO>() {
|
||||
@Override
|
||||
public NicVO doInTransaction(TransactionStatus status) {
|
||||
@ -4595,11 +4590,11 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
||||
NicVO vo = new NicVO(network.getGuruName(), vm.getId(), network.getId(), vm.getType());
|
||||
vo.setMacAddress(macAddressToPersist);
|
||||
vo.setAddressFormat(Networks.AddressFormat.Ip4);
|
||||
Pair<String, String> pair = getNetworkGatewayAndNetmaskForNicImport(network, dataCenter, freeIp);
|
||||
Pair<String, String> pair = getNetworkGatewayAndNetmaskForNicImport(network, dataCenter, finalSelectedIp);
|
||||
String gateway = pair.first();
|
||||
String netmask = pair.second();
|
||||
if (NetUtils.isValidIp4(finalGuestIp) && StringUtils.isNotEmpty(gateway)) {
|
||||
vo.setIPv4Address(finalGuestIp);
|
||||
if (NetUtils.isValidIp4(finalSelectedIp) && StringUtils.isNotEmpty(gateway)) {
|
||||
vo.setIPv4Address(finalSelectedIp);
|
||||
vo.setIPv4Gateway(gateway);
|
||||
vo.setIPv4Netmask(netmask);
|
||||
}
|
||||
@ -4638,27 +4633,42 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
||||
return new Pair<NicProfile, Integer>(vmNic, Integer.valueOf(deviceId));
|
||||
}
|
||||
|
||||
protected IPAddressVO getGuestIpForNicImport(Network network, DataCenter dataCenter, Network.IpAddresses ipAddresses) {
|
||||
protected String getSelectedIpForNicImport(Network network, DataCenter dataCenter, Network.IpAddresses ipAddresses) {
|
||||
if (network.getGuestType() == GuestType.L2) {
|
||||
return null;
|
||||
}
|
||||
if (dataCenter.getNetworkType() == NetworkType.Advanced) {
|
||||
String guestIpAddress = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address());
|
||||
return _ipAddressDao.findByIp(guestIpAddress);
|
||||
return dataCenter.getNetworkType() == NetworkType.Basic ?
|
||||
getSelectedIpForNicImportOnBasicZone(ipAddresses.getIp4Address(), network, dataCenter):
|
||||
_ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address());
|
||||
}
|
||||
|
||||
protected String getSelectedIpForNicImportOnBasicZone(String requestedIp, Network network, DataCenter dataCenter) {
|
||||
IPAddressVO ipAddressVO = StringUtils.isBlank(requestedIp) ?
|
||||
_ipAddressDao.findBySourceNetworkIdAndDatacenterIdAndState(network.getId(), dataCenter.getId(), IpAddress.State.Free):
|
||||
_ipAddressDao.findByIp(requestedIp);
|
||||
if (ipAddressVO == null || ipAddressVO.getState() != IpAddress.State.Free) {
|
||||
String msg = String.format("Cannot find a free IP to assign to VM NIC on network %s", network.getName());
|
||||
s_logger.error(msg);
|
||||
throw new CloudRuntimeException(msg);
|
||||
}
|
||||
return _ipAddressDao.findBySourceNetworkIdAndDatacenterIdAndState(network.getId(), dataCenter.getId(), IpAddress.State.Free);
|
||||
return ipAddressVO.getAddress() != null ? ipAddressVO.getAddress().addr() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the gateway and netmask for a VM NIC to import
|
||||
* If the VM to import is on a Basic Zone, then obtain the information from the vlan table instead of the network
|
||||
*/
|
||||
protected Pair<String, String> getNetworkGatewayAndNetmaskForNicImport(Network network, DataCenter dataCenter, IPAddressVO freeIp) {
|
||||
VlanVO vlan = dataCenter.getNetworkType() == NetworkType.Basic && freeIp != null ?
|
||||
_vlanDao.findById(freeIp.getVlanId()) : null;
|
||||
String gateway = vlan != null ? vlan.getVlanGateway() : network.getGateway();
|
||||
String netmask = vlan != null ? vlan.getVlanNetmask() :
|
||||
(StringUtils.isNotEmpty(network.getCidr()) ? NetUtils.cidr2Netmask(network.getCidr()) : null);
|
||||
protected Pair<String, String> getNetworkGatewayAndNetmaskForNicImport(Network network, DataCenter dataCenter, String selectedIp) {
|
||||
String gateway = network.getGateway();
|
||||
String netmask = StringUtils.isNotEmpty(network.getCidr()) ? NetUtils.cidr2Netmask(network.getCidr()) : null;
|
||||
if (dataCenter.getNetworkType() == NetworkType.Basic) {
|
||||
IPAddressVO freeIp = _ipAddressDao.findByIp(selectedIp);
|
||||
if (freeIp != null) {
|
||||
VlanVO vlan = _vlanDao.findById(freeIp.getVlanId());
|
||||
gateway = vlan != null ? vlan.getVlanGateway() : null;
|
||||
netmask = vlan != null ? vlan.getVlanNetmask() : null;
|
||||
}
|
||||
}
|
||||
return new Pair<>(gateway, netmask);
|
||||
}
|
||||
|
||||
|
||||
@ -717,7 +717,7 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
public void testGetNetworkGatewayAndNetmaskForNicImportAdvancedZone() {
|
||||
Network network = Mockito.mock(Network.class);
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
String ipAddress = "10.1.1.10";
|
||||
|
||||
String networkGateway = "10.1.1.1";
|
||||
String networkNetmask = "255.255.255.0";
|
||||
@ -725,7 +725,7 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
Mockito.when(dataCenter.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
|
||||
Mockito.when(network.getGateway()).thenReturn(networkGateway);
|
||||
Mockito.when(network.getCidr()).thenReturn(networkCidr);
|
||||
Pair<String, String> pair = testOrchastrator.getNetworkGatewayAndNetmaskForNicImport(network, dataCenter, ipAddressVO);
|
||||
Pair<String, String> pair = testOrchastrator.getNetworkGatewayAndNetmaskForNicImport(network, dataCenter, ipAddress);
|
||||
Assert.assertNotNull(pair);
|
||||
Assert.assertEquals(networkGateway, pair.first());
|
||||
Assert.assertEquals(networkNetmask, pair.second());
|
||||
@ -736,8 +736,9 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
Network network = Mockito.mock(Network.class);
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
String ipAddress = "172.1.1.10";
|
||||
|
||||
String defaultNetworkGateway = "10.1.1.1";
|
||||
String defaultNetworkGateway = "172.1.1.1";
|
||||
String defaultNetworkNetmask = "255.255.255.0";
|
||||
VlanVO vlan = Mockito.mock(VlanVO.class);
|
||||
Mockito.when(vlan.getVlanGateway()).thenReturn(defaultNetworkGateway);
|
||||
@ -745,7 +746,8 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
Mockito.when(dataCenter.getNetworkType()).thenReturn(DataCenter.NetworkType.Basic);
|
||||
Mockito.when(ipAddressVO.getVlanId()).thenReturn(1L);
|
||||
Mockito.when(testOrchastrator._vlanDao.findById(1L)).thenReturn(vlan);
|
||||
Pair<String, String> pair = testOrchastrator.getNetworkGatewayAndNetmaskForNicImport(network, dataCenter, ipAddressVO);
|
||||
Mockito.when(testOrchastrator._ipAddressDao.findByIp(ipAddress)).thenReturn(ipAddressVO);
|
||||
Pair<String, String> pair = testOrchastrator.getNetworkGatewayAndNetmaskForNicImport(network, dataCenter, ipAddress);
|
||||
Assert.assertNotNull(pair);
|
||||
Assert.assertEquals(defaultNetworkGateway, pair.first());
|
||||
Assert.assertEquals(defaultNetworkNetmask, pair.second());
|
||||
@ -757,7 +759,7 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
Network.IpAddresses ipAddresses = Mockito.mock(Network.IpAddresses.class);
|
||||
Mockito.when(network.getGuestType()).thenReturn(GuestType.L2);
|
||||
Assert.assertNull(testOrchastrator.getGuestIpForNicImport(network, dataCenter, ipAddresses));
|
||||
Assert.assertNull(testOrchastrator.getSelectedIpForNicImport(network, dataCenter, ipAddresses));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -768,32 +770,76 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
Mockito.when(network.getGuestType()).thenReturn(GuestType.Isolated);
|
||||
Mockito.when(dataCenter.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
|
||||
String ipAddress = "10.1.10.10";
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
Mockito.when(ipAddresses.getIp4Address()).thenReturn(ipAddress);
|
||||
Mockito.when(testOrchastrator._ipAddrMgr.acquireGuestIpAddress(network, ipAddress)).thenReturn(ipAddress);
|
||||
Ip ip = mock(Ip.class);
|
||||
Mockito.when(ipAddressVO.getAddress()).thenReturn(ip);
|
||||
Mockito.when(testOrchastrator._ipAddressDao.findByIp(ipAddress)).thenReturn(ipAddressVO);
|
||||
IPAddressVO guestIp = testOrchastrator.getGuestIpForNicImport(network, dataCenter, ipAddresses);
|
||||
Assert.assertEquals(ip, guestIp.getAddress());
|
||||
String guestIp = testOrchastrator.getSelectedIpForNicImport(network, dataCenter, ipAddresses);
|
||||
Assert.assertEquals(ipAddress, guestIp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGuestIpForNicImportBasicZone() {
|
||||
public void testGetGuestIpForNicImportBasicZoneAutomaticIP() {
|
||||
Network network = Mockito.mock(Network.class);
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
Network.IpAddresses ipAddresses = Mockito.mock(Network.IpAddresses.class);
|
||||
Mockito.when(network.getGuestType()).thenReturn(GuestType.Isolated);
|
||||
Mockito.when(network.getGuestType()).thenReturn(GuestType.Shared);
|
||||
Mockito.when(dataCenter.getNetworkType()).thenReturn(DataCenter.NetworkType.Basic);
|
||||
long networkId = 1L;
|
||||
long dataCenterId = 1L;
|
||||
String freeIp = "172.10.10.10";
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
Ip ip = mock(Ip.class);
|
||||
Mockito.when(ip.addr()).thenReturn(freeIp);
|
||||
Mockito.when(ipAddressVO.getAddress()).thenReturn(ip);
|
||||
Mockito.when(ipAddressVO.getState()).thenReturn(State.Free);
|
||||
Mockito.when(network.getId()).thenReturn(networkId);
|
||||
Mockito.when(dataCenter.getId()).thenReturn(dataCenterId);
|
||||
Mockito.when(testOrchastrator._ipAddressDao.findBySourceNetworkIdAndDatacenterIdAndState(networkId, dataCenterId, State.Free)).thenReturn(ipAddressVO);
|
||||
IPAddressVO guestIp = testOrchastrator.getGuestIpForNicImport(network, dataCenter, ipAddresses);
|
||||
Assert.assertEquals(ip, guestIp.getAddress());
|
||||
String ipAddress = testOrchastrator.getSelectedIpForNicImport(network, dataCenter, ipAddresses);
|
||||
Assert.assertEquals(freeIp, ipAddress);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGuestIpForNicImportBasicZoneManualIP() {
|
||||
Network network = Mockito.mock(Network.class);
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
Network.IpAddresses ipAddresses = Mockito.mock(Network.IpAddresses.class);
|
||||
Mockito.when(network.getGuestType()).thenReturn(GuestType.Shared);
|
||||
Mockito.when(dataCenter.getNetworkType()).thenReturn(DataCenter.NetworkType.Basic);
|
||||
long networkId = 1L;
|
||||
long dataCenterId = 1L;
|
||||
String requestedIp = "172.10.10.10";
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
Ip ip = mock(Ip.class);
|
||||
Mockito.when(ip.addr()).thenReturn(requestedIp);
|
||||
Mockito.when(ipAddressVO.getAddress()).thenReturn(ip);
|
||||
Mockito.when(ipAddressVO.getState()).thenReturn(State.Free);
|
||||
Mockito.when(network.getId()).thenReturn(networkId);
|
||||
Mockito.when(dataCenter.getId()).thenReturn(dataCenterId);
|
||||
Mockito.when(ipAddresses.getIp4Address()).thenReturn(requestedIp);
|
||||
Mockito.when(testOrchastrator._ipAddressDao.findByIp(requestedIp)).thenReturn(ipAddressVO);
|
||||
String ipAddress = testOrchastrator.getSelectedIpForNicImport(network, dataCenter, ipAddresses);
|
||||
Assert.assertEquals(requestedIp, ipAddress);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void testGetGuestIpForNicImportBasicUsedIP() {
|
||||
Network network = Mockito.mock(Network.class);
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
Network.IpAddresses ipAddresses = Mockito.mock(Network.IpAddresses.class);
|
||||
Mockito.when(network.getGuestType()).thenReturn(GuestType.Shared);
|
||||
Mockito.when(dataCenter.getNetworkType()).thenReturn(DataCenter.NetworkType.Basic);
|
||||
long networkId = 1L;
|
||||
long dataCenterId = 1L;
|
||||
String requestedIp = "172.10.10.10";
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
Ip ip = mock(Ip.class);
|
||||
Mockito.when(ip.addr()).thenReturn(requestedIp);
|
||||
Mockito.when(ipAddressVO.getAddress()).thenReturn(ip);
|
||||
Mockito.when(ipAddressVO.getState()).thenReturn(State.Allocated);
|
||||
Mockito.when(network.getId()).thenReturn(networkId);
|
||||
Mockito.when(dataCenter.getId()).thenReturn(dataCenterId);
|
||||
Mockito.when(ipAddresses.getIp4Address()).thenReturn(requestedIp);
|
||||
Mockito.when(testOrchastrator._ipAddressDao.findByIp(requestedIp)).thenReturn(ipAddressVO);
|
||||
testOrchastrator.getSelectedIpForNicImport(network, dataCenter, ipAddresses);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libvirt.Connect;
|
||||
@ -43,6 +44,8 @@ import java.util.List;
|
||||
public final class LibvirtGetUnmanagedInstancesCommandWrapper extends CommandWrapper<GetUnmanagedInstancesCommand, GetUnmanagedInstancesAnswer, LibvirtComputingResource> {
|
||||
private static final Logger LOGGER = Logger.getLogger(LibvirtGetUnmanagedInstancesCommandWrapper.class);
|
||||
|
||||
private static final int requiredVncPasswordLength = 22;
|
||||
|
||||
@Override
|
||||
public GetUnmanagedInstancesAnswer execute(GetUnmanagedInstancesCommand command, LibvirtComputingResource libvirtComputingResource) {
|
||||
LOGGER.info("Fetching unmanaged instance on host");
|
||||
@ -130,7 +133,7 @@ public final class LibvirtGetUnmanagedInstancesCommandWrapper extends CommandWra
|
||||
instance.setMemory((int) LibvirtComputingResource.getDomainMemory(domain) / 1024);
|
||||
instance.setNics(getUnmanagedInstanceNics(parser.getInterfaces()));
|
||||
instance.setDisks(getUnmanagedInstanceDisks(parser.getDisks(),libvirtComputingResource, conn, domain.getName()));
|
||||
instance.setVncPassword(parser.getVncPasswd() + "aaaaaaaaaaaaaa"); // Suffix back extra characters for DB compatibility
|
||||
instance.setVncPassword(getFormattedVncPassword(parser.getVncPasswd()));
|
||||
|
||||
return instance;
|
||||
} catch (Exception e) {
|
||||
@ -139,6 +142,14 @@ public final class LibvirtGetUnmanagedInstancesCommandWrapper extends CommandWra
|
||||
}
|
||||
}
|
||||
|
||||
protected String getFormattedVncPassword(String vncPasswd) {
|
||||
if (StringUtils.isBlank(vncPasswd)) {
|
||||
return null;
|
||||
}
|
||||
String randomChars = RandomStringUtils.random(requiredVncPasswordLength - vncPasswd.length(), true, false);
|
||||
return String.format("%s%s", vncPasswd, randomChars);
|
||||
}
|
||||
|
||||
private UnmanagedInstanceTO.PowerState getPowerState(VirtualMachine.PowerState vmPowerState) {
|
||||
switch (vmPowerState) {
|
||||
case PowerOn:
|
||||
|
||||
@ -4581,7 +4581,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
Host host, Host lastHost, VirtualMachine.PowerState powerState) {
|
||||
if (isImport) {
|
||||
vm.setDataCenterId(zone.getId());
|
||||
if (List.of(HypervisorType.VMware, HypervisorType.KVM).contains(hypervisorType)) {
|
||||
if (List.of(HypervisorType.VMware, HypervisorType.KVM).contains(hypervisorType) && host != null) {
|
||||
vm.setHostId(host.getId());
|
||||
}
|
||||
if (lastHost != null) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user