Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
4f7caa7
shuffle lowest memory utilization tasks instead of highest
Jan 9, 2020
7cfd013
modify unit test to reflect new shuffling logic
Jan 9, 2020
f21141a
slight refactor, postpone larger refactor
Jan 10, 2020
99b1770
raw refactor of shuffle logic
Jan 13, 2020
48e12a0
cleanup shuffle refactor, wire into SingularityUsagePoller
Jan 13, 2020
bfcae86
method consistency for CPU/memory shuffles
Jan 13, 2020
e5fbb6b
resolve checkstyle violations
Jan 13, 2020
54ef4bc
uniform action id per task shuffle
Jan 13, 2020
48c385f
minimal viable shuffle unit tests
Jan 13, 2020
0b9eafa
fix off by one error in shuffle task count check
Jan 13, 2020
1881eb8
actually count initial # of shuffling tasks per host
Jan 13, 2020
2d6dae8
correctly update overusage, attempt to ensure that slave reaches reso…
Jan 13, 2020
c3ebb94
rearrange helper test methods
Jan 13, 2020
5c03641
fix bug in initial CPU utilization calculation + memory shuffle unit …
Jan 14, 2020
0e344c8
more thorough shuffle unit test
Jan 14, 2020
335c3c0
attempts to use helper methods in shuffle unit testing have failed
Jan 14, 2020
7a5ba4f
memory shuffle should take into account external memory pressure
Jan 14, 2020
52d3dca
add slightly more logging if shuffling >= 1 slave
Jan 14, 2020
3745584
sanity check logging, remove after sanity regained
Jan 15, 2020
40d3b59
move shuffle debug logging
Jan 15, 2020
825b744
self-service shuffle backend
Jan 16, 2020
c7cccf6
refactor self-service shuffle backend into own resource/manager
Jan 16, 2020
00324e6
use dynamic shuffle blacklist when computing possible tasks to shuffle
Jan 16, 2020
d19e42e
self-service shuffle fe api actions
Jan 16, 2020
56fc051
remove unused configuration class
Jan 16, 2020
b194deb
add self-service ui backend classes to modules
Jan 16, 2020
51bb0dd
shuffle opt out status should be attached to RequestParent to be cons…
Jan 16, 2020
40f061a
self-service shuffle: breaking the UI for a good cause
Jan 16, 2020
d05e352
I've made a terrible mistake, but it should be checkpointed just in case
Jan 16, 2020
85cea69
revert SingularityRequestParent changes
Jan 17, 2020
2219bae
new base path for shuffle resource
Jan 17, 2020
f2de75f
unbreak the self-service shuffle ui
Jan 17, 2020
0d8e4bc
workaround API structure
Jan 17, 2020
8bfa0e2
silly mistakes
Jan 21, 2020
018c9e1
preload hardcoded configuration blacklist in manager
Jan 21, 2020
68450b6
deprecate hardcoded configuration blacklist
Jan 21, 2020
98b9953
shuffle blacklist tests
Jan 21, 2020
c776862
Clean up FE code, fix {} in resources
Jan 21, 2020
f336d89
use correct redux flow
Jan 21, 2020
627d77d
testing configuration preloading is surprisingly intricate
Jan 21, 2020
2f31deb
undo formatting changes to request resource
Jan 21, 2020
b3a8112
zkmigration to phase out configuration doNotShuffleRequests
Jan 21, 2020
59fd951
remove stray parameter
Jan 21, 2020
7ca2418
the letter a
Jan 21, 2020
b72447c
improve shuffle cfg test
Jan 22, 2020
345716b
improve shuffle resource authorization
Jan 22, 2020
b501e3b
restore RequestForm to master state
Jan 22, 2020
dea8613
revert back to shuffle opt out button in request header
Jan 22, 2020
f03d22f
restore functionality of shuffle opt out button/modal
Jan 22, 2020
b7b7b33
add shuffle opt out button/modal to task detail page
Jan 22, 2020
c79c7e3
should've reset from staging
Jan 22, 2020
62105d5
update shuffle opt-out modal text
Jan 24, 2020
1b15dbe
use hs_qa request resource version
Jan 24, 2020
8838bbc
resolve merge conflicts with smarter-shuffle
Jan 24, 2020
c08b2f0
resolve merge conflicts with hs_qa
Jan 24, 2020
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 @@ -15,6 +15,7 @@ public class ApiPaths {
public static final String REQUEST_RESOURCE_PATH = API_BASE_PATH + "/requests";
public static final String S3_LOG_RESOURCE_PATH = API_BASE_PATH + "/logs";
public static final String SANDBOX_RESOURCE_PATH = API_BASE_PATH + "/sandbox";
public static final String SHUFFLE_RESOURCE_PATH = API_BASE_PATH + "/shuffle";
public static final String SLAVE_RESOURCE_PATH = API_BASE_PATH + "/slaves";
public static final String STATE_RESOURCE_PATH = API_BASE_PATH + "/state";
public static final String TASK_RESOURCE_PATH = API_BASE_PATH + "/tasks";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public class SingularityConfiguration extends Configuration {

private int maxTasksToShufflePerHost = 2;

@Deprecated
private List<String> doNotShuffleRequests = new ArrayList<>();

private int minutesBeforeNewTaskEligibleForShuffle = 15;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.hubspot.singularity.data;

import com.codahale.metrics.MetricRegistry;
import com.google.inject.Inject;
import com.hubspot.singularity.SingularityCreateResult;
import com.hubspot.singularity.SingularityDeleteResult;
import com.hubspot.singularity.config.SingularityConfiguration;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.utils.ZKPaths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class ShuffleConfigurationManager extends CuratorAsyncManager {
private static final Logger LOG = LoggerFactory.getLogger(RequestManager.class);

private static final String ZK_ROOT_PATH = "/shuffle";
private static final String BLACKLIST_PATH = ZK_ROOT_PATH + "/blacklist";

@Inject
public ShuffleConfigurationManager(
CuratorFramework curator,
SingularityConfiguration configuration,
MetricRegistry metricRegistry
) {
super(curator, configuration, metricRegistry);
}

private String getShuffleBlacklistPath(String requestId) {
return ZKPaths.makePath(BLACKLIST_PATH, requestId);
}

public List<String> getShuffleBlacklist() {
return getChildren(BLACKLIST_PATH);
}

public SingularityCreateResult addToShuffleBlacklist(String requestId) {
return create(getShuffleBlacklistPath(requestId));
}

public SingularityDeleteResult removeFromShuffleBlacklist(String requestId) {
return delete(getShuffleBlacklistPath(requestId));
}

public boolean isOnShuffleBlacklist(String requestId) {
return exists(getShuffleBlacklistPath(requestId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ protected void configure() {
bind(SingularityValidator.class).in(Scopes.SINGLETON);
bind(UserManager.class).in(Scopes.SINGLETON);
bind(UsageManager.class).in(Scopes.SINGLETON);
bind(ShuffleConfigurationManager.class).in(Scopes.SINGLETON);

bind(WebhookManager.class).in(Scopes.SINGLETON);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.hubspot.singularity.data.zkmigrations;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.hubspot.singularity.config.SingularityConfiguration;
import com.hubspot.singularity.data.ShuffleConfigurationManager;

@Singleton
public class ShuffleBlacklistMigration extends ZkDataMigration {
private final SingularityConfiguration configuration;
private final ShuffleConfigurationManager manager;


@Inject
public ShuffleBlacklistMigration(SingularityConfiguration configuration, ShuffleConfigurationManager manager) {
super(16);
this.configuration = configuration;
this.manager = manager;
}

@Override
public void applyMigration() {
for (String requestId : configuration.getDoNotShuffleRequests()) {
manager.addToShuffleBlacklist(requestId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public void configure(Binder binder) {
dataMigrations.addBinding().to(NamespacePendingTasksMigration.class);
dataMigrations.addBinding().to(NamespaceActiveTasksMigration.class);
dataMigrations.addBinding().to(ClearUsagesMigration.class);
dataMigrations.addBinding().to(ShuffleBlacklistMigration.class);
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover from a merge conflict?

import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
Expand Down Expand Up @@ -199,7 +200,6 @@ private void submitRequest(SingularityRequest request, Optional<SingularityReque
}
});


if (oldRequest.get().getInstancesSafe() > rackManager.getNumActive()) {
if (request.isRackSensitive() && configuration.isRebalanceRacksOnScaleDown()) {
rebalancingHelper.rebalanceRacks(request, remainingActiveTasks, user.getEmail());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.hubspot.singularity.resources;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.inject.Inject;
import com.hubspot.singularity.SingularityAuthorizationScope;
import com.hubspot.singularity.SingularityRequestWithState;
import com.hubspot.singularity.SingularityUser;
import com.hubspot.singularity.WebExceptions;
import com.hubspot.singularity.auth.SingularityAuthorizationHelper;
import com.hubspot.singularity.config.ApiPaths;
import com.hubspot.singularity.data.RequestManager;
import com.hubspot.singularity.data.ShuffleConfigurationManager;
import com.ning.http.client.AsyncHttpClient;
import io.dropwizard.auth.Auth;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.tags.Tags;
import org.apache.curator.framework.recipes.leader.LeaderLatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;
import java.util.Optional;

@Path(ApiPaths.SHUFFLE_RESOURCE_PATH)
@Produces({ MediaType.APPLICATION_JSON })
@Schema(title = "Manages shuffle configuration of Singularity.")
@Tags({@Tag(name = "Shuffle")})
public class ShuffleConfigurationResource extends AbstractLeaderAwareResource {
private static final Logger LOG = LoggerFactory.getLogger(ShuffleConfigurationResource.class);

private final ShuffleConfigurationManager shuffleCfgManager;
private final SingularityAuthorizationHelper authorizationHelper;

@Inject
public ShuffleConfigurationResource(
AsyncHttpClient httpClient, LeaderLatch leaderLatch, ObjectMapper objectMapper,
ShuffleConfigurationManager shuffleCfgManager,
SingularityAuthorizationHelper authorizationHelper
) {
super(httpClient, leaderLatch, objectMapper);

this.shuffleCfgManager = shuffleCfgManager;
this.authorizationHelper = authorizationHelper;
}

@GET
@Path("/blacklist")
@Operation(summary = "Retrieve the set of request IDs that should not be shuffled.")
public List<String> getShuffleBlacklist(@Parameter(hidden = true) @Auth SingularityUser user) {
authorizationHelper.checkReadAuthorization(user);
return shuffleCfgManager.getShuffleBlacklist();
}

@GET
@Path("/blacklist/{requestId}")
@Operation(summary = "Check if a request ID is on the shuffle blacklist.")
public boolean isOnShuffleBlacklist(
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "The Request ID to fetch crash loops for") @PathParam("requestId") String requestId
) {
authorizationHelper.checkForAuthorizationByRequestId(requestId, user, SingularityAuthorizationScope.READ);
return shuffleCfgManager.isOnShuffleBlacklist(requestId);
}

@POST
@Path("/blacklist/{requestId}")
@Operation(summary = "Add a request ID to the shuffle blacklist. No effect if already present.")
public void addToShuffleBlacklist(
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "The Request ID to fetch crash loops for") @PathParam("requestId") String requestId
) {
authorizationHelper.checkForAuthorizationByRequestId(requestId, user, SingularityAuthorizationScope.WRITE);
shuffleCfgManager.addToShuffleBlacklist(requestId);
}

@DELETE
@Path("/blacklist/{requestId}")
@Operation(summary = "Remove a request ID from the shuffle blacklist. No effect if not present.")
public void removeFromShuffleBlacklist(
@Parameter(hidden = true) @Auth SingularityUser user,
@Parameter(required = true, description = "The Request ID to fetch crash loops for") @PathParam("requestId") String requestId
) {
authorizationHelper.checkForAuthorizationByRequestId(requestId, user, SingularityAuthorizationScope.WRITE);
shuffleCfgManager.removeFromShuffleBlacklist(requestId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ protected void configure() {
bind(UsageResource.class);
bind(RequestGroupResource.class);
bind(InactiveSlaveResource.class);
bind(ShuffleConfigurationResource.class);
bind(TaskTrackerResource.class);
bind(NotificationsResource.class);

bind(RebalancingHelper.class).in(Scopes.SINGLETON);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ protected void configure() {
bind(SingularityPriorityKillPoller.class).in(Scopes.SINGLETON);
bind(SingularityUsageCleanerPoller.class).in(Scopes.SINGLETON);
bind(SingularityUsagePoller.class).in(Scopes.SINGLETON);
bind(SingularityTaskShuffler.class).in(Scopes.SINGLETON);
bind(SingularityMesosTaskPrioritizer.class).in(Scopes.SINGLETON);
bind(SingularityMesosOfferScheduler.class).in(Scopes.SINGLETON);
bind(SingularityLeaderCache.class).in(Scopes.SINGLETON);
Expand Down
Loading