@@ -1020,42 +1020,84 @@ public void saveExtraDhcpOptions(final String networkUuid, final Long nicId, fin
10201020 }
10211021 }
10221022
1023- @ DB
1024- @ Override
1025- public Pair <NicProfile , Integer > allocateNic (final NicProfile requested , final Network network , final Boolean isDefaultNic , int deviceId , final VirtualMachineProfile vm )
1026- throws InsufficientVirtualNetworkCapacityException , InsufficientAddressCapacityException , ConcurrentOperationException {
1023+ private NicVO persistNicAfterRaceCheck (final NicVO nic , final Long networkId , final NicProfile profile , int deviceId ) {
1024+ return Transaction .execute (new TransactionCallback <NicVO >() {
1025+ @ Override
1026+ public NicVO doInTransaction (TransactionStatus status ) {
1027+ NicVO vo = _nicDao .findByIp4AddressAndNetworkId (profile .getIPv4Address (), networkId );
1028+ if (vo == null ) {
1029+ applyProfileToNic (nic , profile , deviceId );
1030+ vo = _nicDao .persist (nic );
1031+ return vo ;
1032+ } else {
1033+ return null ;
1034+ }
1035+ }
1036+ });
1037+ }
10271038
1039+ private NicVO checkForRaceAndAllocateNic (final NicProfile requested , final Network network , final Boolean isDefaultNic , int deviceId , final VirtualMachineProfile vm )
1040+ throws InsufficientVirtualNetworkCapacityException , InsufficientAddressCapacityException {
10281041 final NetworkVO ntwkVO = _networksDao .findById (network .getId ());
10291042 s_logger .debug ("Allocating nic for vm " + vm .getVirtualMachine () + " in network " + network + " with requested profile " + requested );
10301043 final NetworkGuru guru = AdapterBase .getAdapterByName (networkGurus , ntwkVO .getGuruName ());
10311044
1032- if (requested != null && requested .getMode () == null ) {
1033- requested .setMode (network .getMode ());
1034- }
1035- final NicProfile profile = guru .allocate (network , requested , vm );
1036- if (profile == null ) {
1037- return null ;
1038- }
1045+ NicVO vo = null ;
1046+ boolean retryIpAllocation ;
1047+ do {
1048+ retryIpAllocation = false ;
1049+ final NicProfile profile = guru .allocate (network , requested , vm );
1050+ if (profile == null ) {
1051+ return null ;
1052+ }
10391053
1040- if (isDefaultNic != null ) {
1041- profile .setDefaultNic (isDefaultNic );
1042- }
1054+ if (isDefaultNic != null ) {
1055+ profile .setDefaultNic (isDefaultNic );
1056+ }
10431057
1044- if (requested != null && requested .getMode () == null ) {
1045- profile .setMode (requested .getMode ());
1046- } else {
1047- profile .setMode (network .getMode ());
1048- }
1058+ if (requested != null && requested .getMode () == null ) {
1059+ profile .setMode (requested .getMode ());
1060+ } else {
1061+ profile .setMode (network .getMode ());
1062+ }
1063+
1064+ vo = new NicVO (guru .getName (), vm .getId (), network .getId (), vm .getType ());
1065+
1066+ DataCenterVO dcVo = _dcDao .findById (network .getDataCenterId ());
1067+ if (dcVo .getNetworkType () == NetworkType .Basic ) {
1068+ configureNicProfileBasedOnRequestedIp (requested , profile , network );
1069+ }
1070+
1071+ if (profile .getIpv4AllocationRaceCheck ()) {
1072+ vo = persistNicAfterRaceCheck (vo , network .getId (), profile , deviceId );
1073+ } else {
1074+ applyProfileToNic (vo , profile , deviceId );
1075+ vo = _nicDao .persist (vo );
1076+ }
1077+
1078+ if (vo == null ) {
1079+ if (requested .getRequestedIPv4 () != null ) {
1080+ throw new InsufficientVirtualNetworkCapacityException ("Unable to acquire requested Guest IP address " + requested .getRequestedIPv4 () + " for network " + network , DataCenter .class , dcVo .getId ());
1081+ } else {
1082+ requested .setIPv4Address (null );
1083+ }
1084+ retryIpAllocation = true ;
1085+ }
1086+ } while (retryIpAllocation );
10491087
1050- NicVO vo = new NicVO (guru .getName (), vm .getId (), network .getId (), vm .getType ());
1088+ return vo ;
1089+ }
10511090
1052- DataCenterVO dcVo = _dcDao .findById (network .getDataCenterId ());
1053- if (dcVo .getNetworkType () == NetworkType .Basic ) {
1054- configureNicProfileBasedOnRequestedIp (requested , profile , network );
1091+ @ DB
1092+ @ Override
1093+ public Pair <NicProfile , Integer > allocateNic (final NicProfile requested , final Network network , final Boolean isDefaultNic , int deviceId , final VirtualMachineProfile vm )
1094+ throws InsufficientVirtualNetworkCapacityException , InsufficientAddressCapacityException , ConcurrentOperationException {
1095+
1096+ if (requested != null && requested .getMode () == null ) {
1097+ requested .setMode (network .getMode ());
10551098 }
10561099
1057- deviceId = applyProfileToNic (vo , profile , deviceId );
1058- vo = _nicDao .persist (vo );
1100+ NicVO vo = checkForRaceAndAllocateNic (requested , network , isDefaultNic , deviceId , vm );
10591101
10601102 final Integer networkRate = _networkModel .getNetworkRate (network .getId (), vm .getId ());
10611103 final NicProfile vmNic = new NicProfile (vo , network , vo .getBroadcastUri (), vo .getIsolationUri (), networkRate , _networkModel .isSecurityGroupSupportedInNetwork (network ),
0 commit comments