@Override
  public boolean applyRules(
      List<? extends FirewallRule> rules, boolean continueOnError, boolean updateRulesInDB)
      throws ResourceUnavailableException {
    boolean success = true;
    if (rules == null || rules.size() == 0) {
      s_logger.debug("There are no rules to forward to the network elements");
      return true;
    }
    Purpose purpose = rules.get(0).getPurpose();
    if (!_ipAddrMgr.applyRules(rules, purpose, this, continueOnError)) {
      s_logger.warn("Rules are not completely applied");
      return false;
    } else {
      if (updateRulesInDB) {
        for (FirewallRule rule : rules) {
          if (rule.getState() == FirewallRule.State.Revoke) {
            FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(rule.getId());
            if (relatedRule != null) {
              s_logger.warn(
                  "Can't remove the firewall rule id="
                      + rule.getId()
                      + " as it has related firewall rule id="
                      + relatedRule.getId()
                      + "; leaving it in Revoke state");
              success = false;
            } else {
              removeRule(rule);
              if (rule.getSourceIpAddressId() != null) {
                // if the rule is the last one for the ip address assigned to VPC, unassign it from
                // the network
                IpAddress ip = _ipAddressDao.findById(rule.getSourceIpAddressId());
                _vpcMgr.unassignIPFromVpcNetwork(ip.getId(), rule.getNetworkId());
              }
            }
          } else if (rule.getState() == FirewallRule.State.Add) {
            FirewallRuleVO ruleVO = _firewallDao.findById(rule.getId());
            ruleVO.setState(FirewallRule.State.Active);
            _firewallDao.update(ruleVO.getId(), ruleVO);
          }
        }
      }
    }

    return success;
  }
  @Override
  @DB
  public void revokeRule(FirewallRuleVO rule, Account caller, long userId, boolean needUsageEvent) {
    if (caller != null) {
      _accountMgr.checkAccess(caller, null, true, rule);
    }

    Transaction txn = Transaction.currentTxn();
    boolean generateUsageEvent = false;

    txn.start();
    if (rule.getState() == State.Staged) {
      if (s_logger.isDebugEnabled()) {
        s_logger.debug("Found a rule that is still in stage state so just removing it: " + rule);
      }
      removeRule(rule);
      generateUsageEvent = true;
    } else if (rule.getState() == State.Add || rule.getState() == State.Active) {
      rule.setState(State.Revoke);
      _firewallDao.update(rule.getId(), rule);
      generateUsageEvent = true;
    }

    if (generateUsageEvent && needUsageEvent) {
      UsageEventUtils.publishUsageEvent(
          EventTypes.EVENT_NET_RULE_DELETE,
          rule.getAccountId(),
          0,
          rule.getId(),
          null,
          rule.getClass().getName(),
          rule.getUuid());
    }

    txn.commit();
  }