package io.cattle.platform.allocator.constraint; import io.cattle.platform.allocator.service.AllocationCandidate; import io.cattle.platform.core.constants.PortConstants; import io.cattle.platform.core.model.Port; import io.cattle.platform.object.util.DataAccessor; import java.util.List; import org.apache.commons.lang3.StringUtils; public class PortsConstraint extends HardConstraint implements Constraint { List<Port> ports; long instanceId; public PortsConstraint(long instanceId, List<Port> ports) { this.ports = ports; this.instanceId = instanceId; } @Override public boolean matches(AllocationCandidate candidate) { if (candidate.getHost() == null) { return false; } // TODO: Performance improvement. Move more of the filtering into the DB query itself List<Port> portsUsedByHost = candidate.getUsedPorts(); for (Port portUsed : portsUsedByHost) { for (Port requestedPort : ports) { if (requestedPort.getPublicPort() != null && requestedPort.getPublicPort().equals(portUsed.getPublicPort()) && publicIpTheSame(requestedPort, portUsed) && requestedPort.getProtocol().equals(portUsed.getProtocol())) { return false; } } } return true; } private boolean publicIpTheSame(Port requestedPort, Port portUsed) { if (requestedPort.getPublicIpAddressId() != null) { return requestedPort.getPublicIpAddressId().equals(portUsed.getPublicIpAddressId()); } else { String requestedIp = DataAccessor.fields(requestedPort).withKey(PortConstants.FIELD_BIND_ADDR).as(String.class); String usedIp = DataAccessor.fields(portUsed).withKey(PortConstants.FIELD_BIND_ADDR).as(String.class); return StringUtils.equals(requestedIp, usedIp); } } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (Port port: ports) { if (sb.length() > 0) { sb.append(", "); } sb.append(port.getPublicPort()); sb.append("/"); sb.append(port.getProtocol()); } return String.format("host needs ports %s available", sb.toString()); } }