mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fix KVM import unmanaged instances on basic zone (#8465)
This PR fixes import unmanaged instances on KVM basic zones, on top of #8433 Fixes: #8439: point 1
This commit is contained in:
parent
c569fe9119
commit
b8d3e342be
@ -20,6 +20,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey.Scope;
|
||||
@ -338,7 +339,7 @@ public interface NetworkOrchestrationService {
|
||||
*/
|
||||
void cleanupNicDhcpDnsEntry(Network network, VirtualMachineProfile vmProfile, NicProfile nicProfile);
|
||||
|
||||
Pair<NicProfile, Integer> importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses, boolean forced) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
|
||||
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, boolean forced) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException;
|
||||
|
||||
void unmanageNics(VirtualMachineProfile vm);
|
||||
}
|
||||
|
||||
@ -4564,18 +4564,18 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
||||
|
||||
@DB
|
||||
@Override
|
||||
public Pair<NicProfile, Integer> importNic(final String macAddress, int deviceId, final Network network, final Boolean isDefaultNic, final VirtualMachine vm, final Network.IpAddresses ipAddresses, final boolean forced)
|
||||
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;
|
||||
if (ipAddresses != null && StringUtils.isNotEmpty(ipAddresses.getIp4Address())) {
|
||||
if (ipAddresses.getIp4Address().equals("auto")) {
|
||||
ipAddresses.setIp4Address(null);
|
||||
}
|
||||
if (network.getGuestType() != GuestType.L2) {
|
||||
guestIp = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address());
|
||||
} else {
|
||||
guestIp = 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()) {
|
||||
throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class,
|
||||
@ -4583,6 +4583,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
||||
}
|
||||
}
|
||||
final String finalGuestIp = guestIp;
|
||||
final IPAddressVO freeIp = freeIpAddress;
|
||||
final NicVO vo = Transaction.execute(new TransactionCallback<NicVO>() {
|
||||
@Override
|
||||
public NicVO doInTransaction(TransactionStatus status) {
|
||||
@ -4594,12 +4595,13 @@ 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);
|
||||
if (NetUtils.isValidIp4(finalGuestIp) && StringUtils.isNotEmpty(network.getGateway())) {
|
||||
Pair<String, String> pair = getNetworkGatewayAndNetmaskForNicImport(network, dataCenter, freeIp);
|
||||
String gateway = pair.first();
|
||||
String netmask = pair.second();
|
||||
if (NetUtils.isValidIp4(finalGuestIp) && StringUtils.isNotEmpty(gateway)) {
|
||||
vo.setIPv4Address(finalGuestIp);
|
||||
vo.setIPv4Gateway(network.getGateway());
|
||||
if (StringUtils.isNotEmpty(network.getCidr())) {
|
||||
vo.setIPv4Netmask(NetUtils.cidr2Netmask(network.getCidr()));
|
||||
}
|
||||
vo.setIPv4Gateway(gateway);
|
||||
vo.setIPv4Netmask(netmask);
|
||||
}
|
||||
vo.setBroadcastUri(network.getBroadcastUri());
|
||||
vo.setMode(network.getMode());
|
||||
@ -4636,6 +4638,30 @@ 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) {
|
||||
if (network.getGuestType() == GuestType.L2) {
|
||||
return null;
|
||||
}
|
||||
if (dataCenter.getNetworkType() == NetworkType.Advanced) {
|
||||
String guestIpAddress = _ipAddrMgr.acquireGuestIpAddress(network, ipAddresses.getIp4Address());
|
||||
return _ipAddressDao.findByIp(guestIpAddress);
|
||||
}
|
||||
return _ipAddressDao.findBySourceNetworkIdAndDatacenterIdAndState(network.getId(), dataCenter.getId(), IpAddress.State.Free);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return new Pair<>(gateway, netmask);
|
||||
}
|
||||
|
||||
private String generateNewMacAddressIfForced(Network network, String macAddress, boolean forced) {
|
||||
if (!forced) {
|
||||
throw new CloudRuntimeException("NIC with MAC address = " + macAddress + " exists on network with ID = " + network.getId() +
|
||||
|
||||
@ -29,6 +29,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.network.IpAddressManager;
|
||||
import com.cloud.utils.Pair;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -125,6 +128,7 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
testOrchastrator.routerNetworkDao = mock(RouterNetworkDao.class);
|
||||
testOrchastrator._vpcMgr = mock(VpcManager.class);
|
||||
testOrchastrator.routerJoinDao = mock(DomainRouterJoinDao.class);
|
||||
testOrchastrator._ipAddrMgr = mock(IpAddressManager.class);
|
||||
DhcpServiceProvider provider = mock(DhcpServiceProvider.class);
|
||||
|
||||
Map<Network.Capability, String> capabilities = new HashMap<Network.Capability, String>();
|
||||
@ -708,4 +712,88 @@ public class NetworkOrchestratorTest extends TestCase {
|
||||
Assert.assertEquals(ip6Dns[0], profile.getIPv6Dns1());
|
||||
Assert.assertEquals(ip6Dns[1], profile.getIPv6Dns2());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkGatewayAndNetmaskForNicImportAdvancedZone() {
|
||||
Network network = Mockito.mock(Network.class);
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
|
||||
String networkGateway = "10.1.1.1";
|
||||
String networkNetmask = "255.255.255.0";
|
||||
String networkCidr = "10.1.1.0/24";
|
||||
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);
|
||||
Assert.assertNotNull(pair);
|
||||
Assert.assertEquals(networkGateway, pair.first());
|
||||
Assert.assertEquals(networkNetmask, pair.second());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNetworkGatewayAndNetmaskForNicImportBasicZone() {
|
||||
Network network = Mockito.mock(Network.class);
|
||||
DataCenter dataCenter = Mockito.mock(DataCenter.class);
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
|
||||
String defaultNetworkGateway = "10.1.1.1";
|
||||
String defaultNetworkNetmask = "255.255.255.0";
|
||||
VlanVO vlan = Mockito.mock(VlanVO.class);
|
||||
Mockito.when(vlan.getVlanGateway()).thenReturn(defaultNetworkGateway);
|
||||
Mockito.when(vlan.getVlanNetmask()).thenReturn(defaultNetworkNetmask);
|
||||
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);
|
||||
Assert.assertNotNull(pair);
|
||||
Assert.assertEquals(defaultNetworkGateway, pair.first());
|
||||
Assert.assertEquals(defaultNetworkNetmask, pair.second());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGuestIpForNicImportL2Network() {
|
||||
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.L2);
|
||||
Assert.assertNull(testOrchastrator.getGuestIpForNicImport(network, dataCenter, ipAddresses));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGuestIpForNicImportAdvancedZone() {
|
||||
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(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());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetGuestIpForNicImportBasicZone() {
|
||||
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(dataCenter.getNetworkType()).thenReturn(DataCenter.NetworkType.Basic);
|
||||
long networkId = 1L;
|
||||
long dataCenterId = 1L;
|
||||
IPAddressVO ipAddressVO = Mockito.mock(IPAddressVO.class);
|
||||
Ip ip = mock(Ip.class);
|
||||
Mockito.when(ipAddressVO.getAddress()).thenReturn(ip);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,4 +103,6 @@ public interface IPAddressDao extends GenericDao<IPAddressVO, Long> {
|
||||
List<IPAddressVO> listByNetworkId(long networkId);
|
||||
|
||||
void buildQuarantineSearchCriteria(SearchCriteria<IPAddressVO> sc);
|
||||
|
||||
IPAddressVO findBySourceNetworkIdAndDatacenterIdAndState(long sourceNetworkId, long dataCenterId, State state);
|
||||
}
|
||||
|
||||
@ -554,4 +554,13 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
|
||||
|
||||
sc.setParametersIfNotNull("quarantinedPublicIpsIdsNIN", quarantinedIpsIdsAllowedToUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPAddressVO findBySourceNetworkIdAndDatacenterIdAndState(long sourceNetworkId, long dataCenterId, State state) {
|
||||
SearchCriteria<IPAddressVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("sourcenetwork", sourceNetworkId);
|
||||
sc.setParameters("dataCenterId", dataCenterId);
|
||||
sc.setParameters("state", State.Free);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 (hypervisorType == HypervisorType.VMware) {
|
||||
if (List.of(HypervisorType.VMware, HypervisorType.KVM).contains(hypervisorType)) {
|
||||
vm.setHostId(host.getId());
|
||||
}
|
||||
if (lastHost != null) {
|
||||
|
||||
@ -855,7 +855,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
||||
}
|
||||
|
||||
private NicProfile importNic(UnmanagedInstanceTO.Nic nic, VirtualMachine vm, Network network, Network.IpAddresses ipAddresses, int deviceId, boolean isDefaultNic, boolean forced) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException {
|
||||
Pair<NicProfile, Integer> result = networkOrchestrationService.importNic(nic.getMacAddress(), deviceId, network, isDefaultNic, vm, ipAddresses, forced);
|
||||
DataCenterVO dataCenterVO = dataCenterDao.findById(network.getDataCenterId());
|
||||
Pair<NicProfile, Integer> result = networkOrchestrationService.importNic(nic.getMacAddress(), deviceId, network, isDefaultNic, vm, ipAddresses, dataCenterVO, forced);
|
||||
if (result == null) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("NIC ID: %s import failed", nic.getNicId()));
|
||||
}
|
||||
@ -2371,7 +2372,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
|
||||
cleanupFailedImportVM(userVm);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to import volumes while importing vm: %s. %s", instanceName, StringUtils.defaultString(e.getMessage())));
|
||||
}
|
||||
networkOrchestrationService.importNic(macAddress,0,network, true, userVm, requestedIpPair, true);
|
||||
networkOrchestrationService.importNic(macAddress,0,network, true, userVm, requestedIpPair, zone, true);
|
||||
publishVMUsageUpdateResourceCount(userVm, serviceOffering);
|
||||
return userVm;
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.network.PublicIpQuarantine;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
|
||||
@ -1030,7 +1031,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<NicProfile, Integer> importNic(String macAddress, int deviceId, Network network, Boolean isDefaultNic, VirtualMachine vm, IpAddresses ipAddresses, boolean forced) {
|
||||
public Pair<NicProfile, Integer> importNic(String macAddress, int deviceId, Network network, Boolean isDefaultNic, VirtualMachine vm, IpAddresses ipAddresses, DataCenter dataCenter, boolean forced) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -367,7 +367,7 @@ public class UnmanagedVMsManagerImplTest {
|
||||
NicProfile profile = Mockito.mock(NicProfile.class);
|
||||
Integer deviceId = 100;
|
||||
Pair<NicProfile, Integer> pair = new Pair<NicProfile, Integer>(profile, deviceId);
|
||||
when(networkOrchestrationService.importNic(nullable(String.class), nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), Mockito.anyBoolean())).thenReturn(pair);
|
||||
when(networkOrchestrationService.importNic(nullable(String.class), nullable(Integer.class), nullable(Network.class), nullable(Boolean.class), nullable(VirtualMachine.class), nullable(Network.IpAddresses.class), nullable(DataCenter.class), Mockito.anyBoolean())).thenReturn(pair);
|
||||
when(volumeDao.findByInstance(Mockito.anyLong())).thenReturn(volumes);
|
||||
List<UserVmResponse> userVmResponses = new ArrayList<>();
|
||||
UserVmResponse userVmResponse = new UserVmResponse();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user