blob: 184ff4961bf293e8b82fce453c3dcf8be98aee28 [file] [log] [blame]
/**
* 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 org.apache.aurora.scheduler.app;
import java.util.List;
import javax.inject.Singleton;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import org.apache.aurora.GuiceUtils;
import org.apache.aurora.common.inject.TimedInterceptor;
import org.apache.aurora.common.quantity.Time;
import org.apache.aurora.common.stats.Stats;
import org.apache.aurora.common.stats.StatsProvider;
import org.apache.aurora.common.util.Clock;
import org.apache.aurora.gen.Container;
import org.apache.aurora.gen.Container._Fields;
import org.apache.aurora.gen.DockerParameter;
import org.apache.aurora.scheduler.SchedulerModule;
import org.apache.aurora.scheduler.SchedulerServicesModule;
import org.apache.aurora.scheduler.app.SchedulerMain.Options.DriverKind;
import org.apache.aurora.scheduler.async.AsyncModule;
import org.apache.aurora.scheduler.config.CliOptions;
import org.apache.aurora.scheduler.config.splitters.CommaSplitter;
import org.apache.aurora.scheduler.config.validators.PositiveNumber;
import org.apache.aurora.scheduler.configuration.ConfigurationManager;
import org.apache.aurora.scheduler.configuration.ConfigurationManager.ConfigurationManagerSettings;
import org.apache.aurora.scheduler.events.NotifyingSchedulingFilter;
import org.apache.aurora.scheduler.events.PubsubEventModule;
import org.apache.aurora.scheduler.filter.SchedulingFilter;
import org.apache.aurora.scheduler.filter.SchedulingFilterImpl;
import org.apache.aurora.scheduler.http.JettyServerModule;
import org.apache.aurora.scheduler.maintenance.MaintenanceModule;
import org.apache.aurora.scheduler.mesos.SchedulerDriverModule;
import org.apache.aurora.scheduler.metadata.MetadataModule;
import org.apache.aurora.scheduler.offers.OfferManagerModule;
import org.apache.aurora.scheduler.preemptor.PreemptorModule;
import org.apache.aurora.scheduler.pruning.PruningModule;
import org.apache.aurora.scheduler.quota.QuotaModule;
import org.apache.aurora.scheduler.reconciliation.ReconciliationModule;
import org.apache.aurora.scheduler.scheduling.SchedulingModule;
import org.apache.aurora.scheduler.sla.SlaModule;
import org.apache.aurora.scheduler.state.StateModule;
import org.apache.aurora.scheduler.stats.AsyncStatsModule;
import org.apache.aurora.scheduler.thrift.Thresholds;
import org.apache.aurora.scheduler.updater.UpdaterModule;
import org.apache.mesos.Scheduler;
import static java.util.Objects.requireNonNull;
/**
* Binding module for the aurora scheduler application.
*/
public class AppModule extends AbstractModule {
@Parameters(separators = "=")
public static class Options {
@Parameter(names = "-max_tasks_per_job",
validateValueWith = PositiveNumber.class,
description = "Maximum number of allowed tasks in a single job.")
public int maxTasksPerJob = 4000;
@Parameter(names = "-max_update_instance_failures",
validateValueWith = PositiveNumber.class,
description = "Upper limit on the number of "
+ "failures allowed during a job update. This helps cap potentially unbounded entries"
+ " into storage.")
public int maxUpdateInstanceFailures = maxTasksPerJob * 5;
// TODO(wfarner): From jcommander docs - "Also, note that only List<String> is allowed for
// parameters that define an arity. You will have to convert these values yourself..."
@Parameter(names = "-allowed_container_types",
description = "Container types that are allowed to be used by jobs.",
splitter = CommaSplitter.class)
public List<_Fields> allowedContainerTypes = ImmutableList.of(Container._Fields.MESOS);
@Parameter(names = "-allow_docker_parameters",
description = "Allow to pass docker container parameters in the job.",
arity = 1)
public boolean enableDockerParameters = false;
@Parameter(names = "-default_docker_parameters",
description =
"Default docker parameters for any job that does not explicitly declare parameters.",
splitter = CommaSplitter.class)
public List<DockerParameter> defaultDockerParameters = ImmutableList.of();
@Parameter(names = "-require_docker_use_executor",
description = "If false, Docker tasks may run without an executor (EXPERIMENTAL)",
arity = 1)
public boolean requireDockerUseExecutor = true;
@Parameter(names = "-enable_mesos_fetcher", description = "Allow jobs to pass URIs "
+ "to the Mesos Fetcher. Note that enabling this feature could pose "
+ "a privilege escalation threat.",
arity = 1)
public boolean enableMesosFetcher = false;
@Parameter(names = "-allow_container_volumes",
description = "Allow passing in volumes in the job. Enabling this could pose a privilege "
+ "escalation threat.",
arity = 1)
public boolean allowContainerVolumes = false;
@Parameter(names = "-allowed_job_environments", description = "Regular expression describing "
+ "the environments that are allowed to be used by jobs.")
public String allowedJobEnvironments = ConfigurationManager.DEFAULT_ALLOWED_JOB_ENVIRONMENTS;
}
private final ConfigurationManagerSettings configurationManagerSettings;
private final DriverKind kind;
private final CliOptions options;
@VisibleForTesting
public AppModule(
ConfigurationManagerSettings configurationManagerSettings,
DriverKind kind,
CliOptions options) {
this.configurationManagerSettings = requireNonNull(configurationManagerSettings);
this.kind = kind;
this.options = options;
}
public AppModule(CliOptions opts) {
this(new ConfigurationManagerSettings(
ImmutableSet.copyOf(opts.app.allowedContainerTypes),
opts.app.enableDockerParameters,
opts.app.defaultDockerParameters,
opts.app.requireDockerUseExecutor,
opts.main.allowGpuResource,
opts.app.enableMesosFetcher,
opts.app.allowContainerVolumes,
opts.sla.minRequiredInstances,
opts.sla.maxSlaDuration.as(Time.SECONDS),
opts.app.allowedJobEnvironments,
opts.sla.slaAwareKillNonProd),
opts.main.driverImpl,
opts);
}
@Override
protected void configure() {
bind(ConfigurationManagerSettings.class).toInstance(configurationManagerSettings);
bind(Thresholds.class)
.toInstance(
new Thresholds(options.app.maxTasksPerJob,
options.app.maxUpdateInstanceFailures));
// Enable intercepted method timings and context classloader repair.
TimedInterceptor.bind(binder());
GuiceUtils.bindJNIContextClassLoader(binder(), Scheduler.class);
GuiceUtils.bindExceptionTrap(binder(), Scheduler.class);
bind(Clock.class).toInstance(Clock.SYSTEM_CLOCK);
// Filter layering: notifier filter -> base impl
bind(SchedulingFilter.class).to(NotifyingSchedulingFilter.class);
bind(NotifyingSchedulingFilter.class).in(Singleton.class);
bind(SchedulingFilter.class)
.annotatedWith(NotifyingSchedulingFilter.NotifyDelegate.class)
.to(SchedulingFilterImpl.class);
bind(SchedulingFilterImpl.class).in(Singleton.class);
install(new PubsubEventModule());
install(new AsyncModule(options.async));
install(new OfferManagerModule(options));
install(new PruningModule(options.pruning));
install(new ReconciliationModule(options.reconciliation));
install(new SchedulingModule(options.scheduling));
install(new AsyncStatsModule(options.asyncStats));
install(new MetadataModule());
install(new QuotaModule());
install(new JettyServerModule(options));
install(new PreemptorModule(options));
install(new SchedulerDriverModule(kind));
install(new SchedulerServicesModule());
install(new SchedulerModule(options.scheduler));
install(new StateModule(options));
install(new SlaModule(options.sla));
install(new UpdaterModule(options.updater));
install(new MaintenanceModule(options.maintenance));
bind(StatsProvider.class).toInstance(Stats.STATS_PROVIDER);
}
}