Skip to content

SF API Examples

Here, we show some example uses of the SF API as inspiration for your workflow. Please note that some examples may require a client with certain security level. The security level of all endpoints is stored in the x-nersc-scope field which you can find by clicking on an API endpoint at https://api.nersc.gov/api/v1.2.

Most of the following Python examples assume that a session has been created in the manner described below. However, general informational queries like system status can be made without authenticating.

from authlib.integrations.requests_client import OAuth2Session
from authlib.oauth2.rfc7523 import PrivateKeyJWT

token_url = "https://oidc.nersc.gov/c2id/token"
client_id = "<your client id>"
private_key = "<your private key>"

session = OAuth2Session(
    client_id, 
    private_key, 
    PrivateKeyJWT(token_url),
    grant_type="client_credentials",
    token_endpoint=token_url
)
session.fetch_token()

Checking System Status

To check the status of a given NERSC system, one can use the "status" method and specify the name of the NERSC system of interest. For example, to get the status of Perlmutter:

system = "perlmutter"
r = session.get("https://api.nersc.gov/api/v1.2/status/"+system)
perlmutter_status = r.json()
print(perlmutter_status)

This will print out something like:

{'name': 'perlmutter', 'full_name': 'Perlmutter', 'description': 'System is active', 'system_type': 'compute', 'notes': [], 'status': 'active', 'updated_at': '2021-07-22T04:55:00-07:00'}

To see the status of all NERSC systems, you can use the "status" method with no field, like so:

r = session.get("https://api.nersc.gov/api/v1.2/status")
systems_status = r.json()
print(systems_status)

Checking System Status without Logging In

You can also use the requests module to see system status without first creating a session.

import requests
system = "archive"
url = "https://api.nersc.gov/api/v1.2/status/"+system
resp = requests.get(url)
perlmutter_status = resp.json()
print(perlmutter_status)
print(perlmutter_status["status"])

Listing Directory Contents and File Information

Listing Directory Contents

To list the contents of a directory on a NERSC file system, the ls utility method can be used in combination with the directory of interest. For example, to list the contents of one's home directory on Perlmutter, we specify both the system and the full directory path to the request:

system = "perlmutter"
home = "<your home dir>" # (e.g., /global/homes/u/username)
r = session.get("https://api.nersc.gov/api/v1.2/utilities/ls/"+system+home)
home_ls = r.json()
print(json.dumps(home_ls, indent=2))

If the user elvis ran this command on their home directory which only contained a file called test.sh, an example of what this printout would look like is:

{
  "status": "ok",
  "entries": [
    {
      "perms": "drwx--x--x",
      "hardlinks": 75,
      "user": "elvis",
      "group": "elvis",
      "size": 12800.0,
      "date": "2020-01-01T00:00:00",
      "name": "."
    },
    {
      "perms": "drwxr-xr-x",
      "hardlinks": 594,
      "user": "root",
      "group": "root",
      "size": 64000.0,
      "date": "2020-01-01T00:00:00",
      "name": ".."
    },
    {
      "perms": "-rwxrwx---",
      "hardlinks": 1,
      "user": "elvis",
      "group": "elvis",
      "size": 30.0,
      "date": "2021-01-01T12:00:00",
      "name": "test.sh"
    },
  ],
  "error": null,
  "file": null,
  "is_binary": null
}

We can see here that the output contains the request status and the list of entries returned by the ls utility.

Retrieving File Information

The ls utility can also be used to see information about specific files. For example, if the user elvis wanted to know about the file test.sh in their home directory, they could use the command

system = "perlmutter"
filename = "/global/homes/e/elvis/test.sh"
r = session.get("https://api.nersc.gov/api/v1.2/utilities/ls/"+system+filename)
file_ls = r.json()
print(json.dumps(file_ls, indent=2))

which would print

{
  "status": "ok",
  "entries": [
    {
      "perms": "-rwxrwx---",
      "hardlinks": 1,
      "user": "elvis",
      "group": "elvis",
      "size": 30.0,
      "date": "2021-01-01T12:00:00",
      "name": "/global/homes/e/elvis/test.sh"
    }
  ],
  "error": null,
  "file": null,
  "is_binary": null
}

Running Commands and Scripts on Login Nodes

Running a Command on a Login Node

Running commands on a login node is done via POST requests to the /utilities/command path. This request takes two parameters:

  • A path parameter of the system name
  • A form data parameter executable, which is a string of the command you wish to run on the system

For example, to print a file's contents with the cat command, we would use a request like the following:

system = "perlmutter"
cmd = "cat <path to file>" # (e.g., "cat /global/homes/u/username/script.sh")
r = session.post("https://api.nersc.gov/api/v1.2/utilities/command/"+system,
                  data = {"executable": cmd})
print(r.json())

This will print the SF API task ID corresponding to the POST request and the status of the associated HTTP request:

{'task_id': '123', 'status': 'ok', 'error': None}

This feature requires elevated client permissions

See our API client policies

Getting Task Information and Output

To see the information associated with an SF API task (e.g., the output of the cat command run above), one can use a GET request on the tasks URL using the task_id like so:

r = session.get("https://api.nersc.gov/api/v1.2/tasks/123")
print(r.json())

This will print the task ID, the task status, and the task result:

{
  "id": "123",
  "status": "completed",
  "result": "{\"status\": \"ok\", \"output\": \"#!/bin/bash\\n#\\n#SBATCH -N 1\\n#SBATCH -C cpu\\n#SBATCH -q regular\\n#SBATCH -t 5\\n\\nsrun hostname\\n\\n\", \"error\": null}"
}

To look at the output of the cat command itself, we can extract the result of the task and then print the output of that result (here, we simply use the most recent task again):

result = json.loads(r['result'])
print(result["output"])

This will print:

#!/bin/bash
#
#SBATCH -N 1
#SBATCH -C cpu
#SBATCH -q regular
#SBATCH -t 5

srun hostname

which is the file contents that the cat command wrote to standard output.

Job Submission

Job submissions are done via POST requests to the /compute/jobs path. This request takes several parameters:

  • A path parameter of the system name
  • Form data parameters of the job script path on the file system and a boolean value indicating whether specified file is a job to be run via Slurm or a shell script to be run directly on a login node

Batch Job Submission

Here, we demonstrate submitting a job to the Slurm scheduler via the SF API. The system name, perlmutter, is placed in the URL path, following the API base path and the /compute/jobs path. Additionally, a data dictionary of key-value pairs is included in the POST request. The data dictionary specifies the job submission script path as the value to the job key and the value of True to the isPath key to indicate that the file should be sent to the Slurm scheduler.

system = "perlmutter"
submit_script = "<path to script>" # (e.g., /global/homes/u/username/script.sub)
r = session.post("https://api.nersc.gov/api/v1.2/compute/jobs/"+system,
                  data = {"job": submit_script, "isPath": True})
print(r.json())

The result output will include the SF API task ID, the status of the POST request, and any error text:

{'task_id': '124', 'status': 'ok', 'error': None}

POST request status does not indicate job submission status

The result output status is that of the POST request only and does not indicate whether or not the job submission was accepted by the Slurm scheduler.

This feature requires elevated client permissions

See our API client policies

Getting Job Status and Information

To see the information associated with jobs you have submitted via the SF API, one can use a GET request on the tasks URL (here task_id is 124):

r = session.get("https://api.nersc.gov/api/v1.2/tasks/124")
print(r.json())

This will print the SF API task ID, the status of the associated HTTP request, and the result of the request. For successful batch job submission, the request result will include the job ID of the submitted Slurm job.

{'id': '124',
 'status': 'completed',
 'result': '{"status": "ok", "jobid": "12345678", "error": null}'}