You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by wf...@apache.org on 2013/12/31 22:20:39 UTC
[46/51] [partial] Rename twitter* and com.twitter to apache and
org.apache directories to preserve all file history before the refactor.
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/HttpStatsFilter.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/HttpStatsFilter.java b/src/main/java/com/twitter/aurora/scheduler/http/HttpStatsFilter.java
deleted file mode 100644
index a846383..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/HttpStatsFilter.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.io.IOException;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
-import com.twitter.common.net.http.filters.AbstractHttpFilter;
-import com.twitter.common.stats.SlidingStats;
-
-/**
- * An HTTP filter that exports counts and timing for requests based on response code.
- */
-public class HttpStatsFilter extends AbstractHttpFilter {
-
- private final LoadingCache<Integer, SlidingStats> counters = CacheBuilder.newBuilder()
- .build(new CacheLoader<Integer, SlidingStats>() {
- @Override public SlidingStats load(Integer status) {
- return new SlidingStats("http_" + status + "_responses", "nanos");
- }
- });
-
- private static class ResponseWithStatus extends HttpServletResponseWrapper {
- // 200 response code is the default if none is explicitly set.
- private int wrappedStatus = 200;
-
- ResponseWithStatus(HttpServletResponse resp) {
- super(resp);
- }
-
- @Override public void setStatus(int sc) {
- super.setStatus(sc);
- wrappedStatus = sc;
- }
-
- @Override public void setStatus(int sc, String sm) {
- super.setStatus(sc, sm);
- wrappedStatus = sc;
- }
- }
-
- @Override
- public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
- throws IOException, ServletException {
-
- long start = System.nanoTime();
- ResponseWithStatus wrapper = new ResponseWithStatus(response);
- chain.doFilter(request, wrapper);
- counters.getUnchecked(wrapper.wrappedStatus).accumulate(System.nanoTime() - start);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/JerseyTemplateServlet.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/JerseyTemplateServlet.java b/src/main/java/com/twitter/aurora/scheduler/http/JerseyTemplateServlet.java
deleted file mode 100644
index 5c13de5..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/JerseyTemplateServlet.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.io.StringWriter;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
-
-import org.antlr.stringtemplate.StringTemplate;
-
-import com.twitter.common.base.Closure;
-import com.twitter.common.util.templating.StringTemplateHelper;
-import com.twitter.common.util.templating.StringTemplateHelper.TemplateException;
-
-/**
- * Base class for common functions needed in a jersey stringtemplate servlet.
- */
-abstract class JerseyTemplateServlet {
-
- private final StringTemplateHelper templateHelper;
-
- JerseyTemplateServlet(String templatePath) {
- templateHelper = new StringTemplateHelper(getClass(), templatePath, true);
- }
-
- protected final Response fillTemplate(Closure<StringTemplate> populator) {
- StringWriter output = new StringWriter();
- try {
- templateHelper.writeTemplate(output, populator);
- } catch (TemplateException e) {
- throw new WebApplicationException(e);
- }
- return Response.ok(output.toString()).build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirect.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirect.java b/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirect.java
deleted file mode 100644
index 20e4446..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirect.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.net.InetSocketAddress;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-import javax.servlet.http.HttpServletRequest;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.net.HostAndPort;
-import com.google.common.util.concurrent.Atomics;
-
-import com.twitter.common.application.modules.LocalServiceRegistry;
-import com.twitter.common.net.pool.DynamicHostSet;
-import com.twitter.common.net.pool.DynamicHostSet.HostChangeMonitor;
-import com.twitter.common.net.pool.DynamicHostSet.MonitorException;
-import com.twitter.thrift.Endpoint;
-import com.twitter.thrift.ServiceInstance;
-
-/**
- * Redirect logic for finding the leading scheduler in the event that this process is not the
- * leader.
- */
-public class LeaderRedirect {
-
- // TODO(wfarner): Should we tie this directly to the producer of the node (HttpModule? It seems
- // like the right thing to do, but would introduce an otherwise unnecessary dependency.
- @VisibleForTesting
- static final String HTTP_PORT_NAME = "http";
-
- private static final Logger LOG = Logger.getLogger(LeaderRedirect.class.getName());
-
- private final LocalServiceRegistry serviceRegistry;
- private final DynamicHostSet<ServiceInstance> schedulers;
-
- private final AtomicReference<ServiceInstance> leader = Atomics.newReference();
-
- @Inject
- LeaderRedirect(LocalServiceRegistry serviceRegistry, DynamicHostSet<ServiceInstance> schedulers) {
- this.serviceRegistry = Preconditions.checkNotNull(serviceRegistry);
- this.schedulers = Preconditions.checkNotNull(schedulers);
- }
-
- /**
- * Initiates the monitor that will watch the scheduler host set.
- *
- * @throws MonitorException If monitoring failed to initialize.
- */
- public void monitor() throws MonitorException {
- schedulers.watch(new SchedulerMonitor());
- }
-
- private Optional<HostAndPort> getLeaderHttp() {
- ServiceInstance leadingScheduler = leader.get();
- if (leadingScheduler == null) {
- return Optional.absent();
- }
-
- if (leadingScheduler.isSetAdditionalEndpoints()) {
- Endpoint leaderHttp = leadingScheduler.getAdditionalEndpoints().get(HTTP_PORT_NAME);
- if (leaderHttp != null && leaderHttp.isSetHost() && leaderHttp.isSetPort()) {
- return Optional.of(HostAndPort.fromParts(leaderHttp.getHost(), leaderHttp.getPort()));
- }
- }
-
- LOG.warning("Leader service instance seems to be incomplete: " + leadingScheduler);
- return Optional.absent();
- }
-
- private Optional<HostAndPort> getLocalHttp() {
- InetSocketAddress localHttp = serviceRegistry.getAuxiliarySockets().get(HTTP_PORT_NAME);
- return (localHttp == null) ? Optional.<HostAndPort>absent()
- : Optional.of(HostAndPort.fromParts(localHttp.getHostName(), localHttp.getPort()));
- }
-
- /**
- * Gets the optional HTTP endpoint that should be redirected to in the event that this
- * scheduler is not the leader.
- *
- * @return Optional redirect target.
- */
- @VisibleForTesting
- Optional<HostAndPort> getRedirect() {
- Optional<HostAndPort> leaderHttp = getLeaderHttp();
- Optional<HostAndPort> localHttp = getLocalHttp();
-
- if (leaderHttp.isPresent()) {
- if (leaderHttp.equals(localHttp)) {
- return Optional.absent();
- } else {
- return leaderHttp;
- }
- } else {
- LOG.info("No leader found, not redirecting.");
- return Optional.absent();
- }
- }
-
- /**
- * Gets the optional redirect URI target in the event that this process is not the leading
- * scheduler.
- *
- * @param req HTTP request.
- * @return An optional redirect destination to route the request to the leading scheduler.
- */
- public Optional<String> getRedirectTarget(HttpServletRequest req) {
- Optional<HostAndPort> redirectTarget = getRedirect();
- if (redirectTarget.isPresent()) {
- HostAndPort target = redirectTarget.get();
- StringBuilder redirect = new StringBuilder()
- .append(req.getScheme())
- .append("://")
- .append(target.getHostText())
- .append(":")
- .append(target.getPort())
- .append(req.getRequestURI());
-
- String queryString = req.getQueryString();
- if (queryString != null) {
- redirect.append("?").append(queryString);
- }
-
- return Optional.of(redirect.toString());
- } else {
- return Optional.absent();
- }
- }
-
- /**
- * Monitor to track scheduler leader changes.
- */
- private class SchedulerMonitor implements HostChangeMonitor<ServiceInstance> {
- @Override public void onChange(ImmutableSet<ServiceInstance> hostSet) {
- switch (hostSet.size()) {
- case 0:
- LOG.warning("No schedulers in host set, will not redirect despite not being leader.");
- leader.set(null);
- break;
-
- case 1:
- LOG.info("Found leader scheduler at " + hostSet);
- leader.set(Iterables.getOnlyElement(hostSet));
- break;
-
- default:
- LOG.severe("Multiple schedulers detected, will not redirect: " + hostSet);
- leader.set(null);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirectFilter.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirectFilter.java b/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirectFilter.java
deleted file mode 100644
index 86f0567..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/LeaderRedirectFilter.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.io.IOException;
-
-import javax.inject.Inject;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-import com.twitter.common.net.http.filters.AbstractHttpFilter;
-
-/**
- * An HTTP filter that will redirect the request to the leading scheduler.
- */
-public class LeaderRedirectFilter extends AbstractHttpFilter {
-
- private final LeaderRedirect redirector;
-
- @Inject
- LeaderRedirectFilter(LeaderRedirect redirector) {
- this.redirector = Preconditions.checkNotNull(redirector);
- }
-
- @Override
- public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
- throws IOException, ServletException {
-
- Optional<String> leaderRedirect = redirector.getRedirectTarget(request);
- if (leaderRedirect.isPresent()) {
- response.sendRedirect(leaderRedirect.get());
- } else {
- chain.doFilter(request, response);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/Maintenance.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/Maintenance.java b/src/main/java/com/twitter/aurora/scheduler/http/Maintenance.java
deleted file mode 100644
index fb71539..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/Maintenance.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-
-import com.twitter.aurora.gen.HostAttributes;
-import com.twitter.aurora.gen.MaintenanceMode;
-import com.twitter.aurora.scheduler.base.Query;
-import com.twitter.aurora.scheduler.base.Tasks;
-import com.twitter.aurora.scheduler.storage.Storage;
-import com.twitter.aurora.scheduler.storage.Storage.StoreProvider;
-import com.twitter.aurora.scheduler.storage.Storage.Work;
-import com.twitter.aurora.scheduler.storage.entities.IScheduledTask;
-
-import static com.twitter.aurora.gen.MaintenanceMode.DRAINED;
-import static com.twitter.aurora.gen.MaintenanceMode.DRAINING;
-import static com.twitter.aurora.gen.MaintenanceMode.SCHEDULED;
-
-/**
- * Servlet that exposes the maintenance state of hosts.
- */
-@Path("/maintenance")
-public class Maintenance {
- private final Storage storage;
-
- @Inject
- Maintenance(Storage storage) {
- this.storage = Preconditions.checkNotNull(storage);
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getHosts() {
- return storage.weaklyConsistentRead(new Work.Quiet<Response>() {
- @Override public Response apply(StoreProvider storeProvider) {
- Multimap<MaintenanceMode, String> hostsByMode =
- Multimaps.transformValues(
- Multimaps.index(storeProvider.getAttributeStore().getHostAttributes(), GET_MODE),
- HOST_NAME);
-
- Map<MaintenanceMode, Object> hosts = Maps.newHashMap();
- hosts.put(DRAINED, ImmutableSet.copyOf(hostsByMode.get(DRAINED)));
- hosts.put(SCHEDULED, ImmutableSet.copyOf(hostsByMode.get(SCHEDULED)));
- hosts.put(DRAINING, getTasksByHosts(storeProvider, hostsByMode.get(DRAINING)).asMap());
- return Response.ok(hosts).build();
- }
- });
- }
-
- private Multimap<String, String> getTasksByHosts(StoreProvider provider, Iterable<String> hosts) {
- ImmutableSet.Builder<IScheduledTask> drainingTasks = ImmutableSet.builder();
- for (String host : hosts) {
- drainingTasks.addAll(provider.getTaskStore().fetchTasks(Query.slaveScoped(host).active()));
- }
- return Multimaps.transformValues(
- Multimaps.index(drainingTasks.build(), TASK_TO_HOST),
- Tasks.SCHEDULED_TO_ID);
- }
-
- private static final Function<IScheduledTask, String> TASK_TO_HOST =
- new Function<IScheduledTask, String>() {
- @Override public String apply(IScheduledTask task) {
- return task.getAssignedTask().getSlaveHost();
- }
- };
-
- private static final Function<HostAttributes, String> HOST_NAME =
- new Function<HostAttributes, String>() {
- @Override public String apply(HostAttributes attributes) {
- return attributes.getHost();
- }
- };
-
- private static final Function<HostAttributes, MaintenanceMode> GET_MODE =
- new Function<HostAttributes, MaintenanceMode>() {
- @Override public MaintenanceMode apply(HostAttributes attrs) {
- return attrs.getMode();
- }
- };
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/Mname.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/Mname.java b/src/main/java/com/twitter/aurora/scheduler/http/Mname.java
deleted file mode 100644
index c97560f..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/Mname.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
-import com.twitter.aurora.scheduler.base.JobKeys;
-import com.twitter.aurora.scheduler.base.Query;
-import com.twitter.aurora.scheduler.storage.Storage;
-import com.twitter.aurora.scheduler.storage.entities.IAssignedTask;
-import com.twitter.aurora.scheduler.storage.entities.IScheduledTask;
-
-import static javax.ws.rs.core.Response.Status.NOT_FOUND;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import static com.twitter.aurora.gen.ScheduleStatus.RUNNING;
-
-/**
- * Simple redirector from the canonical name of a task to its configured HTTP port.
- *
- * <p>Forwards for GET, PUT, POST and DELETE requests using HTTP 307 allowing compliant clients to
- * seamlessly perform re-directed mutations.
- */
-@Path("/mname")
-public class Mname {
-
- private static final Set<String> HTTP_PORT_NAMES = ImmutableSet.of(
- "health", "http", "HTTP", "web");
-
- private final Storage storage;
-
- @Inject
- public Mname(Storage storage) {
- this.storage = checkNotNull(storage);
- }
-
- @GET
- @Produces(MediaType.TEXT_HTML)
- public Response getUsage() {
- return Response
- .status(Status.BAD_REQUEST)
- .entity("<html>Usage: /mname/{role}/{env}/{job}/{instance}</html>")
- .build();
- }
-
- @GET
- @Path("/{role}/{env}/{job}/{instance}/{forward:.+}")
- @Produces(MediaType.TEXT_HTML)
- public Response getWithForwardRequest(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @PathParam("forward") String forward,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.of(forward));
- }
-
- @PUT
- @Path("/{role}/{env}/{job}/{instance}/{forward:.+}")
- @Produces(MediaType.TEXT_HTML)
- public Response putWithForwardRequest(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @PathParam("forward") String forward,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.of(forward));
- }
-
- @POST
- @Path("/{role}/{env}/{job}/{instance}/{forward:.+}")
- @Produces(MediaType.TEXT_HTML)
- public Response postWithForwardRequest(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @PathParam("forward") String forward,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.of(forward));
- }
-
- @DELETE
- @Path("/{role}/{env}/{job}/{instance}/{forward:.+}")
- @Produces(MediaType.TEXT_HTML)
- public Response deleteWithForwardRequest(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @PathParam("forward") String forward,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.of(forward));
- }
-
- @GET
- @Path("/{role}/{env}/{job}/{instance}")
- @Produces(MediaType.TEXT_HTML)
- public Response get(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.<String>absent());
- }
-
- @PUT
- @Path("/{role}/{env}/{job}/{instance}")
- @Produces(MediaType.TEXT_HTML)
- public Response put(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.<String>absent());
- }
-
- @POST
- @Path("/{role}/{env}/{job}/{instance}")
- @Produces(MediaType.TEXT_HTML)
- public Response post(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.<String>absent());
- }
-
- @DELETE
- @Path("/{role}/{env}/{job}/{instance}")
- @Produces(MediaType.TEXT_HTML)
- public Response delete(
- @PathParam("role") String role,
- @PathParam("env") String env,
- @PathParam("job") String job,
- @PathParam("instance") int instanceId,
- @Context UriInfo uriInfo) {
-
- return get(role, env, job, instanceId, uriInfo, Optional.<String>absent());
- }
-
- private Response get(
- String role,
- String env,
- String job,
- int instanceId,
- UriInfo uriInfo,
- Optional<String> forwardRequest) {
-
- IScheduledTask task = Iterables.getOnlyElement(
- Storage.Util.consistentFetchTasks(storage,
- Query.instanceScoped(JobKeys.from(role, env, job), instanceId).active()),
- null);
- if (task == null) {
- return respond(NOT_FOUND, "No such live instance found.");
- }
-
- if (task.getStatus() != RUNNING) {
- return respond(NOT_FOUND, "The selected instance is currently in state " + task.getStatus());
- }
-
- IAssignedTask assignedTask = task.getAssignedTask();
- Optional<Integer> port = getRedirectPort(assignedTask);
- if (!port.isPresent()) {
- return respond(NOT_FOUND, "The task does not have a registered http port.");
- }
-
- UriBuilder redirect = UriBuilder
- .fromPath(forwardRequest.or("/"))
- .scheme("http")
- .host(assignedTask.getSlaveHost())
- .port(port.get());
- for (Entry<String, List<String>> entry : uriInfo.getQueryParameters().entrySet()) {
- for (String value : entry.getValue()) {
- redirect.queryParam(entry.getKey(), value);
- }
- }
-
- return Response.temporaryRedirect(redirect.build()).build();
- }
-
- @VisibleForTesting
- static Optional<Integer> getRedirectPort(IAssignedTask task) {
- Map<String, Integer> ports = task.isSetAssignedPorts()
- ? task.getAssignedPorts() : ImmutableMap.<String, Integer>of();
- for (String httpPortName : HTTP_PORT_NAMES) {
- Integer port = ports.get(httpPortName);
- if (port != null) {
- return Optional.of(port);
- }
- }
- return Optional.absent();
- }
-
- private Response respond(Status status, String message) {
- return Response.status(status).entity(message).build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/Offers.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/Offers.java b/src/main/java/com/twitter/aurora/scheduler/http/Offers.java
deleted file mode 100644
index e90f1cc..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/Offers.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-
-import org.apache.mesos.Protos.Attribute;
-import org.apache.mesos.Protos.ExecutorID;
-import org.apache.mesos.Protos.Offer;
-import org.apache.mesos.Protos.Resource;
-import org.apache.mesos.Protos.Value.Range;
-
-import com.twitter.aurora.scheduler.async.OfferQueue;
-
-/**
- * Servlet that exposes resource offers that the scheduler is currently retaining.
- */
-@Path("/offers")
-public class Offers {
-
- private final OfferQueue offerQueue;
-
- @Inject
- Offers(OfferQueue offerQueue) {
- this.offerQueue = Preconditions.checkNotNull(offerQueue);
- }
-
- /**
- * Dumps the offers queued in the scheduler.
- *
- * @return HTTP response.
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getOffers() {
- return Response.ok(
- FluentIterable.from(offerQueue.getOffers()).transform(TO_BEAN).toList()).build();
- }
-
- private static final Function<ExecutorID, String> EXECUTOR_ID_TOSTRING =
- new Function<ExecutorID, String>() {
- @Override public String apply(ExecutorID id) {
- return id.getValue();
- }
- };
-
- private static final Function<Range, Object> RANGE_TO_BEAN = new Function<Range, Object>() {
- @Override public Object apply(Range range) {
- return range.getBegin() + "-" + range.getEnd();
- }
- };
-
- private static final Function<Attribute, Object> ATTRIBUTE_TO_BEAN =
- new Function<Attribute, Object>() {
- @Override public Object apply(Attribute attr) {
- ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
- builder.put("name", attr.getName());
- if (attr.hasScalar()) {
- builder.put("scalar", attr.getScalar().getValue());
- }
- if (attr.hasRanges()) {
- builder.put("ranges", immutable(attr.getRanges().getRangeList(), RANGE_TO_BEAN));
- }
- if (attr.hasSet()) {
- builder.put("set", attr.getSet().getItemList());
- }
- if (attr.hasText()) {
- builder.put("text", attr.getText().getValue());
- }
- return builder.build();
- }
- };
-
- private static final Function<Resource, Object> RESOURCE_TO_BEAN =
- new Function<Resource, Object>() {
- @Override public Object apply(Resource resource) {
- ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
- builder.put("name", resource.getName());
- if (resource.hasScalar()) {
- builder.put("scalar", resource.getScalar().getValue());
- }
- if (resource.hasRanges()) {
- builder.put("ranges", immutable(resource.getRanges().getRangeList(), RANGE_TO_BEAN));
- }
- if (resource.hasSet()) {
- builder.put("set", resource.getSet().getItemList());
- }
- return builder.build();
- }
- };
-
- private static <A, B> Iterable<B> immutable(Iterable<A> iterable, Function<A, B> transform) {
- return FluentIterable.from(iterable).transform(transform).toList();
- }
-
- private static final Function<Offer, Map<String, ?>> TO_BEAN =
- new Function<Offer, Map<String, ?>>() {
- @Override public Map<String, ?> apply(Offer offer) {
- return ImmutableMap.<String, Object>builder()
- .put("id", offer.getId().getValue())
- .put("framework_id", offer.getFrameworkId().getValue())
- .put("slave_id", offer.getSlaveId().getValue())
- .put("hostname", offer.getHostname())
- .put("resources", immutable(offer.getResourcesList(), RESOURCE_TO_BEAN))
- .put("attributes", immutable(offer.getAttributesList(), ATTRIBUTE_TO_BEAN))
- .put("executor_ids", immutable(offer.getExecutorIdsList(), EXECUTOR_ID_TOSTRING))
- .build();
- }
- };
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/PendingTasks.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/PendingTasks.java b/src/main/java/com/twitter/aurora/scheduler/http/PendingTasks.java
deleted file mode 100644
index 359fb97..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/PendingTasks.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.google.common.base.Preconditions;
-
-import com.twitter.aurora.scheduler.async.TaskGroups;
-
-/**
- * Servlet that exposes detailed information about tasks that are pending.
- */
-@Path("/pendingtasks")
-public class PendingTasks {
-
- private final TaskGroups taskGroups;
-
- @Inject
- PendingTasks(TaskGroups taskGroups) {
- this.taskGroups = Preconditions.checkNotNull(taskGroups);
- }
-
- /**
- * Returns information about pending tasks.
- *
- * @return HTTP response.
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getOffers() {
- return Response.ok(taskGroups.getGroups()).build();
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/Quotas.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/Quotas.java b/src/main/java/com/twitter/aurora/scheduler/http/Quotas.java
deleted file mode 100644
index 1183275..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/Quotas.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-
-import com.twitter.aurora.scheduler.storage.Storage;
-import com.twitter.aurora.scheduler.storage.Storage.StoreProvider;
-import com.twitter.aurora.scheduler.storage.Storage.Work;
-import com.twitter.aurora.scheduler.storage.entities.IQuota;
-
-/**
- * Servlet that exposes allocated resource quotas.
- */
-@Path("/quotas")
-public class Quotas {
-
- private final Storage storage;
-
- @Inject
- Quotas(Storage storage) {
- this.storage = Preconditions.checkNotNull(storage);
- }
-
- /**
- * Dumps allocated resource quotas.
- *
- * @return HTTP response.
- */
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public Response getOffers(@QueryParam("role") final String role) {
- return storage.weaklyConsistentRead(new Work.Quiet<Response>() {
- @Override public Response apply(StoreProvider storeProvider) {
- Map<String, IQuota> quotas;
- if (role == null) {
- quotas = storeProvider.getQuotaStore().fetchQuotas();
- } else {
- Optional<IQuota> quota = storeProvider.getQuotaStore().fetchQuota(role);
- if (quota.isPresent()) {
- quotas = ImmutableMap.of(role, quota.get());
- } else {
- quotas = ImmutableMap.of();
- }
- }
-
- return Response.ok(Maps.transformValues(quotas, TO_BEAN)).build();
- }
- });
- }
-
- private static final Function<IQuota, QuotaBean> TO_BEAN = new Function<IQuota, QuotaBean>() {
- @Override public QuotaBean apply(IQuota quota) {
- return new QuotaBean(quota.getNumCpus(), quota.getRamMb(), quota.getDiskMb());
- }
- };
-
- private static final class QuotaBean {
- private final double cpu;
- private final long ramMb;
- private final long diskMb;
-
- private QuotaBean(double cpu, long ramMb, long diskMb) {
- this.cpu = cpu;
- this.ramMb = ramMb;
- this.diskMb = diskMb;
- }
-
- @JsonProperty("cpu_cores")
- public double getCpu() {
- return cpu;
- }
-
- @JsonProperty("ram_mb")
- public long getRamMb() {
- return ramMb;
- }
-
- @JsonProperty("disk_mb")
- public long getDiskMb() {
- return diskMb;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzHome.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzHome.java b/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzHome.java
deleted file mode 100644
index 07a3259..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzHome.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.google.common.base.Function;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
-import org.antlr.stringtemplate.StringTemplate;
-
-import com.twitter.aurora.scheduler.base.Query;
-import com.twitter.aurora.scheduler.base.Tasks;
-import com.twitter.aurora.scheduler.state.CronJobManager;
-import com.twitter.aurora.scheduler.storage.Storage;
-import com.twitter.aurora.scheduler.storage.entities.IJobConfiguration;
-import com.twitter.aurora.scheduler.storage.entities.IScheduledTask;
-import com.twitter.aurora.scheduler.storage.entities.ITaskConfig;
-import com.twitter.common.base.Closure;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import static com.twitter.common.base.MorePreconditions.checkNotBlank;
-
-/**
- * HTTP interface to serve as a HUD for the aurora scheduler.
- */
-@Path("/scheduler")
-public class SchedulerzHome extends JerseyTemplateServlet {
-
- private static final Function<String, Role> CREATE_ROLE = new Function<String, Role>() {
- @Override public Role apply(String ownerRole) {
- Role role = new Role();
- role.role = ownerRole;
- return role;
- }
- };
-
- private final Storage storage;
- private final CronJobManager cronScheduler;
- private final String clusterName;
-
- /**
- * Creates a new scheduler home servlet.
- *
- * @param storage Backing store to fetch tasks from.
- * @param cronScheduler Cron scheduler.
- * @param clusterName Name of the serving cluster.
- */
- @Inject
- public SchedulerzHome(
- Storage storage,
- CronJobManager cronScheduler,
- @ClusterName String clusterName) {
-
- super("schedulerzhome");
- this.storage = checkNotNull(storage);
- this.cronScheduler = checkNotNull(cronScheduler);
- this.clusterName = checkNotBlank(clusterName);
- }
-
- /**
- * Fetches the scheduler landing page.
- *
- * @return HTTP response.
- */
- @GET
- @Produces(MediaType.TEXT_HTML)
- public Response get() {
- return fillTemplate(new Closure<StringTemplate>() {
- @Override public void execute(StringTemplate template) {
- template.setAttribute("cluster_name", clusterName);
-
- LoadingCache<String, Role> owners =
- CacheBuilder.newBuilder().build(CacheLoader.from(CREATE_ROLE));
-
- // TODO(William Farner): Render this page without an expensive query.
- Set<IScheduledTask> tasks =
- Storage.Util.weaklyConsistentFetchTasks(storage, Query.unscoped());
- for (ITaskConfig task : Iterables.transform(tasks, Tasks.SCHEDULED_TO_INFO)) {
- owners.getUnchecked(task.getOwner().getRole()).accumulate(task);
- }
-
- // Add cron job counts for each role.
- for (IJobConfiguration job : cronScheduler.getJobs()) {
- owners.getUnchecked(job.getOwner().getRole()).accumulate(job);
- }
-
- template.setAttribute(
- "owners",
- DisplayUtils.ROLE_ORDERING.sortedCopy(owners.asMap().values()));
- }
- });
- }
-
- /**
- * Template object to represent a role.
- */
- static class Role {
- private String role;
- private Set<String> jobs = Sets.newHashSet();
- private Set<String> cronJobs = Sets.newHashSet();
-
- private void accumulate(ITaskConfig task) {
- jobs.add(task.getJobName());
- }
-
- private void accumulate(IJobConfiguration job) {
- cronJobs.add(job.getKey().getName());
- }
-
- public String getRole() {
- return role;
- }
-
- public int getJobCount() {
- return jobs.size();
- }
-
- public int getCronJobCount() {
- return cronJobs.size();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzJob.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzJob.java b/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzJob.java
deleted file mode 100644
index 12b0bec..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzJob.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.Ordering;
-
-import org.antlr.stringtemplate.StringTemplate;
-
-import com.twitter.aurora.gen.ScheduleStatus;
-import com.twitter.aurora.gen.apiConstants;
-import com.twitter.aurora.scheduler.base.JobKeys;
-import com.twitter.aurora.scheduler.base.Query;
-import com.twitter.aurora.scheduler.base.Tasks;
-import com.twitter.aurora.scheduler.filter.SchedulingFilter.Veto;
-import com.twitter.aurora.scheduler.metadata.NearestFit;
-import com.twitter.aurora.scheduler.state.CronJobManager;
-import com.twitter.aurora.scheduler.storage.Storage;
-import com.twitter.aurora.scheduler.storage.entities.IAssignedTask;
-import com.twitter.aurora.scheduler.storage.entities.IConstraint;
-import com.twitter.aurora.scheduler.storage.entities.IJobKey;
-import com.twitter.aurora.scheduler.storage.entities.IScheduledTask;
-import com.twitter.aurora.scheduler.storage.entities.ITaskConfig;
-import com.twitter.aurora.scheduler.storage.entities.ITaskConstraint;
-import com.twitter.aurora.scheduler.storage.entities.ITaskEvent;
-import com.twitter.common.base.Closure;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import static com.twitter.aurora.gen.ScheduleStatus.ASSIGNED;
-import static com.twitter.aurora.gen.ScheduleStatus.FAILED;
-import static com.twitter.aurora.gen.ScheduleStatus.FINISHED;
-import static com.twitter.aurora.gen.ScheduleStatus.KILLED;
-import static com.twitter.aurora.gen.ScheduleStatus.KILLING;
-import static com.twitter.aurora.gen.ScheduleStatus.LOST;
-import static com.twitter.aurora.gen.ScheduleStatus.PENDING;
-import static com.twitter.aurora.gen.ScheduleStatus.RUNNING;
-import static com.twitter.aurora.gen.ScheduleStatus.STARTING;
-import static com.twitter.common.base.MorePreconditions.checkNotBlank;
-
-/**
- * HTTP interface to view information about a job in the aurora scheduler.
- */
-@Path("/scheduler/{role}/{environment}/{job}")
-public class SchedulerzJob extends JerseyTemplateServlet {
- private static final String STATUS_FILTER_PARAM = "status";
- private static final String ADMIN_VIEW_PARAM = "admin";
-
- // Pagination controls.
- private static final String OFFSET_PARAM = "o";
- private static final int PAGE_SIZE = 50;
-
- private static final Ordering<IScheduledTask> INSTANCE_ID_COMPARATOR =
- Ordering.natural().onResultOf(Tasks.SCHEDULED_TO_INSTANCE_ID);
-
- private static final Map<ScheduleStatus, Set<ScheduleStatus>> FILTER_MAP =
- ImmutableMap.<ScheduleStatus, Set<ScheduleStatus>>builder()
- .put(PENDING, EnumSet.of(PENDING))
- .put(RUNNING, EnumSet.of(ASSIGNED, STARTING, RUNNING, KILLING))
- .put(FINISHED, EnumSet.of(KILLED, FINISHED))
- .put(FAILED, EnumSet.of(LOST, FAILED))
- .build();
-
- private static final Comparator<IScheduledTask> REVERSE_CHRON_COMPARATOR =
- new Comparator<IScheduledTask>() {
- @Override public int compare(IScheduledTask taskA, IScheduledTask taskB) {
- // Sort in reverse chronological order.
- Iterable<ITaskEvent> taskAEvents = taskA.getTaskEvents();
- Iterable<ITaskEvent> taskBEvents = taskB.getTaskEvents();
-
- boolean taskAHasEvents = taskAEvents != null && !Iterables.isEmpty(taskAEvents);
- boolean taskBHasEvents = taskBEvents != null && !Iterables.isEmpty(taskBEvents);
- if (taskAHasEvents && taskBHasEvents) {
- return Long.signum(Iterables.getLast(taskBEvents).getTimestamp()
- - Iterables.getLast(taskAEvents).getTimestamp());
- } else {
- return 0;
- }
- }
- };
-
- private static final Function<Veto, String> GET_REASON = new Function<Veto, String>() {
- @Override public String apply(Veto veto) {
- return veto.getReason();
- }
- };
-
- // Double percents to escape formatting sequence.
- private static final String PORT_FORMAT = "%%port:%s%%";
- // TODO(William Farner): Search for usage of this, figure out a deprecation strategy to switch
- // to %instance_id%.
- private static final String INSTANCE_ID_REGEXP = "%shard_id%";
- private static final String TASK_ID_REGEXP = "%task_id%";
- private static final String HOST_REGEXP = "%host%";
-
- private static String expandText(String value, IAssignedTask task) {
- String expanded = value
- .replaceAll(INSTANCE_ID_REGEXP, String.valueOf(task.getInstanceId()))
- .replaceAll(TASK_ID_REGEXP, task.getTaskId());
-
- if (task.isSetSlaveHost()) {
- expanded = expanded.replaceAll(HOST_REGEXP, task.getSlaveHost());
- }
-
- // Expand ports.
- if (task.isSetAssignedPorts()) {
- for (Map.Entry<String, Integer> portEntry : task.getAssignedPorts().entrySet()) {
- expanded = expanded.replaceAll(
- String.format(PORT_FORMAT, portEntry.getKey()),
- String.valueOf(portEntry.getValue()));
- }
- }
-
- return expanded;
- }
-
- private final Function<IScheduledTask, Map<String, Object>> taskToStringMap =
- new Function<IScheduledTask, Map<String, Object>>() {
- @Override public Map<String, Object> apply(IScheduledTask scheduledTask) {
- final IAssignedTask task = scheduledTask.getAssignedTask();
- ImmutableMap.Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
- .put("taskId", task.getTaskId())
- .put("instanceId", task.getInstanceId())
- .put("slaveHost", task.isSetSlaveHost() ? task.getSlaveHost() : "")
- .put("status", scheduledTask.getStatus())
- .put("statusTimestamp", Iterables.getLast(scheduledTask.getTaskEvents()).getTimestamp())
- .put("taskEvents", scheduledTask.getTaskEvents());
-
- if (scheduledTask.getStatus() == ScheduleStatus.PENDING) {
- String pendingReason;
- Set<Veto> vetoes = nearestFit.getNearestFit(task.getTaskId());
- if (vetoes.isEmpty()) {
- pendingReason = "No matching hosts.";
- } else {
- pendingReason = Joiner.on(",").join(Iterables.transform(vetoes, GET_REASON));
- }
- builder.put("pendingReason", pendingReason);
- }
-
- Function<String, String> expander = new Function<String, String>() {
- @Override public String apply(String input) {
- return expandText(input, task);
- }
- };
-
- Map<String, String> links = ImmutableMap.of();
- if (apiConstants.LIVE_STATES.contains(scheduledTask.getStatus())) {
- links =
- ImmutableMap.copyOf(Maps.transformValues(task.getTask().getTaskLinks(), expander));
- }
- builder.put("links", links);
- builder.put("executorPort", 1338);
- if (task.isSetSlaveHost()) {
- builder.put("executorUri",
- "http://" + task.getSlaveHost() + ":1338/task/" + task.getTaskId());
- }
- return builder.build();
- }
- };
-
- private final Storage storage;
- private final String clusterName;
- private final NearestFit nearestFit;
- private final CronJobManager cronJobManager;
-
- /**
- * Creates a new job servlet.
- *
- * @param storage Backing store to fetch tasks from.
- * @param clusterName Name of the serving cluster.
- */
- @Inject
- public SchedulerzJob(
- Storage storage,
- CronJobManager cronJobManager,
- @ClusterName String clusterName,
- NearestFit nearestFit) {
-
- super("schedulerzjob");
- this.storage = checkNotNull(storage);
- this.clusterName = checkNotBlank(clusterName);
- this.nearestFit = checkNotNull(nearestFit);
- this.cronJobManager = checkNotNull(cronJobManager);
- }
-
- private static <T> Iterable<T> offsetAndLimit(Iterable<T> iterable, int offset) {
- return ImmutableList.copyOf(Iterables.limit(Iterables.skip(iterable, offset), PAGE_SIZE));
- }
-
- private static String scaleMb(long mb) {
- return (mb >= 1024) ? ((mb / 1024) + " GiB") : (mb + " MiB");
- }
-
- private static final Function<IConstraint, String> DISPLAY_CONSTRAINT =
- new Function<IConstraint, String>() {
- @Override public String apply(IConstraint constraint) {
- StringBuilder sb = new StringBuilder().append(constraint.getName()).append(": ");
- ITaskConstraint taskConstraint = constraint.getConstraint();
- switch (taskConstraint.getSetField()) {
- case VALUE:
- if (taskConstraint.getValue().isNegated()) {
- sb.append("not ");
- }
- sb.append(Joiner.on(", ").join(taskConstraint.getValue().getValues()));
- break;
-
- case LIMIT:
- sb.append("limit ").append(taskConstraint.getLimit().getLimit());
- break;
-
- default:
- sb.append("Unhandled constraint type " + taskConstraint.getSetField());
- }
-
- return sb.toString();
- }
- };
-
- private static final Function<ITaskConfig, SchedulingDetails> CONFIG_TO_DETAILS =
- new Function<ITaskConfig, SchedulingDetails>() {
- @Override public SchedulingDetails apply(ITaskConfig task) {
- String resources = Joiner.on(", ").join(
- "cpu: " + task.getNumCpus(),
- "ram: " + scaleMb(task.getRamMb()),
- "disk: " + scaleMb(task.getDiskMb()));
- ImmutableMap.Builder<String, Object> details = ImmutableMap.<String, Object>builder()
- .put("resources", resources);
- if (!task.getConstraints().isEmpty()) {
- Iterable<String> displayConstraints = FluentIterable.from(task.getConstraints())
- .transform(DISPLAY_CONSTRAINT)
- .toSortedList(Ordering.<String>natural());
- details.put("constraints", Joiner.on(", ").join(displayConstraints));
- }
- if (task.isIsService()) {
- details.put("service", "true");
- }
- if (task.isProduction()) {
- details.put("production", "true");
- }
- if (!task.getRequestedPorts().isEmpty()) {
- details.put("ports",
- Joiner.on(", ").join(ImmutableSortedSet.copyOf(task.getRequestedPorts())));
- }
- if (!task.getPackages().isEmpty()) {
- List<String> packages = Ordering.natural().sortedCopy(
- Iterables.transform(task.getPackages(), TransformationUtils.PACKAGE_TOSTRING));
- details.put(
- "packages",
- Joiner.on(',').join(packages));
- }
- details.put("contact", task.isSetContactEmail() ? task.getContactEmail() : "none");
- return new SchedulingDetails(details.build());
- }
- };
-
- static class SchedulingDetails {
- private final Map<String, Object> details;
-
- SchedulingDetails(ImmutableMap<String, Object> details) {
- this.details = details;
- }
-
- public Map<String, Object> getDetails() {
- return details;
- }
-
- @Override
- public int hashCode() {
- return details.hashCode();
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof SchedulingDetails)) {
- return false;
- }
-
- SchedulingDetails other = (SchedulingDetails) o;
- return other.details.equals(details);
- }
- }
-
-
-
- private static Map<String, SchedulingDetails> buildSchedulingTable(
- Iterable<IAssignedTask> tasks) {
-
- Map<Integer, ITaskConfig> byInstance = Maps.transformValues(
- Maps.uniqueIndex(tasks, Tasks.ASSIGNED_TO_INSTANCE_ID),
- Tasks.ASSIGNED_TO_INFO);
- Map<Integer, SchedulingDetails> detailsByInstance =
- Maps.transformValues(byInstance, CONFIG_TO_DETAILS);
- Multimap<SchedulingDetails, Integer> instancesByDetails = Multimaps.invertFrom(
- Multimaps.forMap(detailsByInstance), HashMultimap.<SchedulingDetails, Integer>create());
- Map<SchedulingDetails, String> instanceStringsByDetails =
- Maps.transformValues(instancesByDetails.asMap(), TransformationUtils.INSTANCES_TOSTRING);
- return HashBiMap.create(instanceStringsByDetails).inverse();
- }
-
- /**
- * Fetches the landing page for a job within a role.
- *
- * @return HTTP response.
- */
- @GET
- @Produces(MediaType.TEXT_HTML)
- public Response get(
- @PathParam("role") final String role,
- @PathParam("environment") final String environment,
- @PathParam("job") final String job,
- @QueryParam(OFFSET_PARAM) final int offset,
- @QueryParam(STATUS_FILTER_PARAM) final String filterArg,
- @QueryParam(ADMIN_VIEW_PARAM) final String adminView) {
-
- return fillTemplate(new Closure<StringTemplate>() {
- @Override public void execute(StringTemplate template) {
- template.setAttribute("cluster_name", clusterName);
- template.setAttribute(ADMIN_VIEW_PARAM, adminView != null);
- IJobKey jobKey = JobKeys.from(role, environment, job);
-
- boolean isCron = cronJobManager.hasJob(jobKey);
- template.setAttribute("is_cron", isCron);
-
- ScheduleStatus statusFilter = null;
- if (filterArg != null) {
- template.setAttribute(STATUS_FILTER_PARAM, filterArg);
-
- try {
- statusFilter = ScheduleStatus.valueOf(filterArg.toUpperCase());
- } catch (IllegalArgumentException e) {
- template.setAttribute("exception", "Invalid status type: " + filterArg);
- return;
- }
- }
-
- template.setAttribute("role", role);
- template.setAttribute("environment", environment);
- template.setAttribute("job", job);
- template.setAttribute("statsUrl", DisplayUtils.getJobDashboardUrl(jobKey));
- boolean hasMore = false;
-
- Query.Builder builder = Query.jobScoped(JobKeys.from(role, environment, job));
-
- Optional<Query.Builder> activeQuery = Optional.absent();
- Optional<Query.Builder> completedQuery = Optional.absent();
- if (statusFilter != null) {
- Collection<ScheduleStatus> queryStatuses = FILTER_MAP.get(statusFilter);
- if (Tasks.isActive(statusFilter)) {
- activeQuery = Optional.of(builder.byStatus(queryStatuses));
- } else {
- completedQuery = Optional.of(builder.byStatus(queryStatuses));
- }
- } else {
- activeQuery = Optional.of(builder.active());
- completedQuery = Optional.of(builder.terminal());
- }
-
- if (activeQuery.isPresent()) {
- Set<IScheduledTask> activeTasks =
- Storage.Util.weaklyConsistentFetchTasks(storage, activeQuery.get());
- List<IScheduledTask> liveTasks = INSTANCE_ID_COMPARATOR.sortedCopy(activeTasks);
- template.setAttribute("activeTasks",
- ImmutableList.copyOf(
- Iterables.transform(offsetAndLimit(liveTasks, offset), taskToStringMap)));
- hasMore = hasMore || (liveTasks.size() > (offset + PAGE_SIZE));
- template.setAttribute("schedulingDetails",
- buildSchedulingTable(Iterables.transform(liveTasks, Tasks.SCHEDULED_TO_ASSIGNED)));
- }
- if (completedQuery.isPresent()) {
- List<IScheduledTask> completedTasks = Lists.newArrayList(
- Storage.Util.weaklyConsistentFetchTasks(storage, completedQuery.get()));
- Collections.sort(completedTasks, REVERSE_CHRON_COMPARATOR);
- template.setAttribute("completedTasks",
- ImmutableList.copyOf(
- Iterables.transform(offsetAndLimit(completedTasks, offset), taskToStringMap)));
- hasMore = hasMore || (completedTasks.size() > (offset + PAGE_SIZE));
- }
-
- template.setAttribute("offset", offset);
- if (offset > 0) {
- template.setAttribute("prevOffset", Math.max(0, offset - PAGE_SIZE));
- }
- if (hasMore) {
- template.setAttribute("nextOffset", offset + PAGE_SIZE);
- }
- }
- });
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzRole.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzRole.java b/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzRole.java
deleted file mode 100644
index 756c672..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/SchedulerzRole.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Ordering;
-import com.google.common.collect.Sets;
-
-import org.antlr.stringtemplate.StringTemplate;
-
-import com.twitter.aurora.gen.CronCollisionPolicy;
-import com.twitter.aurora.gen.ScheduleStatus;
-import com.twitter.aurora.gen.apiConstants;
-import com.twitter.aurora.scheduler.base.JobKeys;
-import com.twitter.aurora.scheduler.base.Query;
-import com.twitter.aurora.scheduler.base.Tasks;
-import com.twitter.aurora.scheduler.cron.CronPredictor;
-import com.twitter.aurora.scheduler.quota.QuotaManager;
-import com.twitter.aurora.scheduler.quota.Quotas;
-import com.twitter.aurora.scheduler.state.CronJobManager;
-import com.twitter.aurora.scheduler.storage.Storage;
-import com.twitter.aurora.scheduler.storage.entities.IJobConfiguration;
-import com.twitter.aurora.scheduler.storage.entities.IJobKey;
-import com.twitter.aurora.scheduler.storage.entities.IQuota;
-import com.twitter.aurora.scheduler.storage.entities.IScheduledTask;
-import com.twitter.aurora.scheduler.storage.entities.ITaskConfig;
-import com.twitter.common.base.Closure;
-import com.twitter.common.quantity.Amount;
-import com.twitter.common.quantity.Time;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import static com.twitter.aurora.scheduler.base.Tasks.GET_STATUS;
-import static com.twitter.aurora.scheduler.base.Tasks.LATEST_ACTIVITY;
-import static com.twitter.common.base.MorePreconditions.checkNotBlank;
-
-/**
- * HTTP interface to provide information about jobs for a specific role.
- */
-@Path("/scheduler/{role}")
-public class SchedulerzRole extends JerseyTemplateServlet {
-
- private static final List<ScheduleStatus> STATUSES = ImmutableList.<ScheduleStatus>builder()
- .addAll(apiConstants.TERMINAL_STATES)
- .addAll(apiConstants.ACTIVE_STATES)
- .build();
-
- // The freshest task is the latest active task
- // or the latest inactive task if no active task exists.
- private static final Ordering<IScheduledTask> FRESH_TASK_ORDER =
- Ordering.explicit(STATUSES).onResultOf(GET_STATUS).compound(LATEST_ACTIVITY);
-
- @VisibleForTesting
- static IScheduledTask getFreshestTask(Iterable<IScheduledTask> tasks) {
- return FRESH_TASK_ORDER.max(tasks);
- }
-
- private final Storage storage;
- private final CronJobManager cronJobManager;
- private final CronPredictor cronPredictor;
- private final String clusterName;
- private final QuotaManager quotaManager;
-
- @Inject
- SchedulerzRole(
- Storage storage,
- CronJobManager cronJobManager,
- CronPredictor cronPredictor,
- @ClusterName String clusterName,
- QuotaManager quotaManager) {
-
- super("schedulerzrole");
- this.storage = checkNotNull(storage);
- this.cronJobManager = checkNotNull(cronJobManager);
- this.cronPredictor = checkNotNull(cronPredictor);
- this.clusterName = checkNotBlank(clusterName);
- this.quotaManager = checkNotNull(quotaManager);
- }
-
- /**
- * Fetches the landing page for a role.
- *
- * @return HTTP response.
- */
- @GET
- @Produces(MediaType.TEXT_HTML)
- public Response get(@PathParam("role") final String role) {
- return processRequest(Optional.of(role), Optional.<String>absent());
- }
-
- private Response processRequest(final Optional<String> role, final Optional<String> environment) {
- return fillTemplate(new Closure<StringTemplate>() {
- @Override public void execute(StringTemplate template) {
-
- if (!role.isPresent()) {
- template.setAttribute("exception", "Please specify a user.");
- return;
- }
-
- Map<IJobKey, Map<?, ?>> cronJobs = fetchCronJobsBy(role.get(), environment);
- List<Job> jobs = fetchJobsBy(role.get(), environment, cronJobs);
- if (jobs.isEmpty() && cronJobs.isEmpty()) {
- String msg = "No jobs found for role " + role.get()
- + (environment.isPresent() ? (" and environment " + environment.get()) : "");
- throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity(msg).build());
- }
-
- template.setAttribute("cluster_name", clusterName);
- template.setAttribute("role", role.get());
- template.setAttribute("environment", environment.orNull());
- template.setAttribute("jobs", jobs);
- template.setAttribute("cronJobs", cronJobs.values());
-
- // TODO(Suman Karumuri): In future compute consumption for role and environment.
- template.setAttribute("prodResourcesUsed", quotaManager.getConsumption(role.get()));
- template.setAttribute("nonProdResourcesUsed", getNonProdConsumption(role.get()));
- template.setAttribute("resourceQuota", getQuota(role.get()));
- }
- });
- }
-
- private IQuota getQuota(final String role) {
- return Storage.Util.consistentFetchQuota(storage, role).or(Quotas.noQuota());
- }
-
- private IQuota getNonProdConsumption(String role) {
- FluentIterable<ITaskConfig> tasks = FluentIterable
- .from(Storage.Util.weaklyConsistentFetchTasks(storage, Query.roleScoped(role).active()))
- .transform(Tasks.SCHEDULED_TO_INFO)
- .filter(Predicates.not(Tasks.IS_PRODUCTION));
-
- return Quotas.fromTasks(tasks);
- }
-
- /**
- * Display jobs for a role and environment.
- */
- @Path("/{environment}")
- @GET
- @Produces(MediaType.TEXT_HTML)
- public Response get(
- @PathParam("role") final String role,
- @PathParam("environment") final String environment) {
-
- Optional<String> env = Optional.of(environment);
- if (env.isPresent() && env.get().isEmpty()) {
- env = Optional.absent();
- }
-
- return processRequest(Optional.of(role), env);
- }
-
- private Map<IJobKey, Map<?, ?>> fetchCronJobsBy(
- final String role,
- final Optional<String> environment) {
-
- Predicate<IJobConfiguration> byRoleEnv = new Predicate<IJobConfiguration>() {
- @Override public boolean apply(IJobConfiguration job) {
- boolean roleMatch = job.getOwner().getRole().equals(role);
- boolean envMatch = !environment.isPresent()
- || job.getKey().getEnvironment().equals(environment.get());
- return roleMatch && envMatch;
- }
- };
-
- Iterable<IJobConfiguration> jobs = FluentIterable
- .from(cronJobManager.getJobs())
- .filter(byRoleEnv);
-
- return Maps.transformValues(Maps.uniqueIndex(jobs, JobKeys.FROM_CONFIG),
- new Function<IJobConfiguration, Map<?, ?>>() {
- @Override public Map<?, ?> apply(IJobConfiguration job) {
- return ImmutableMap.<Object, Object>builder()
- .put("jobKey", job.getKey())
- .put("name", job.getKey().getName())
- .put("environment", job.getKey().getEnvironment())
- .put("pendingTaskCount", job.getInstanceCount())
- .put("cronSchedule", job.getCronSchedule())
- .put("nextRun", cronPredictor.predictNextRun(job.getCronSchedule()).getTime())
- .put("cronCollisionPolicy", cronCollisionPolicy(job))
- .put("packages", getPackages(job))
- .build();
- }
- });
- }
-
- private static CronCollisionPolicy cronCollisionPolicy(IJobConfiguration jobConfiguration) {
- return CronJobManager.orDefault(jobConfiguration.getCronCollisionPolicy());
- }
-
- private static String getPackages(IJobConfiguration job) {
- Set<String> packages = Sets.newHashSet();
-
- // Insert all packages for all tasks in the set to eliminate duplicates
- ITaskConfig task = job.getTaskConfig();
- if (!task.getPackages().isEmpty()) {
- packages.addAll(Lists.newArrayList(
- Iterables.transform(task.getPackages(), TransformationUtils.PACKAGE_TOSTRING)));
- }
- return Joiner.on(',').join(packages);
- }
-
- private List<Job> fetchJobsBy(
- final String role,
- final Optional<String> environment,
- final Map<IJobKey, Map<?, ?>> cronJobs) {
-
- final Function<Map.Entry<IJobKey, Collection<IScheduledTask>>, Job> toJob =
- new Function<Map.Entry<IJobKey, Collection<IScheduledTask>>, Job>() {
- @Override public Job apply(Map.Entry<IJobKey, Collection<IScheduledTask>> tasksByJobKey) {
- IJobKey jobKey = tasksByJobKey.getKey();
- Collection<IScheduledTask> tasks = tasksByJobKey.getValue();
-
- Job job = new Job();
- job.environment = jobKey.getEnvironment();
- job.name = jobKey.getName();
-
- // Pick the freshest task's config and associate it with the job.
- ITaskConfig freshestConfig = getFreshestTask(tasks).getAssignedTask().getTask();
- job.production = freshestConfig.isProduction();
-
- // TODO(Suman Karumuri): Add a source/job type to TaskConfig and replace logic below
- if (freshestConfig.isIsService()) {
- job.type = JobType.SERVICE;
- } else if (cronJobs.containsKey(jobKey)) {
- job.type = JobType.CRON;
- } else {
- job.type = JobType.ADHOC;
- }
-
- for (IScheduledTask task : tasks) {
- switch (task.getStatus()) {
- case INIT:
- case PENDING:
- job.pendingTaskCount++;
- break;
-
- case ASSIGNED:
- case STARTING:
- case RESTARTING:
- case RUNNING:
- case KILLING:
- case PREEMPTING:
- job.activeTaskCount++;
- break;
-
- case KILLED:
- case FINISHED:
- job.finishedTaskCount++;
- break;
-
- case LOST:
- case FAILED:
- case UNKNOWN:
- job.failedTaskCount++;
- Date now = new Date();
- long elapsedMillis = now.getTime()
- - Iterables.getLast(task.getTaskEvents()).getTimestamp();
-
- if (Amount.of(elapsedMillis, Time.MILLISECONDS).as(Time.HOURS) < 6) {
- job.recentlyFailedTaskCount++;
- }
- break;
-
- default:
- throw new IllegalArgumentException("Unsupported status: " + task.getStatus());
- }
- }
-
- return job;
- }
- };
-
- Query.Builder query = environment.isPresent()
- ? Query.envScoped(role, environment.get())
- : Query.roleScoped(role);
-
- Multimap<IJobKey, IScheduledTask> tasks =
- Tasks.byJobKey(Storage.Util.weaklyConsistentFetchTasks(storage, query));
-
- Iterable<Job> jobs = FluentIterable
- .from(tasks.asMap().entrySet())
- .transform(toJob);
-
- return DisplayUtils.JOB_ORDERING.sortedCopy(jobs);
- }
-
- /**
- * Template object to represent a job.
- */
- static class Job {
- private String name;
- private String environment;
- private int pendingTaskCount = 0;
- private int activeTaskCount = 0;
- private int finishedTaskCount = 0;
- private int failedTaskCount = 0;
- private int recentlyFailedTaskCount = 0;
- private boolean production = false;
- private JobType type;
-
- public String getName() {
- return name;
- }
-
- public String getEnvironment() {
- return environment;
- }
-
- public int getPendingTaskCount() {
- return pendingTaskCount;
- }
-
- public int getActiveTaskCount() {
- return activeTaskCount;
- }
-
- public int getFinishedTaskCount() {
- return finishedTaskCount;
- }
-
- public int getFailedTaskCount() {
- return failedTaskCount;
- }
-
- public int getRecentlyFailedTaskCount() {
- return recentlyFailedTaskCount;
- }
-
- public boolean getProduction() {
- return production;
- }
-
- public String getType() {
- return type.toString();
- }
- }
-
- static enum JobType {
- ADHOC("adhoc"), CRON("cron"), SERVICE("service");
-
- private String jobType;
-
- private JobType(String jobType) {
- this.jobType = jobType;
- }
-
- public String toString() {
- return jobType;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/bc1635df/src/main/java/com/twitter/aurora/scheduler/http/ServletModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/com/twitter/aurora/scheduler/http/ServletModule.java b/src/main/java/com/twitter/aurora/scheduler/http/ServletModule.java
deleted file mode 100644
index 825e2e1..0000000
--- a/src/main/java/com/twitter/aurora/scheduler/http/ServletModule.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.twitter.aurora.scheduler.http;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.io.Resources;
-import com.google.common.net.MediaType;
-import com.google.inject.AbstractModule;
-import com.google.inject.Key;
-import com.google.inject.TypeLiteral;
-import com.google.inject.servlet.GuiceFilter;
-import com.sun.jersey.api.container.filter.GZIPContentEncodingFilter;
-import com.sun.jersey.guice.JerseyServletModule;
-import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
-
-import com.twitter.aurora.scheduler.quota.QuotaManager;
-import com.twitter.aurora.scheduler.state.CronJobManager;
-import com.twitter.aurora.scheduler.state.SchedulerCore;
-import com.twitter.common.application.http.Registration;
-import com.twitter.common.application.modules.LifecycleModule;
-import com.twitter.common.application.modules.LocalServiceRegistry;
-import com.twitter.common.base.ExceptionalCommand;
-import com.twitter.common.net.pool.DynamicHostSet;
-import com.twitter.common.net.pool.DynamicHostSet.MonitorException;
-import com.twitter.thrift.ServiceInstance;
-
-import static com.sun.jersey.api.core.ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS;
-import static com.sun.jersey.api.core.ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS;
-import static com.sun.jersey.api.json.JSONConfiguration.FEATURE_POJO_MAPPING;
-
-/**
- * Binding module for scheduler HTTP servlets.
- */
-public class ServletModule extends AbstractModule {
-
- private static final Map<String, String> CONTAINER_PARAMS = ImmutableMap.of(
- FEATURE_POJO_MAPPING, Boolean.TRUE.toString(),
- PROPERTY_CONTAINER_REQUEST_FILTERS, GZIPContentEncodingFilter.class.getName(),
- PROPERTY_CONTAINER_RESPONSE_FILTERS, GZIPContentEncodingFilter.class.getName());
-
- @Override
- protected void configure() {
- requireBinding(SchedulerCore.class);
- requireBinding(CronJobManager.class);
- requireBinding(Key.get(String.class, ClusterName.class));
- requireBinding(QuotaManager.class);
-
- // Bindings required for the leader redirector.
- requireBinding(LocalServiceRegistry.class);
- requireBinding(Key.get(new TypeLiteral<DynamicHostSet<ServiceInstance>>() { }));
- Registration.registerServletFilter(binder(), GuiceFilter.class, "/*");
- install(new JerseyServletModule() {
- private void registerJerseyEndpoint(String indexPath, Class<?>... servlets) {
- filter(indexPath + "*").through(LeaderRedirectFilter.class);
- filter(indexPath + "*").through(GuiceContainer.class, CONTAINER_PARAMS);
- Registration.registerEndpoint(binder(), indexPath);
- for (Class<?> servlet : servlets) {
- bind(servlet);
- }
- }
-
- @Override protected void configureServlets() {
- bind(HttpStatsFilter.class).in(Singleton.class);
- filter("/scheduler*").through(HttpStatsFilter.class);
- bind(LeaderRedirectFilter.class).in(Singleton.class);
- registerJerseyEndpoint("/cron", Cron.class);
- registerJerseyEndpoint("/maintenance", Maintenance.class);
- registerJerseyEndpoint("/mname", Mname.class);
- registerJerseyEndpoint("/offers", Offers.class);
- registerJerseyEndpoint("/pendingtasks", PendingTasks.class);
- registerJerseyEndpoint("/quotas", Quotas.class);
- registerJerseyEndpoint(
- "/scheduler",
- SchedulerzHome.class,
- SchedulerzRole.class,
- SchedulerzJob.class);
- registerJerseyEndpoint("/slaves", Slaves.class);
- registerJerseyEndpoint("/structdump", StructDump.class);
- registerJerseyEndpoint("/utilization", Utilization.class);
- }
- });
-
- // Static assets.
- registerJQueryAssets();
- registerBootstrapAssets();
-
- registerAsset("assets/util.js", "/js/util.js");
- registerAsset("assets/dictionary.js", "/js/dictionary.js");
- registerAsset("assets/images/viz.png", "/images/viz.png");
- registerAsset("assets/images/aurora.png", "/images/aurora.png");
-
- // Register datatables
- registerAsset("assets/datatables/css/jquery.dataTables.css", "/css/jquery.dataTables.css");
- registerAsset("assets/datatables/images/back_disabled.png", "/images/back_disabled.png");
- registerAsset(
- "assets/datatables/images/back_enabled_hover.png",
- "/images/back_enabled_hover.png");
- registerAsset("assets/datatables/images/back_enabled.png", "/images/back_enabled.png");
- registerAsset(
- "assets/datatables/images/forward_disabled.png",
- "/images/forward_disabled.png");
- registerAsset(
- "assets/datatables/images/forward_enabled_hover.png",
- "/images/forward_enabled_hover.png");
- registerAsset(
- "assets/datatables/images/forward_enabled.png",
- "/images/forward_enabled.png");
- registerAsset(
- "assets/datatables/images/sort_asc_disabled.png",
- "/images/sort_asc_disabled.png");
- registerAsset("assets/datatables/images/sort_asc.png", "/images/sort_asc.png");
- registerAsset("assets/datatables/images/sort_both.png", "/images/sort_both.png");
- registerAsset(
- "assets/datatables/images/sort_desc_disabled.png",
- "/images/sort_desc_disabled.png");
- registerAsset("assets/datatables/images/sort_desc.png", "/images/sort_desc.png");
- registerAsset(
- "assets/datatables/js/jquery.dataTables.min.js",
- "/js/jquery.dataTables.min.js");
- registerAsset(
- "assets/datatables/js/dataTables.bootstrap.js",
- "/js/dataTables.bootstrap.js");
- registerAsset(
- "assets/datatables/js/dataTables.localstorage.js",
- "/js/dataTables.localstorage.js");
- registerAsset(
- "assets/datatables/js/dataTables.htmlNumberType.js",
- "/js/dataTables.htmlNumberType.js");
-
- bind(LeaderRedirect.class).in(Singleton.class);
- LifecycleModule.bindStartupAction(binder(), RedirectMonitor.class);
- }
-
- private void registerJQueryAssets() {
- registerAsset("bower_components/jquery/jquery.js", "/js/jquery.min.js", false);
- }
-
- private void registerBootstrapAssets() {
- final String BOOTSTRAP_PATH = "bower_components/bootstrap.css/";
-
- registerAsset(BOOTSTRAP_PATH + "js/bootstrap.min.js", "/js/bootstrap.min.js", false);
- registerAsset(BOOTSTRAP_PATH + "css/bootstrap.min.css", "/css/bootstrap.min.css", false);
- registerAsset(BOOTSTRAP_PATH + "css/bootstrap-responsive.min.css",
- "/css/bootstrap-responsive.min.css",
- false);
- registerAsset(BOOTSTRAP_PATH + "img/glyphicons-halflings-white.png",
- "/img/glyphicons-halflings-white.png",
- false);
- registerAsset(BOOTSTRAP_PATH + "img/glyphicons-halflings.png",
- "/img/glyphicons-halflings.png",
- false);
- }
-
- private void registerAsset(String resourceLocation, String registerLocation) {
- registerAsset(resourceLocation, registerLocation, true);
- }
-
- private void registerAsset(String resourceLocation, String registerLocation, boolean isRelative) {
- String mediaType = getMediaType(registerLocation).toString();
-
- if (isRelative) {
- Registration.registerHttpAsset(
- binder(),
- registerLocation,
- ServletModule.class,
- resourceLocation,
- mediaType,
- true);
- } else {
- Registration.registerHttpAsset(
- binder(),
- registerLocation,
- Resources.getResource(resourceLocation),
- mediaType,
- true);
- }
- }
-
- private MediaType getMediaType(String filePath) {
- if (filePath.endsWith(".png")) {
- return MediaType.PNG;
- } else if (filePath.endsWith(".js")) {
- return MediaType.JAVASCRIPT_UTF_8;
- } else if (filePath.endsWith(".html")) {
- return MediaType.HTML_UTF_8;
- } else if (filePath.endsWith(".css")) {
- return MediaType.CSS_UTF_8;
- } else {
- throw new IllegalArgumentException("Could not determine media type for " + filePath);
- }
- }
-
- static class RedirectMonitor implements ExceptionalCommand<MonitorException> {
-
- private final LeaderRedirect redirector;
-
- @Inject
- RedirectMonitor(LeaderRedirect redirector) {
- this.redirector = Preconditions.checkNotNull(redirector);
- }
-
- @Override public void execute() throws MonitorException {
- redirector.monitor();
- }
- }
-}