Exposing system status information via Balena SDK

Hi, y’all

I’ve got a python script that currently monitors all my Balena devices using the fabulous Balena SDK. I’m thinking of expanding the script to include status info about my container applications, so I can easily check if all processes are running, etc. I’ve managed to do this by using Device Environment Variables (balena.models.environment_variables.device), but my gut feeling tells me that this is an ugly hack. Is there a better way to do this?

I already tried to use the dict in balena.models.device.get(uuid), but any changes to the dict is not reflected outside my device. So far, Device Environment Variables seems to be my only optinon.

Hey @erlendaasland ,

Do you mean you are using device environment variables to check the status of the containers?

I already tried to use the dict in balena.models.device.get(uuid), but any changes to the dict is not reflected outside my device. So far, Device Environment Variables seems to be my only optinon.

Can you expand more on “any changes to the dict is not reflected outside my device”? Are trying to set device environment variables using the SDK? That shouldn’t be needed in order to read the status of the containers back, right?

Hi, @jviotti, and thanks for your reply.

Do you mean you are using device environment variables to check the status of the containers?

I’ve got a set of ROS nodes running inside my containers, and I’d like to be able to retrieve a list of all running nodes via the SDK. So, per now, I’ve made a proof-of-concept script where I push this information into a variable on the device, and then read it back from my script on my laptop.

Can you expand more on “any changes to the dict is not reflected outside my device”?

Of course. If you use dev = balena.models.device.get(uuid), the SDK returns a python dictionary with a set of status variables (‘uuid’, ‘is_online’, etc.). I figured the easy fix to my problem was to do dev['test'] = 'somefancythings', but any changes in this dictionary seems to be local, and thus does not show when I try to read them back using my script. Try it, and you’ll get a KeyError, because your custom key is not available.

Are trying to set device environment variables using the SDK?

That’s what I’m doing now, and it works, but I’m pretty sure this isn’t orthodox use of dev env variables.

That shouldn’t be needed in order to read the status of the containers back, right?

Nope. I use balena.models.device to collect what I need from Balena.

Hi @erlendaasland . Just jumping into this, they way I would probably approach getting the services from specific devices would be via the supervisor proxy api, basically just doing a python request similar to:

curl -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <auth token>' \
  -d '{"uuid": "<uuid>", "method": "GET"}' \
  "https://api.balena-cloud.com/supervisor/v2/applications/state"

which would return something like:

{
  "appname": {
    "appId": 1011165,
    "commit": "217d55237092995e4576367e529ebb03",
    "services": {
      "main": {
        "status": "Downloaded",
        "releaseId": 557617,
        "downloadProgress": null
      },
      "frontend": {
        "status": "Downloading",
        "releaseId": 557631,
        "downloadProgress": 0
      },
      "proxy": {
        "status": "Downloaded",
        "releaseId": 557631,
        "downloadProgress": null
      },
      "data": {
        "status": "Downloading",
        "releaseId": 557631,
        "downloadProgress": 7
      },
      "metrics": {
        "status": "Downloading",
        "releaseId": 557631,
        "downloadProgress": 35
      }
    }
  }
}

Hi, @shaunmulligan! Thanks, but I’m not interested in the «balena services», I’m interested in process specific information inside my «main» service, so unfortunately, this is no solution to my problem.

Hi @erlendaasland , sorry I seem to be confused about what you are trying to achieve, I interpreted “nodes” as containers (people use this term for all kinds of things these days :/) What type of process specific info are you trying to capture and how dynamic is it? it definitely doesn’t seem like env vars are the right way to go, since changing an env var on a device or service will cause that service to be restarted, which I assume is unwanted behaviour. I think the device tags feature is probably more suitable for this type of data, but would need to have a example of what the data looks like and how dynamic it is to say for sure.

1 Like

Sorry, @shaunmulligan, I should’ve been more specific! (And, yes, everybody uses «nodes» and «services» about all sorts of stuff, nowadays!)

The information I’m trying to transfer is kinda like the output of a ps command on Linux. It’s not very dynamic, but I would like to create some kind of notification if one of my processes crashes for whatever reason. A 1 hour update interval would be sufficient. Of course, as you mention, I can’t live with the service being restarted, so I need another approach.

I’ll check if tags is the way to go. Thanks!

Cool, thanks for the info, I think definitely tags are the right way to go for this, it was designed to add additional meta data to the device resource, so seems appropriate for this type of info.

1 Like

Great, thanks, @shaunmulligan!