Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop provisioning exclusivity=provision #33337

Merged
merged 1 commit into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,14 @@ public interface HostProvisioner {

enum HostSharing {

/** The host must be provisioned exclusively for the application ID. */
provision,

/** The host must be exclusive to a single application ID */
exclusive,

/** The host may be provisioned to be shared with other applications, otherwise falls back to exclusive. */
shared;

public boolean isExclusiveAllocation() {
return this == provision || this == exclusive;
return this == exclusive;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,9 @@ private boolean canProvisionDynamically(NodeType hostType) {
}

private HostSharing hostSharing(ClusterSpec cluster, NodeType hostType) {
if ( hostType.isSharable())
return nodeRepository.exclusivity().provisioning(cluster) ? HostSharing.provision :
nodeRepository.exclusivity().allocation(cluster) ? HostSharing.exclusive :
HostSharing.shared;
else
return HostSharing.shared;
if (hostType.isSharable() && nodeRepository.exclusivity().allocation(cluster))
return HostSharing.exclusive;
return HostSharing.shared;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public class ProvisionedHost {
private final String hostHostname;
private final Flavor hostFlavor;
private final NodeType hostType;
private final Optional<ApplicationId> provisionedForApplicationId;
private final Optional<ApplicationId> exclusiveToApplicationId;
private final Optional<ClusterSpec.Type> exclusiveToClusterType;
private final List<HostName> nodeHostnames;
Expand All @@ -39,7 +38,6 @@ public class ProvisionedHost {
private final CloudAccount cloudAccount;

public ProvisionedHost(String id, String hostHostname, Flavor hostFlavor, NodeType hostType,
Optional<ApplicationId> provisionedForApplicationId,
Optional<ApplicationId> exclusiveToApplicationId,
Optional<ClusterSpec.Type> exclusiveToClusterType,
List<HostName> nodeHostnames, NodeResources nodeResources,
Expand All @@ -49,7 +47,6 @@ public ProvisionedHost(String id, String hostHostname, Flavor hostFlavor, NodeTy
this.hostHostname = Objects.requireNonNull(hostHostname, "Host hostname must be set");
this.hostFlavor = Objects.requireNonNull(hostFlavor, "Host flavor must be set");
this.hostType = Objects.requireNonNull(hostType, "Host type must be set");
this.provisionedForApplicationId = Objects.requireNonNull(provisionedForApplicationId, "provisionedForApplicationId must be set");
this.exclusiveToApplicationId = Objects.requireNonNull(exclusiveToApplicationId, "exclusiveToApplicationId must be set");
this.exclusiveToClusterType = Objects.requireNonNull(exclusiveToClusterType, "exclusiveToClusterType must be set");
this.nodeHostnames = validateNodeAddresses(nodeHostnames);
Expand All @@ -71,7 +68,6 @@ public Node generateHost(Duration hostTTL) {
Node.Builder builder = Node.create(id, IP.Config.of(List.of(), List.of(), nodeHostnames), hostHostname, hostFlavor, hostType)
.status(Status.initial().withOsVersion(OsVersion.EMPTY.withCurrent(Optional.of(osVersion))))
.cloudAccount(cloudAccount);
provisionedForApplicationId.ifPresent(builder::provisionedForApplicationId);
exclusiveToApplicationId.ifPresent(builder::exclusiveToApplicationId);
exclusiveToClusterType.ifPresent(builder::exclusiveToClusterType);
if ( ! hostTTL.isZero()) builder.hostTTL(hostTTL);
Expand All @@ -89,7 +85,6 @@ public Node generateNode() {
public String hostHostname() { return hostHostname; }
public Flavor hostFlavor() { return hostFlavor; }
public NodeType hostType() { return hostType; }
public Optional<ApplicationId> provisionedForApplicationId() { return provisionedForApplicationId; }
public Optional<ApplicationId> exclusiveToApplicationId() { return exclusiveToApplicationId; }
public Optional<ClusterSpec.Type> exclusiveToClusterType() { return exclusiveToClusterType; }
public List<HostName> nodeHostnames() { return nodeHostnames; }
Expand All @@ -108,7 +103,6 @@ public boolean equals(Object o) {
hostHostname.equals(that.hostHostname) &&
hostFlavor.equals(that.hostFlavor) &&
hostType == that.hostType &&
provisionedForApplicationId.equals(that.provisionedForApplicationId) &&
exclusiveToApplicationId.equals(that.exclusiveToApplicationId) &&
exclusiveToClusterType.equals(that.exclusiveToClusterType) &&
nodeHostnames.equals(that.nodeHostnames) &&
Expand All @@ -119,7 +113,7 @@ public boolean equals(Object o) {

@Override
public int hashCode() {
return Objects.hash(id, hostHostname, hostFlavor, hostType, provisionedForApplicationId, exclusiveToApplicationId, exclusiveToClusterType, nodeHostnames, nodeResources, osVersion, cloudAccount);
return Objects.hash(id, hostHostname, hostFlavor, hostType, exclusiveToApplicationId, exclusiveToClusterType, nodeHostnames, nodeResources, osVersion, cloudAccount);
}

@Override
Expand All @@ -129,7 +123,6 @@ public String toString() {
", hostHostname='" + hostHostname + '\'' +
", hostFlavor=" + hostFlavor +
", hostType=" + hostType +
", provisionedForApplicationId=" + provisionedForApplicationId +
", exclusiveToApplicationId=" + exclusiveToApplicationId +
", exclusiveToClusterType=" + exclusiveToClusterType +
", nodeHostnames=" + nodeHostnames +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ public Runnable provisionHosts(HostProvisionRequest request, Predicate<NodeResou
hostHostname,
hostFlavor,
request.type(),
request.sharing() == HostSharing.provision ? Optional.of(request.owner()) : Optional.empty(),
request.sharing().isExclusiveAllocation() ? Optional.of(request.owner()) : Optional.empty(),
Optional.empty(),
createHostnames(request.type(), hostFlavor, index),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,40 +217,6 @@ private void assertHostSharing(Environment environment, ClusterSpec.Type cluster
assertEquals(expectShared ? 2 : 4, tester.nodeRepository().nodes().list().nodeType(NodeType.host).size());
}

@Test
public void retires_on_exclusivity_violation() {
var tester = tester(false);
tester.flagSource().withJacksonFlag(PermanentFlags.SHARED_HOST.id(), new SharedHost(List.of(new HostResources(1., 1., 1., 1., "fast", "local", null, 10, "x86_64"))), SharedHost.class);
ApplicationId application1 = applicationId();
NodeResources resources = new NodeResources(4, 80, 100, 1);
prepareAndActivate(application1, clusterSpec("mycluster"), 4, 1, resources, tester);
NodeList initialNodes = tester.nodeRepository().nodes().list().owner(application1);
assertEquals(4, initialNodes.size());

// Redeploy same application with exclusive=true
NodeResources smallerExclusiveResources = new NodeResources(2, 20, 50, 1);
prepareAndActivate(application1, clusterSpec("mycluster", true), 4, 1, smallerExclusiveResources, tester);
assertEquals(8, tester.nodeRepository().nodes().list().owner(application1).size());
assertEquals(initialNodes, tester.nodeRepository().nodes().list().owner(application1).retired());

// Redeploy without exclusive again is no-op
prepareAndActivate(application1, clusterSpec("mycluster"), 4, 1, smallerExclusiveResources, tester);
NodeList nodes = tester.nodeRepository().nodes().list();
assertEquals(8, nodes.owner(application1).size());
assertEquals(initialNodes, nodes.owner(application1).retired());

// Remove the old retired nodes and make 2 random parents of current nodes violate exclusivity
tester.patchNodes(initialNodes.asList(), node -> node.removable(true));
NodeList exclusiveViolators = nodes.owner(application1).not().retired().first(2);
List<Node> parents = exclusiveViolators.mapToList(node -> nodes.parentOf(node).get());
tester.patchNode(parents.get(0), node -> node.withProvisionedForApplicationId(ApplicationId.defaultId()));
tester.patchNode(parents.get(1), node -> node.withExclusiveToClusterType(container));

prepareAndActivate(application1, clusterSpec("mycluster"), 4, 1, smallerExclusiveResources, tester);
assertEquals(10, tester.nodeRepository().nodes().list().owner(application1).size());
assertEquals(exclusiveViolators, tester.nodeRepository().nodes().list().owner(application1).retired());
}

@Test
public void node_indices_are_unique_even_when_a_node_is_left_in_reserved_state() {
var tester = tester(true);
Expand Down