public void releaseIp(long ipId, long userId, Account caller) { s_logger.info("ELB: Release public IP for loadbalancing " + ipId); IPAddressVO ipvo = _ipAddressDao.findById(ipId); ipvo.setAssociatedWithNetworkId(null); _ipAddressDao.update(ipvo.getId(), ipvo); _networkMgr.disassociatePublicIpAddress(ipId, userId, caller); _ipAddressDao.unassignIpAddress(ipId); }
@Override public List<UserVmVO> listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException { Account caller = UserContext.current().getCaller(); Long loadBalancerId = cmd.getId(); Boolean applied = cmd.isApplied(); if (applied == null) { applied = Boolean.TRUE; } LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId); if (loadBalancer == null) { return null; } _accountMgr.checkAccess(caller, null, loadBalancer); List<UserVmVO> loadBalancerInstances = new ArrayList<UserVmVO>(); List<LoadBalancerVMMapVO> vmLoadBalancerMappings = null; vmLoadBalancerMappings = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId); List<Long> appliedInstanceIdList = new ArrayList<Long>(); if ((vmLoadBalancerMappings != null) && !vmLoadBalancerMappings.isEmpty()) { for (LoadBalancerVMMapVO vmLoadBalancerMapping : vmLoadBalancerMappings) { appliedInstanceIdList.add(vmLoadBalancerMapping.getInstanceId()); } } IPAddressVO addr = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId()); List<UserVmVO> userVms = _vmDao.listVirtualNetworkInstancesByAcctAndZone( loadBalancer.getAccountId(), addr.getDataCenterId(), loadBalancer.getNetworkId()); for (UserVmVO userVm : userVms) { // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it switch (userVm.getState()) { case Destroyed: case Expunging: case Error: case Unknown: continue; } boolean isApplied = appliedInstanceIdList.contains(userVm.getId()); if ((isApplied && applied) || (!isApplied && !applied)) { loadBalancerInstances.add(userVm); } } return loadBalancerInstances; }
@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; }
@DB public PublicIp allocDirectIp(Account account, long guestNetworkId) throws InsufficientAddressCapacityException { Network frontEndNetwork = _networkModel.getNetwork(guestNetworkId); Transaction txn = Transaction.currentTxn(); txn.start(); PublicIp ip = _networkMgr.assignPublicIpAddress( frontEndNetwork.getDataCenterId(), null, account, VlanType.DirectAttached, frontEndNetwork.getId(), null, true); IPAddressVO ipvo = _ipAddressDao.findById(ip.getId()); ipvo.setAssociatedWithNetworkId(frontEndNetwork.getId()); _ipAddressDao.update(ipvo.getId(), ipvo); txn.commit(); s_logger.info("Acquired frontend IP for ELB " + ip); return ip; }
@Override @DB public RemoteAccessVpn createRemoteAccessVpn( final long publicIpId, String ipRange, boolean openFirewall, final Boolean forDisplay) throws NetworkRuleConflictException { CallContext ctx = CallContext.current(); final Account caller = ctx.getCallingAccount(); Long networkId = null; // make sure ip address exists final PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId); if (ipAddr == null) { throw new InvalidParameterValueException( "Unable to create remote access vpn, invalid public IP address id" + publicIpId); } _accountMgr.checkAccess(caller, null, true, ipAddr); if (!ipAddr.readyToUse()) { throw new InvalidParameterValueException( "The Ip address is not ready to be used yet: " + ipAddr.getAddress()); } IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId); networkId = ipAddress.getAssociatedWithNetworkId(); if (networkId != null) { _networkMgr.checkIpForService(ipAddress, Service.Vpn, null); } final Long vpcId = ipAddress.getVpcId(); /* IP Address used for VPC must be the source NAT IP of whole VPC */ if (vpcId != null && ipAddress.isSourceNat()) { assert networkId == null; // No firewall setting for VPC, it would be open internally openFirewall = false; } final boolean openFirewallFinal = openFirewall; if (networkId == null && vpcId == null) { throw new InvalidParameterValueException( "Unable to create remote access vpn for the ipAddress: " + ipAddr.getAddress().addr() + " as ip is not associated with any network or VPC"); } RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId); if (vpnVO != null) { // if vpn is in Added state, return it to the api if (vpnVO.getState() == RemoteAccessVpn.State.Added) { return vpnVO; } throw new InvalidParameterValueException( "A Remote Access VPN already exists for this public Ip address"); } if (ipRange == null) { ipRange = RemoteAccessVpnClientIpRange.valueIn(ipAddr.getAccountId()); } final String[] range = ipRange.split("-"); if (range.length != 2) { throw new InvalidParameterValueException("Invalid ip range"); } if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])) { throw new InvalidParameterValueException("Invalid ip in range specification " + ipRange); } if (!NetUtils.validIpRange(range[0], range[1])) { throw new InvalidParameterValueException("Invalid ip range " + ipRange); } Pair<String, Integer> cidr = null; // TODO: assumes one virtual network / domr per account per zone if (networkId != null) { vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId); if (vpnVO != null) { // if vpn is in Added state, return it to the api if (vpnVO.getState() == RemoteAccessVpn.State.Added) { return vpnVO; } throw new InvalidParameterValueException( "A Remote Access VPN already exists for this account"); } // Verify that vpn service is enabled for the network Network network = _networkMgr.getNetwork(networkId); if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) { throw new InvalidParameterValueException( "Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId()); } cidr = NetUtils.getCidr(network.getCidr()); } else { // Don't need to check VPC because there is only one IP(source NAT IP) available for // VPN Vpc vpc = _vpcDao.findById(vpcId); cidr = NetUtils.getCidr(vpc.getCidr()); } // FIXME: This check won't work for the case where the guest ip range // changes depending on the vlan allocated. String[] guestIpRange = NetUtils.getIpRangeFromCidr(cidr.first(), cidr.second()); if (NetUtils.ipRangesOverlap(range[0], range[1], guestIpRange[0], guestIpRange[1])) { throw new InvalidParameterValueException( "Invalid ip range: " + ipRange + " overlaps with guest ip range " + guestIpRange[0] + "-" + guestIpRange[1]); } // TODO: check sufficient range // TODO: check overlap with private and public ip ranges in datacenter long startIp = NetUtils.ip2Long(range[0]); final String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1]; final String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength); return Transaction.execute( new TransactionCallbackWithException<RemoteAccessVpn, NetworkRuleConflictException>() { @Override public RemoteAccessVpn doInTransaction(TransactionStatus status) throws NetworkRuleConflictException { if (vpcId == null) { _rulesMgr.reservePorts( ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewallFinal, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT); } RemoteAccessVpnVO vpnVO = new RemoteAccessVpnVO( ipAddr.getAccountId(), ipAddr.getDomainId(), ipAddr.getAssociatedWithNetworkId(), publicIpId, vpcId, range[0], newIpRange, sharedSecret); if (forDisplay != null) { vpnVO.setDisplay(forDisplay); } return _remoteAccessVpnDao.persist(vpnVO); } }); }
@DB public LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb, boolean openFirewall) throws NetworkRuleConflictException { long ipId = lb.getSourceIpAddressId(); UserContext caller = UserContext.current(); int srcPortStart = lb.getSourcePortStart(); int defPortStart = lb.getDefaultPortStart(); int srcPortEnd = lb.getSourcePortEnd(); IPAddressVO ipAddr = _ipAddressDao.findById(lb.getSourceIpAddressId()); Long networkId = ipAddr.getSourceNetworkId(); // make sure ip address exists if (ipAddr == null || !ipAddr.readyToUse()) { throw new InvalidParameterValueException( "Unable to create load balancer rule, invalid IP address id" + ipId); } _firewallMgr.validateFirewallRule( caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(), Purpose.LoadBalancing); networkId = ipAddr.getAssociatedWithNetworkId(); if (networkId == null) { throw new InvalidParameterValueException( "Unable to create load balancer rule ; ip id=" + ipId + " is not associated with any network"); } NetworkVO network = _networkDao.findById(networkId); _accountMgr.checkAccess(caller.getCaller(), null, ipAddr); // verify that lb service is supported by the network if (!_networkMgr.isServiceSupported(network.getNetworkOfferingId(), Service.Lb)) { throw new InvalidParameterValueException( "LB service is not supported in network id= " + networkId); } Transaction txn = Transaction.currentTxn(); txn.start(); LoadBalancerVO newRule = new LoadBalancerVO( lb.getXid(), lb.getName(), lb.getDescription(), lb.getSourceIpAddressId(), lb.getSourcePortEnd(), lb.getDefaultPortStart(), lb.getAlgorithm(), network.getId(), ipAddr.getAccountId(), ipAddr.getDomainId()); newRule = _lbDao.persist(newRule); if (openFirewall) { _firewallMgr.createRuleForAllCidrs( ipId, caller.getCaller(), lb.getSourcePortStart(), lb.getSourcePortEnd(), lb.getProtocol(), null, null, newRule.getId()); } boolean success = true; try { _firewallMgr.detectRulesConflict(newRule, ipAddr); if (!_firewallDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } s_logger.debug( "Load balancer " + newRule.getId() + " for Ip address id=" + ipId + ", public port " + srcPortStart + ", private port " + defPortStart + " is added successfully."); UserContext.current().setEventDetails("Load balancer Id: " + newRule.getId()); UsageEventVO usageEvent = new UsageEventVO( EventTypes.EVENT_LOAD_BALANCER_CREATE, ipAddr.getAllocatedToAccountId(), ipAddr.getDataCenterId(), newRule.getId(), null); _usageEventDao.persist(usageEvent); txn.commit(); return newRule; } catch (Exception e) { success = false; if (e instanceof NetworkRuleConflictException) { throw (NetworkRuleConflictException) e; } throw new CloudRuntimeException( "Unable to add rule for ip address id=" + newRule.getSourceIpAddressId(), e); } finally { if (!success && newRule != null) { txn.start(); _firewallMgr.revokeRelatedFirewallRule(newRule.getId(), false); _lbDao.remove(newRule.getId()); txn.commit(); } } }
@Override @DB public LoadBalancer handleCreateLoadBalancerRule( CreateLoadBalancerRuleCmd lb, Account account, long networkId) throws InsufficientAddressCapacityException, NetworkRuleConflictException { // this part of code is executed when the LB provider is Elastic Load Balancer vm if (!_networkModel.isProviderSupportServiceInNetwork( lb.getNetworkId(), Service.Lb, Provider.ElasticLoadBalancerVm)) { return null; } Long ipId = lb.getSourceIpAddressId(); if (ipId != null) { return null; } boolean newIp = false; account = _accountDao.acquireInLockTable(account.getId()); if (account == null) { s_logger.warn("ELB: CreateLoadBalancer: Failed to acquire lock on account"); throw new CloudRuntimeException("Failed to acquire lock on account"); } try { List<LoadBalancerVO> existingLbs = findExistingLoadBalancers( lb.getName(), lb.getSourceIpAddressId(), lb.getAccountId(), lb.getDomainId(), lb.getSourcePortStart()); if (existingLbs == null) { existingLbs = findExistingLoadBalancers( lb.getName(), lb.getSourceIpAddressId(), lb.getAccountId(), lb.getDomainId(), null); if (existingLbs == null) { if (lb.getSourceIpAddressId() != null) { existingLbs = findExistingLoadBalancers( lb.getName(), null, lb.getAccountId(), lb.getDomainId(), null); if (existingLbs != null) { throw new InvalidParameterValueException( "Supplied LB name " + lb.getName() + " is not associated with IP " + lb.getSourceIpAddressId()); } } else { s_logger.debug( "Could not find any existing frontend ips for this account for this LB rule, acquiring a new frontent IP for ELB"); PublicIp ip = allocDirectIp(account, networkId); ipId = ip.getId(); newIp = true; } } else { ipId = existingLbs.get(0).getSourceIpAddressId(); s_logger.debug( "ELB: Found existing frontend ip for this account for this LB rule " + ipId); } } else { s_logger.warn("ELB: Found existing load balancers matching requested new LB"); throw new NetworkRuleConflictException( "ELB: Found existing load balancers matching requested new LB"); } Network network = _networkModel.getNetwork(networkId); IPAddressVO ipAddr = _ipAddressDao.findById(ipId); LoadBalancer result = null; try { lb.setSourceIpAddressId(ipId); result = _lbMgr.createLoadBalancer(lb, false); } catch (NetworkRuleConflictException e) { s_logger.warn("Failed to create LB rule, not continuing with ELB deployment"); if (newIp) { releaseIp(ipId, UserContext.current().getCallerUserId(), account); } throw e; } DomainRouterVO elbVm = null; if (existingLbs == null) { elbVm = findELBVmWithCapacity(network, ipAddr); if (elbVm == null) { elbVm = deployLoadBalancerVM(networkId, ipAddr, account.getId()); if (elbVm == null) { s_logger.warn( "Failed to deploy a new ELB vm for ip " + ipAddr + " in network " + network + "lb name=" + lb.getName()); if (newIp) releaseIp(ipId, UserContext.current().getCallerUserId(), account); } } } else { ElasticLbVmMapVO elbVmMap = _elbVmMapDao.findOneByIp(ipId); if (elbVmMap != null) { elbVm = _routerDao.findById(elbVmMap.getElbVmId()); } } if (elbVm == null) { s_logger.warn("No ELB VM can be found or deployed"); s_logger.warn("Deleting LB since we failed to deploy ELB VM"); _lbDao.remove(result.getId()); return null; } ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId(), result.getId()); _elbVmMapDao.persist(mapping); return result; } finally { if (account != null) { _accountDao.releaseFromLockTable(account.getId()); } } }
@Override public RemoteAccessVpn createRemoteAccessVpn( long publicIpId, String ipRange, boolean openFirewall, long networkId) throws NetworkRuleConflictException { UserContext ctx = UserContext.current(); Account caller = ctx.getCaller(); // make sure ip address exists PublicIpAddress ipAddr = _networkMgr.getPublicIpAddress(publicIpId); if (ipAddr == null) { throw new InvalidParameterValueException( "Unable to create remote access vpn, invalid public IP address id" + publicIpId); } _accountMgr.checkAccess(caller, null, true, ipAddr); if (!ipAddr.readyToUse()) { throw new InvalidParameterValueException( "The Ip address is not ready to be used yet: " + ipAddr.getAddress()); } IPAddressVO ipAddress = _ipAddressDao.findById(publicIpId); _networkMgr.checkIpForService(ipAddress, Service.Vpn, null); RemoteAccessVpnVO vpnVO = _remoteAccessVpnDao.findByPublicIpAddress(publicIpId); if (vpnVO != null) { // if vpn is in Added state, return it to the api if (vpnVO.getState() == RemoteAccessVpn.State.Added) { return vpnVO; } throw new InvalidParameterValueException( "A Remote Access VPN already exists for this public Ip address"); } // TODO: assumes one virtual network / domr per account per zone vpnVO = _remoteAccessVpnDao.findByAccountAndNetwork(ipAddr.getAccountId(), networkId); if (vpnVO != null) { // if vpn is in Added state, return it to the api if (vpnVO.getState() == RemoteAccessVpn.State.Added) { return vpnVO; } throw new InvalidParameterValueException( "A Remote Access VPN already exists for this account"); } // Verify that vpn service is enabled for the network Network network = _networkMgr.getNetwork(networkId); if (!_networkMgr.areServicesSupportedInNetwork(network.getId(), Service.Vpn)) { throw new InvalidParameterValueException( "Vpn service is not supported in network id=" + ipAddr.getAssociatedWithNetworkId()); } if (ipRange == null) { ipRange = _clientIpRange; } String[] range = ipRange.split("-"); if (range.length != 2) { throw new InvalidParameterValueException("Invalid ip range"); } if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])) { throw new InvalidParameterValueException("Invalid ip in range specification " + ipRange); } if (!NetUtils.validIpRange(range[0], range[1])) { throw new InvalidParameterValueException("Invalid ip range " + ipRange); } Pair<String, Integer> cidr = NetUtils.getCidr(network.getCidr()); // FIXME: This check won't work for the case where the guest ip range // changes depending on the vlan allocated. String[] guestIpRange = NetUtils.getIpRangeFromCidr(cidr.first(), cidr.second()); if (NetUtils.ipRangesOverlap(range[0], range[1], guestIpRange[0], guestIpRange[1])) { throw new InvalidParameterValueException( "Invalid ip range: " + ipRange + " overlaps with guest ip range " + guestIpRange[0] + "-" + guestIpRange[1]); } // TODO: check sufficient range // TODO: check overlap with private and public ip ranges in datacenter long startIp = NetUtils.ip2Long(range[0]); String newIpRange = NetUtils.long2Ip(++startIp) + "-" + range[1]; String sharedSecret = PasswordGenerator.generatePresharedKey(_pskLength); _rulesMgr.reservePorts( ipAddr, NetUtils.UDP_PROTO, Purpose.Vpn, openFirewall, caller, NetUtils.VPN_PORT, NetUtils.VPN_L2TP_PORT, NetUtils.VPN_NATT_PORT); vpnVO = new RemoteAccessVpnVO( ipAddr.getAccountId(), ipAddr.getDomainId(), ipAddr.getAssociatedWithNetworkId(), publicIpId, range[0], newIpRange, sharedSecret); return _remoteAccessVpnDao.persist(vpnVO); }
@Override public Pair<List<? extends FirewallRule>, Integer> listFirewallRules(ListFirewallRulesCmd cmd) { Long ipId = cmd.getIpAddressId(); Long id = cmd.getId(); Long networkId = null; Map<String, String> tags = cmd.getTags(); FirewallRule.TrafficType trafficType = cmd.getTrafficType(); Account caller = CallContext.current().getCallingAccount(); List<Long> permittedAccounts = new ArrayList<Long>(); if (ipId != null) { IPAddressVO ipAddressVO = _ipAddressDao.findById(ipId); if (ipAddressVO == null || !ipAddressVO.readyToUse()) { throw new InvalidParameterValueException( "Ip address id=" + ipId + " not ready for firewall rules yet"); } _accountMgr.checkAccess(caller, null, true, ipAddressVO); } Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<Long, Boolean, ListProjectResourcesCriteria>( cmd.getDomainId(), cmd.isRecursive(), null); _accountMgr.buildACLSearchParameters( caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); Filter filter = new Filter(FirewallRuleVO.class, "id", false, cmd.getStartIndex(), cmd.getPageSizeVal()); SearchBuilder<FirewallRuleVO> sb = _firewallDao.createSearchBuilder(); _accountMgr.buildACLSearchBuilder( sb, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); sb.and("id", sb.entity().getId(), Op.EQ); sb.and("trafficType", sb.entity().getTrafficType(), Op.EQ); if (cmd instanceof ListEgressFirewallRulesCmd) { networkId = ((ListEgressFirewallRulesCmd) cmd).getNetworkId(); sb.and("networkId", sb.entity().getNetworkId(), Op.EQ); } else { sb.and("ip", sb.entity().getSourceIpAddressId(), Op.EQ); } sb.and("purpose", sb.entity().getPurpose(), Op.EQ); if (tags != null && !tags.isEmpty()) { SearchBuilder<ResourceTagVO> tagSearch = _resourceTagDao.createSearchBuilder(); for (int count = 0; count < tags.size(); count++) { tagSearch .or() .op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); tagSearch.and( "value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); tagSearch.cp(); } tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); sb.groupBy(sb.entity().getId()); sb.join( "tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); } SearchCriteria<FirewallRuleVO> sc = sb.create(); _accountMgr.buildACLSearchCriteria( sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); if (id != null) { sc.setParameters("id", id); } if (tags != null && !tags.isEmpty()) { int count = 0; sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.FirewallRule.toString()); for (String key : tags.keySet()) { sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); count++; } } if (ipId != null) { sc.setParameters("ip", ipId); } else if (cmd instanceof ListEgressFirewallRulesCmd) { if (networkId != null) { sc.setParameters("networkId", networkId); } } sc.setParameters("purpose", Purpose.Firewall); sc.setParameters("trafficType", trafficType); Pair<List<FirewallRuleVO>, Integer> result = _firewallDao.searchAndCount(sc, filter); return new Pair<List<? extends FirewallRule>, Integer>(result.first(), result.second()); }
@DB protected FirewallRule createFirewallRule( Long ipAddrId, Account caller, String xId, Integer portStart, Integer portEnd, String protocol, List<String> sourceCidrList, Integer icmpCode, Integer icmpType, Long relatedRuleId, FirewallRule.FirewallRuleType type, Long networkId, FirewallRule.TrafficType trafficType) throws NetworkRuleConflictException { IPAddressVO ipAddress = null; if (ipAddrId != null) { // this for ingress firewall rule, for egress id is null ipAddress = _ipAddressDao.findById(ipAddrId); // Validate ip address if (ipAddress == null && type == FirewallRule.FirewallRuleType.User) { throw new InvalidParameterValueException( "Unable to create firewall rule; " + "couldn't locate IP address by id in the system"); } _networkModel.checkIpForService(ipAddress, Service.Firewall, null); } validateFirewallRule( caller, ipAddress, portStart, portEnd, protocol, Purpose.Firewall, type, networkId, trafficType); // icmp code and icmp type can't be passed in for any other protocol rather than icmp if (!protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (icmpCode != null || icmpType != null)) { throw new InvalidParameterValueException( "Can specify icmpCode and icmpType for ICMP protocol only"); } if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) && (portStart != null || portEnd != null)) { throw new InvalidParameterValueException( "Can't specify start/end port when protocol is ICMP"); } Long accountId = null; Long domainId = null; if (ipAddress != null) { // Ingress firewall rule accountId = ipAddress.getAllocatedToAccountId(); domainId = ipAddress.getAllocatedInDomainId(); } else if (networkId != null) { // egress firewall rule Network network = _networkModel.getNetwork(networkId); accountId = network.getAccountId(); domainId = network.getDomainId(); } Transaction txn = Transaction.currentTxn(); txn.start(); FirewallRuleVO newRule = new FirewallRuleVO( xId, ipAddrId, portStart, portEnd, protocol.toLowerCase(), networkId, accountId, domainId, Purpose.Firewall, sourceCidrList, icmpCode, icmpType, relatedRuleId, trafficType); newRule.setType(type); newRule = _firewallDao.persist(newRule); if (type == FirewallRuleType.User) detectRulesConflict(newRule); if (!_firewallDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } CallContext.current().setEventDetails("Rule Id: " + newRule.getId()); txn.commit(); return newRule; }