Scheduling Working Group Alain Roy

Scheduling Working Document: 9.3 The University of Chicago

Category: Best Current Practice Volker Sander

Forschungszentrum Jülich GmbH

> May 14th, 2001

Advance Reservation API

Status of this Draft

> This document specifies a best current practices for the grid
> scheduling community. Discussion and suggestions are requested.
> Distribution of this memo is unlimited.

Copyright Notice

> Copyright (c) The Grid Forum (2000-2001). All rights reserved.

1\. Introduction

The Grid Scheduling architecture should provide programmers with
convenient access to end-to-end quality of service (QoS) for programs.
To do so, mechanisms for making advance QoS reservations for different
types of resources, including computers, networks, and disks are
required. A reservation is a promise from the system that an application
will receive a certain level of service from a resource. For example, a
reservation may promise a certain bandwidth on a network or a certain
percentage of a CPU.

A Grid resource reservation API should provide two interesting
capabilities. First, it should allow users to make reservations either
in advance of when the resource is needed or at the time that the user
needs theman *immediate reservation*. Second, the same API should be
capable of making and manipulating a reservation regardless of the type
of the underlying resource, thereby simplifying the programming when an
application needs to work with multiple kinds of resources and multiple
simultaneous reservations.

1.  Scope

This document presents an advance reservation API. It does not present
any mechanisms or interfaces for querying the status of previously made
reservations, in order to assist users in discovering good times to make
reservations. It is expected that another document will describe such
mechanisms and interfaces.

This document uses the Resource Specification Language (RSL) to describe
a reservation request. While we believe that RSL is a good interim
solution, we expect that a longer-term solution will be developed
separately in cooperation with the Information Services working group.

Advance reservations for computer resources are only just beginning to
be used. We expect that as advance reservations become more widely used,
our understanding will deepen and grow. During this time, it will be
useful for different advance reservation systems to provide the same
interface, in order to enable broad experimentation with such systems.
This document provides such an interface, but we expect that as our
knowledge grows, we will desire an updated interface. We expect this
interface to serve us well for two to five years, at which point a new
interface will be developed, to reflect new understanding.

1.2 A context

The proposed Grid Advance Reservation API can be considered a remote
procedure call mechanism to communication with a reservation manager. A
reservation manager controls reservations for a resource: it performs
admission control and controls the resource to enforce the reservations.
Some resources already have the ability to work with advanced
reservations, so the reservation manager is a simple program. Most
resources cannot deal with advanced reservations, so the reservation
manager tracks the reservations and does admission control for new
reservation requests.

To create a flexible architecture, supporting co-allocation, resource
location and resource acquisition steps as described in S-RFC 3, a
layered architecture with three levels of APIs and one level of
low-level mechanisms is proposed:

The remaining document describes the intermediate API in Figure 1, the
Grid Advance Reservation API. Please note that there is no requirement
that the Grid Advance Reservation API must be implemented by using a
Local Reservation API, but this is just a conceptual guide to add
understanding of where this API fits in a larger context. Note that this
API is both immediately useful to programmers wishing to make advance
reservation and is useful for building higher-level tools which may
include superschedulers, co-reservation agents, or other as yet
unforseen tools.

We envision that when users desire advance reservations for multiple
resources and different kinds of resources at the same time, they will
build tools on top of the Grid Advance Reservation API to handle this.
For example, users may wish to reserve time on two computers, disk space
on those two computers for storage of intermediate results, and network
bandwidth between the two computers for communication. This API will be
useful for these sorts of *co-reservations*.

3.  Terms

Within the document several terms are used to precisely describe the
semantic of the API-calls. To clarify the use of these terms and to
avoid misunderstandings, the following list introduces their use:

*Reservation:* A promise from the system that an application will
receive a certain level of service from a resource.

*Creating a Reservation:* Asking for a specific resource behavior of
given duration within a specified time interval.

*Committing a Reservation:* To facilitate the use of co-reservations,
implementers might select to use a two-phase commit protocol. Once, a
reservation is created, it is on hold for a specific time. If the
reservation is not committed within this time interval, it is canceled.

*Binding a Reservation:* Some reservation cannot be instantiated without
the provision of additional run-time information. The binding step is
supposed to facilitate the creation of reservations without requiring a
detailed knowledge about all required attributes. However, to actually
use the reservation, it has to be bound, i.e. the user must provide the
missing attributes.

2\. Reservations

Reservations have five important attributes:

> *Start Time:* The earliest time that the reservation may begin. A
> reservation always has a start time, even if it is an immediate
> reservation, which begins as soon as you make the reservation. The
> start time is in seconds since 00:00:00 UTC, January 1, 1970. For
> example, if you want an immediate reservation, you can just call the
> Unix time() function to discover the current time, and use that as the
> start time.
>
> *Duration:* How long the reservation lasts, in seconds. All
> reservations MUST specify how long they will last, so that the
> underlying reservation managers can do appropriate admission control
> for reservations granted in advance.
>
> *Resource Type:* The type of underlying resource, such as a network, a
> computer, or a disk.
>
> *Reservation Type*: A particular kind of reservation. See *Types of
> Network Reservations*, below.
>
> *Resource-Specific Parameters:* Parameters that are unique to each
> type of resource, such as bandwidth for a network reservation and
> number of nodes for a computation reservation.

Optionally, a reservation MAY specify the attribute *End Time* in the
same way that *Start Time* is specified. If the difference between *End
Time* and *Start Time* exceeds the value of *Duration*, any given time
interval of the correct duration starting at or after *Start Time* and
not ending past *End Time* is accepted for the reservation. The exact
start time is made by the reservation manager.

When a reservation is requested, one MUST specify these attributes, as
shown below in the API description. If the reservation request is
accepted, a *reservation handle* is returned from the system. This is an
opaque string that uniquely identifies your reservation. All future
operations require you to provide this handle. The internal format of
this string will be described in a different S-RFC. Generally,
programmers and users do not need to be aware the format of this
reservation handle. It may vary from reservation manager to reservation
manager, and it does not need to be interpreted by anything other than
the reservation manager for correct operation. However, note that the
reservation handle SHOULD encode how the reservation manager for that
reservation can be contacted, because only the create reservation
function actually allows the user to specify the reservation manager.

Once the application has received a reservation handle, it can perform
several operations with that handle:

-   *Modify Reservation:* One can request a modification to an existing
    reservation. For instance, one can increase the bandwidth that has
    already been requested. A modification which reduces its
    requirements normally succeeds. There may be factors that cause
    reduction modifications to fail, such as local policy that does not
    allow small reservations on some resources. However, the underlying
    implementation SHOUILD NOT implement modification by canceling the
    reservation then making a new reservation, because if the new
    reservation fails, the old reservation may be unable to be
    reclaimed.

-   *Cancel Reservation:* One can inform the reservation manager that
    the reservation is no longer needed, by canceling it.

-   *Bind Reservation:* When the application is ready to use a
    reservation, in order to use the reservation, it may need to provide
    run-time information that was not available at the time the
    reservation was made. This is known as *binding* a reservation. For
    example, network reservations require port numbers to be specified,
    but they are not usually known at reservation time. Not all
    reservations require such run-time parameters.

-   *Unbind Reservation:* A reservation can be unbound. It will no
    longer be usable by the person using the reservation. It can then be
    rebound with new run-time parameters.

-   *Committing Reservation:* When a reservation is created, it can be
    specified as a two-phase commit reservation. Such reservations
    time-out after a specified time period, unless the reservation is
    committed.

-   *Query Reservation Status:* One can discover the status of a
    reservation by polling it. The status includes whether the start of
    the reservation has begun and whether the reservation has been
    committed.

-   *Query Reservation Attribute:* One can discover attributes
    associated with an existing reservation. This includes begin and end
    time of the given reservation, and whether it is a two-phase commit
    reservation. It also includes specific information required to
    actually use a reservation. Example attributes are a directory name
    where data was staged on, or a queue name which has to be used for
    submitting a job.

-   *Register Callback:* One can provide a function that will be called
    when the status of a reservation changes or when the reservation
    manager wishes to provide extra information to the application. This
    information MAY include notification that the related reservation
    appears to be too small. Callbacks implement the monitor
    functionality described in S-RFC 3.

3\. Using the API

The API SHOULD be provided as a library that can be linked by programs
written in C. Additional bindings, as Java implementation, are not
described here. Notice that this API is derived from the GARA API and
has some references to Globus. An implementation of the API is not
required to include any such references to Globus.

3.1 Initialization

Before one can use the API, an initialization of the module is required.

grid_reservation_activate();

Programs are allowed to call this activate function more than once and
invocations after the first have no effect. However, the advance
reservation module keeps track of how many times it has been activated.
The deactivation function (See Section 3.10) has to be called that many
times before it actually deactivates the grid reservation module.

The idea of this behavior is to simplify application development if
several portions of a program (particularly libraries) wish to
independently use the grid reservation API. Each portion of the program
can independently invoke the grid reservation API without worrying about
when the module will be activated or deactivated.

3.2 Describing a Reservation Request

Until the Grid Information Group has finished its work in progress and
defines a standard resource description language such as MDSML,
reservation attributes or allocation properties are described using the
Resource Specification Language (RSL) of the Globus project. The authors
of this draft believe that RSL is an excellent *interim* solution until
the Grid Information Group comes up with a final proposal. Note that RSL
is capable of handling Boolean operations and comparison operations,
although its use is not demonstrated in this document.

Also note that the API treats the reservation attribute specification as
a string which means that we should not have to change the API once we
describe a new specification method.

An RSL string is simply a list of attribute-value pairs that looks like

&(attribute-1=value-1) (attribute-2=value-2) ... (attribute-N=value-N)

An example RSL string for requesting a network reservation for 150Kbps
between looks like this:

&(resource-type=network)

> (endpoint-a=140.221.48.146)
>
> (endpoint-b=140.221.48.106)
>
> (bandwidth=150)

Note that this string was spaced out on several lines for readability,
while RSL strings do not have newlines in them. Also note that RSL
supports Boolean operations, including or, greater than, less than or
equal, and so forth. More information about RSL is available from the
Globus web page: http://www.globus.org.

Below is a list of attributes that may be used to specify a reservation.
The universal attributes are for all types of reservations, while the
other attributes are for specific types of resources. Note that the
compute resource attributes are mutually exclusive. This minimal set of
supported attributes might be extended in future version of the
document.

<table>
<colgroup>
<col style="width: 21%" />
<col style="width: 7%" />
<col style="width: 7%" />
<col style="width: 1%" />
<col style="width: 7%" />
<col style="width: 1%" />
<col style="width: 1%" />
<col style="width: 5%" />
<col style="width: 14%" />
<col style="width: 1%" />
<col style="width: 29%" />
</colgroup>
<tbody>
<tr class="odd">
<td><strong>Attribute</strong></td>
<td><strong>Units</strong></td>
<td colspan="3"><strong>Default</strong></td>
<td colspan="3"><strong>Req?</strong></td>
<td colspan="3"><strong>Description</strong></td>
</tr>
<tr class="even">
<td colspan="2">Universal Attributes</td>
<td colspan="6"></td>
<td colspan="3"></td>
</tr>
<tr class="odd">
<td>resource-type</td>
<td></td>
<td colspan="3"></td>
<td colspan="3">Y</td>
<td colspan="3">Allowable values: “network”, “compute”, “disk”, or
“graphic-pipeline”.</td>
</tr>
<tr class="even">
<td>reservation-type</td>
<td></td>
<td colspan="3"></td>
<td colspan="3"></td>
<td colspan="3">Currently valid only for network reservations. If it is
not specified, it is a foreground reservation. Otherwise it is one of
“background” or “low-latency”. For more information, see <em>Types of
Network Reservations</em> above.</td>
</tr>
<tr class="odd">
<td>start-time</td>
<td>secs</td>
<td colspan="3"></td>
<td colspan="3">Y</td>
<td colspan="3">Earliest acceptable time the reservation starts in
seconds since 00:00:00 UTC, January 1, 1970. If you specify “now”, then
the reservation will begin immediately.</td>
</tr>
<tr class="even">
<td>end-time</td>
<td>secs</td>
<td colspan="3"></td>
<td colspan="3"></td>
<td colspan="3"><p>Latest acceptable time the reservation</p>
<p>might be active; UTC format as above.</p></td>
</tr>
<tr class="odd">
<td>duration</td>
<td>secs</td>
<td colspan="3">100</td>
<td colspan="3"></td>
<td colspan="3">Length of the reservation, in seconds.</td>
</tr>
<tr class="even">
<td>two-phase</td>
<td>n/a</td>
<td colspan="3">false</td>
<td colspan="3"></td>
<td colspan="3">If “true”, then the reservation will time-out after some
time, unless it is committed. See discussion in text.</td>
</tr>
<tr class="odd">
<td>two-phase-timeout</td>
<td>secs</td>
<td colspan="3">implementation-dependent</td>
<td colspan="3"></td>
<td colspan="3">The time for the timeout when the two-phase commit
option is specified.</td>
</tr>
<tr class="even">
<td colspan="3">Compute Resource Attributes</td>
<td colspan="3"></td>
<td colspan="3"></td>
<td colspan="2"></td>
</tr>
<tr class="odd">
<td>number-of-cpus</td>
<td>Int</td>
<td colspan="3">1</td>
<td colspan="3"></td>
<td colspan="3">Number of CPUs to be reserved.</td>
</tr>
<tr class="even">
<td>percent-cpu</td>
<td>%</td>
<td colspan="3">20</td>
<td colspan="3"></td>
<td colspan="3">Percentage of the CPU’s time given to the reserved
process.</td>
</tr>
<tr class="odd">
<td colspan="4">Network Resource Attributes</td>
<td colspan="3"></td>
<td colspan="3"></td>
<td></td>
</tr>
<tr class="even">
<td>endpoint-a</td>
<td></td>
<td colspan="3"></td>
<td colspan="3">Y</td>
<td colspan="3">The machine at one end of the network flow. This may be
specified as a dotted IP address, such as 140.221.48.162, or a machine
name, such as dslnet2.mcs.anl.gov</td>
</tr>
<tr class="odd">
<td>endpoint-b</td>
<td></td>
<td colspan="3"></td>
<td colspan="3">Y</td>
<td colspan="3">The machine at the other end of the network flow. This
may be specified as a dotted IP address, such as 140.221.48.162, or a
machine name, such as dslnet2.mcs.anl.gov</td>
</tr>
<tr class="even">
<td>bandwidth</td>
<td>Kbps</td>
<td colspan="3">8</td>
<td colspan="3"></td>
<td colspan="3">How fast a flow can transfer data.</td>
</tr>
<tr class="odd">
<td>directionality</td>
<td></td>
<td colspan="3">bidirectional</td>
<td colspan="3"></td>
<td colspan="3"><p>unidirectional-ab: reservation for traffic from a to
b.</p>
<p>unidirectional-ba: reservation for traffic from b to a.</p>
<p>bidirectional: reservation for traffic in both directions.</p></td>
</tr>
<tr class="even">
<td colspan="4">Disk Resource Attributes</td>
<td colspan="3"></td>
<td colspan="3"></td>
<td></td>
</tr>
<tr class="odd">
<td>size</td>
<td>KB</td>
<td colspan="3"></td>
<td colspan="3"></td>
<td colspan="3">The storage space needed for a single file or set of
files.</td>
</tr>
<tr class="even">
<td>bandwidth</td>
<td>Kbps</td>
<td colspan="3">8</td>
<td colspan="3"></td>
<td colspan="3">Speed for reading/writing file.</td>
</tr>
</tbody>
</table>

3.3 Passing Authorization Information

Before any of the following operations can be done, an important data
structure MUST be initialized. The intention of the data structure is to
pass mandatory information such as user credentials or authorization
attributes. For example, some reservations may only be granted when
specific authorization attributes are provided. The final implementation
of the data structure will depend on the input from the Grid Security
working group. For now, we assume that user credentials are accessed by
denoting the file name of the proxy file which contains a valid pair of
certificate and private key. If no name is supplied (NULL), it is
assumed that the user identity can be extracted from the environment.
Some toolkits, such as the Globus toolkit, support this extraction of
the user identity from the environment, and it simplifies many
programming tasks. A superscheduler, on the other hand, is likely to
wish to supply the identity since it will be handling requests for many
different users.

Enabling the specification of authorization and policy information in
the API is important for implementing high-level functionalities such as
a superscheduler. An example of policy information set by such an entity
would be the distinguished name of the owner of a reservation, a list of
group memberships, and a list of user or groups allowed to use the
reservation in subsequent calls. To ensure the integrity of the policy
field, it MUST be signed by a trusted entity.

Data Structure:

> struct authorization_info_s
>
> {
>
> char \*user_proxy_file;
>
> int number_of_policies;
>
> policy_sequence_t \*policies;
>
> }

typedef struct authorization_info_s

authorization_info_t;

struct policy_entry_s

{

char \*attribute;

char \*value;

}

typedef struct policy_entry_s policy_entry_t;

struct policy_sequence_s

{

policy_entry_t policy_list\[\];

char dn_of_signing_entity

unsigned char \*signature;

}

typedef struct policy_sequence_s policy_sequence_t;

3.4 Creating a Reservation

Before a reservation can be created, its needs have to be specified as
described above. To request a reservation the application has to call
grid_reservation_create():

int error;

char \*request_rsl = "&(resource-type=compute)

(number-of-nodes=14)";

char \*time_rsl = "&(start-time=953158862) (duration=3600)"

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_create( reservation_manager_contact,

&auth_info,

request_rsl, time_rsl,

&reservation_handle);

Note that the reservation manager contact is a string obtained from
another location, such as the Grid Information Service. Its intention is
to specify the URL of the related reservation manager.

Also note that if the reservation had specified "(two-phase=true)" in
the request_rsl, it would need to commit the reservation. See below.

3.5 Modifying a Reservation

Modifying a reservation is similar to creating a reservation, except
that instead of providing a reservation manager contact, the application
provides the handle to the reservation that was created earlier:

int error;

char \*request_rsl = "&(resource-type=compute)

(number-of-nodes=128)";

char \*time_rsl = "(start-time=953158862) (end-time=953173262)

(duration=7200)"

char \*old_reservation_handle;

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_modify(&auth_info, old_reservation_handle,

request_rsl, time_rsl,

&reservation_handle);

3.6 Querying a Reservation

To find out the status of a reservation, it can be queried by:

int error;

int status;

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_status(&auth_info, reservation_handle,

&status);

If there is not an error, the status will be one of

GRID_RESERVATION_STATUS_NOT_STARTED

GRID_RESERVATION_STATUS_NOT_STARTED_BOUND

GRID_RESERVATION_STATUS_READY_NOT_BOUND

GRID_RESERVATION_STATUS_ACTIVE

GRID_RESERVATION_STATUS_FINISHED

A reservation is bound if a previous call to reservation_bind succeeded.
A reservation is ready if the current time is later than the start time,
and the duration has not yet elapsed. A reservation is active if it is
both ready and bound. A reservation is finished if the current time is
later than the start time plus the duration.

3.7 Reservation Attributes

This is a generalized version of the status call that allows more
attributes to be queried. Here is an example of querying the time that a
reservation begins.

int error;

char \*reservation_handle;

authorization_info_t auth_info;

reservation_attributes_t attribute;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_attribute(&auth_info, reservation_handle,

GRID_RESERVATION_ATTRIBUTE_BEGIN_TIME, &attribute);

printf("Start time is %s\\n", ctime(attribute.value.time));

3.8 Committing a Reservation

When a reservation is a two-phase commit reservation (as specified in
the reservation request, see Sections 3.2 and 3.4), it needs to be
committed before the reservation times out. Note that the time-out
period can be specified when the reservation is made, but it defaults to
an implementation-specified time that can be discovered through some
external query mechanism.

int error;

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_commit(&auth_info, reservation_handle);

3.9 Binding a Reservation

When the application ready to use a reservation, it may need to *bind*
it in order to begin using the reservation. Binding a reservation is a
required step if the creation was done without providing all required
attributes to instantiate it. The following example binds a process-id
to a given reservation:

int error;

char \*bind_paramters = "&(process-id=5631)";

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_bind(&auth_info, reservation_handle,

&bind_parameters);

Notice that the run-time parameters are specified as an RSL string. This
allows the integration of different reservation managers within one API.
Bind parameters are resource dependant. For compute reservations, for
instance, the only parameter to be specified might be the process-id,
which specifies the process ID of the process that will be receiving the
reservation. For some reservations, such as ones requesting a number of
nodes on a machine, there may be no bind parameters, but it is still
required that the call be made. For network reservations, there are more
parameters:

-   which-endpoint: If the reservation is being bound from a machine
    involved in the reservation, this specifies which machine it is. The
    machine is either "a" or "b", and it matches what was specified in
    the reservation request. If a different machine is binding the
    reservation on behalf of the processes involved, simply use "a".

-   endpoint-a-port: This is the port used by endpoint-a, as specified
    in the reservation request. The implementation assumes that data is
    being sent from endpoint-a to endpoint-b, this will be the port used
    by the sender.

-   endpoint-b-port: This is the port use by endpoint-b, as specified in
    the reservation request. The implementation assumes that data is
    being sent from endpoint-a to endpoint-b, this will be the port used
    by the receiver.

Note that a reservation is not considered active until it is bound. Once
a reservation has both begun and been bound, the reservation manager do
whatever setup is necessary in order to ensure that the reservation is
granted. It is okay if the reservation is bound before it has begun,
because the reservation manager will automatically enable the
reservation once it begins.

If the application will temporarily not be using a reservation but it
will resume using it before it has expired, it can unbind the
reservation:

int error;

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_unbind(&auth_info, reservation_handle);

Once an application unbind a reservation, it may bind it again.

3.10 Using Callbacks

Callbacks are used to communicate monitoring functions to the user. If
the application would like to be informed whenever the status of a
reservation changes (see *Querying a Reservation* above), it can use a
callback function. Once the user registers a callback function, it will
immediately be called once, to provide the current status, and will be
called every time the status changes afterwards.

First the application needs to create a callback function:

static void callback_handler(

char \*reservation_handle,

grid_reservation_event_t event,

void \*user_parameter)

{

/\* Place code here to examine the event \*/

/\* If it is a status event, event.event_type will be

STATUS_EVENT, and the status will be in

event.event. \*/

if (event.event == STATUS_EVENT)

{

if (event.event_type == RESERVATION_STATUS_FINISHED)

{

/\* React to reservation being finished \*/

}

}

return;

}

Then the application needs to register this function. The user needs to
register the function for each reservation that he wishes to monitor:

int error;

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

error = grid_reservation_callback_register(&auth_info,

reservation_handle,

callback_handler, NULL);

Note that the last parameter you pass to the registration function will
be forwarded as the user_parameter to your callback function.

If you would no longer like to have a function called when the status
changes, you can unregister it:

int error;

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

> error = grid_reservation_callback_remove(&auth_info,
> reservation_handle callback_handler);

Note you can register multiple callback functions for a single
reservation handle.

3.11 Canceling a Reservation

When the application has finished using a reservation, it SHOULD cancel
it, using the reservation handle that was obtained when the reservation
was created.

char \*reservation_handle;

authorization_info_t auth_info;

auth_info.user_proxy_file = NULL;

auth_info.number_of_policies = 0;

auth_info.policies = NULL;

grid_reservation_cancel(&auth_info, reservation_handle);

When the user cancels a reservation, all of the callbacks that have been
registered for that reservation will automatically be cancelled.

It is important to note that all reservation managers SHOULD clean up
reservations automatically, once they are expired. However, the cancel
call MUST not fail if the reservation manager has removed a reservation
already.

3.12 Deactivating the Advance Reservation Module

When the application has finished using API, it SHOULD deactivate it, to
allow it to clean up:

grid_reservation_deactivate();

4 Grid Advance Reservation API Reference

4.1 Constants

This section describes the constants used by the API.

Errors

Currently we define N errors, with the specific values as shown here. We
reserve the right to use errors with the values 0-256. Implementations
may use any other errors values they like, but until they become
standardized, they MUST not use the values 0-256.

GRID_ERROR_NONE (0)

No error has occurred.

GRID_ERROR_UNKNOWN (1)

An error has occurred, but the reservation manager just doesn't know
what it is.

GRID_ERROR_MODULE_NOT_ACTIVE (2)

The user has tried to use the API without activating the module first.

GRID_ERROR_BAD_PARAMETER (3)

A bad parameter, such as a NULL reservation handle, has been passed to
an API function that actually expected a good parameter.

GRID_ERROR_ZERO_LENGTH_RESOURCE_SPECIFICATION (4)

> An resource description was provided, but it is empty. It may be that
> this is never returned.

GRID_ERROR_BAD_RESOURCE_DESCRIPTION (5)

> There is an error, probably a syntax error, in the resource
> description string.

GRID_ERROR_BAD_RESERVATION_HANDLE (6)

The reservation handle that was provided isn't really a reservation
handle.

GRID_ERROR_BAD_USER_CREDENTIALS (7)

The credentials specified in the authorization_info_t structure are no
good. Who are you anyway?

GRID_ERROR_NO_USER_CREDENTIALS (8)

The credentials specified in the authorization_info_t were NULL and they
could not be extracted from the environment, leading the reservation
manager to suspect you are a non-person.

GRID_ERROR_BAD_POLICY_DESCRIPTION (9)

The policy specification was not accepted

GRID_ERROR_CONNECTION_FAILED (10)

> The API was unable to connect to the reservation manager.

GRID_ERROR_AUTHORIZATION (11)

> The API was unable to authenticate and authorize the user.

GRID_ERROR_VERSION_MISMATCH (12)

> Protocol error with the reservation manager due to mismatch of
> version.

GRID_ERROR_INVALID_REQUEST (13)

The request can not be handled by the reservation manager.

GRID_ERROR_UNKNOWN_RESERVATION_TYPE (14)

> The reservation type in the reservation request must be one of
> "network", "compute", or "disk", but it wasn't.

GRID_ERROR_PROTOCOL_FAILED (15)

> There was a problem communicating with the reservation manager.

GRID_ERROR_MISSING_RESERVATION_TYPE (16)

> The reservation type in the RSL reservation request wasn't provided.

GRID_ERROR_OUT_OF_MEMORY (17)

> A request for memory failed.

GRID_ERROR_MISSING_ENDPOINT_A (18)

> A network reservation request didn't specify endpoint-a.

GRID_ERROR_MISSING_ENDPOINT_B (19)

> A network reservation request didn't specify endpoint-b.

GRID_ERROR_CANT_MAKE_RESERVATION (20)

> The reservation can't be made. Probably there are other reservations
> already at the same time, and there isn't room for the new
> reservation.

GRID_ERROR_BAD_RESERVATION_OBJECT (21)

> This error probably means that the user tried to make a network
> reservation for an endpoint that the reservation manager hasn't been
> configured to allow reservations for.

GRID_ERROR_SERVICE_EXECUTABLE_NOT_FOUND (22)

> The reservation manager is misconfigured.

GRID_ERROR_CANT_CONTACT_RESERVATION_MANAGER (23)

> The reservation manager is unavailable. Check to make sure that it's
> running or whether the correct resource location was specified.

GRID_ERROR_UNKNOWN_GRAM_ERROR (24)

> Some error in the underlying protocol has failed.

GRID_ERROR_MISSING_RESERVATION_TYPE (25)

The request indicates that a subtype has to be specified, but it wasn´t.

GRID_ERROR_ATTRIBUTE_UNAVAILABLE_FOR_RESERVATION_TYPE (26)

> An attribute was requested for a type of reservation that can never
> have that attribute. For example, a queue name was requested for a
> network reservation.

GRID_ERROR_ATTRIBUTE_UNAVAILABLE_IN_IMPLEMENTATION (27)

> An attribute that might be reasonable to request is not available,
> because the implementation doesn't support it.

GRID_ERROR_ATTRIBUTE_ONLY_AFTER_BIND (28)

> The reservation has not yet been bound, but the attribute can only be
> provided after the reservation has been bound.

GRID_ERROR_ATTRIBUTE_ONLY_AFTER_COMMIT (29)

> The reservation has not yet been committed, but the attribute can only
> be provided after the reservation has been committed.

GRID_ERROR_INTERNAL_ERROR (256)

The request indicates that some other error occurred. (We need a good
way to deal with these other errors in a regular way. Different errors
can occur for different implementations, so how do we report them?)

Callback and Status Constants

The following events are reported to callbacks:

GRID_RESERVATION_STATUS_EVENT

> The status of the reservation has changed. See the lists of status
> constants below.

GRID_RESERVATION_CHANGE_EVENT

> The reservation has been preempted, or the reservation quantity (like
> bandwidth) has changed. See the list changes below.

GRID_RESERVATION_MONITOR_EVENT

> Informs the user about specific monitor events such as that he is
> exceeding its reservation.

The following statuses can be reported to callbacks on a status event or
in response to a user calling reservation_status.

GRID_RESERVATION_STATUS_NOT_STARTED

> The reservation has not yet begun (the current time is before the
> start time).

GRID_RESERVATION_STATUS_NOT_STARTED_BOUND

> Although the reservation has not yet begun, the reservation has been
> bound.

GRID_RESERVATION_STATUS_READY_NOT_BOUND

The reservation has begun (the current time is after the start time) but
can't yet be used because it has not been bound yet.

GRID_RESERVATION_STATUS_ACTIVE

> The reservation has begun and been bound.

GRID_RESERVATION_STATUS_FINISHED

The reservation is over. That is, the current time is greater than the
start time plus the duration of the reservation.

The following changes can be reported on a CHANGE_EVENT:

GRID_RESERVATION_RESERVATION_CHANGE_PREEMPTED

> The reservation has been preempted because a more important
> reservation has occurred. Currently, this will not be reported,
> because preemption has not yet been implemented.

GRID_RESERVATION_CHANGE_QUANTITY

> The quantity (like bandwidth) has been changed. This occurs for bulk
> transfer network reservations, or reservations that are adaptable in
> response to changing conditions.

Attribute Types

The following types of attributes can be requested in the
grid_reservation_attribute function. Currently we define 12 attributes,
with the specific values as shown here. We reserve the right to use
attributes with the values 0-256. Implementations may use any other
attribute values they like, but until they become standardized, they
must not use the values 0-256.

GRID_RESERVATION_ATTRIBUTE_BEGIN_TIME (0)

> The time a reservation begins

GRID_RESERVATION_ATTRIBUTE_END_TIME (1)

> The time a reservation ends

GRID_RESERVATION_ATTRIBUTE_HAS_BEGUN (2)

> A boolean indicating if a reservation has begun, and has not yet
> ended.

GRID_RESERVATION_ATTRIBUTE_IS_BOUND (3)

> A boolean indicating if a reservation has been bound, and has not yet
> ended.

GRID_RESERVATION_ATTRIBUTE_IS_COMMITTED (4)

> A boolean indicating if a reservation has been committed, and has not
> yet ended.

GRID_RESERVATION_ATTRIBUTE_NEEDS_BIND (5)

> A boolean indicating if a reservation needs to be bound.

GRID_RESERVATION_ATTRIBUTE_NEEDS_COMMIT (6)

> A boolean indicating if a reservation needs to be committed.

GRID_RESERVATION_ATTRIBUTE_AUTHORIZED (7)

> A boolean indicating if the identity/authorization given in the
> attribute request function call is sufficient to operate on the
> reservation. (In case different users want to work with a
> reservation.)

GRID_RESERVATION_ATTRIBUTE_QUEUE_NAME (8)

> A string indicating the queue a job should be submitted to, in order
> for the reservation to work.

GRID_RESERVATION_ATTRIBUTE_PATH_NAME (9)

> A string indicating where files should be written, in order to for the
> disk reservation to work.

GRID_RESERVATION_ATTRIBUTE_MAX_NETWORK_DELAY_ESTIMATE (10)

> A floating point number indicating the best guess as to the delay
> packets using a network reservation will experience

GRID_RESERVATION_ATTRIBUTE_LIKELIHOOD_OF_FULFILMENT (11)

> A number from 0-100 indicating the systems best guess of the percent
> chance that your reservation will actually be given to you.
> Preemptions, downtimes, and nasty system administrators may affect
> this percentage, and there is no guarantee that a system can
> accurately provide this estimate.

Variable Types

The following types are used to indicate what variable type is returned
for an attribute.

GRID_RESERVATION_VARIABLE_INT

> The variable is of type "int" for an integer.

GRID_RESERVATION_VARIABLE_BOOLEAN

> The variable is of type "int" for an boolean (TRUE or FALSE).

GRID_RESERVATION_VARIABLE_FLOAT

> The variable is of type "float" for an floating point number.

GRID_RESERVATION_VARIABLE_STRING

> The variable is of type "char \*" for an string.

GRID_RESERVATION_VARIABLE_TIME

> The variable is of type "time_t" for a specific time.

Miscellaneous Constants

The following types are used to indicate what variable type is returned
for an attribute.

GRID_RESERVATION_API_VERSION (1)

> The version of the library you have compiled against, or are running
> against. Currently this is defined to be 1.

4.2 Data Structures

This is a description of the data structures used by the API.

The Event Data Structure

typedef struct

{

int event_type;

int event;

double quantity;

} grid_reservation_event_t;

This structure is provided to callback functions. The event type and
event are constants from the list above. The quantity is provided when
the event is a change event indicating that the quantity has changed.

The Authorization information Structure

typedef struct

{

char \*user_proxy_file;

int number_of_policies;

policy_sequence_t \*policies;

} authorization_info_t;

This structure is provided to callback functions. The event type and
event are constants from the list above. The quantity is provided when
the event is a change event indicating that the quantity has changed.

The Attribute Structure

typedef struct

{

reservation_attribute_type_t which_attribute;

variable_type_t variable_type;

union

{

int boolean; /\* TRUE or FALSE \*/

int integer;

float number;

char \*text;

time_t time;

};

} grid_reservation_attribute_t;

This structure is returned to describe an attribute that is requested by
grid_reservatin_attribute().

Callback functions

typedef void (\*grid_reservation_callback_t)(

char \*reservation_handle,

grid_reservation_event_t event,

void \*user_parameter);

This is the type of function that MUST be used for callback functions.

4.3 Functions

Note that all of the functions of the API return an integer. This
integer is the error code, if any error occurred. See the list of errors
under *Constants*.

grid_reservation_activate

int grid_reservation_activate(void);

This function initializes the Grid Advance Reservation Module. You MUST
call this before you call any other function in the module. Programs are
allowed to call this activate function more than once and invocations
after the first have no effect. However, the advance reservation module
keeps track of how many times it has been activated. The deactivation
function (See Section 3.10) has to be called that many times before it
actually deactivates the grid reservation module.

grid_reservation_deactivate

int grid_reservation_deactivate(void);

This function informs the Grid Advance Reservation Module that it is no
longer needed, so that it can perform any cleanup that it might need to
do.

grid_reservation_create

int grid_reservation_create(

const char \*manager_contact,

const authorization_info_t \*auth_info,

const char \*reservation_specification, /\* RSL \*/

const char \*time_specification, /\* RSL \*/

char \*\*reservation_handle);

This function attempts to make a reservation.

**In:**

> manager_contact: The contact string for access to the reservation
> manager for the resource the user wishes to make a reservation with.
>
> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_specification: An RSL string describing the attributes the
> user wishes to have for the reservation. See *Describing a Reservation
> Request* above.
>
> time_specification: An RSL string describing the time interval the
> reservation should be in place. See *Describing a Reservation Request*
> above.

**In/Out:**

> reservation_handle: If the reservation was successfully made, a
> pointer to your reservation handle will be provided in the reservation
> handle member of the advance_reservation_handle_s. The memory for this
> reservation handle is allocated by malloc(), and it is your
> responsibility to free the memory with free() when the user is done.

grid_reservation_modify

int grid_reservation_modify(

const authorization_info_t \*auth_info,

const char \*old_reservation_handle,

const char \*reservation_specification, /\* RSL \*/

const char \*time_specification, /\* RSL \*/

char \*\*reservation_handle);

This function attempts to modify a new reservation. Note that if the
reservation is changed, you are might receive a new reservation handle.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> old_reservation_handle: The handle of an existing reservation that the
> user wishes to modify. The memory for this reservation handle MUST be
> deallocated by the user.
>
> reservation_specification: An RSL string describing the new attributes
> you wish to have for your reservation. See *Describing a Reservation
> Request* above.
>
> time_specification: An RSL string describing the new time interval the
> reservation should be in place. See *Describing a Reservation Request*
> above.

**Out:**

> reservation_handle: If the reservation was successfully modified, a
> pointer to a new reservation handle will be provided. The memory for
> the reservation handle is allocated by malloc(), and it is under the
> responsibility of the user to free the memory with free().

grid_reservation_commit

int grid_reservation_commit(

const authorization_info_t \*auth_info,

const char \*reservation_handle);

This commits a two-phase commit reservation. It is not a replacement for
binding run-time parameters.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation that the user
> wishes to bind.

grid_reservation_bind

int grid_reservation_bind(

const authorization_info_t \*auth_info,

const char \*reservation_handle,

const char \*bind_parameters);

This binds a reservation by providing run-time parameters.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation that the user
> wishes to bind.
>
> bind_parameters: An RSL string describing the new attributes the user
> wishes to have for the reservation. See *Binding a Reservation* above.

grid_reservation_unbind

int grid_reservation_unbind(

const authorization_info_t \*auth_info,

const char \*reservation_handle);

This undoes the "bind" for a reservation that has been bound. The
reservation is still valid and can be used again by calling
reservation_bind() again.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation that the user
> wishes to bind.

grid_reservation_status

int grid_reservation_status(

const authorization_info_t \*auth_info,

const char \*reservation_handle,

int \*status;

This function queries for a reservation's status.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation that the user
> wishes to query.

**Out:**

> status: The status of the reservation. It is one of the constants
> described in *Callback and Status Constants.*

grid_reservation_attribute

int grid_reservation_attribute(

const authorization_info_t \*auth_info,

const char \*reservation_handle,

reservation_attribute_type_t which_attribute,

grid_reservation_attribute_t attribute);

This function queries a reservation for a specific attribute.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation that the user
> wishes to query.
>
> which_attribute: The desired attribute, described in *Attribute
> Types*, above.

**Out:**

> attribute: Information about the attribute. The data structure is
> described above in *The Attribute Structure*. Note that the programmer
> can retrieve the correct attribute value by examining the
> variable_type field and checking the defined variable types above.

**Common Errors:**

GRID_ERROR_ATTRIBUTE_UNAVAILABLE_FOR_RESERVATION_TYPE

GRID_ERROR_ATTRIBUTE_UNAVAILABLE_IN_IMPLEMENTATION

GRID_ERROR_ATTRIBUTE_ONLY_AFTER_BIND

GRID_ERROR_ATTRIBUTE_ONLY_AFTER_COMMIT

grid_reservation_callback_register

int grid_reservation_callback_register(

const authorization_info_t \*auth_info,

const char \*reservation_handle,

reservation_callback_t callback_function,

void \*user_parameter);

After this function successfully completes, the specified callback
function will be called whenever the status of a reservation changes. It
will also be immediately called once to provide the current status of
the reservation. Note that multiple callbacks can be registered for a
single reservation.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation for which the user
> wishes to receive callbacks.
>
> callback_function: The function that will be called by GARA when the
> status of a reservation changes.
>
> user_parameter: The value provided here will be passed to the callback
> function unmodified.

grid_reservation_callback_remove

int reservation_callback_remove(

const authorization_info_t \*auth_info,

const char \*reservation_handle,

reservation_callback_t callback_function);

After this function successfully completes, the specified callback
function will no longer be called when the status of the reservation
changes.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation for which the user
> wishes to receive callbacks.
>
> callback_function: The function that will be called by GARA when the
> status of a reservation changes.
>
> user_parameter: The value provided here will be passed to the callback
> function unmodified.

grid_reservation_cancel

int grid_reservation_cancel(

const authorization_info_t \*auth_info,

const char \*reservation_handle);

This cancels a reservation. When a reservation is cancelled, the
reservation handle (and copies of it) may not be used anymore. For
example, if the user tries to bind the cancelled reservation, it will
fail.

**In:**

> auth_info: Data structure providing access to the user's credentials
> and additional policy information which might be used for approving
> authorization.
>
> reservation_handle: The handle for the reservation that the user
> wishes to cancel.

grid_reservation_version

int grid_reservation_version(void);

This returns the current version number for the reservation manager. The
current version number is GRID_RESERVATION_API_VERSION, as defined
above.

grid_reservation_client_debug

int grid_reservation_client_debug(int debug_on);

**In:**

> debug_on: If true, debugging is turned on. If false, it is turned off.
> The exact effect of turning on debugging mode is
> implementation-dependent.

grid_client_error_string

const char \*grid_client_error_string(

int error_code);

For any error code returned by the reservation manager, this provides a
printable string that corresponds to the error code.

**In:**

> error_code: The error code for which the user wishes to obtain a
> string representation.

4\. Contact Author Address

Alain Roy Volker Sander

Building 221 Central Institute for Applied Mathematics

Mathematics and CS Forschungszentrum Jülich GmbH

9700 South Cass 52425 Jülich,

Argonne, IL 60439 Germany,

630\) 252-5686 +49 2461 616586

<roy@mcs.anl.gov> v.sander@fz-juelich.de