Search in sources :

Example 1 with SubmitDryRunResponse

use of com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse in project heron by twitter.

the class SubmitterMain method main.

public static void main(String[] args) throws Exception {
    Options options = constructOptions();
    Options helpOptions = constructHelpOptions();
    CommandLineParser parser = new DefaultParser();
    // parse the help options first.
    CommandLine cmd = parser.parse(helpOptions, args, true);
    if (cmd.hasOption("h")) {
        usage(options);
        return;
    }
    try {
        // Now parse the required options
        cmd = parser.parse(options, args);
    } catch (ParseException e) {
        usage(options);
        throw new RuntimeException("Error parsing command line options: ", e);
    }
    Level logLevel = Level.INFO;
    if (isVerbose(cmd)) {
        logLevel = Level.ALL;
    }
    // init log
    LoggingHelper.loggerInit(logLevel, false);
    // load the topology definition into topology proto
    TopologyAPI.Topology topology = TopologyUtils.getTopology(cmd.getOptionValue("topology_defn"));
    Config config = loadConfig(cmd, topology);
    LOG.fine("Static config loaded successfully");
    LOG.fine(config.toString());
    SubmitterMain submitterMain = new SubmitterMain(config, topology);
    /* Meaning of exit status code:
       - status code = 0:
         program exits without error
       - 0 < status code < 100:
         program fails to execute before program execution. For example,
         JVM cannot find or load main class
       - 100 <= status code < 200:
         program fails to launch after program execution. For example,
         topology definition file fails to be loaded
       - status code >= 200
         program sends out dry-run response */
    try {
        submitterMain.submitTopology();
    } catch (SubmitDryRunResponse response) {
        LOG.log(Level.FINE, "Sending out dry-run response");
        // Output may contain UTF-8 characters, so we should print using UTF-8 encoding
        PrintStream out = new PrintStream(System.out, true, StandardCharsets.UTF_8.name());
        out.print(submitterMain.renderDryRunResponse(response));
        // Exit with status code 200 to indicate dry-run response is sent out
        // SUPPRESS CHECKSTYLE RegexpSinglelineJava
        System.exit(200);
    // SUPPRESS CHECKSTYLE IllegalCatch
    } catch (Exception e) {
        /* Since only stderr is used (by logging), we use stdout here to
         propagate error message back to Python's executor.py (invoke site). */
        LOG.log(Level.FINE, "Exception when submitting topology", e);
        System.out.println(e.getMessage());
        // Exit with status code 100 to indicate that error has happened on user-land
        // SUPPRESS CHECKSTYLE RegexpSinglelineJava
        System.exit(100);
    }
    LOG.log(Level.FINE, "Topology {0} submitted successfully", topology.getName());
}
Also used : Options(org.apache.commons.cli.Options) PrintStream(java.io.PrintStream) Config(com.twitter.heron.spi.common.Config) LauncherException(com.twitter.heron.spi.scheduler.LauncherException) UploaderException(com.twitter.heron.spi.uploader.UploaderException) PackingException(com.twitter.heron.spi.packing.PackingException) ParseException(org.apache.commons.cli.ParseException) TopologyAPI(com.twitter.heron.api.generated.TopologyAPI) SubmitDryRunResponse(com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse) CommandLine(org.apache.commons.cli.CommandLine) Level(java.util.logging.Level) CommandLineParser(org.apache.commons.cli.CommandLineParser) ParseException(org.apache.commons.cli.ParseException) DefaultParser(org.apache.commons.cli.DefaultParser)

Example 2 with SubmitDryRunResponse

use of com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse in project heron by twitter.

the class LaunchRunner method call.

/**
   * Call launcher to launch topology
   *
   * @throws LauncherException
   * @throws PackingException
   * @throws SubmitDryRunResponse
   */
public void call() throws LauncherException, PackingException, SubmitDryRunResponse {
    SchedulerStateManagerAdaptor statemgr = Runtime.schedulerStateManagerAdaptor(runtime);
    TopologyAPI.Topology topology = Runtime.topology(runtime);
    String topologyName = Context.topologyName(config);
    PackingPlan packedPlan = LauncherUtils.getInstance().createPackingPlan(config, runtime);
    if (Context.dryRun(config)) {
        throw new SubmitDryRunResponse(topology, config, packedPlan);
    }
    // initialize the launcher
    launcher.initialize(config, runtime);
    // Set topology def first since we determine whether a topology is running
    // by checking the existence of topology def
    // store the trimmed topology definition into the state manager
    // TODO(rli): log-and-false anti-pattern is too nested on this path. will not refactor
    Boolean result = statemgr.setTopology(trimTopology(topology), topologyName);
    if (result == null || !result) {
        throw new LauncherException(String.format("Failed to set topology definition for topology '%s'", topologyName));
    }
    result = statemgr.setPackingPlan(createPackingPlan(packedPlan), topologyName);
    if (result == null || !result) {
        statemgr.deleteTopology(topologyName);
        throw new LauncherException(String.format("Failed to set packing plan for topology '%s'", topologyName));
    }
    // store the execution state into the state manager
    ExecutionEnvironment.ExecutionState executionState = createExecutionState();
    result = statemgr.setExecutionState(executionState, topologyName);
    if (result == null || !result) {
        statemgr.deletePackingPlan(topologyName);
        statemgr.deleteTopology(topologyName);
        throw new LauncherException(String.format("Failed to set execution state for topology '%s'", topologyName));
    }
    // launch the topology, clear the state if it fails
    if (!launcher.launch(packedPlan)) {
        statemgr.deleteExecutionState(topologyName);
        statemgr.deletePackingPlan(topologyName);
        statemgr.deleteTopology(topologyName);
        throw new LauncherException(String.format("Failed to launch topology '%s'", topologyName));
    }
}
Also used : SubmitDryRunResponse(com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse) LauncherException(com.twitter.heron.spi.scheduler.LauncherException) ExecutionEnvironment(com.twitter.heron.proto.system.ExecutionEnvironment) PackingPlan(com.twitter.heron.spi.packing.PackingPlan) SchedulerStateManagerAdaptor(com.twitter.heron.spi.statemgr.SchedulerStateManagerAdaptor) TopologyAPI(com.twitter.heron.api.generated.TopologyAPI)

Example 3 with SubmitDryRunResponse

use of com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse in project incubator-heron by apache.

the class SubmitterMain method main.

public static void main(String[] args) throws Exception {
    Options options = constructOptions();
    Options helpOptions = constructHelpOptions();
    CommandLineParser parser = new DefaultParser();
    // parse the help options first.
    CommandLine cmd = parser.parse(helpOptions, args, true);
    if (cmd.hasOption("h")) {
        usage(options);
        return;
    }
    try {
        // Now parse the required options
        cmd = parser.parse(options, args);
    } catch (ParseException e) {
        usage(options);
        throw new RuntimeException("Error parsing command line options: ", e);
    }
    Level logLevel = Level.INFO;
    if (isVerbose(cmd)) {
        logLevel = Level.ALL;
    }
    // init log
    LoggingHelper.loggerInit(logLevel, false);
    // load the topology definition into topology proto
    TopologyAPI.Topology topology = TopologyUtils.getTopology(cmd.getOptionValue("topology_defn"));
    Config config = loadConfig(cmd, topology);
    LOG.fine("Static config loaded successfully");
    LOG.fine(config.toString());
    SubmitterMain submitterMain = new SubmitterMain(config, topology);
    /* Meaning of exit status code:
       - status code = 0:
         program exits without error
       - 0 < status code < 100:
         program fails to execute before program execution. For example,
         JVM cannot find or load main class
       - 100 <= status code < 200:
         program fails to launch after program execution. For example,
         topology definition file fails to be loaded
       - status code >= 200
         program sends out dry-run response */
    try {
        submitterMain.submitTopology();
    } catch (SubmitDryRunResponse response) {
        LOG.log(Level.FINE, "Sending out dry-run response");
        // Output may contain UTF-8 characters, so we should print using UTF-8 encoding
        PrintStream out = new PrintStream(System.out, true, StandardCharsets.UTF_8.name());
        out.print(DryRunRenders.render(response, Context.dryRunFormatType(config)));
        // Exit with status code 200 to indicate dry-run response is sent out
        // SUPPRESS CHECKSTYLE RegexpSinglelineJava
        System.exit(200);
    // SUPPRESS CHECKSTYLE IllegalCatch
    } catch (Exception e) {
        /* Since only stderr is used (by logging), we use stdout here to
         propagate error message back to Python's executor.py (invoke site). */
        LOG.log(Level.FINE, "Exception when submitting topology", e);
        System.out.println(e.getMessage());
        // Exit with status code 100 to indicate that error has happened on user-land
        // SUPPRESS CHECKSTYLE RegexpSinglelineJava
        System.exit(100);
    }
    LOG.log(Level.FINE, "Topology {0} submitted successfully", topology.getName());
}
Also used : Options(org.apache.commons.cli.Options) PrintStream(java.io.PrintStream) Config(com.twitter.heron.spi.common.Config) LauncherException(com.twitter.heron.spi.scheduler.LauncherException) UploaderException(com.twitter.heron.spi.uploader.UploaderException) PackingException(com.twitter.heron.spi.packing.PackingException) ParseException(org.apache.commons.cli.ParseException) TopologyAPI(com.twitter.heron.api.generated.TopologyAPI) SubmitDryRunResponse(com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse) CommandLine(org.apache.commons.cli.CommandLine) Level(java.util.logging.Level) CommandLineParser(org.apache.commons.cli.CommandLineParser) ParseException(org.apache.commons.cli.ParseException) DefaultParser(org.apache.commons.cli.DefaultParser)

Example 4 with SubmitDryRunResponse

use of com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse in project incubator-heron by apache.

the class TopologyResource method submit.

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings({ "IllegalCatch", "JavadocMethod" })
public Response submit(FormDataMultiPart form) throws IOException {
    // verify that all we have all the required params
    final List<String> missingDataKeys = verifyKeys(form.getFields().keySet(), REQUIRED_SUBMIT_TOPOLOGY_PARAMS);
    if (!missingDataKeys.isEmpty()) {
        // return error since we are missing required parameters
        final String message = String.format("Validation failed missing required params: %s", missingDataKeys.toString());
        return Response.status(HTTP_UNPROCESSABLE_ENTITY_CODE).type(MediaType.APPLICATION_JSON).entity(Utils.createValidationError(message, missingDataKeys)).build();
    }
    final String cluster = Forms.getString(form, FORM_KEY_CLUSTER);
    if (!doesClusterMatch(cluster)) {
        return Response.status(HTTP_UNPROCESSABLE_ENTITY_CODE).type(MediaType.APPLICATION_JSON).entity(Utils.createMessage(String.format("Unknown cluster %s expecting '%s'", cluster, getCluster()))).build();
    }
    final String topologyName = Forms.getString(form, FORM_KEY_NAME);
    final String role = Forms.getString(form, FORM_KEY_ROLE);
    final String environment = Forms.getString(form, FORM_KEY_ENVIRONMENT, Constants.DEFAULT_HERON_ENVIRONMENT);
    final String user = Forms.getString(form, FORM_KEY_USER, role);
    // submit overrides are passed key=value
    final Map<String, String> submitOverrides = getSubmitOverrides(form);
    final String topologyDirectory = Files.createTempDirectory(topologyName).toFile().getAbsolutePath();
    try {
        // upload the topology definition file to the topology directory
        final FormDataBodyPart definitionFilePart = form.getField(FORM_KEY_DEFINITION);
        final File topologyDefinitionFile = Forms.uploadFile(definitionFilePart, topologyDirectory);
        // upload the topology binary file to the topology directory
        final FormDataBodyPart topologyFilePart = form.getField(FORM_KEY_TOPOLOGY);
        final File topologyBinaryFile = Forms.uploadFile(topologyFilePart, topologyDirectory);
        final boolean isDryRun = form.getFields().containsKey(PARAM_DRY_RUN);
        // copy configuration files to the sandbox config location
        // topology-dir/<default-heron-sandbox-config>
        FileHelper.copyDirectory(Paths.get(getConfigurationDirectory()), Paths.get(topologyDirectory, Constants.DEFAULT_HERON_SANDBOX_CONFIG));
        final java.nio.file.Path overridesPath = Paths.get(topologyDirectory, Constants.DEFAULT_HERON_SANDBOX_CONFIG, Constants.OVERRIDE_FILE);
        // copy override file into topology configuration directory
        FileHelper.copy(Paths.get(getConfigurationOverridePath()), overridesPath);
        // apply submit overrides
        ConfigUtils.applyOverrides(overridesPath, submitOverrides);
        // apply overrides to state manager config
        ConfigUtils.applyOverridesToStateManagerConfig(overridesPath, Paths.get(topologyDirectory, Constants.DEFAULT_HERON_SANDBOX_CONFIG, Constants.STATE_MANAGER_FILE));
        // create tar file from the contents of the topology directory
        final File topologyPackageFile = Paths.get(topologyDirectory, TOPOLOGY_TAR_GZ_FILENAME).toFile();
        FileHelper.createTarGz(topologyPackageFile, FileHelper.getChildren(topologyDirectory));
        // create configs
        Config topologyConfig = ConfigUtils.getTopologyConfig(topologyPackageFile.getAbsolutePath(), topologyBinaryFile.getName(), topologyDefinitionFile.getAbsolutePath());
        List<Pair<String, Object>> val = new LinkedList<>();
        for (Map.Entry<String, Object> entry : topologyConfig.getEntrySet()) {
            val.add(Pair.create(entry.getKey(), entry.getValue()));
        }
        val.addAll(Arrays.asList(Pair.create(Key.CLUSTER.value(), cluster), Pair.create(Key.TOPOLOGY_NAME.value(), topologyName), Pair.create(Key.ROLE.value(), role), Pair.create(Key.ENVIRON.value(), environment), Pair.create(Key.SUBMIT_USER.value(), user), Pair.create(Key.DRY_RUN.value(), isDryRun)));
        final Config config = createConfig(val, submitOverrides);
        // submit the topology
        getActionFactory().createSubmitAction(config, topologyPackageFile.getAbsolutePath(), topologyBinaryFile.getName(), topologyDefinitionFile.getAbsolutePath()).execute();
        return Response.created(URI.create(String.format(TOPOLOGY_PATH_FORMAT, cluster, role, environment, topologyName))).type(MediaType.APPLICATION_JSON).entity(createdResponse(cluster, role, environment, topologyName)).build();
    } catch (SubmitDryRunResponse response) {
        return createDryRunResponse(response, Forms.getString(form, PARAM_DRY_RUN_FORMAT, DEFAULT_DRY_RUN_FORMAT));
    } catch (Exception ex) {
        LOG.error("error submitting topology {}", topologyName, ex);
        return Response.serverError().type(MediaType.APPLICATION_JSON).entity(Utils.createMessage(ex.getMessage())).build();
    } finally {
        FileUtils.deleteDir(topologyDirectory);
    }
}
Also used : Config(com.twitter.heron.spi.common.Config) LinkedList(java.util.LinkedList) IOException(java.io.IOException) SubmitDryRunResponse(com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse) FormDataBodyPart(org.glassfish.jersey.media.multipart.FormDataBodyPart) File(java.io.File) Map(java.util.Map) HashMap(java.util.HashMap) MultivaluedMap(javax.ws.rs.core.MultivaluedMap) Pair(com.twitter.heron.common.basics.Pair) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces)

Example 5 with SubmitDryRunResponse

use of com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse in project incubator-heron by apache.

the class LaunchRunner method call.

/**
 * Call launcher to launch topology
 *
 * @throws LauncherException
 * @throws PackingException
 * @throws SubmitDryRunResponse
 */
public void call() throws LauncherException, PackingException, SubmitDryRunResponse {
    SchedulerStateManagerAdaptor statemgr = Runtime.schedulerStateManagerAdaptor(runtime);
    TopologyAPI.Topology topology = Runtime.topology(runtime);
    String topologyName = Context.topologyName(config);
    PackingPlan packedPlan = LauncherUtils.getInstance().createPackingPlan(config, runtime);
    if (Context.dryRun(config)) {
        throw new SubmitDryRunResponse(topology, config, packedPlan);
    }
    // initialize the launcher
    launcher.initialize(config, runtime);
    // Set topology def first since we determine whether a topology is running
    // by checking the existence of topology def
    // store the trimmed topology definition into the state manager
    // TODO(rli): log-and-false anti-pattern is too nested on this path. will not refactor
    Boolean result = statemgr.setTopology(trimTopology(topology), topologyName);
    if (result == null || !result) {
        throw new LauncherException(String.format("Failed to set topology definition for topology '%s'", topologyName));
    }
    result = statemgr.setPackingPlan(createPackingPlan(packedPlan), topologyName);
    if (result == null || !result) {
        statemgr.deleteTopology(topologyName);
        throw new LauncherException(String.format("Failed to set packing plan for topology '%s'", topologyName));
    }
    // store the execution state into the state manager
    ExecutionEnvironment.ExecutionState executionState = createExecutionState();
    result = statemgr.setExecutionState(executionState, topologyName);
    if (result == null || !result) {
        statemgr.deletePackingPlan(topologyName);
        statemgr.deleteTopology(topologyName);
        throw new LauncherException(String.format("Failed to set execution state for topology '%s'", topologyName));
    }
    // launch the topology, clear the state if it fails
    if (!launcher.launch(packedPlan)) {
        statemgr.deleteExecutionState(topologyName);
        statemgr.deletePackingPlan(topologyName);
        statemgr.deleteTopology(topologyName);
        throw new LauncherException(String.format("Failed to launch topology '%s'", topologyName));
    }
}
Also used : SubmitDryRunResponse(com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse) LauncherException(com.twitter.heron.spi.scheduler.LauncherException) ExecutionEnvironment(com.twitter.heron.proto.system.ExecutionEnvironment) PackingPlan(com.twitter.heron.spi.packing.PackingPlan) SchedulerStateManagerAdaptor(com.twitter.heron.spi.statemgr.SchedulerStateManagerAdaptor) TopologyAPI(com.twitter.heron.api.generated.TopologyAPI)

Aggregations

SubmitDryRunResponse (com.twitter.heron.scheduler.dryrun.SubmitDryRunResponse)5 TopologyAPI (com.twitter.heron.api.generated.TopologyAPI)4 LauncherException (com.twitter.heron.spi.scheduler.LauncherException)4 Config (com.twitter.heron.spi.common.Config)3 ExecutionEnvironment (com.twitter.heron.proto.system.ExecutionEnvironment)2 PackingException (com.twitter.heron.spi.packing.PackingException)2 PackingPlan (com.twitter.heron.spi.packing.PackingPlan)2 SchedulerStateManagerAdaptor (com.twitter.heron.spi.statemgr.SchedulerStateManagerAdaptor)2 UploaderException (com.twitter.heron.spi.uploader.UploaderException)2 PrintStream (java.io.PrintStream)2 Level (java.util.logging.Level)2 CommandLine (org.apache.commons.cli.CommandLine)2 CommandLineParser (org.apache.commons.cli.CommandLineParser)2 DefaultParser (org.apache.commons.cli.DefaultParser)2 Options (org.apache.commons.cli.Options)2 ParseException (org.apache.commons.cli.ParseException)2 Pair (com.twitter.heron.common.basics.Pair)1 File (java.io.File)1 IOException (java.io.IOException)1 HashMap (java.util.HashMap)1