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