public void createOrUpdateIpCapacity(Long dcId, Long podId, short capacityType) { SearchCriteria<CapacityVO> capacitySC = _capacityDao.createSearchCriteria(); List<CapacityVO> capacities = _capacityDao.search(capacitySC, null); capacitySC = _capacityDao.createSearchCriteria(); capacitySC.addAnd("podId", SearchCriteria.Op.EQ, podId); capacitySC.addAnd("dataCenterId", SearchCriteria.Op.EQ, dcId); capacitySC.addAnd("capacityType", SearchCriteria.Op.EQ, capacityType); int totalIPs; int allocatedIPs; capacities = _capacityDao.search(capacitySC, null); if (capacityType == CapacityVO.CAPACITY_TYPE_PRIVATE_IP) { totalIPs = _privateIPAddressDao.countIPs(podId, dcId, false); allocatedIPs = _privateIPAddressDao.countIPs(podId, dcId, true); } else if (capacityType == CapacityVO.CAPACITY_TYPE_VIRTUAL_NETWORK_PUBLIC_IP) { totalIPs = _publicIPAddressDao.countIPsForNetwork(dcId, false, VlanType.VirtualNetwork); allocatedIPs = _publicIPAddressDao.countIPsForNetwork(dcId, true, VlanType.VirtualNetwork); } else { totalIPs = _publicIPAddressDao.countIPsForNetwork(dcId, false, VlanType.DirectAttached); allocatedIPs = _publicIPAddressDao.countIPsForNetwork(dcId, true, VlanType.DirectAttached); } if (capacities.size() == 0) { CapacityVO newPublicIPCapacity = new CapacityVO(null, dcId, podId, null, allocatedIPs, totalIPs, capacityType); _capacityDao.persist(newPublicIPCapacity); } else if (!(capacities.get(0).getUsedCapacity() == allocatedIPs && capacities.get(0).getTotalCapacity() == totalIPs)) { CapacityVO capacity = capacities.get(0); capacity.setUsedCapacity(allocatedIPs); capacity.setTotalCapacity(totalIPs); _capacityDao.update(capacity.getId(), capacity); } }
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<IPAddressVO> listAllocatedDirectIps(long zoneId) { SearchCriteria<IPAddressVO> sc = AllocatedIpSearch.create(); sc.setParameters("dc", zoneId); sc.setJoinParameters("network", "guestType", Network.GuestType.Shared); return _ipAddressDao.search(sc, null); }
@Override @DB public void deallocate( Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) { if (s_logger.isDebugEnabled()) { s_logger.debug( "Deallocate network: networkId: " + nic.getNetworkId() + ", ip: " + nic.getIp4Address()); } IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIp4Address()); if (ip != null) { Transaction txn = Transaction.currentTxn(); txn.start(); _networkMgr.markIpAsUnavailable(ip.getId()); _ipAddressDao.unassignIpAddress(ip.getId()); txn.commit(); } nic.deallocate(); }
@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; }
@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 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 public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { AllocatedIpSearch = _ipAddressDao.createSearchBuilder(); AllocatedIpSearch.and("allocated", AllocatedIpSearch.entity().getAllocatedTime(), Op.NNULL); AllocatedIpSearch.and("dc", AllocatedIpSearch.entity().getDataCenterId(), Op.EQ); SearchBuilder<NetworkVO> networkJoin = _networksDao.createSearchBuilder(); networkJoin.and("guestType", networkJoin.entity().getGuestType(), Op.EQ); AllocatedIpSearch.join( "network", networkJoin, AllocatedIpSearch.entity().getSourceNetworkId(), networkJoin.entity().getId(), JoinBuilder.JoinType.INNER); AllocatedIpSearch.done(); _networkStatsInterval = NumbersUtil.parseInt(_configDao.getValue(Config.DirectNetworkStatsInterval.key()), 86400); _TSinclZones = _configDao.getValue(Config.TrafficSentinelIncludeZones.key()); _TSexclZones = _configDao.getValue(Config.TrafficSentinelExcludeZones.key()); _agentMgr.registerForHostEvents( new DirectNetworkStatsListener(_networkStatsInterval), true, false, false); _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; }
@Override public List<LoadBalancerVO> searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) { Account caller = UserContext.current().getCaller(); Long ipId = cmd.getPublicIpId(); Long zoneId = cmd.getZoneId(); String path = null; Pair<String, Long> accountDomainPair = _accountMgr.finalizeAccountDomainForList(caller, cmd.getAccountName(), cmd.getDomainId()); String accountName = accountDomainPair.first(); Long domainId = accountDomainPair.second(); if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { Domain domain = _domainMgr.getDomain(caller.getDomainId()); path = domain.getPath(); } Filter searchFilter = new Filter(LoadBalancerVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); Object id = cmd.getId(); Object name = cmd.getLoadBalancerRuleName(); Object keyword = cmd.getKeyword(); Object instanceId = cmd.getVirtualMachineId(); SearchBuilder<LoadBalancerVO> sb = _lbDao.createSearchBuilder(); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ); sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ); sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); if (instanceId != null) { SearchBuilder<LoadBalancerVMMapVO> lbVMSearch = _lb2VmMapDao.createSearchBuilder(); lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); sb.join( "lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER); } if (path != null) { // for domain admin we should show only subdomains information SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder(); domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); sb.join( "domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); } if (zoneId != null) { SearchBuilder<IPAddressVO> ipSearch = _ipAddressDao.createSearchBuilder(); ipSearch.and("zoneId", ipSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); sb.join( "ipSearch", ipSearch, sb.entity().getSourceIpAddressId(), ipSearch.entity().getId(), JoinBuilder.JoinType.INNER); } SearchCriteria<LoadBalancerVO> sc = sb.create(); if (keyword != null) { SearchCriteria<LoadBalancerVO> ssc = _lbDao.createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } if (name != null) { sc.setParameters("name", "%" + name + "%"); } if (id != null) { sc.setParameters("id", id); } if (ipId != null) { sc.setParameters("sourceIpAddress", ipId); } if (instanceId != null) { sc.setJoinParameters("lbVMSearch", "instanceId", instanceId); } if (domainId != null) { sc.setParameters("domainId", domainId); if (accountName != null) { Account account = _accountMgr.getActiveAccountByName(accountName, domainId); sc.setParameters("accountId", account.getId()); } } if (path != null) { sc.setJoinParameters("domainSearch", "path", path + "%"); } if (zoneId != null) { sc.setJoinParameters("ipSearch", "zoneId", zoneId); } return _lbDao.search(sc, searchFilter); }
@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()); } } }
@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; }
@Override public boolean implement( Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { DataCenter zone = _configMgr.getZone(network.getDataCenterId()); if (zone.getNetworkType() == NetworkType.Basic) { s_logger.debug("Not handling network implement in zone of type " + NetworkType.Basic); return false; } if (!canHandle(network)) { return false; } List<CiscoVnmcControllerVO> devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); if (devices.isEmpty()) { s_logger.error("No Cisco Vnmc device on network " + network.getName()); return false; } List<CiscoAsa1000vDeviceVO> asaList = _ciscoAsa1000vDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); if (asaList.isEmpty()) { s_logger.debug("No Cisco ASA 1000v device on network " + network.getName()); return false; } NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId()); if (asaForNetwork != null) { s_logger.debug("Cisco ASA 1000v device already associated with network " + network.getName()); return true; } if (!_networkModel.isProviderSupportServiceInNetwork( network.getId(), Service.SourceNat, Provider.CiscoVnmc)) { s_logger.error( "SourceNat service is not provided by Cisco Vnmc device on network " + network.getName()); return false; } Transaction txn = Transaction.currentTxn(); boolean status = false; try { txn.start(); // ensure that there is an ASA 1000v assigned to this network CiscoAsa1000vDevice assignedAsa = assignAsa1000vToNetwork(network); if (assignedAsa == null) { s_logger.error("Unable to assign ASA 1000v device to network " + network.getName()); return false; } ClusterVO asaCluster = _clusterDao.findById(assignedAsa.getClusterId()); ClusterVSMMapVO clusterVsmMap = _clusterVsmMapDao.findByClusterId(assignedAsa.getClusterId()); if (clusterVsmMap == null) { s_logger.error( "Vmware cluster " + asaCluster.getName() + " has no Cisco Nexus VSM device associated with it"); return false; } CiscoNexusVSMDeviceVO vsmDevice = _vsmDeviceDao.findById(clusterVsmMap.getVsmId()); if (vsmDevice == null) { s_logger.error( "Unable to load details of Cisco Nexus VSM device associated with cluster " + asaCluster.getName()); return false; } CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0); HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId()); _hostDao.loadDetails(ciscoVnmcHost); Account owner = context.getAccount(); PublicIp sourceNatIp = _ipAddrMgr.assignSourceNatIpAddressToGuestNetwork(owner, network); String vlan = network.getBroadcastUri().getHost(); long vlanId = Long.parseLong(vlan); List<VlanVO> vlanVOList = _vlanDao.listVlansByPhysicalNetworkId(network.getPhysicalNetworkId()); List<String> publicGateways = new ArrayList<String>(); for (VlanVO vlanVO : vlanVOList) { publicGateways.add(vlanVO.getVlanGateway()); } // due to VNMC limitation of not allowing source NAT ip as the outside ip of firewall, // an additional public ip needs to acquired for assigning as firewall outside ip. // In case there are already additional ip addresses available (network restart) use one // of them such that it is not the source NAT ip IpAddress outsideIp = null; List<IPAddressVO> publicIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null); for (IPAddressVO ip : publicIps) { if (!ip.isSourceNat()) { outsideIp = ip; break; } } if (outsideIp == null) { // none available, acquire one try { Account caller = CallContext.current().getCallingAccount(); long callerUserId = CallContext.current().getCallingUserId(); outsideIp = _ipAddrMgr.allocateIp(owner, false, caller, callerUserId, zone); } catch (ResourceAllocationException e) { s_logger.error("Unable to allocate additional public Ip address. Exception details " + e); return false; } try { outsideIp = _ipAddrMgr.associateIPToGuestNetwork(outsideIp.getId(), network.getId(), true); } catch (ResourceAllocationException e) { s_logger.error( "Unable to assign allocated additional public Ip " + outsideIp.getAddress().addr() + " to network with vlan " + vlanId + ". Exception details " + e); return false; } } // create logical edge firewall in VNMC String gatewayNetmask = NetUtils.getCidrNetmask(network.getCidr()); // due to ASA limitation of allowing single subnet to be assigned to firewall interfaces, // all public ip addresses must be from same subnet, this essentially means single public // subnet in zone if (!createLogicalEdgeFirewall( vlanId, network.getGateway(), gatewayNetmask, outsideIp.getAddress().addr(), sourceNatIp.getNetmask(), publicGateways, ciscoVnmcHost.getId())) { s_logger.error( "Failed to create logical edge firewall in Cisco VNMC device for network " + network.getName()); return false; } // create stuff in VSM for ASA device if (!configureNexusVsmForAsa( vlanId, network.getGateway(), vsmDevice.getUserName(), vsmDevice.getPassword(), vsmDevice.getipaddr(), assignedAsa.getInPortProfile(), ciscoVnmcHost.getId())) { s_logger.error( "Failed to configure Cisco Nexus VSM " + vsmDevice.getipaddr() + " for ASA device for network " + network.getName()); return false; } // configure source NAT if (!configureSourceNat(vlanId, network.getCidr(), sourceNatIp, ciscoVnmcHost.getId())) { s_logger.error( "Failed to configure source NAT in Cisco VNMC device for network " + network.getName()); return false; } // associate Asa 1000v instance with logical edge firewall if (!associateAsaWithLogicalEdgeFirewall( vlanId, assignedAsa.getManagementIp(), ciscoVnmcHost.getId())) { s_logger.error( "Failed to associate Cisco ASA 1000v (" + assignedAsa.getManagementIp() + ") with logical edge firewall in VNMC for network " + network.getName()); return false; } status = true; txn.commit(); } finally { if (!status) { txn.rollback(); // FIXME: also undo changes in VNMC, VSM if anything failed } } return true; }
@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()); }
@Override public LinkedHashMap<Network, List<? extends NicProfile>> configureGuestNic( final RouterDeploymentDefinition routerDeploymentDefinition) throws ConcurrentOperationException, InsufficientAddressCapacityException { // Form networks final LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<Network, List<? extends NicProfile>>(3); // 1) Guest network final Network guestNetwork = routerDeploymentDefinition.getGuestNetwork(); if (guestNetwork != null) { s_logger.debug("Adding nic for Virtual Router in Guest network " + guestNetwork); String defaultNetworkStartIp = null, defaultNetworkStartIpv6 = null; if (!routerDeploymentDefinition.isPublicNetwork()) { final Nic placeholder = _networkModel.getPlaceholderNicForRouter( guestNetwork, routerDeploymentDefinition.getPodId()); if (guestNetwork.getCidr() != null) { if (placeholder != null && placeholder.getIPv4Address() != null) { s_logger.debug( "Requesting ipv4 address " + placeholder.getIPv4Address() + " stored in placeholder nic for the network " + guestNetwork); defaultNetworkStartIp = placeholder.getIPv4Address(); } else { final String startIp = _networkModel.getStartIpAddress(guestNetwork.getId()); if (startIp != null && _ipAddressDao .findByIpAndSourceNetworkId(guestNetwork.getId(), startIp) .getAllocatedTime() == null) { defaultNetworkStartIp = startIp; } else if (s_logger.isDebugEnabled()) { s_logger.debug( "First ipv4 " + startIp + " in network id=" + guestNetwork.getId() + " is already allocated, can't use it for domain router; will get random ip address from the range"); } } } if (guestNetwork.getIp6Cidr() != null) { if (placeholder != null && placeholder.getIPv6Address() != null) { s_logger.debug( "Requesting ipv6 address " + placeholder.getIPv6Address() + " stored in placeholder nic for the network " + guestNetwork); defaultNetworkStartIpv6 = placeholder.getIPv6Address(); } else { final String startIpv6 = _networkModel.getStartIpv6Address(guestNetwork.getId()); if (startIpv6 != null && _ipv6Dao.findByNetworkIdAndIp(guestNetwork.getId(), startIpv6) == null) { defaultNetworkStartIpv6 = startIpv6; } else if (s_logger.isDebugEnabled()) { s_logger.debug( "First ipv6 " + startIpv6 + " in network id=" + guestNetwork.getId() + " is already allocated, can't use it for domain router; will get random ipv6 address from the range"); } } } } final NicProfile gatewayNic = new NicProfile(defaultNetworkStartIp, defaultNetworkStartIpv6); if (routerDeploymentDefinition.isPublicNetwork()) { if (routerDeploymentDefinition.isRedundant()) { gatewayNic.setIPv4Address(_ipAddrMgr.acquireGuestIpAddress(guestNetwork, null)); } else { gatewayNic.setIPv4Address(guestNetwork.getGateway()); } gatewayNic.setBroadcastUri(guestNetwork.getBroadcastUri()); gatewayNic.setBroadcastType(guestNetwork.getBroadcastDomainType()); gatewayNic.setIsolationUri(guestNetwork.getBroadcastUri()); gatewayNic.setMode(guestNetwork.getMode()); final String gatewayCidr = guestNetwork.getCidr(); gatewayNic.setIPv4Netmask(NetUtils.getCidrNetmask(gatewayCidr)); } else { gatewayNic.setDefaultNic(true); } networks.put(guestNetwork, new ArrayList<NicProfile>(Arrays.asList(gatewayNic))); } return networks; }
@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 @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); } }); }
@Override public void deallocate( Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) { _ipAddressDao.unassignIpAddress(new Ip(nic.getIp4Address())); nic.deallocate(); }