@@ -194,57 +194,54 @@ public FirewallRule createIngressFirewallRule(FirewallRule rule) throws NetworkR
194
194
return createFirewallRule (sourceIpAddressId , caller , rule .getXid (), rule .getSourcePortStart (), rule .getSourcePortEnd (), rule .getProtocol (),
195
195
rule .getSourceCidrList (), null , rule .getIcmpCode (), rule .getIcmpType (), null , rule .getType (), rule .getNetworkId (), rule .getTrafficType (), rule .isDisplay ());
196
196
}
197
+
197
198
//Destination CIDR capability is currently implemented for egress rules only. For others, the field is passed as null.
198
199
@ 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 {
204
203
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
+ }
214
214
215
- validateFirewallRule (caller , ipAddress , portStart , portEnd , protocol , Purpose .Firewall , type , networkId , trafficType );
215
+ validateFirewallRule (caller , ipAddress , portStart , portEnd , protocol , Purpose .Firewall , type , networkId , trafficType );
216
216
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
+ }
221
221
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
+ }
225
225
226
- Long accountId = null ;
227
- Long domainId = null ;
226
+ Long accountId = null ;
227
+ Long domainId = null ;
228
228
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
235
235
Network network = _networkModel .getNetwork (networkId );
236
236
accountId = network .getAccountId ();
237
237
domainId = network .getDomainId ();
238
- }
238
+ }
239
239
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 );
248
245
newRule .setType (type );
249
246
if (forDisplay != null ) {
250
247
newRule .setDisplay (forDisplay );
@@ -261,8 +258,12 @@ public FirewallRuleVO doInTransaction(TransactionStatus status) throws NetworkRu
261
258
CallContext .current ().putContextParameter (FirewallRule .class , newRule .getId ());
262
259
263
260
return newRule ;
261
+ });
262
+ } finally {
263
+ if (ipAddrId != null ) {
264
+ _ipAddressDao .releaseFromLockTable (ipAddrId );
264
265
}
265
- });
266
+ }
266
267
}
267
268
268
269
@ Override
@@ -668,9 +669,19 @@ public boolean applyIngressFwRules(long ipId, Account caller) throws ResourceUna
668
669
}
669
670
670
671
@ Override
672
+ @ DB
671
673
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
+ }
674
685
}
675
686
676
687
@ Override
0 commit comments