@@ -194,57 +194,54 @@ public FirewallRule createIngressFirewallRule(FirewallRule rule) throws NetworkR
194194 return createFirewallRule (sourceIpAddressId , caller , rule .getXid (), rule .getSourcePortStart (), rule .getSourcePortEnd (), rule .getProtocol (),
195195 rule .getSourceCidrList (), null , rule .getIcmpCode (), rule .getIcmpType (), null , rule .getType (), rule .getNetworkId (), rule .getTrafficType (), rule .isDisplay ());
196196 }
197+
197198 //Destination CIDR capability is currently implemented for egress rules only. For others, the field is passed as null.
198199 @ DB
199- protected FirewallRule createFirewallRule (final Long ipAddrId , Account caller , final String xId , final Integer portStart , final Integer portEnd ,
200- final String protocol , final List <String > sourceCidrList , final List <String > destCidrList , final Integer icmpCode , final Integer icmpType , final Long relatedRuleId ,
201- final FirewallRule .FirewallRuleType type ,
202- final Long networkId , final FirewallRule .TrafficType trafficType , final Boolean forDisplay ) throws NetworkRuleConflictException {
203-
200+ protected FirewallRule createFirewallRule (final Long ipAddrId , Account caller , final String xId , final Integer portStart , final Integer portEnd , final String protocol ,
201+ final List <String > sourceCidrList , final List <String > destCidrList , final Integer icmpCode , final Integer icmpType , final Long relatedRuleId ,
202+ final FirewallRule .FirewallRuleType type , final Long networkId , final FirewallRule .TrafficType trafficType , final Boolean forDisplay ) throws NetworkRuleConflictException {
204203 IPAddressVO ipAddress = null ;
205- if (ipAddrId != null ) {
206- // this for ingress firewall rule, for egress id is null
207- ipAddress = _ipAddressDao .findById (ipAddrId );
208- // Validate ip address
209- if (ipAddress == null && type == FirewallRule .FirewallRuleType .User ) {
210- throw new InvalidParameterValueException ("Unable to create firewall rule; " + "couldn't locate IP address by id in the system" );
211- }
212- _networkModel .checkIpForService (ipAddress , Service .Firewall , null );
213- }
204+ try {
205+ // Validate ip address
206+ if (ipAddrId != null ) {
207+ // this for ingress firewall rule, for egress id is null
208+ ipAddress = _ipAddressDao .acquireInLockTable (ipAddrId );
209+ if (ipAddress == null ) {
210+ throw new InvalidParameterValueException ("Unable to create firewall rule; " + "couldn't locate IP address by id in the system" );
211+ }
212+ _networkModel .checkIpForService (ipAddress , Service .Firewall , null );
213+ }
214214
215- validateFirewallRule (caller , ipAddress , portStart , portEnd , protocol , Purpose .Firewall , type , networkId , trafficType );
215+ validateFirewallRule (caller , ipAddress , portStart , portEnd , protocol , Purpose .Firewall , type , networkId , trafficType );
216216
217- // icmp code and icmp type can't be passed in for any other protocol rather than icmp
218- if (!protocol .equalsIgnoreCase (NetUtils .ICMP_PROTO ) && (icmpCode != null || icmpType != null )) {
219- throw new InvalidParameterValueException ("Can specify icmpCode and icmpType for ICMP protocol only" );
220- }
217+ // icmp code and icmp type can't be passed in for any other protocol rather than icmp
218+ if (!protocol .equalsIgnoreCase (NetUtils .ICMP_PROTO ) && (icmpCode != null || icmpType != null )) {
219+ throw new InvalidParameterValueException ("Can specify icmpCode and icmpType for ICMP protocol only" );
220+ }
221221
222- if (protocol .equalsIgnoreCase (NetUtils .ICMP_PROTO ) && (portStart != null || portEnd != null )) {
223- throw new InvalidParameterValueException ("Can't specify start/end port when protocol is ICMP" );
224- }
222+ if (protocol .equalsIgnoreCase (NetUtils .ICMP_PROTO ) && (portStart != null || portEnd != null )) {
223+ throw new InvalidParameterValueException ("Can't specify start/end port when protocol is ICMP" );
224+ }
225225
226- Long accountId = null ;
227- Long domainId = null ;
226+ Long accountId = null ;
227+ Long domainId = null ;
228228
229- if (ipAddress != null ) {
230- //Ingress firewall rule
231- accountId = ipAddress .getAllocatedToAccountId ();
232- domainId = ipAddress .getAllocatedInDomainId ();
233- } else if (networkId != null ) {
234- //egress firewall rule
229+ if (ipAddress != null ) {
230+ //Ingress firewall rule
231+ accountId = ipAddress .getAllocatedToAccountId ();
232+ domainId = ipAddress .getAllocatedInDomainId ();
233+ } else if (networkId != null ) {
234+ //egress firewall rule
235235 Network network = _networkModel .getNetwork (networkId );
236236 accountId = network .getAccountId ();
237237 domainId = network .getDomainId ();
238- }
238+ }
239239
240- final Long accountIdFinal = accountId ;
241- final Long domainIdFinal = domainId ;
242- return Transaction .execute (new TransactionCallbackWithException <FirewallRuleVO , NetworkRuleConflictException >() {
243- @ Override
244- public FirewallRuleVO doInTransaction (TransactionStatus status ) throws NetworkRuleConflictException {
245- FirewallRuleVO newRule =
246- new FirewallRuleVO (xId , ipAddrId , portStart , portEnd , protocol .toLowerCase (), networkId , accountIdFinal , domainIdFinal , Purpose .Firewall ,
247- sourceCidrList , destCidrList , icmpCode , icmpType , relatedRuleId , trafficType );
240+ final Long accountIdFinal = accountId ;
241+ final Long domainIdFinal = domainId ;
242+ return Transaction .execute ((TransactionCallbackWithException <FirewallRuleVO , NetworkRuleConflictException >) status -> {
243+ FirewallRuleVO newRule = new FirewallRuleVO (xId , ipAddrId , portStart , portEnd , protocol .toLowerCase (), networkId , accountIdFinal , domainIdFinal , Purpose .Firewall ,
244+ sourceCidrList , destCidrList , icmpCode , icmpType , relatedRuleId , trafficType );
248245 newRule .setType (type );
249246 if (forDisplay != null ) {
250247 newRule .setDisplay (forDisplay );
@@ -261,8 +258,12 @@ public FirewallRuleVO doInTransaction(TransactionStatus status) throws NetworkRu
261258 CallContext .current ().putContextParameter (FirewallRule .class , newRule .getId ());
262259
263260 return newRule ;
261+ });
262+ } finally {
263+ if (ipAddrId != null ) {
264+ _ipAddressDao .releaseFromLockTable (ipAddrId );
264265 }
265- });
266+ }
266267 }
267268
268269 @ Override
@@ -668,9 +669,19 @@ public boolean applyIngressFwRules(long ipId, Account caller) throws ResourceUna
668669 }
669670
670671 @ Override
672+ @ DB
671673 public boolean applyIngressFirewallRules (long ipId , Account caller ) throws ResourceUnavailableException {
672- List <FirewallRuleVO > rules = _firewallDao .listByIpAndPurpose (ipId , Purpose .Firewall );
673- return applyFirewallRules (rules , false , caller );
674+ try {
675+ IPAddressVO ipAddress = _ipAddressDao .acquireInLockTable (ipId );
676+ if (ipAddress == null ) {
677+ s_logger .error (String .format ("Unable to acquire lock for public IP [%s]." , ipId ));
678+ throw new CloudRuntimeException ("Unable to acquire lock for public IP." );
679+ }
680+ List <FirewallRuleVO > rules = _firewallDao .listByIpAndPurpose (ipId , Purpose .Firewall );
681+ return applyFirewallRules (rules , false , caller );
682+ } finally {
683+ _ipAddressDao .releaseFromLockTable (ipId );
684+ }
674685 }
675686
676687 @ Override
0 commit comments