@@ -847,9 +847,10 @@ private Pair<DiskProfile, StoragePool> importDisk(UnmanagedInstanceTO.Disk disk,
847847 return new Pair <DiskProfile , StoragePool >(profile , storagePool );
848848 }
849849
850- private NicProfile importNic (UnmanagedInstanceTO .Nic nic , VirtualMachine vm , Network network , Network .IpAddresses ipAddresses , int deviceId , boolean isDefaultNic , boolean forced ) throws InsufficientVirtualNetworkCapacityException , InsufficientAddressCapacityException {
850+ private NicProfile importNic (UnmanagedInstanceTO .Nic nic , VirtualMachine vm , Network network , Network .IpAddresses ipAddresses , int deviceId , boolean isDefaultNic ,
851+ boolean forced , boolean allowDuplicateMacAddress ) throws InsufficientVirtualNetworkCapacityException , InsufficientAddressCapacityException {
851852 DataCenterVO dataCenterVO = dataCenterDao .findById (network .getDataCenterId ());
852- Pair <NicProfile , Integer > result = networkOrchestrationService .importNic (nic .getMacAddress (), deviceId , network , isDefaultNic , vm , ipAddresses , dataCenterVO , forced );
853+ Pair <NicProfile , Integer > result = networkOrchestrationService .importNic (nic .getMacAddress (), deviceId , network , isDefaultNic , vm , ipAddresses , dataCenterVO , forced , allowDuplicateMacAddress );
853854 if (result == null ) {
854855 throw new ServerApiException (ApiErrorCode .INTERNAL_ERROR , String .format ("NIC ID: %s import failed" , nic .getNicId ()));
855856 }
@@ -1056,7 +1057,8 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedI
10561057 final VirtualMachineTemplate template , final String displayName , final String hostName , final Account caller , final Account owner , final Long userId ,
10571058 final ServiceOfferingVO serviceOffering , final Map <String , Long > dataDiskOfferingMap ,
10581059 final Map <String , Long > nicNetworkMap , final Map <String , Network .IpAddresses > callerNicIpAddressMap , final Long guestOsId ,
1059- final Map <String , String > details , final boolean migrateAllowed , final boolean forced , final boolean isImportUnmanagedFromSameHypervisor ) {
1060+ final Map <String , String > details , final boolean migrateAllowed , final boolean forced , final boolean allowDuplicateMacAddress ,
1061+ final boolean isImportUnmanagedFromSameHypervisor ) {
10601062 logger .debug (LogUtils .logGsonWithoutException ("Trying to import VM [%s] with name [%s], in zone [%s], cluster [%s], and host [%s], using template [%s], service offering [%s], disks map [%s], NICs map [%s] and details [%s]." ,
10611063 unmanagedInstance , displayName , zone , cluster , host , template , serviceOffering , dataDiskOfferingMap , nicNetworkMap , details ));
10621064 UserVm userVm = null ;
@@ -1186,7 +1188,7 @@ private UserVm importVirtualMachineInternal(final UnmanagedInstanceTO unmanagedI
11861188 for (UnmanagedInstanceTO .Nic nic : unmanagedInstance .getNics ()) {
11871189 Network network = networkDao .findById (allNicNetworkMap .get (nic .getNicId ()));
11881190 Network .IpAddresses ipAddresses = nicIpAddressMap .get (nic .getNicId ());
1189- importNic (nic , userVm , network , ipAddresses , nicIndex , nicIndex == 0 , forced );
1191+ importNic (nic , userVm , network , ipAddresses , nicIndex , nicIndex == 0 , forced , allowDuplicateMacAddress );
11901192 nicIndex ++;
11911193 }
11921194 } catch (Exception e ) {
@@ -1319,6 +1321,10 @@ private UserVmResponse baseImportInstance(ImportUnmanagedInstanceCmd cmd) {
13191321 final Map <String , Long > dataDiskOfferingMap = cmd .getDataDiskToDiskOfferingList ();
13201322 final Map <String , String > details = cmd .getDetails ();
13211323 final boolean forced = cmd .isForced ();
1324+ final boolean allowDuplicateMacAddress = cmd .isAllowDuplicateMacAddresses ();
1325+ if (forced && allowDuplicateMacAddress ) {
1326+ throw new InvalidParameterValueException (String .format ("%s and %s are mutually exclusive" , ApiConstants .FORCED , ApiConstants .ALLOW_DUPLICATE_MAC_ADDRESSES ));
1327+ }
13221328 List <HostVO > hosts = resourceManager .listHostsInClusterByStatus (clusterId , Status .Up );
13231329 UserVm userVm = null ;
13241330 List <String > additionalNameFilters = getAdditionalNameFilters (cluster );
@@ -1342,15 +1348,15 @@ private UserVmResponse baseImportInstance(ImportUnmanagedInstanceCmd cmd) {
13421348 template , instanceName , displayName , hostName , caller , owner , userId ,
13431349 serviceOffering , dataDiskOfferingMap ,
13441350 nicNetworkMap , nicIpAddressMap ,
1345- details , importVmCmd , forced );
1351+ details , importVmCmd , forced , allowDuplicateMacAddress );
13461352 }
13471353 } else {
13481354 if (List .of (Hypervisor .HypervisorType .VMware , Hypervisor .HypervisorType .KVM ).contains (cluster .getHypervisorType ())) {
13491355 userVm = importUnmanagedInstanceFromHypervisor (zone , cluster , hosts , additionalNameFilters ,
13501356 template , instanceName , displayName , hostName , caller , owner , userId ,
13511357 serviceOffering , dataDiskOfferingMap ,
13521358 nicNetworkMap , nicIpAddressMap ,
1353- details , cmd .getMigrateAllowed (), managedVms , forced );
1359+ details , cmd .getMigrateAllowed (), managedVms , forced , allowDuplicateMacAddress );
13541360 }
13551361 }
13561362
@@ -1497,7 +1503,8 @@ private UserVm importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cl
14971503 String hostName , Account caller , Account owner , long userId ,
14981504 ServiceOfferingVO serviceOffering , Map <String , Long > dataDiskOfferingMap ,
14991505 Map <String , Long > nicNetworkMap , Map <String , Network .IpAddresses > nicIpAddressMap ,
1500- Map <String , String > details , Boolean migrateAllowed , List <String > managedVms , boolean forced ) throws ResourceAllocationException {
1506+ Map <String , String > details , Boolean migrateAllowed , List <String > managedVms , boolean forced ,
1507+ boolean allowDuplicateMacAddress ) throws ResourceAllocationException {
15011508 UserVm userVm = null ;
15021509 for (HostVO host : hosts ) {
15031510 HashMap <String , UnmanagedInstanceTO > unmanagedInstances = getUnmanagedInstancesForHost (host , instanceName , managedVms );
@@ -1549,7 +1556,7 @@ private UserVm importUnmanagedInstanceFromHypervisor(DataCenter zone, Cluster cl
15491556 template , displayName , hostName , CallContext .current ().getCallingAccount (), owner , userId ,
15501557 serviceOffering , dataDiskOfferingMap ,
15511558 nicNetworkMap , nicIpAddressMap , null ,
1552- details , migrateAllowed , forced , true );
1559+ details , migrateAllowed , forced , allowDuplicateMacAddress , true );
15531560 } finally {
15541561 ReservationHelper .closeAll (reservations );
15551562 }
@@ -1648,7 +1655,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
16481655 Account caller , Account owner , long userId ,
16491656 ServiceOfferingVO serviceOffering , Map <String , Long > dataDiskOfferingMap ,
16501657 Map <String , Long > nicNetworkMap , Map <String , Network .IpAddresses > nicIpAddressMap ,
1651- Map <String , String > details , ImportVmCmd cmd , boolean forced ) throws ResourceAllocationException {
1658+ Map <String , String > details , ImportVmCmd cmd , boolean forced , boolean allowDuplicateMacAddress ) throws ResourceAllocationException {
16521659 Long existingVcenterId = cmd .getExistingVcenterId ();
16531660 String vcenter = cmd .getVcenter ();
16541661 String datacenterName = cmd .getDatacenterName ();
@@ -1741,7 +1748,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
17411748 checkConversionSupportOnHost (convertHost , sourceVMName , true , useVddk , details );
17421749 }
17431750
1744- checkNetworkingBeforeConvertingVmwareInstance (zone , owner , displayName , hostName , sourceVMwareInstance , nicNetworkMap , nicIpAddressMap , forced );
1751+ checkNetworkingBeforeConvertingVmwareInstance (zone , owner , displayName , hostName , sourceVMwareInstance , nicNetworkMap , nicIpAddressMap , forced , allowDuplicateMacAddress );
17451752 UnmanagedInstanceTO convertedInstance ;
17461753 if (!useVddk && (forceMsToImportVmFiles || !isOvfExportSupported )) {
17471754 // Uses MS for OVF export to temporary conversion location
@@ -1769,7 +1776,7 @@ protected UserVm importUnmanagedInstanceFromVmwareToKvm(DataCenter zone, Cluster
17691776 template , displayName , hostName , caller , owner , userId ,
17701777 serviceOffering , dataDiskOfferingMap ,
17711778 nicNetworkMap , nicIpAddressMap , guestOsId ,
1772- details , false , forced , false );
1779+ details , false , forced , allowDuplicateMacAddress , false );
17731780 long timeElapsedInSecs = (System .currentTimeMillis () - importStartTime ) / 1000 ;
17741781 logger .debug (String .format ("VMware VM %s imported successfully to CloudStack instance %s (%s), Time taken: %d secs, OVF files imported from %s, Source VMware VM details - OS: %s, PowerState: %s, Disks: %s, NICs: %s" ,
17751782 sourceVMName , displayName , displayName , timeElapsedInSecs , (ovfTemplateOnConvertLocation != null )? "MS" : "KVM Host" , sourceVMwareInstance .getOperatingSystem (), sourceVMwareInstance .getPowerState (), sourceVMwareInstance .getDisks (), sourceVMwareInstance .getNics ()));
@@ -1859,7 +1866,7 @@ private void checkNetworkingBeforeConvertingVmwareInstance(DataCenter zone, Acco
18591866 String hostName , UnmanagedInstanceTO sourceVMwareInstance ,
18601867 Map <String , Long > nicNetworkMap ,
18611868 Map <String , Network .IpAddresses > nicIpAddressMap ,
1862- boolean forced ) {
1869+ boolean forced , boolean allowDuplicateMacAddress ) {
18631870 List <UnmanagedInstanceTO .Nic > nics = sourceVMwareInstance .getNics ();
18641871 List <Long > networkIds = new ArrayList <>(nicNetworkMap .values ());
18651872 if (nics .size () != networkIds .size ()) {
@@ -1882,18 +1889,19 @@ private void checkNetworkingBeforeConvertingVmwareInstance(DataCenter zone, Acco
18821889 ipAddresses = nicIpAddressMap .get (nic .getNicId ());
18831890 }
18841891 boolean autoImport = ipAddresses != null && ipAddresses .getIp4Address () != null && ipAddresses .getIp4Address ().equalsIgnoreCase ("auto" );
1885- checkUnmanagedNicAndNetworkMacAddressForImport (network , nic , forced );
1892+ checkUnmanagedNicAndNetworkMacAddressForImport (network , nic , forced , allowDuplicateMacAddress );
18861893 checkUnmanagedNicAndNetworkForImport (displayName , nic , network , zone , owner , autoImport , Hypervisor .HypervisorType .KVM );
18871894 checkUnmanagedNicAndNetworkHostnameForImport (displayName , nic , network , hostName );
18881895 checkUnmanagedNicIpAndNetworkForImport (displayName , nic , network , ipAddresses );
18891896 }
18901897 }
18911898
1892- private void checkUnmanagedNicAndNetworkMacAddressForImport (NetworkVO network , UnmanagedInstanceTO .Nic nic , boolean forced ) {
1899+ private void checkUnmanagedNicAndNetworkMacAddressForImport (NetworkVO network , UnmanagedInstanceTO .Nic nic , boolean forced , boolean allowDuplicateMacAddress ) {
18931900 NicVO existingNic = nicDao .findByNetworkIdAndMacAddress (network .getId (), nic .getMacAddress ());
1894- if (existingNic != null && !forced ) {
1895- String err = String .format ("NIC %s with MAC address %s already exists on network %s and forced flag is disabled. " +
1896- "Retry with forced flag enabled if a new MAC address to be generated." , nic , nic .getMacAddress (), network );
1901+ if (existingNic != null && !forced && !allowDuplicateMacAddress ) {
1902+ String err = String .format ("NIC %s with MAC address %s already exists on network %s. " +
1903+ "Retry with %s=true to generate a new MAC address or %s=true to preserve the duplicate MAC address." ,
1904+ nic , nic .getMacAddress (), network , ApiConstants .FORCED , ApiConstants .ALLOW_DUPLICATE_MAC_ADDRESSES );
18971905 logger .error (err );
18981906 throw new CloudRuntimeException (err );
18991907 }
@@ -2809,7 +2817,7 @@ private UserVm importExternalKvmVirtualMachine(final UnmanagedInstanceTO unmanag
28092817 for (UnmanagedInstanceTO .Nic nic : unmanagedInstance .getNics ()) {
28102818 Network network = networkDao .findById (allNicNetworkMap .get (nic .getNicId ()));
28112819 Network .IpAddresses ipAddresses = nicIpAddressMap .get (nic .getNicId ());
2812- importNic (nic , userVm , network , ipAddresses , nicIndex , nicIndex ==0 , true );
2820+ importNic (nic , userVm , network , ipAddresses , nicIndex , nicIndex ==0 , true , false );
28132821 nicIndex ++;
28142822 }
28152823 } catch (Exception e ) {
@@ -2980,7 +2988,7 @@ private UserVm importKvmVirtualMachineFromDisk(final ImportSource importSource,
29802988 cleanupFailedImportVM (userVm );
29812989 throw new ServerApiException (ApiErrorCode .INTERNAL_ERROR , String .format ("Failed to import volumes while importing vm: %s. %s" , instanceName , StringUtils .defaultString (e .getMessage ())));
29822990 }
2983- networkOrchestrationService .importNic (macAddress , 0 , network , true , userVm , requestedIpPair , zone , true );
2991+ networkOrchestrationService .importNic (macAddress , 0 , network , true , userVm , requestedIpPair , zone , true , false );
29842992 publishVMUsageUpdateResourceCount (userVm , dummyOffering , template );
29852993 return userVm ;
29862994
0 commit comments