Containerization

Containerization is the process of encapsulating the running environment for one or more given programs, and being able to execute them in an isolated virtual environment as close as possible to the OpenDrives storage (without actually being on it). This allows us to make sure we are not affecting core functionality of the system, while still allowing core extensibility (maximizized performance and minimized latency).

These preformulated, encapsulated environment configurations are referred to as Recipes.The isolated virtual environment created as an executable instance of a Recipe is called a Pod.

Basic Operations

For Recipes, the basic operations of List and Get are available.

For Pods, the basic operations of Create, List, Get, Update, and Destroy are available. Furthermore, you may Inspect, Get Logs of, Test the Valid Configuration of, Pause, Unpause, and Kill Pods. To Enable and Disable Pods, please refer to the System Services documentation.

For initial System Configuration (required before first time Pod creation), the operations of Get and Set Config are available.

List all Pods

Call to /pod to get all Pods

Request Object

+ URL
  /api/v2/pod

+ Method
  GET

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns an array of objects with Pod name and Pod service information

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  [
    {
        "name": "od-pod-my-dashboard",
        "service": {
            "id": "od-pod-my-dashboard.service",
            "state": "offline",
            "locked": true
        }
    },
    {
        "name": "od-pod-my_folding_at_home",
        "service": {
            "id": "od-pod-my_folding_at_home.service",
            "state": "online",
            "locked": true
        }
    },
    {
        "name": "od-pod-postgres_latest",
        "service": {
            "id": "od-pod-postgres_latest.service",
            "state": "disabled",
            "locked": false
        }
    }
  ]

Get a specific pod

Call to /pod/$NAME/details to get a specific pod

Request Object

+ URL
  /api/v2/pod/$NAME/details

+ Method
  GET

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like back

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns an object with the configuration and service information of the Pod you requested

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "name": "od-pod-postgres_latest",
    "compose_file": {
        "version": "3",
        "services": {
            "postgres_pg": {
                "network_mode": "host",
                "image": "postgres:latest",
                "ports": [
                    "5432:5432"
                ],
                "volumes": [
                    "/usr/share/canteen/data/od-pod-postgres_latest/postgres_pg/data:/var/lib/postgresql/data"
                ],
                "environment": {
                    "POSTGRES_PASSWORD": "postgres",
                    "POSTGRES_USER": "postgres"
                }
            }
        }
    },
    "service": [
        {
            "id": "od-pod-postgres_latest.service",
            "state": "disabled",
            "locked": false
        }
    ]
  }

Create a new pod

To create a pod, make a call to /pod/$NAME/set with the JSON fileContents from the Recipe, and an array of the Recipe names used in the Body.

Request Object

+ URL
  /api/v2/pod/$NAME/set

+ Method
  POST

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to create
  fileContents (object, required, body) - a json object containing the version and services of the pod
  recipes (array, optional, body) - an array of recipes for suggested pod configurations on your OpenDrives system. Call to /pod/suggested to list all recipes available.

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {
    "fileContents": {
        "version": "3",
        "services": {
          "hello_world": {
              "image": "ubuntu",
              "command": [
                "/bin/echo",
                "Hello world"
              ]
          },
          "my-website": {
              "build": "static_site/image/",
              "ports": [
                "3001:3000"
              ],
              "volumes": [
                "/usr/share/canteen/data/od-pod-hello-site/static_site/www/:/www/"
              ],
              "restart": "always"
          }
        }
    },
    "recipes": [
        "hello_world",
        "static_site"
    ]
  }

Response Object

Returns an object with the configuration and service information of the Pod you created

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "name": "od-pod-test",
    "compose_file": {
        "version": "3",
        "services": {
            "hello_world": {
                "image": "ubuntu",
                "command": [
                    "/bin/echo",
                    "Hello world"
                ]
            },
            "my-website": {
                "build": "static_site/image/",
                "ports": [
                    "3001:3000"
                ],
                "volumes": [
                    "/usr/share/canteen/data/od-pod-test/static_site/www/:/www/"
                ],
                "restart": "always"
            }
        }
    },
    "service": [
        {
            "id": "od-pod-test.service",
            "state": "disabled",
            "locked": false
        }
    ]
  }

Update an existing pod

To update a pod, make a call to /pod/$NAME/update with the changed JSON fileContents, and an array of any added Recipe names used in the Body.

Request Object

+ URL
  /api/v2/pod/$NAME/update

+ Method
  POST

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to update
  fileContents (object, required, body) - a json object containing the version and services of the pod
  recipes (array, optional, body) - an array of recipes for suggested pod configurations on your OpenDrives system. Call to /pod/suggested to list all recipes available.

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {
    "fileContents":{
        "version":"3",
        "services":{
          "hello_world":{
              "image":"ubuntu",
              "command":[
                "/bin/echo",
                "Hello world, how do you do?"
              ]
          },
          "my-website":{
              "build":"static_site/image/",
              "ports":[
                "3002:3000"
              ],
              "volumes":[
                "/usr/share/canteen/data/od-pod-hello-site/static_site/www/:/www/"
              ],
              "restart":"always"
          }
        }
    },
    "recipes":[]
  }

Response Object

Returns an object with the configuration and service information of the Pod you updated

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "name": "od-pod-test",
    "compose_file": {
        "version": "3",
        "services": {
            "hello_world": {
                "image": "ubuntu",
                "command": [
                    "/bin/echo",
                    "Hello world, how do you do?"
                ]
            },
            "my-website": {
                "build": "static_site/image/",
                "ports": [
                    "3002:3000"
                ],
                "volumes": [
                    "/usr/share/canteen/data/od-pod-test/static_site/www/:/www/"
                ],
                "restart": "always"
            }
        }
    },
    "service": [
        {
            "id": "od-pod-test.service",
            "state": "disabled",
            "locked": false
        }
    ]
  }

Destroy a pod

Call /pod/$NAME/destroy to destroy the pod and its associated service file from the system

Request Object

+ URL
  /api/v2/pod/$NAME/destroy

+ Method
  POST

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to destroy

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns the output of destroying the pod.

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "containerResponse": "",
    "serviceResponse": {}
  }

Inspect a pod

Call /pod/$NAME/inspect to inspect the pod’s container statuses and running processes

Request Object

+ URL
  /api/v2/pod/$NAME/inspect

+ Method
  GET

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to inspect

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns an object of the Pod name, container statuses, and running processes

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "name":"od-pod-my_folding_at_home",
    "container_status":"    Name        Command   State   Ports\n---------------------------------------\nfoldingathome   /init     Up           \n",
    "running_processes":"foldingathome\n  UID      PID    PPID   C   STIME   TTY     TIME                                                         CMD                                                     \n------------------------------------------------------------------------------------------------------------------------------------------------------------------\nroot       9116   9092   0   Sep17   ?     00:00:00   s6-svscan -t0 /var/run/s6/services                                                                          \nroot       9198   9116   0   Sep17   ?     00:00:00   s6-supervise s6-fdholderd                                                                                   \nroot       9656   9116   0   Sep17   ?     00:00:00   s6-supervise foldingathome                                                                                  \nhasShell   9659   9656   0   Sep17   ?     00:22:10   /app/usr/bin/FAHClient --http-addresses 0.0.0.0:7396 --allow 0/0 --web-allow 0/0 --command-allow-no-pass 0/0\n"
  }

Get Logs of a pod

Call /pod/$NAME/log to get the system logs of the pod’s service

Request Object

+ URL
  /api/v2/pod/$NAME/log

+ Method
  GET

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to get logs of

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns the log output of the Pod service

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  "Attaching to foldingathome\nfoldingathome      | [s6-init] making user provided files available at /var/run/s6/etc...exited 0.\nfoldingathome      | [s6-init] ensuring user provided files have correct perms...exited 0.\nfoldingathome      | [fix-attrs.d] applying ownership & permissions fixes...\nfoldingathome      | [fix-attrs.d] done.\nfoldingathome      | [cont-init.d] executing container initialization scripts...\nfoldingathome      | [cont-init.d] 01-envfile: executing... \nfoldingathome      | [cont-init.d] 01-envfile: exited 0.\nfoldingathome      | [cont-init.d] 10-adduser: executing... \nfoldingathome      | \nfoldingathome      | -------------------------------------\nfoldingathome      |           _         ()\nfoldingathome      |          | |  ___   _    __\nfoldingathome      |          | | / __| | |  /  \\ \nfoldingathome      |          | | \\__ \\ | | | () |\nfoldingathome      |          |_| |___/ |_|  \\__/\nfoldingathome      | \nfoldingathome      | \nfoldingathome      | Brought to you by linuxserver.io\nfoldingathome      | -------------------------------------\nfoldingathome      | \nfoldingathome      | To support the app dev(s) visit:\nfoldingathome      | Folding@home: https://foldingathome.org/about/donate/\nfoldingathome      | \nfoldingathome      | To support LSIO projects visit:\nfoldingathome      | https://www.linuxserver.io/donate/\nfoldingathome      | -------------------------------------\nfoldingathome      | GID/UID\nfoldingathome      | -------------------------------------\nfoldingathome      | \nfoldingathome      | User uid:    1000\nfoldingathome      | User gid:    1000\nfoldingathome      | -------------------------------------\nfoldingathome      | \nfoldingathome      | [cont-init.d] 10-adduser: exited 0.\nfoldingathome      | [cont-init.d] 50-config: executing... \nfoldingathome      | [cont-init.d] 50-config: exited 0.\nfoldingathome      | [cont-init.d] 60-gid-video: executing... \nfoldingathome      | [cont-init.d] 60-gid-video: exited 0.\nfoldingathome      | [cont-init.d] 99-custom-scripts: executing... \nfoldingathome      | [custom-init] no custom files found exiting...\nfoldingathome      | [cont-init.d] 99-custom-scripts: exited 0.\nfoldingathome      | [cont-init.d] done.\nfoldingathome      | [services.d] starting services\nfoldingathome      | [services.d] done.\nfoldingathome      | 22:26:37:Trying to access database...\nfoldingathome      | 22:26:37:Successfully acquired database lock\nfoldingathome      | 22:26:37:Read GPUs.txt\nfoldingathome      | 22:26:37:Enabled folding slot 00: READY cpu:11\nfoldingathome      | 22:26:37:****************************** FAHClient ******************************\nfoldingathome      | 22:26:37:    Version: 7.6.13\nfoldingathome      | 22:26:37:     Author: Joseph Coffland <joseph@cauldrondevelopment.com>\nfoldingathome      | 22:26:37:  Copyright: 2020 foldingathome.org\nfoldingathome      | 22:26:37:   Homepage: https://foldingathome.org/\nfoldingathome      | 22:26:37:       Date: Apr 28 2020\nfoldingathome      | 22:26:37:       Time: 04:20:16\nfoldingathome      | 22:26:37:   Revision: 5a652817f46116b6e135503af97f18e094414e3b\nfoldingathome      | 22:26:37:     Branch: master\nfoldingathome      | 22:26:37:   Compiler: GNU 8.3.0\nfoldingathome      | 22:26:37:    Options: -std=c++11 -ffunction-sections -fdata-sections -O3 -funroll-loops\nfoldingathome      | 22:26:37:             -fno-pie\nfoldingathome      | 22:26:37:   Platform: linux2 4.19.0-5-amd64\nfoldingathome      | 22:26:37:       Bits: 64\nfoldingathome      | 22:26:37:       Mode: Release\nfoldingathome      | 22:26:37:       Args: --http-addresses 0.0.0.0:7396 --allow 0/0 --web-allow 0/0\nfoldingathome      | 22:26:37:             --command-allow-no-pass 0/0\nfoldingathome      | 22:26:37:     Config: /config/config.xml\nfoldingathome      | 22:26:37:******************************** CBang ********************************\nfoldingathome      | 22:26:37:       "

Test a pod

Call /pod/$NAME/test to test the Pod Name and the JSON fileContents in the Body

Request Object

+ URL
  /api/v2/pod/$NAME/test

+ Method
  POST

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to test

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {
    "fileContents":{
        "version":"3",
        "services":{
          "hello_world":{
              "image":"ubuntu",
              "command":[
                "/bin/echo",
                "Hello world"
              ]
          },
          "my-website":{
              "build":"static_site/image/",
              "ports":[
                "3002:3000"
              ],
              "volumes":[
                "/usr/share/canteen/data/od-pod-test/static_site/www/:/www/"
              ],
              "restart":"always"
          }
        }
    }
  }

Response Object

Returns an object with the valid JSON fileContents, and with a boolean to indicate if the Pod name already exists on the system

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "name": "od-pod-hello-world",
    "data": {
        "version": "3",
        "services": {
            "hello_world": {
                "image": "ubuntu",
                "command": [
                    "/bin/echo",
                    "Hello world"
                ]
            },
            "my-website": {
                "build": "static_site/image/",
                "ports": [
                    "3002:3000"
                ],
                "volumes": [
                    "/usr/share/canteen/data/od-pod-test/static_site/www/:/www/"
                ],
                "restart": "always"
            }
        }
    },
    "exists": false
  }

Pause a pod

Call /pod/$NAME/pause to pause the running processes of the Pod

Request Object

+ URL
  /api/v2/pod/$NAME/pause

+ Method
  POST

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to pause

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns the output of pausing all the processes of the Pod

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  "Pausing od-pod-hello-site_my-website_1 ... \r\n\rPausing od-pod-hello-site_my-website_1 ... done\r"

Unpause a pod

Call /pod/$NAME/unpause to unpause all the processes of the Pod

Request Object

+ URL
  /api/v2/pod/$NAME/unpause

+ Method
  POST

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to unpause

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns the output of unpausing all the processes of the Pod

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  "Unpausing od-pod-hello-site_my-website_1 ... \r\n\rPausing od-pod-hello-site_my-website_1 ... done\r"

Kill a pod

Call /pod/$NAME/kill to kill all the containers in the Pod

Request Object

+ URL
  /api/v2/pod/$NAME/kill

+ Method
  POST

+ Parameters
  pod name (string, required, URL param) - the name of the pod you'd like to kill

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns the output of killing all the processes of the Pod

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  "Killing od-pod-hello-site_my-website_1 ... \r\n\rKilling od-pod-hello-site_my-website_1 ... done\r"

List all Recipes

Call to /pod/suggested to get all Recipes

Request Object

+ URL
  /api/v2/pod/suggested

+ Method
  GET

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns an array of Recipe names

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  [
    "code-server",
    "folding_at_home",
    "goofys3mounter",
    "harbor-registry",
    "hello_world",
    "kazuhm_host_agent",
    "minio",
    "node_red",
    "od_stats_dash",
    "openspeedtest",
    "pgadmin4",
    "plex",
    "postgres_davinci",
    "postgres_latest",
    "splunk_universal_forwarder",
    "static_site"
  ]

Get a specific Recipe

Call to /pod/suggested/$NAME to get a specific pod

Request Object

+ URL
  /api/v2/pod/suggested/$NAME

+ Method
  GET

+ Parameters
  recipe name (string, required, URL param) - the name of the recipe you'd like back

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns an object with the suggested configuration you requested

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "name": "folding_at_home",
    "description": "A distributed computing project for performing molecular dynamics simulations of protein dynamics.",
    "images": [
        "linuxserver/foldingathome"
    ],
    "version": "1.0.0",
    "services": [
        {
            "service_name": "folding_at_home",
            "service_config": {
                "image": "linuxserver/foldingathome",
                "container_name": "foldingathome",
                "environment": [
                    "PUID=1000",
                    "PGID=1000",
                    "TZ=America/LosAngeles",
                    "NVIDIA_VISIBLE_DEVICES=none"
                ],
                "volumes": [
                    "./foldingathome/config:/config"
                ],
                "ports": [
                    "7396:7396"
                ],
                "restart": "unless-stopped"
            }
        }
    ]
  }

Get System Configuration

Call to /pod/config to get the configuration of /etc/docker/daemon.json and the mount location of the pod data, if it exists.

Request Object

+ URL
  /api/v2/pod/config

+ Method
  GET

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {}

Response Object

Returns, an object containing the configuration of /etc/docker/daemon.json

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
{
    "daemonJson": {
        "data-root": "/usr/share/docker",
        "storage-driver": "zfs",
        "storage-opts": [
            "zfs.fsname=rpool/docker"
        ]
    },
    "podDataMount": {
        "source": "Pool1/MyPodData",
        "mountpoint": "/usr/share/canteen/data",
        "type": "zfs",
        "options": {
            "rw": true,
            "mand": true,
            "noatime": true,
            "xattr": true,
            "posixacl": true
        },
        "fs_freq": 0,
        "fs_passno": 0
    }
}

Set System Configuration

To set a system configuration, make a call to /pod/config with the configJson, podImageFs, and podDataFs in the Body.

Request Object

+ URL
  /api/v2/pod/config

+ Method
  POST

+ Headers
  Content-Type: application/json
  token: ThisIsNotARealTokenGenerateYourOwnToken

+ Body
  {
    "configJson":{
        "data-root":"/usr/share/docker",
        "storage-driver":"zfs",
        "storage-opts":[
          "zfs.fsname=Pool1/myDockerImages"
        ]
    },
    "podImageFs":"Pool1/myDockerImages",
    "podDataFs":"Pool1/myDockerPods"
  }

Response Object

Returns an object with the podImageFs and podDataFs selected

+ Headers
  X-Powered-By: OpenDrives
  Access-Control-Allow-Origin: *
  Content-Type: application/json; charset=utf-8

+ Body
  {
    "podImageFs":"Pool1/myDockerImages",
    "podDataFs":"Pool1/myDockerPods"
  }