protected boolean revokeFirewallRule(long ruleId, boolean apply, Account caller, long userId) {

    FirewallRuleVO rule = _firewallDao.findById(ruleId);
    if (rule == null || rule.getPurpose() != Purpose.Firewall) {
      throw new InvalidParameterValueException(
          "Unable to find " + ruleId + " having purpose " + Purpose.Firewall);
    }

    if (rule.getType() == FirewallRuleType.System
        && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) {
      throw new InvalidParameterValueException(
          "Only root admin can delete the system wide firewall rule");
    }

    _accountMgr.checkAccess(caller, null, true, rule);

    revokeRule(rule, caller, userId, false);

    boolean success = false;
    Long networkId = rule.getNetworkId();

    if (apply) {
      // ingress firewall rule
      if (rule.getSourceIpAddressId() != null) {
        // feteches ingress firewall, ingress firewall rules associated with the ip
        List<FirewallRuleVO> rules =
            _firewallDao.listByIpAndPurpose(rule.getSourceIpAddressId(), Purpose.Firewall);
        return applyFirewallRules(rules, false, caller);
        // egress firewall rule
      } else if (networkId != null) {
        List<FirewallRuleVO> rules =
            _firewallDao.listByNetworkPurposeTrafficType(
                rule.getNetworkId(), Purpose.Firewall, FirewallRule.TrafficType.Egress);
        return applyFirewallRules(rules, false, caller);
      }
    } else {
      success = true;
    }

    return success;
  }
  @Override
  @ActionEvent(
      eventType = EventTypes.EVENT_FIREWALL_CLOSE,
      eventDescription = "revoking firewall rule",
      async = true)
  public boolean revokeFirewallRulesForVm(long vmId) {
    boolean success = true;
    UserVmVO vm = _vmDao.findByIdIncludingRemoved(vmId);
    if (vm == null) {
      return false;
    }

    List<PortForwardingRuleVO> pfRules = _pfRulesDao.listByVm(vmId);
    List<FirewallRuleVO> staticNatRules = _firewallDao.listStaticNatByVmId(vm.getId());
    List<FirewallRuleVO> firewallRules = new ArrayList<FirewallRuleVO>();

    // Make a list of firewall rules to reprogram
    for (PortForwardingRuleVO pfRule : pfRules) {
      FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(pfRule.getId());
      if (relatedRule != null) {
        firewallRules.add(relatedRule);
      }
    }

    for (FirewallRuleVO staticNatRule : staticNatRules) {
      FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(staticNatRule.getId());
      if (relatedRule != null) {
        firewallRules.add(relatedRule);
      }
    }

    Set<Long> ipsToReprogram = new HashSet<Long>();

    if (firewallRules.isEmpty()) {
      s_logger.debug("No firewall rules are found for vm id=" + vmId);
      return true;
    } else {
      s_logger.debug("Found " + firewallRules.size() + " to cleanup for vm id=" + vmId);
    }

    for (FirewallRuleVO rule : firewallRules) {
      // Mark firewall rules as Revoked, but don't revoke it yet (apply=false)
      revokeFirewallRule(
          rule.getId(), false, _accountMgr.getSystemAccount(), Account.ACCOUNT_ID_SYSTEM);
      ipsToReprogram.add(rule.getSourceIpAddressId());
    }

    // apply rules for all ip addresses
    for (Long ipId : ipsToReprogram) {
      s_logger.debug(
          "Applying firewall rules for ip address id=" + ipId + " as a part of vm expunge");
      try {
        success = success && applyIngressFirewallRules(ipId, _accountMgr.getSystemAccount());
      } catch (ResourceUnavailableException ex) {
        s_logger.warn("Failed to apply port forwarding rules for ip id=" + ipId);
        success = false;
      }
    }

    return success;
  }