Application default device type

Hi!

We created an application with default device type of RPi3.
We can manually add to it devices of type both RPi3 & 4.
However, when we do the same operation via the cli, by calling

balena config generate

with the parameter

–device-type raspberrypi4-64

we get the error:

BalenaInvalidDeviceType: Invalid device type: Device type raspberrypi4-64 is incompatible with application RavenDB

The device itself is able to boot, and is displayed as RPi3 in the cloud, although it is actually RPi4.

  1. What is the significance of default device type for an application?
  2. Why an application cannot contain different devices? In other words - we would prefer it to be device agnostic and be capable of containing devices of different types.
  3. Why does the cli behave differently then the manual provisioning via the cloud dashboard?

Thanks!
Vitaliy

Hi Vitaliy,

A device type in balena describes devices that have the same boot configuration and are capable of booting the same Operating system. When a new device type is created, it is usually because the system-on-a-chip (SoC) or configuration is distinctly different from others that exist.

As an example, the Raspberry Pi 1 model B+ and Raspberry Pi Zero W are part of the same device type since they are both armv6l architecture SoCs and the boot loader is capable of booting both boards. However, the Raspberry Pi 3 model B+ is by default a armv7l CPU and we therefore separate it into a new device type.

In balenaCloud the device type is also used to define what architecture the built containers for each app will be. So in the above example RPi ZERO deployments are built for the armv6l architecture where as RPi 3 applications will target the armv7l architecture and the Intel NUC device type will target x86_64 architecture.

Since your original app was created with RPi 3, have you tried defining the --device-type as raspberrypi3-64 or raspberrypi3?

John

Thank you John for the response,

I still don’t understand the following points:

  1. Why a balena application cannot host devices with different device types?
    We don’t want to define an app per device…
  2. Why does the cli behave differently then the manual provisioning via the cloud dashboard?
  3. What does the default device type of an application effect?

Thanks,
Vitaliy

Hi @Vitaliy,

Balena application can host various device types, as long as all of them are of the same or a compatible device type as the selected default device type of the application.
That is, you can have an Raspberry Pi 3 application having both Raspberry Pi 3s and Raspberry Pi 4s, but not Raspberry Pi Zeros.
That’s because the images are built only for the CPU architecture of the application’s default device type, and devices can only run executables of architectures that they have compatibility with.
The default device type of an application is what controls the architecture for which the images will be build for.
Let me point you to the respective FAQ entry in our documentation page:
https://www.balena.io/docs/faq/troubleshooting/faq/#can-i-mix-device-types-in-an-application

Regarding the issue that you are facing it seems that this is a limitation of the balena-cli which we should definitely fix.
I’ve opened a GitHub issue for this, which you can use to track progress:

We will give you a note once this gets implemented and released.

Kind regards,
Thodoris

1 Like

Hello @Vitaliy

Just to let you know that we’ve implemented the fix that allows the use of mixed architectures on the CLI’s config generate command.

Cheers,
Nico

1 Like

Awesome, Thanks allot @thgreasi & @ntzovanis for the exceptionally quick fix!

Please note that the error in cli is resolved,
however I still see in the cloud’s dashboard a wrong device type - although I specified raspberrypi4-64 in the command, RPi 3 is displayed as the type of the device.
The command:

balena config generate --device-type raspberrypi4-64

still generates a config file, with

“deviceType”: “raspberrypi3”

I believe that might be the reason.

Many Thanks,
Vitaliy

Can you please confirm the exact balena config generate command that you used, since the one you mentioned does error complaining of missing arguments?
Please also confirm:

  • the exact commands that you used to inject the generated config to the balenaOS images.
  • how the image that this was injected was downloaded and that it is indeed for a Rasperry Pi 4. Was this downloaded from the balenaCloud dashboard? If so confirming that raspberrypi4-64 is part of the filename should make things cleaner.

Kind regards,
Thodoris

I can confirm that running :

balena config generate --app myRPi3App --version 2.51.1 --device-type raspberrypi4-64

on my side with balena-cli v12.5.0 does generate a config with thedeviceType: raspberrypi4-64 field as expected.

Sure @thgreasi !

Here’s our sequence of commands:

balena os download raspberrypi4-64 -o device.img --version v2.51.1+rev1

balena preload device.img --app APP --commit current

balena device register APP
This command returns a UUID which we store into $UUID

balena config generate --device $UUID --version v2.51.1+rev1 --network ethernet --appUpdatePollInterval 10 --app APP --device-type raspberrypi4-64 --o config.json

config inject config.json --type raspberrypi4-64 -d /dev/sda

Please see resulting config.json file, with some sensitive field values changed to 9999999999 & XXXXXXX:

{
“applicationId”: 99999999,
“deviceType”: “raspberrypi3”,
“userId”: 99999999,
“appUpdatePollInterval”: 600000,
“listenPort”: 48484,
“vpnPort”: 443,
“apiEndpoint”: “https://api.balena-cloud.com”,
“vpnEndpoint”: “vpn.balena-cloud.com”,
“registryEndpoint”: “registry2.balena-cloud.com”,
“deltaEndpoint”: “https://delta.balena-cloud.com”,
“mixpanelToken”: “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”,
“files”: {
“network/settings”: “[global]\nOfflineMode=false\nTimeUpdates=manual\n\n[WiFi]\nEnable=true\nTethering=false\n\n[Wired]\nEnable=true\nTethering=false\n\n[Bluetooth]\nEnable=true\nTethering=false”,
“network/network.config”: “[service_home_ethernet]\nType = ethernet\nNameservers = 8.8.8.8,8.8.4.4”
},
“connectivity”: “connman”,
“deviceApiKey”: “XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”,
“registered_at”: 9999999999999,
“deviceId”: 9999999999,
“uuid”: “XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX”
}

That makes things clear.
The issue is that the device is pre-registered with balena device register and you can see that after that point the device shows up in the dashboard with a device type matching the default device type of the application.
As a result, when you later use balena config generate you change the device type of the already registered device.
Perhaps it might be better to have the CLI error when ---device and --device-type are used together, so that it’s clear which option is respected.
It also seem that in order to be able to cover your use case, we should also add a --device-type parameter to the belana device register command.

We will let you know once these get implemented and released.

Kind regards,
Thodoris

Great, thanks allot @thgreasi!

Hi @thgreasi
we are running into the same issues. We have a mixed fleet of RPI3 and RPiZero2W devices but all are displayed as Raspberry PI 3.
Using the similar approach:

  • Downloading the image for the desired device type (Raspberry Pi Zero 2W, 64bit)
  • Flash it using etcher
  • Register device (balena device reigster --uuid
  • balena config generate --device --version – output config.json
  • copying the config.json to the resin-boot partition

Devices are displayed as Rasperrby Pi 3.
Two questions:

  1. How can we now detect the correct device type (and set it to be displayed correctly in Dashboard)?
  2. How can we flash/configure the devices correctly in the future?

Thanks

Hi @fritz,
The balena device register command at the moment doesn’t support specifying a specific device, which result be registered device to use the fleet’s default device type by default.
Can you clarify how you inject the uuid that you use in the balena device register --uuid step, into the config.json that ends up in the device?

Kind regards,
Thodoris

Hi @thgreasi,
as stated, via
balena config generate --device $DEVICE_UUID ... --output config.json
and then copying the file to the resin-boot partition.
Clear so far?

Thanks
Cheers

I see @fritz .
I think the correct approach is to allow user to specify a different device type as a parameter to the balena device register command in the balena-cli.
This currently is not supported, but I’ve opened a GitHub issue about it and associated it with this thread so that we can let you know once it gets implemented.
Let me also point you there so that you can track progress:
See: Balena device register should allow specifying the device type · Issue #2531 · balena-io/balena-cli · GitHub

Kind regards,
Thodoris

Thanks @thgreasi,
anyway: is there a way in the meantime for us to find out the real device type that is running in the field?
Thanks!
Fritz

Hi @fritz,
I would like to let you know that we just released balena-cli v14.4.0 which adds a --deviceType option to the balena device register command, which allows you to properly provision new devices of different device type than the default of your mix fleets.

As of figuring out the actual device type of a device record, I would suggest you to use the webterminal to SSH into the HostOS of the device and from there run cat /etc/os-release and check the value that it holds on either the MACHINE or the SLUG property.
This should hold the device type of the OS image that you provisioned, so it’s the most accurate thing to check.

Kind regards,
Thodoris

Hi @thgreasi
thanks for that, will give it a try.
How are the chances that this check (for existing devices) might be automated into a future OS release, or similar os that the devices are updated?
We have thousands of devices and SSHing into the individually is not possible I fear…
Thanks!

@fritz are you saying that you have provisioned thousands of devices that show up as being of the wrong device type in the dashboard?
What device do they show up and what OS image was used for provisioning?
Having them showing the wrong device type can cause issues by accidentally downloading a supervisor release of a potentially incompatible architecture.
Moreover this needs to be fixed before running any HostOS update, because otherwise the update might fail or even complete but with the device not being able to boot because it applied the wrong hostApp release.

With “automate” you mean having devices update our backend to set the correct device type of the OS if it’s different?
I will pass this internally for consideration but let me give you a workaround in the mean time that can be scripted.
You can query run commands in the HostOS by simply piping balena ssh, so in this case you can do something like:

echo "cat /etc/os-release | grep MACHINE; exit;" | balena ssh <uuid>

and that will give you back the device type of the OS image.
Then you can parse and store the device type into a variable and find the device type id by doing:

curl $'https://api.balena-cloud.com/v6/device_type(slug=\'<DEVICE_TYPE_SLUG>\')' | jq ".d[0].id"

and finally you can fix the device type of the device if needed by doing:

curl $'https://api.balena-cloud.com/v6/device(uuid=\'<DEVICE_UUID>\')' \
  -X 'PATCH' \
  -H 'authorization: Bearer <TOKEN>' \
  -H 'content-type: application/json' \
  --data-raw '{"is_of__device_type": <CORRECT_DEVICE_TYPE_ID>}'

Please make sure to first try this in a local test device before you apply it to production devices.

Kind regards,
Thodoris

Hi @thgreasi
thanks for the comprehensive explanation! Great support.
In fact we have thousands of devices where roughly 98% are RPi3s but recently we switched to RPI Zero and did notice too late that in the dashboard the device type is not shown properly (we test our application and tried it first in dedicated fleet whose starting point was a RPI Zero, and there it was fine). Then we deployed a bunch of devices to the main fleet and did not notice early enough the wrong device type.

Regarding “automate”: yes, that would be great that in some point in time it would be auto-detected and e.g. a warning issued that the device type is wrong.
But the workaround looks good so far!

Thanks and cheers,
Fritz