Skip to main contentIBM ST4SD

ST4SD Runtime Service API

The ST4SD runtime service (swagger available here) supports adding virtual experiment entries to a catalog and interacting with them, including:

  1. launching virtual experiment instances
  2. monitoring virtual experiment instances
  3. downloading outputs and measured properties of virtual experiment instances

ST4SD provides a python client for the ST4SD runtime service REST-API. The python client is currently part of st4sd-runtime-core. You can find instructions for installing the local client here.

The FAQ below assumes:

  1. you have already installed a local client.

How do I connect to the ST4SD runtime service?

First, you need to get the URL to the ST4SD runtime service endpoint. Ask the administrator of the ST4SD instance to provide this URL to you. They will also need to create an account for you on their ST4SD instance and configure RBAC so that your account can read Service objects in the namespace that ST4SD is installed in.

If the ST4SD instance is on IBM Cloud you will need to login to the OpenShift Web Console once so that IBM Cloud completes the setup of your account.

Connect to the ST4SD runtime service using an oauth-token

You need to obtain an auth-token. the python code below will open a URL in your browser. The web-page will ask you to login to ST4SD typically by delegating the authentication to the OpenShift server hosting ST4SD. If this is the very first time you login to this ST4SD URL you may be asked for your permission to allow ST4SD to know that you are logging in.

After you log in you will be presented with a page that contains your auth-token, copy it and return to this document. By default, this token expires every 168 hours (1 week).

import webbrowser
# enter the https:// ST4SD url below
url="https://${your ST4SD url}"
if url.endswith("/"):
url = url[:-1]
url = '/'.join([url, "authorisation/token"])

You should now have an auth-token. Use it below to login to ST4SD.

import experiment.service.db
# enter the https:// ST4SD url below
url="https://${your ST4SD url}"
# enter your auth-token below
auth_token="put your authentication/token - do not share it with anyone"
api=experiment.service.db.ExperimentRestAPI(url, cc_auth_token=auth_token)

The ExperimentRestAPI initializer validates the authentication token you provided and will raise an exception if it is invalid. If you do not get an Exception that means you can use api to interact with the st4sd-runtime-service and st4sd-datastore REST-APIs.

Connect to the ST4SD runtime service using an api-token

You can use the token that OpenShift associates with ServiceAccounts in the same namespace as your ST4SD to access the ST4SD microservices. You may want to use a API-key over an authorisation token if you need a way to authenticate to ST4SD that does not have an expiration date. For example if you build a MicroService that accesses the ST4SD microservices.

Generate an API-key using an OpenShift ServiceAccount:

  1. Create a new ServiceAccount on the same namespace as your ST4SD instance:

    • oc project <NAMESPACE_THAT_HOSTS_ST4SD>
    • oc create serviceaccount <SERVICE_ACCOUNT_NAME> (e.g. oc create serviceaccount sa-auth-st4sd)
  2. OpenShift creates 2 Secret objects for the ServiceAccount

    • <SERVICE_ACCOUNT_NAME>-token-<random-alphanumeric>:

      This is an OpenShift token that you can use to impersonate the ServiceAccount and log on the OpenShift cluster.

    • <SERVICE_ACCOUNT_NAME>.dockercfg or <SERVICE_ACCOUNT_NAME>.dockerconfigjson:

      That contains docker registry credentials and is used for pulling images from the private container registry of your OpenShift cluster - Openshift Image Registry.

  3. Bind the ServiceAccount <SERVICE_ACCOUNT_NAME> to the namespaced role st4sd-authenticate-microservice - we have configured oauth-proxy to authorize OpenShift users that can get services in the same namespace as the st4sd deployment. For that you can use the following snippet in a new role_binding.yaml file:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
    name: st4sd-custom-authenticated
    namespace: <NAMESPACE_THAT_HOSTS_ST4SD>
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: Role
    name: st4sd-authenticate-microservices

    Create the new RoleBinding object:

    oc create -f role_binding.yaml
  4. Extract the token of of the <SERVICE_ACCOUNT_NAME>-token-<random-alphanumeric> Secret. The secret may include the ca.crt and service-ca.crt fields that contain the CA certificate used for validating the OpenShift API server’s TLS certificate. However the token we want to extract is under the token field. The token in the Secret is base64 encoded meaning that you need to decode to its raw value after you extract it.

    • oc get secret <SERVICE_ACCOUNT_NAME>-token-<random-alphanumeric> -o jsonpath='{.data.token}' | base64 --decode | sed 's/$/\n/'
    • Save the raw value of the token in a bearer_key variable in your python code.
  5. Use your API-key to access ST4SD:

    import experiment.service.db
    # enter the https:// ST4SD url below
    url="https://${your ST4SD url}"
    bearer_key="<THE_SERVICEACCOUNT_KEY_YOU_EXTRACTED_ABOVE>"
    api=experiment.service.db.ExperimentRestAPI(url, cc_bearer_key=bearer_key)

Best practices:

  • Store the API-key in a secure way, immediately revoke it if it leaks.
    • You can revoke a API-key by deleting the Secret associated with that ServiceAccount and Openshift will auto-generate a new Secret to replace it.
  • Use each API-key in just one place.
    • For example, if you build 2 microservices and wish for both of them to have access to the ST4SD microservices you should repeat the above steps twice, once for each microservice.

How do I use the python api to ?

First, instantiate api = experiment.service.db.ExperimentRestAPI before you continue ay further. See How do I connect to the ST4SD runtime service? for instructions. Below, you will find a list of the most common actions you can do with the api.

How do I get a list of available experiments ?

Use api.api_experiment_list() to get the list of all registered experiments on your ST4SD registry. This API returns a dictionary with the following format:

{
"full-experiment-identifier@with-hash": {
a parameterised virtual experiment package definition
}
}

A parameterised virtual experiment package is a python dictionary (or YAML or JSON structure) that describes:

  • How to access a virtual experiment
  • What options to allow users to change
  • What options have preset values
  • Metadata about the package.

You can find more information on the structure of a parameterised package here.

How do I get the status of a virtual experiment instance?

All virtual experiment instances have a unique REST-API identifier. We use the term rest_uid to refer such identifiers.

# put here the rest_uid of the virtual experiment instance
rest_uid = "toxicity-predictions-trol7a"
status = api.api_rest_uid_status(rest_uid)

The variable status contains a plethora of information including metadata about the status of the virtual experiment instance and its outputs. Here, we will focus on the status.

Let’s try printing this information to get a better look:

import json
print(json.dumps(status['status'], indent=2))

Here is an example:

{
"experiment-state": "finished",
"total-progress": 1.0,
"exit-status": "Success",
"stages": [
"Toxicity-prediction"
],
"current-stage": "Toxicity-prediction",
"stage-state": "finished",

The virtual experiment instance above reports that:

  1. The orchestrator observed that the virtual experiment instance terminated (experiment-state = finished)
  2. The virtual experiment instance has produced all its outputs (total-progress = 1.0)
  3. The virtual experiment instance completed successfully (exit-status = Success)
  4. The experiment had 1 stage (stages = ["Toxicity-prediction"])
  5. Toxicity-prediction was the most recently executed stage with the lowest stage index (current-stage = Toxicity-prediction).
    1. All its tasks terminated and they were all successful (stage-state = finished)
    2. It reached its max progress (stage-progress = 1.0)
  6. The virtual experiment instance did not raise any errors (error-description = "")
Click to show the full specification of the status dictionary
  • exit-status: The status of the completed experiment. This receives its final value after experiment-state transitions to either finished or failed. Value is one of ["Success", "Failed", "Stopped", ""]. Value may be empty while Kubernetes initializes objects.
  • experiment-state: Indicates the state of the orchestrator that is executing the experiment tasks. Not to be confused with status of experiment (exit-status). For example, an experiment status can have experiment-state=finished with exit-status=failed. This means that the experiment completed with a failure. The value of experiment-state is one of ["unscheduled", "running", "finished", "failed", "unschedulable", ""]. Value may be empty while Kubernetes initializes objects.
  • stage-state: Indicates the state of the active stage in the experiment with the lowest stage index. Value is one of ["Initializing", "finished", "waiting_on_resource","running", "component_shutdown", "failed"]
  • error-description: A string, which when printed is a human readable description that explains why exit-status is Failed.
  • total-progress: A number in [0.0, 1.0] indicating the progress of the experiment. Note that workflow developers may decide to control this value.
  • stage-progress: A number in [0.0, 1.0] indicating the progress of the active stage with the lowest stage index. Note that workflow developers may decide to control this value.
  • stages: A list of human-readable stage names
  • current-stage: UID of stage (e.g. stage0)
  • meta: This is a nested dictionary
    • arguments: The command-line of the orchestrator
    • data: The list of files that override data files
    • input: The list of input files
    • pid: The process ID of the st4sd orchestrator
    • platform: The name of the platform that the virtual experiment instance executes
    • userVariables: User provided variables, the schema is {'global':{name:value}, 'stages':{index:{name:value}}}
    • variables: Global and stage variables active in the platform-scope that the virtual experiment executes. The schema is {'global':{name:value}, 'stages':{index:{name:value}}}
    • hybridPlatform: Name of hybrid-platform for communicating with LSF (can be None),
    • userMetadata: A dictionary with key(str): Any value pairs that users can provide
    • instanceName: The name of the directory containing the virtual experiment instance.
    • version: The version of the st4sd orchestrator

How do I find out the key-outputs of my experiment ?

Recall that the definition of a virtual experiment contains an optional key-outputs dictionary that describes its outputs. If you have direct access to the source code of the experiment you can just read this output dictionary. It’s a field under the entrypoint of DSL 2.0 experiments and a top-level field for experiments that use the older FlowIR schema.

If your experiment is already registered on your ST4SD registry you can use the api_experiment_get() method to get the Parameterised Virtual Experiment Package (PVEP) of your experiment. You will find the metadata about the key-outputs of your experiment under the field metadata.registry.output. For more information on the metadata that the ST4SD registry automatically generates for your experiments see our docs.

How do I find out the key-outputs of an instance of my experiment ?

A virtual experiment may have several key-outputs but an instance (i.e. execution) of this virtual experiment may not have succeeded in producing all its key-outputs. To find out the available outputs of an instance for an experiment use the method api.api_rest_uid_output_list(rest_uid=${instance uid})

The API will return the following dictionary containing 1 entry for each available key-output:

{
"name of key-output": {
"creationtime": a floating point epoch number,
"description": "The value of the @description field in the definition of this key-output",
"filename": "The filename e.g. foo.bar",
"filepath": "The path to the file relative to the instance dir e.g. stages/stage2/MyComponent/foo.bar",
"type": "The value of the @type field in the definition of this key-output",
}
}

How do I download the key-outputs of my experiment ?

Use the method api.api_rest_uid_output_get(rest_uid=${instance uid}, output_name=${name of key-output}).