@@ -322,31 +322,30 @@ private IPAddressVO assignAndAllocateIpAddressEntry(final Account owner, final V
322322 }
323323 }
324324
325- for (final IPAddressVO possibleAddr : addressVOS ) {
325+ for (IPAddressVO possibleAddr : addressVOS ) {
326326 if (possibleAddr .getState () != State .Free ) {
327327 continue ;
328328 }
329- final IPAddressVO addressVO = possibleAddr ;
330- addressVO .setSourceNat (sourceNat );
331- addressVO .setAllocatedTime (new Date ());
332- addressVO .setAllocatedInDomainId (owner .getDomainId ());
333- addressVO .setAllocatedToAccountId (owner .getId ());
334- addressVO .setSystem (isSystem );
329+ possibleAddr .setSourceNat (sourceNat );
330+ possibleAddr .setAllocatedTime (new Date ());
331+ possibleAddr .setAllocatedInDomainId (owner .getDomainId ());
332+ possibleAddr .setAllocatedToAccountId (owner .getId ());
333+ possibleAddr .setSystem (isSystem );
335334
336335 if (displayIp != null ) {
337- addressVO .setDisplay (displayIp );
336+ possibleAddr .setDisplay (displayIp );
338337 }
339338
340339 if (vlanUse != VlanType .DirectAttached ) {
341- addressVO .setAssociatedWithNetworkId (guestNetworkId );
342- addressVO .setVpcId (vpcId );
340+ possibleAddr .setAssociatedWithNetworkId (guestNetworkId );
341+ possibleAddr .setVpcId (vpcId );
343342 }
344343 if (_ipAddressDao .lockRow (possibleAddr .getId (), true ) != null ) {
345- final IPAddressVO userIp = _ipAddressDao .findById (addressVO .getId ());
344+ final IPAddressVO userIp = _ipAddressDao .findById (possibleAddr .getId ());
346345 if (userIp .getState () == State .Free ) {
347- addressVO .setState (State .Allocating );
348- if (_ipAddressDao .update (addressVO .getId (), addressVO )) {
349- finalAddress = addressVO ;
346+ possibleAddr .setState (State .Allocating );
347+ if (_ipAddressDao .update (possibleAddr .getId (), possibleAddr )) {
348+ finalAddress = possibleAddr ;
350349 break ;
351350 }
352351 }
@@ -783,9 +782,22 @@ public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<L
783782 public PublicIp fetchNewPublicIp (final long dcId , final Long podId , final List <Long > vlanDbIds , final Account owner , final VlanType vlanUse , final Long guestNetworkId ,
784783 final boolean sourceNat , final boolean assign , final boolean allocate , final String requestedIp , final boolean isSystem , final Long vpcId , final Boolean displayIp , final boolean forSystemVms )
785784 throws InsufficientAddressCapacityException {
786- IPAddressVO addr = Transaction .execute (new TransactionCallbackWithException <IPAddressVO , InsufficientAddressCapacityException >() {
785+ List <IPAddressVO > addrs = listAvailablePublicIps (dcId , podId , vlanDbIds , owner , vlanUse , guestNetworkId , sourceNat , assign , allocate , requestedIp , isSystem , vpcId , displayIp , forSystemVms , true );
786+ IPAddressVO addr = addrs .get (0 );
787+ if (vlanUse == VlanType .VirtualNetwork ) {
788+ _firewallMgr .addSystemFirewallRules (addr , owner );
789+ }
790+
791+ return PublicIp .createFromAddrAndVlan (addr , _vlanDao .findById (addr .getVlanId ()));
792+ }
793+
794+ @ Override
795+ public List <IPAddressVO > listAvailablePublicIps (final long dcId , final Long podId , final List <Long > vlanDbIds , final Account owner , final VlanType vlanUse , final Long guestNetworkId ,
796+ final boolean sourceNat , final boolean assign , final boolean allocate , final String requestedIp , final boolean isSystem ,
797+ final Long vpcId , final Boolean displayIp , final boolean forSystemVms , final boolean lockOneRow ) throws InsufficientAddressCapacityException {
798+ return Transaction .execute (new TransactionCallbackWithException <List <IPAddressVO >, InsufficientAddressCapacityException >() {
787799 @ Override
788- public IPAddressVO doInTransaction (TransactionStatus status ) throws InsufficientAddressCapacityException {
800+ public List < IPAddressVO > doInTransaction (TransactionStatus status ) throws InsufficientAddressCapacityException {
789801 StringBuilder errorMessage = new StringBuilder ("Unable to get ip address in " );
790802 boolean fetchFromDedicatedRange = false ;
791803 List <Long > dedicatedVlanDbIds = new ArrayList <Long >();
@@ -823,23 +835,26 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
823835 if (vlanDbIds == null || vlanDbIds .contains (nonDedicatedVlan .getId ()))
824836 nonDedicatedVlanDbIds .add (nonDedicatedVlan .getId ());
825837 }
826- if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds .isEmpty ()) {
827- fetchFromDedicatedRange = true ;
828- sc .setParameters ("vlanId" , dedicatedVlanDbIds .toArray ());
829- errorMessage .append (", vlanId id=" + Arrays .toString (dedicatedVlanDbIds .toArray ()));
830- } else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds .isEmpty ()) {
831- sc .setParameters ("vlanId" , nonDedicatedVlanDbIds .toArray ());
832- errorMessage .append (", vlanId id=" + Arrays .toString (nonDedicatedVlanDbIds .toArray ()));
833- } else {
834- if (podId != null ) {
835- InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException ("Insufficient address capacity" , Pod .class , podId );
836- ex .addProxyObject (ApiDBUtils .findPodById (podId ).getUuid ());
838+
839+ if (vlanUse == VlanType .VirtualNetwork ) {
840+ if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds .isEmpty ()) {
841+ fetchFromDedicatedRange = true ;
842+ sc .setParameters ("vlanId" , dedicatedVlanDbIds .toArray ());
843+ errorMessage .append (", vlanId id=" + Arrays .toString (dedicatedVlanDbIds .toArray ()));
844+ } else if (nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds .isEmpty ()) {
845+ sc .setParameters ("vlanId" , nonDedicatedVlanDbIds .toArray ());
846+ errorMessage .append (", vlanId id=" + Arrays .toString (nonDedicatedVlanDbIds .toArray ()));
847+ } else {
848+ if (podId != null ) {
849+ InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException ("Insufficient address capacity" , Pod .class , podId );
850+ ex .addProxyObject (ApiDBUtils .findPodById (podId ).getUuid ());
851+ throw ex ;
852+ }
853+ s_logger .warn (errorMessage .toString ());
854+ InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException ("Insufficient address capacity" , DataCenter .class , dcId );
855+ ex .addProxyObject (ApiDBUtils .findZoneById (dcId ).getUuid ());
837856 throw ex ;
838857 }
839- s_logger .warn (errorMessage .toString ());
840- InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException ("Insufficient address capacity" , DataCenter .class , dcId );
841- ex .addProxyObject (ApiDBUtils .findZoneById (dcId ).getUuid ());
842- throw ex ;
843858 }
844859
845860 sc .setParameters ("dc" , dcId );
@@ -864,21 +879,31 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
864879
865880 filter .addOrderBy (IPAddressVO .class ,"vlanId" , true );
866881
867- List <IPAddressVO > addrs = _ipAddressDao .search (sc , filter , false );
882+ List <IPAddressVO > addrs ;
883+
884+ if (lockOneRow ) {
885+ addrs = _ipAddressDao .lockRows (sc , filter , true );
886+ } else {
887+ addrs = new ArrayList <>(_ipAddressDao .search (sc , null ));
888+ }
868889
869890 // If all the dedicated IPs of the owner are in use fetch an IP from the system pool
870- if (addrs .size () == 0 && fetchFromDedicatedRange ) {
891+ if ((! lockOneRow || ( lockOneRow && addrs .size () == 0 )) && fetchFromDedicatedRange && vlanUse == VlanType . VirtualNetwork ) {
871892 // Verify if account is allowed to acquire IPs from the system
872893 boolean useSystemIps = UseSystemPublicIps .valueIn (owner .getId ());
873894 if (useSystemIps && nonDedicatedVlanDbIds != null && !nonDedicatedVlanDbIds .isEmpty ()) {
874895 fetchFromDedicatedRange = false ;
875896 sc .setParameters ("vlanId" , nonDedicatedVlanDbIds .toArray ());
876897 errorMessage .append (", vlanId id=" + Arrays .toString (nonDedicatedVlanDbIds .toArray ()));
877- addrs = _ipAddressDao .search (sc , filter , false );
898+ if (lockOneRow ) {
899+ addrs = _ipAddressDao .lockRows (sc , filter , true );
900+ } else {
901+ addrs .addAll (_ipAddressDao .search (sc , null ));
902+ }
878903 }
879904 }
880905
881- if (addrs .size () == 0 ) {
906+ if (lockOneRow && addrs .size () == 0 ) {
882907 if (podId != null ) {
883908 InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException ("Insufficient address capacity" , Pod .class , podId );
884909 // for now, we hardcode the table names, but we should ideally do a lookup for the tablename from the VO object.
@@ -891,23 +916,16 @@ public IPAddressVO doInTransaction(TransactionStatus status) throws Insufficient
891916 throw ex ;
892917 }
893918
894- assert (addrs .size () == 1 ) : "Return size is incorrect: " + addrs .size ();
895- IPAddressVO finalAddr = null ;
919+ if (lockOneRow ) {
920+ assert (addrs .size () == 1 ) : "Return size is incorrect: " + addrs .size ();
921+ }
896922 if (assign ) {
897- finalAddr = assignAndAllocateIpAddressEntry (owner , vlanUse , guestNetworkId , sourceNat , allocate ,
923+ assignAndAllocateIpAddressEntry (owner , vlanUse , guestNetworkId , sourceNat , allocate ,
898924 isSystem ,vpcId , displayIp , fetchFromDedicatedRange , addrs );
899- } else {
900- finalAddr = addrs .get (0 );
901925 }
902- return finalAddr ;
926+ return addrs ;
903927 }
904928 });
905-
906- if (vlanUse == VlanType .VirtualNetwork ) {
907- _firewallMgr .addSystemFirewallRules (addr , owner );
908- }
909-
910- return PublicIp .createFromAddrAndVlan (addr , _vlanDao .findById (addr .getVlanId ()));
911929 }
912930
913931 @ DB
0 commit comments