blob: 5bf55ee76d39045a8cc2ead45592359c9a59b0f8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.uima.ducc.cli;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Properties;
import org.apache.uima.ducc.common.utils.DuccSchedulerClasses;
import org.apache.uima.ducc.common.utils.IllegalConfigurationException;
import org.apache.uima.ducc.transport.event.IDuccContext.DuccContext;
import org.apache.uima.ducc.transport.event.SubmitReservationDuccEvent;
import org.apache.uima.ducc.transport.event.SubmitReservationReplyDuccEvent;
import org.apache.uima.ducc.transport.event.cli.ReservationRequestProperties;
/**
* Submit a DUCC reservation
*/
public class DuccReservationSubmit
extends CliBase
{
ReservationRequestProperties requestProperties = new ReservationRequestProperties();
IDuccCallback resCB = new ReservationCallback();
private String nodeList = "";
/**
* @param args Array of string arguments as described in the
* <a href="/doc/duccbook.html#DUCC_CLI_RESERVE">DUCC CLI reference.</a>
*/
public DuccReservationSubmit(String[] args)
throws Exception
{
init (this.getClass().getName(), opts, args, requestProperties, resCB);
}
/**
* @param args List of string arguments as described in the
* <a href="/doc/duccbook.html#DUCC_CLI_RESERVE">DUCC CLI reference.</a>
*/
public DuccReservationSubmit(ArrayList<String> args)
throws Exception
{
String[] arg_array = args.toArray(new String[args.size()]);
init (this.getClass().getName(), opts, arg_array, requestProperties, resCB);
}
/**
* @param props Properties file of arguments, as described in the
* <a href="/doc/duccbook.html#DUCC_CLI_RESERVE">DUCC CLI reference.</a>
*/
public DuccReservationSubmit(Properties props)
throws Exception
{
init (this.getClass().getName(), opts, props, requestProperties, resCB);
}
UiOption[] opts = new UiOption[] {
UiOption.Help,
UiOption.Debug,
UiOption.Description,
UiOption.SchedulingClass,
UiOption.Specification,
UiOption.ReservationMemorySize,
UiOption.Timestamp,
UiOption.WaitForCompletion,
UiOption.CancelOnInterrupt,
};
/**
* Execute collects the parameters for the reservation and sends them to the DUCC Orchestrator
* to schedule the reservation. This method blocks until either the reservation is
* granted, or it fails. Failure is always do to lack of resources, in some form or another.
* Reservations must be from one of the 'reserve' classes i.e for a whole machine.
*
* @return True if the DUCC grants the reservation.
* @throws Exception
*/
public boolean execute() throws Exception
{
String pname = UiOption.SchedulingClass.pname();
String scheduling_class = requestProperties.getProperty(pname);
if (scheduling_class != null) {
String[] reserveClasses;
try {
reserveClasses = DuccSchedulerClasses.getInstance().getReserveClasses();
} catch (Exception e) {
throw new IllegalConfigurationException("Error in DUCC configuration files - see administrator", e);
}
if (!Arrays.asList(reserveClasses).contains(scheduling_class)) {
throw new IllegalArgumentException("Invalid value for scheduling_class - must be one of the reserve classes");
}
}
SubmitReservationDuccEvent ev = new SubmitReservationDuccEvent(requestProperties, CliVersion.getVersion());
SubmitReservationReplyDuccEvent reply = null;
try {
reply = (SubmitReservationReplyDuccEvent) dispatcher.dispatchAndWaitForDuccReply(ev);
} catch (Exception e) {
message("Reservation not submitted:", e.getMessage());
return false;
} finally {
dispatcher.close();
}
/*
* process reply (gets friendlyId and messages.
*/
boolean rc = extractReply(reply);
// If request was accepted, default to starting a monitor so can report the state
// but only if the user has not specified this option
if (rc) {
if (!commandLine.contains(UiOption.WaitForCompletion)) {
requestProperties.setProperty(UiOption.WaitForCompletion.pname(), "");
}
startMonitors(false, DuccContext.Reservation); // starts conditionally, based on job spec and console listener present
}
// Note: in DUCC 1.x this waited for a response. With 2.0 requests are queued and the caller can
// choose to not wait, although that is the default.
// Now like the other requests, the wait is done when getting the rc
return rc;
}
/**
* If the reservation is granted, this method returns the reserved host
* @return Name of host where the reservation is granted.
*/
public String getHost()
{
return nodeList;
}
/**
* If the reservation is granted, this method returns the set of hosts containing the reservation.
* @return String array of hosts where the reservation is granted.
*/
@Deprecated
public String[] getHosts()
{
return this.nodeList.split("\\s");
}
/**
* If the reservation is granted, this method returns the set of hosts containing the reservation as
* a single blank-delimited string.
* @return Blank-delimited string of hosts where the reservation is granted.
*/
@Deprecated
public String getHostsAsString()
{
return nodeList;
}
/**
* Main method, as used by the executable jar or direct java invocation.
* @param args arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_RESERVE">DUCC CLI reference.</a>
*/
public static void main(String[] args) {
int code = 1;
try {
// Instantiate the object with args similar to the CLI, or a pre-built properties file
DuccReservationSubmit ds = new DuccReservationSubmit(args);
// Run the API. If process_attach_console was specified in the args, a console listener is
// started but this call does NOT block on it.
boolean rc = ds.execute();
// If the return is 'true' then as best the API can tell, the submit worked
if ( rc ) {
System.out.println("Reservation "+ds.getDuccId()+" submitted.");
code = ds.getReturnCode();
// Note: code is not (but should be) non-zero when request fails
String node = ds.getHost();
if (!node.isEmpty()) {
System.out.println("Node: " + node);
}
} else {
System.out.println("Could not submit reservation.");
}
} catch (Throwable e) {
System.out.println("Cannot initialize: " + e);
while ((e = e.getCause()) != null) {
System.out.println(" ... " + e);
}
} finally {
// Set the process exit code
System.exit(code);
}
}
/*
* Special callback that extracts the assigned node
*/
private class ReservationCallback implements IDuccCallback {
private final String nodesPrefix = "nodes: ";
public void console(int pnum, String msg) {
System.out.println("[" + pnum + "] " + msg);
}
public void status(String msg) {
if (msg.startsWith(nodesPrefix)) {
nodeList = msg.substring(nodesPrefix.length());
} else {
System.out.println(msg);
}
}
}
}