How the Compute Cluster Server Works

Applies To: Windows Compute Cluster Server 2003

This section covers the following topics:

  • Terms and definitions

  • Network architecture

  • Software architecture

  • Types of parallel computing jobs

  • Creating and submitting jobs

  • Role of the Job Scheduler

  • Scheduling politics

  • Resource sorting

  • Run-time job and task management

  • Task execution

  • Job status and life cycle

  • Task status and life cycle

  • Node status and life cycle

  • Standard job and task options

  • Content format

  • Job XML schema file

  • Task XML schema file

Terms and definitions

The following table contains a list of terms necessary for a basic understanding of compute cluster operations.

Term Definition

Job

A job is a resource request submitted to the Job Scheduler that contains or will contain one or more tasks.

Task

A task is a discrete call to a user application. A task cannot be run independently of a job. However, a job can consist of only a single task.

Node

A node is a single named host in the cluster.

Processor

A processor is an individual CPU on a node. Typically, a 64-bit node has two or more processors. A dual-core processor is usually seen as two processors.

Queue

The queue is a list of jobs that have been submitted to the Job Scheduler, each of which has its own place and status in the list.

Task List

The task list is the task equivalent of the queue.

Job Scheduler

The Job Scheduler is a service responsible for queuing jobs and tasks, allocating resources, dispatching the tasks to the compute nodes, and monitoring the status of the job, tasks, and nodes.

Network architecture

Network configuration consists of a head node and a scalable number of compute nodes. The nodes can be connected as part of a larger server network, or as a private network with the head node serving as a gateway. The following illustrations show both types of arrangement.

Network Topology Scenario 5Network Topology Scenario 1

The networking medium can be Ethernet or it can be a high-speed medium such as InfiniBand (typically used only for MPI or similar communication among the nodes).

Software architecture

The software architecture consists of a user interface layer, a scheduling layer, and an execution layer.

Three Layers: Interface, Scheduling, Execution.

The interface and scheduling layers reside on the head node. The execution layer resides primarily on the compute nodes. The execution layer as shown here includes the Microsoft implementation of MPI, called MS MPI, which was developed for Windows and is included in the Microsoft® Compute Cluster Pack. This application is based on the Argonne National Laboratories MPICH2 implementation of the MPI-2 standard.

Interface layer

The user interface layers consist of the Compute Cluster Job Manager, the Compute Cluster Administrator, and Command Line Interface (CLI).

The Compute Cluster Job Manager is a WIN32 graphic user interface to the Job Scheduler that is used for job creation and submission.

The Compute Cluster Administrator is a Microsoft Management Console (MMC) snap-in that is used for configuration and management of the cluster.

The Command Line Interface is a standard Windows command prompt which provides a command-line alternative to use of the Job Manager and the Administrator.

Scheduling layer

The scheduling layer consists of the Job Scheduler, which is responsible for queuing the jobs and tasks, reserving resources, and dispatching jobs to the compute nodes.

Execution layer

In this example, the execution layer consists of the following components replicated on each compute node: the Node Manager Service, the MS MPI launcher mpiexec, and the MS MPI Service.

The Node Manager is a service that runs on all compute nodes in the cluster. The Node Manager executes jobs on the node, sets task environmental variables, and sends a heartbeat (health check) signal to the Job Scheduler at specified intervals (the default interval is one minute).

Mpiexec is the MPICH2-compatible multithreading executable within which all MPI tasks are run.

The MS MPI Service is responsible for starting the job tasks on the various processors.

Types of parallel computing jobs

In general, there are three types of parallel computing jobs: parallel task, parametric sweep, and task flow. The three types are not mutually exclusive.

Parallel task

A parallel task can take one of many forms, depending on the application and the software that supports it. For a Message Passing Interface (MPI) application, a parallel task usually consists of a single executable running concurrently on multiple processors, with communication between the processes. This is shown in the following diagram:

Three processes, two-way communication

The process numbers 0, 1 and 2represent the process rank and have greater or less significance depending on the processing paradigm. At the minimum, Process 0 handles the input/output and determines what other processes are running. In one paradigm, Process 0 also acts as a master process; the others are worker processes that communicate with the master process but not with each other. In another paradigm, the relationship among the processes is symmetrical, with all processes equal and each communicating with every other process.

From the cluster perspective, what most distinguishes a parallel task from a serial task is that the user application, and therefore the task itself, is intrinsically parallel, and parallel processing takes place independently of whether the task is running concurrently with other tasks. For parallel tasks, Windows Compute Cluster Server 2003 includes an MPI package based on Argonne National Laboratory's MPICH2 standard. The Microsoft implementation of MPI, called MS MPI, includes the launcher mpiexec, node-specific MPI services, and an SDK for user application development. Windows Compute Cluster Server 2003 also supports applications that provide their own parallel processing mechanisms. Documentation for the Compute Cluster Pack, including the SDK, can be found online at the MSDN Web site (https://go.microsoft.com/fwlink/?linkid=55873.)

Parametric sweep

A parametric sweep job is illustrated in the following figure:

Four serial tasks, separate input and output files

A parametric sweep is the concurrent running of multiple instances of the same program, usually serial, with input supplied by an input file and output directed to output file. There is no communication or interdependency among the tasks. Typically, the parallelization is performed exclusively (or almost exclusively) by the scheduler alone, based on the fact that all tasks are in the same job.

Task flow

A task flow job is one in which a set of unlike tasks are executed in a prescribed order, usually because one task depends on the result of another task.

A task flow job is illustrated in the following figure. Note that only Tasks 2 and 3 are performed in parallel, because neither is dependent on the other.

Task flow job, dependent tasks

Creating and submitting jobs

Creating a job is the first step in cluster computing. A job is a resource request containing one or more computing tasks to be run in parallel. Each task may in turn be parallel (for example, an MPI task) or it may be serial. A typical example of a job that runs multiple serial tasks in parallel is a parametric sweep, in which the multiple iterations of the same executable are run using different input and output files.

You can create a job using the Job Manager or the CLI. To create a job, first you specify its job properties, which are a set of options that determine such elements as job priority, run time limit, number of processors required, specific nodes requested, and whether nodes will be reserved exclusively for the job. Then you add the tasks that the job will execute. In addition to the command line to be executed, each task contains properties that are similar to the job properties. The task's properties also include any input, output, and error files required, as well as a list of any other tasks on which this task depends.

When you have fully defined your job and its tasks, the next step is to submit it to the Job Scheduler. After the job is submitted, it takes its place in the job queue with the status Queued and waits its turn to be activated.

Role of the Job Scheduler

When a job is submitted, it is placed under the management of Job Scheduler. Job Scheduler determines the job's place in the queue and allocates resources to the job when the job reaches the top of the queue and as resources become available. Jobs are ordered in the queue according to a set of rules called scheduling policies. Resource allocation is based on resource sorting.

When the requested resources have been allocated, the scheduler dispatches the job tasks to the compute nodes and takes on a management and monitoring function. The scheduler manages jobs by enforcing certain job and task options, as well as managing job or task status changes. It monitors jobs by reporting on the status of the job and its tasks, as well as the health of the nodes.

Job Scheduler serves as the sole gateway to the cluster for job submission, running the user application under the individual user's security context. For more information about credential handling, see Compute Cluster Security.

Scheduling policies

Job Scheduler implements the following scheduling policies:

  • Priority-based, first-come, first-served scheduling

  • Backfilling

  • Exclusive scheduling

Priority-based, first-come, first-served scheduling

Priority-based, first-come, first-served (FCFS) scheduling is a combination of FCFS and priority-based scheduling. Using priority-based FCFS scheduling, the scheduler places a job into a higher or lower priority group depending on the job's priority setting, but always places that job at the end of the queue in that priority group because it is the last submitted job.

Backfilling

Backfilling maximizes node utilization by allowing a smaller job or jobs lower in the queue to run ahead of a job waiting at the top of the queue, as long as the job at the top is not delayed as a result.

When a job reaches the top of the queue, a sufficient number of nodes may not be available to meet its minimum processors requirement. When this happens, the job reserves any nodes that are immediately available and waits for the job that is currently running to complete. Backfilling then utilizes the reserved idle nodes as follows:

  • Based on the run time specified for the job that is currently running, a start time for the waiting job is established.

  • The start time is used to define a backfill window of nodes (n) by time (t). For example, four nodes idle for 15 minutes would create a 4 x 15 backfill window.

  • Job Scheduler searches for the first job in the queue that can complete within the backfill window. For example, a job that requires a minimum of eight processors (four nodes, assuming dual-processor nodes) and has a run time of 10 minutes would fit the 4 x 15 window exactly.

  • If a job is found that fits the window, it is activated and run ahead of the job waiting at the top of the queue.

Exclusive scheduling

By default, a job has exclusive use of the nodes reserved by it. This can produce idle reserved processors on a node. Idle reserved processors are processors that are not used by the job but are also not available to other jobs. By turning off the exclusive property, the user allows the job to share its unused processors with other jobs that have also been set as nonexclusive. Therefore, nonexclusivity is a reciprocal agreement among participating jobs, allowing each to take advantage of the other's unused processors.

Task nonexclusivity

By default, a task has nonexclusive use of the node it runs on. Otherwise the node would always run as if it had only one processor. The exclusive option is provided for exceptional cases, such as a task that reboots the node.

Resource sorting

To allocate nodes, Job Scheduler sorts the candidate nodes by memory size, and, within each size group, by processor speed. The nodes are then allocated in the resulting order.

Run-time job and task management

Job Scheduler is responsible for run-time management of the job and its tasks. This includes the following functions:

  • Enforcement of job and task run time properties

  • State (status) transition

Enforcement of job and task properties

Most job and task properties are enforced by Job Scheduler in one way or another. Some of these properties are enforced prior to run time and are used either for job and task identification or for job ordering and resource allocation as determined by the scheduling policies. These properties include job and task name, job and task ID, job priority, run time, number of processors, asked nodes and required nodes, and exclusive and nonexclusive use of nodes. Most of the remaining properties are enforced during run time. The following table lists the properties that are passed to the Job Scheduler and describes how the Job Scheduler handles them (or, in some cases, leaves that task to the Node Manager).

Job Option Definition Job Scheduler Action

/runtime:[[[days:<num>]hours:<num>]minutes: <num>| infinite]

Maximum run time in day-hour-minute format. The job will be cancelled rather than allowed to run past the maximum run time. Default is Infinite.

Job Scheduler holds all resources until the run time is used up or until the job ends, whichever happens first, then releases them for the next job. The exception is when rununtilcancelled is set to TRUE.

/rununtilcanceled: true | false

Flag indicating that the job will hold its resources until it is cancelled or reaches its run time limit. This way, additional tasks can be run on the nodes.

When rununtilcanceled is set to TRUE, Job Scheduler holds all of the job resources until the run time is used up or the job is cancelled, then releases them for the next job. If the run time is left at the default value Infinite, the job will run indefinitely until canceled.

Task Option Definition Job Scheduler Action

/rerunnable: true | false

Flag indicating that that a task can be rerun after a failure. Default is TRUE.

The scheduler allows a failed job to be requeued if the failure is due to any error that can be fixed without changing the task command line. If the task fails because of system failure (for example, a node crashes), the scheduler requeues the job automatically. Only incomplete tasks are re-run.

/env:name1=val1 /env:<name2=val2 … /env:nameN=valN>

Specify the environment variables for the task. (For more information about environment variables, see Use Environment Variables.)

Job Scheduler retrieves the value of the environment variable and places it in the command line.

/runtime:[[[days:<num>]hours:<num>]minutes: <num>| infinite]

Maximum run time in day-hour-minute format. The job will be cancelled rather than allowed to run past the maximum run time. Default is Infinite.

Job Scheduler holds all resources until the run time is used up or until the job ends, whichever happens first, then releases them for the next job. The exception is when rununtilcancelled is set to TRUE.

/workdir:<path>

The full path of the work directory (the directory for input, output, and error files). The path may contain environment variables. Default is %USERPROFILE%.

No action is taken by Job Scheduler. The work directory is set by the node manager.

/stdin:<file_name>

Take standard input for the task from file <file_name>.

No action is taken by Job Scheduler. The node manager locates the file by its path relative to the working directory (or its full path).

/stdout:<file_name>

Redirect standard output of the task to the file <file_name>.

No action is taken by Job Scheduler. The node manager writes the file in the folder specified by its path relative to the working directory (or its full path).

/stderr:<file_name>

Redirect standard error of the task to a file <file_name>.

No action is taken by Job Scheduler. The node manager writes the file in the folder specified by its path relative to the working directory (or its full path).

/depend:<task_name1,taskname2,…tasknameN>

Specify that this task depends on tasks of the name <task_name>.

Job Scheduler creates a dependency table that reorders the task according to dependencies. By default, tasks are run first-come, first-served.

State (status) transition

Job Scheduler is also responsible for job and task status transition from Queued to Running to Finished, Cancelled, or Failed. If a task has failed due to a system failure, the scheduler will also requeue the task and the job containing it automatically, provided the Rerunnable property of the task is set to True.

Automatic job and task transitioning can be overridden by the user or administrator using the Cancel or Requeue commands.

Task execution

Job Scheduler dispatches tasks to the compute nodes in the order that they appear in the task list. To dispatch the task, Job Scheduler passes the task to a designated node, which can be any of the compute nodes allocated to the job. Unless dependencies have been specified, the tasks are dispatched a first-come, first-served (FCFS) basis.

For serial tasks, the first two tasks will be dispatched to and run on the designated node (assuming it has two processors), the next two tasks will be dispatched to and run on a second designated node, and the sequence will repeat itself until there are no more tasks or until all the processors in the cluster are being used. Any remaining tasks must wait for the next available processor and run when it becomes available. The following illustration shows this process.

Note

The file server shown on the head node may not actually reside there. It can reside anywhere in the external or internal network. (See Store Store and Access Data Files.) An MSDE server stores the job specifications and user logon credentials. The task ID number, which also contains the job ID number, allows Job Scheduler to keep track of the status of the task as part of the job, displaying both job and task status to the user.

Serial task flow

For parallel tasks, execution flow depends on the user application and the software that supports it. For jobs that are run using the Microsoft Message Passing Interface Service (MS MPI, which is included in the Compute Cluster Pack), tasks are executed as follows follows. The MS MPI executable mpiexec is started on the designated node. Mpiexec, in turn, starts all the task processes through the node-specific MS MPI Service. If more than one node is required for the task, additional instances of MS MPI, one per node, are spawned before the task processes themselves are started. Parallel task flow is shown in the following illustration.

Note

The file server shown on the head node may not actually reside there. It can reside anywhere in the external network. Microsoft® SQL Server™ 2000 Desktop Engine (MSDE) stores the job specifications and user logon credentials. For more information, see Store and Access Data Files

Parallel task flow

In the previous figure, P0 through P5 represent the processes that are created, each part of a single task. This illustration shows the most common case, in which only one process, P0, handles all the standard input and output files.

Job status and life cycle

The following table summarizes the job life cycle status flags.

Flag Definition

Not_Submitted

Job has been created using job new but has not been submitted. Job has job ID.

Queued

Job has been submitted and is waiting to be activated (run).

Running

Job is running.

Finished

Job has completed successfully.

Failed

Job has failed to complete.

Canceled

Job has been canceled.

Task status and life cycle

Task life cycle and status flags are identical to those of the job listed in the previous table.

Node status and life cycle

The following table summarizes the node life cycle and status flags.

Flag Definition

Pending

Node has been added to cluster but not yet approved by administrator.

Ready

Node has been added to cluster and approved by administrator.

Paused

Node has been paused. When a node is in the Paused state, jobs running on the node continue to run but no new jobs from users without administrative rights will be started. New administrator jobs will be started.

Unreachable

System cannot establish a connection with node.

Standard job and task options

Standard job and task options (referred to as job terms and task terms) are defined in XML schema files named job.xsd and task.xsd.

The format of the schema content is shown in this table, followed by the full text of the schema files.

Content format

The format of the content is defined as follows.

Name XPATH Width (Unicode Byte) Format

Id

/Job@Id

10

Int32

<=2147483647

AllocateNodes

/Job@AllocatedNodes

N/A

<node1> <node2>…<nodeN>

IsBackfill

/Job@IsBackfill

N/A

true | false

Message

/Job@Message

320

string

SubmittedBy

/Job@SubmittedBy

80

String (the submission user)

User

/Job@User

80

Credential user string (the job will run as this user)

Status

/Job@Status

N/A

NotSubmitted, Queued, Running, Completed, Failed, Canceled

Minprocessors

/Job@Minimum

NumberOfProcessors

N/A

Int32

MaxProcessors

/Job@Maximum

NumberOfProcessors

N/A

Int32

Askednodes

/Job@AskedNodes

2080

<node1> <node2>…<nodeN>

32 nodes * 64 + 32

Priority

/Job@Priority

N/A

Highest | AboveNormal | Normal | BelowNormal | Lowest

exclusive

/Job@IsExclusive

N/A

true | false

runtime

/Job@Runtime

8

[[<dd>:]<hh>:]<mm> OR Infinite

runtillcancelled

/Job@RuntillCancelled

N/A

true | false

Jobname

/Job@Name

80

String

Projectname

/Job@Project

80

String

License

/Job@SoftwareLicense

160

<feature1>:<amt1>,<feature2>:<amt2>…

<featureN>:<amtN>

Status

/Job/Task@Status

N/A

NotSubmitted, Queued, Running, Completed, Failed, Cancelled

Id

/Job/Task@Id

10

Int32

<=2147483647

ExitCode

/Job/Task@ExitCode

N/A

Int32

ParentJobId

/Job/Task@ParentJobId

N/A

Int32

Name

/Job/Task/@Name

80

String

Cmdline

/Job/Task/CommandLine

480

<executablepath> <arg1> <arg2> …<argN>

Environment

/Job/Task/EnvironmentVariables

2048

String

Rerunnable

/Job/Task@IsRerunnable

N/A

true | false

Runtime

/Job/Task@Runtime

8

[[<dd>:]<hh>:]<mm>

MinProcessors

/Job/Task@MinimumNumberOfProcessors

N/A

Int32

Numprocessors

/Job/Task@MaximumNumberOfProcessors

N/A

Int32

Askednodes

/Job/Task@AskedNodes

2080

<node1> <node2>…<nodeN>

Exclusive

/Job/Task@IsExclusive

N/A

true | false

Workdir

/Job/Task@WorkDirectory

160

Full path for work directory. The path can contain environment variables.

Stdin

/Job/Task@Stdin

160

Full path for standard input file.

Stdout

/Job/Task@stdout

160

Full path for standard output file.

Stderr

/Job/Task@Stderr

160

Full path for standard error file.

Depend

/Job/Task@Depend

320

Name of task on which focal task depends. All tasks by this name must complete before focal task can be run.

The password is not part of the job XML file. Password size is 256 Unicode bytes.

Job XML schema file

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="https://www.microsoft.com/ComputeCluster/" elementFormDefault="qualified" targetNamespace="https://www.microsoft.com/ComputeCluster/" xmlns:xs="https://www.w3.org/2001/XMLSchema">
  <xs:element name="Job" nillable="true" xmlns:ns="https://www.microsoft.com/ComputeCluster/" type="ns:Job" />
  <xs:complexType name="Job">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="ExtendedTerms" nillable="true" type="tns:NameValueCollection" />
      <xs:element minOccurs="1" maxOccurs="1" name="Tasks" nillable="true" type="tns:ArrayOfTask" />
    </xs:sequence>
    <xs:attribute default="" name="AllocatedNodes" type="xs:string" />
    <xs:attribute default="" name="AskedNodes" type="xs:string" />
    <xs:attribute default="0" name="Id" type="xs:int" />
    <xs:attribute default="false" name="IsBackfill" type="xs:boolean" />
    <xs:attribute default="true" name="IsExclusive" type="xs:boolean" />
    <xs:attribute default="1" name="MaximumNumberOfProcessors" type="xs:int" />
    <xs:attribute default="1" name="MinimumNumberOfProcessors" type="xs:int" />
    <xs:attribute default="" name="Message" type="xs:string" />
    <xs:attribute default="" name="Name" type="xs:string" />
    <xs:attribute default="" name="SubmittedBy" type="xs:string" />
    <xs:attribute default="Normal" name="Priority" type="tns:JobPriority" />
    <xs:attribute default="" name="Project" type="xs:string" />
    <xs:attribute default="false" name="RuntillCancelled" type="xs:boolean" />
    <xs:attribute default="Infinite" name="Runtime" type="xs:string" />
    <xs:attribute default="" name="SoftwareLicense" type="xs:string" />
    <xs:attribute default="NotSubmitted" name="Status" type="tns:JobStatus" />
    <xs:attribute default="" name="User" type="xs:string" />
  </xs:complexType>
  <xs:complexType name="NameValueCollection">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Term" nillable="true" type="tns:NameValue" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="NameValue">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="Value" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ArrayOfTask">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Task" nillable="true" type="tns:Task" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Task">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="EnvironmentVariables" nillable="true" type="tns:NameValueCollection1" />
      <xs:element minOccurs="1" maxOccurs="1" name="ExtendedTerms" nillable="true" type="tns:NameValueCollection" />
    </xs:sequence>
    <xs:attribute default="" name="AskedNodes" type="xs:string" />
    <xs:attribute name="CommandLine" type="xs:string" />
    <xs:attribute default="" name="Depend" type="xs:string" />
    <xs:attribute default="0" name="ExitCode" type="xs:int" />
    <xs:attribute default="0" name="Id" type="xs:int" />
    <xs:attribute default="false" name="IsExclusive" type="xs:boolean" />
    <xs:attribute default="false" name="IsRerunnable" type="xs:boolean" />
    <xs:attribute default="1" name="MaximumNumberOfProcessors" type="xs:int" />
    <xs:attribute default="1" name="MinimumNumberOfProcessors" type="xs:int" />
    <xs:attribute default="" name="Message" type="xs:string" />
    <xs:attribute default="" name="Name" type="xs:string" />
    <xs:attribute default="0" name="ParentJobId" type="xs:int" />
    <xs:attribute default="Infinite" name="Runtime" type="xs:string" />
    <xs:attribute default="NotSubmitted" name="Status" type="tns:TaskStatus" />
    <xs:attribute default="" name="Stdin" type="xs:string" />
    <xs:attribute default="" name="Stdout" type="xs:string" />
    <xs:attribute default="" name="Stderr" type="xs:string" />
    <xs:attribute default="" name="WorkDirectory" type="xs:string" />
  </xs:complexType>
  <xs:complexType name="NameValueCollection1">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Variable" nillable="true" type="tns:NameValue" />
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="TaskStatus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="NotSubmitted" />
      <xs:enumeration value="Queued" />
      <xs:enumeration value="Running" />
      <xs:enumeration value="Completed" />
      <xs:enumeration value="Failed" />
      <xs:enumeration value="Cancelled" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="JobPriority">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Lowest" />
      <xs:enumeration value="BelowNormal" />
      <xs:enumeration value="Normal" />
      <xs:enumeration value="AboveNormal" />
      <xs:enumeration value="Highest" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="JobStatus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="NotSubmitted" />
      <xs:enumeration value="Queued" />
      <xs:enumeration value="Running" />
      <xs:enumeration value="Completed" />
      <xs:enumeration value="Failed" />
      <xs:enumeration value="Cancelled" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

Task XML schema file

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="https://www.microsoft.com/ComputeCluster/" elementFormDefault="qualified" targetNamespace="https://www.microsoft.com/ComputeCluster/" xmlns:xs="https://www.w3.org/2001/XMLSchema">
  <xs:complexType name="Task">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="EnvironmentVariables" nillable="true" type="tns:NameValueCollection" />
      <xs:element minOccurs="1" maxOccurs="1" name="ExtendedTerms" nillable="true" type="tns:NameValueCollection1" />
    </xs:sequence>
    <xs:attribute default="" name="AskedNodes" type="xs:string" />
    <xs:attribute name="CommandLine" type="xs:string" />
    <xs:attribute default="" name="Depend" type="xs:string" />
    <xs:attribute default="0" name="ExitCode" type="xs:int" />
    <xs:attribute default="0" name="Id" type="xs:int" />
    <xs:attribute default="false" name="IsExclusive" type="xs:boolean" />
    <xs:attribute default="false" name="IsRerunnable" type="xs:boolean" />
    <xs:attribute default="1" name="MaximumNumberOfProcessors" type="xs:int" />
    <xs:attribute default="1" name="MinimumNumberOfProcessors" type="xs:int" />
    <xs:attribute default="" name="Message" type="xs:string" />
    <xs:attribute default="" name="Name" type="xs:string" />
    <xs:attribute default="0" name="ParentJobId" type="xs:int" />
    <xs:attribute default="Infinite" name="Runtime" type="xs:string" />
    <xs:attribute default="NotSubmitted" name="Status" type="tns:TaskStatus" />
    <xs:attribute default="" name="Stdin" type="xs:string" />
    <xs:attribute default="" name="Stdout" type="xs:string" />
    <xs:attribute default="" name="Stderr" type="xs:string" />
    <xs:attribute default="" name="WorkDirectory" type="xs:string" />
  </xs:complexType>
  <xs:complexType name="NameValueCollection">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Variable" nillable="true" type="tns:NameValue" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="NameValue">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="1" name="Value" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="NameValueCollection1">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Term" nillable="true" type="tns:NameValue" />
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="TaskStatus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="NotSubmitted" />
      <xs:enumeration value="Queued" />
      <xs:enumeration value="Running" />
      <xs:enumeration value="Completed" />
      <xs:enumeration value="Failed" />
      <xs:enumeration value="Cancelled" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>