Cleanbuild remote on pi grabs wrong arch lxc image

I’ve setup Ubuntu Core and lxd on a remote Pi. If I use “snapcraft cleanbuild --remote pi” on my laptop, it ships the build over to the pi, but errors with:-

$ snapcraft cleanbuild --remote pi2
Creating snapcraft-mildly-pumped-liger
error: Requested architecture isn't supported by this host
Stopping pi2:snapcraft-mildly-pumped-liger
error: not found

Looking at the lxd logs on the pi, I see:-

alias=xenial/amd64 image=8fa08537ae51c880966626561987153e72d073cbe19dfe5abc062713d929254d lvl=info msg="Downloading image" operation=2473916e-5f52-49f7-b9de-d1399487f25c server=https://cloud-images.ubuntu.com/releases t=2017-05-19T09:02:39+0000 trigger=/1.0/operations/2473916e-5f52-49f7-b9de-d1399487f25c
alias=xenial/amd64 image=8fa08537ae51c880966626561987153e72d073cbe19dfe5abc062713d929254d lvl=info msg="Image downloaded" operation=2473916e-5f52-49f7-b9de-d1399487f25c server=https://cloud-images.ubuntu.com/releases t=2017-05-19T09:03:11+0000 trigger=/1.0/operations/2473916e-5f52-49f7-b9de-d1399487f25c

Why is it downloading an amd64 image on a pi (armhf) device?

This was resolved by using a newer snapcraft (snap refresh --edge snapcraft). It still isn’t happy though:

$ snapcraft cleanbuild --remote rpi

Setting up python3-magic (1:5.25-2ubuntu1) …
Setting up snapcraft (2.29) …
Processing triggers for libc-bin (2.23-0ubuntu7) …
Setting target machine to ‘amd64’
Building for a different target architecture requires a plugin specific implementation in the ‘emoji’ plugin
Stopping rpi:snapcraft-superelaborately-nondisparate-carley
Command ‘[‘lxc’, ‘exec’, ‘rpi:snapcraft-superelaborately-nondisparate-carley’, ‘–env’, ‘HOME=/build_emoji’, ‘–’, ‘snapcraft’, ‘snap’, ‘–output’, ‘emoji_0.3.0_amd64.snap’, ‘–target-arch’, ‘amd64’]’ returned non-zero exit status 1.

1 Like

@sergiusens, @kalikiana this doesn’t seem like a safe assumption, given lxd remotes. Could we make it conditional on using local lxd?

Yes, we can fix this.

What exactly isn’t a safe assumption?
That code gets the architecture of the LXD host. armhf in the case of the Pi. By default snapcraft builds for the client architecture, which is amd64 here. So we end up cross-compiling on armhf for amd64.
If the intention was to build for armhf one would use --target-arch=armhf.

Right, I don’t think that’s the right default. If I call snapcraft cleanbuild --remote rpi, I would expect it to produce an armhf build of the snap on the Raspberry Pi and then ferry it back to my amd64 machine.

1 Like

I think this should be the case as well; as in native to the target and not native to the source.

So we want the default to be the LXD host architecture? In that case we need to figure out how to pass this on cleanly, because ProjectOptions gets its default from the client, before LXD comes into the picture.

https://github.com/snapcore/snapcraft/pull/1493

Aaaaaand the code was merged!

I just tried using snapcraft from edge (2.34+git28.bf216fd) on my x86_64 PC to connect to my raspberry pi 3 running lxd in snappy Ubuntu core. It failed complaining that armhf and amd64 are not equal:

$ snapcraft cleanbuild --remote pi
Creating snapcraft-temptedly-defunct-ashlee
Starting snapcraft-temptedly-defunct-ashlee   
Waiting for a network connection...
Network connection established
<<<snipped>>>
Looking up assertion ['account-key', 'public-key-sha3-384=<<<snipped>>>']
Looking up assertion ['snap-declaration', 'snap-name=core']
Looking up assertion ['snap-revision', 'snap-revision=2898', 'snap-id=99T7MUlRhtI3U0QFgl5mXXESAiSwt776']
Adding assertion core_2898.assert
Installing /run/core_2898.snap
error: cannot perform the following tasks:
- Mount snap "core" (2898) (snap "core" supported architectures (amd64) are incompatible with this system (armhf))
Stopping pi:snapcraft-temptedly-defunct-ashlee
Traceback (most recent call last):
<<<snipped>>>
subprocess.CalledProcessError: Command '['lxc', 'exec', 'pi:snapcraft-temptedly-defunct-ashlee', '--', 'snap', 'install', '/run/core_2898.snap']' returned non-zero exit status 1.

Thanks for testing! I’ll have a look at that shortly. From the looks of it, Snapcraft mistakenly tries to inject the core snap of the host even though it has a different architecture. This is an interesting case as revisions of architectures don’t match. I’ll have to find out if I can map the revision or find the closest match, like latest on the same channel.

Surely for cleanbuilds it shouldn’t matter what is on the host. Why is snapcraft matching host to guest for cleanbuilds, even when they’re both the same PC/Arch?? The point of cleanbuild I thought was that it was an entirely isolated instance with nothing depending on your host system!

What Snapcraft does here is install the same versions of core snap and itself for predictable behavior. Since Snapcraft re-runs itself in the container, an older Snapcraft in the container eg. from apt would lead to potentially unexpected behavior. Fixes for plugins wouldn’t work even if the host has a newer version. And if you’re running from a specific channel, you want the version from that channel.

The PR was just merged!

but is not the whole point of cleanbuild that it builds in a completely virgin environment with no ties to the host?!

this still isn’t working?

$ snapcraft cleanbuild --remote 192.168.88.14
Creating snapcraft-undilatorily-prohibitive-dusty
Starting snapcraft-undilatorily-prohibitive-dusty
Waiting for a network connection...
Network connection established
... <apt fetching> ...
... <apt installing> ...
Looking up assertion ['account-key', 'public-key-sha3-384=BWDEoaqyr25nF5SNCvEv2v7QnM9QsfCc0PBMYD_i2NGSQ32EF2d4D0hqUel3m8ul']
Looking up assertion ['snap-declaration', 'snap-name=core']
Looking up assertion ['snap-revision', 'snap-revision=4443', 'snap-id=99T7MUlRhtI3U0QFgl5mXXESAiSwt776']
Adding assertion core_4443.assert
Installing /run/core_4443.snap
error: cannot perform the following tasks:
- Mount snap "core" (4443) (snap "core" supported architectures (amd64) are incompatible with this system (armhf))
Stopping 192.168.88.14:snapcraft-undilatorily-prohibitive-dusty
The following command failed to run: 'snap install /run/core_4443.snap' exited with 1

and

$ snapcraft cleanbuild --remote 192.168.88.14 --target-arch armhf
Setting target machine to 'armhf'
Traceback (most recent call last):
  File "/snap/snapcraft/1390/bin/snapcraft", line 11, in <module>
    load_entry_point('snapcraft==2.40.1', 'console_scripts', 'snapcraft')()
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/snap/snapcraft/1390/usr/lib/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/click/core.py", line 87, in augment_usage_errors
    yield
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/cli/lifecycle.py", line 218, in cleanbuild
    lifecycle.cleanbuild(project_options, remote)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/internal/lifecycle/_containers.py", line 60, in cleanbuild
    config = project_loader.load_config(project_options)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/internal/project_loader/__init__.py", line 25, in load_config
    return Config(project_options)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/internal/project_loader/_config.py", line 129, in __init__
    snapcraft_yaml=self.snapcraft_yaml_path)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/internal/project_loader/_parts_config.py", line 55, in __init__
    self._process_parts()
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/internal/project_loader/_parts_config.py", line 85, in _process_parts
    self.load_part(part_name, plugin_name, properties)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/internal/project_loader/_parts_config.py", line 169, in load_part
    definitions_schema=self._validator.definitions_schema)
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/internal/pluginhandler/_plugin_loader.py", line 78, in load_plugin
    plugin.enable_cross_compilation()
  File "/snap/snapcraft/1390/lib/python3.5/site-packages/snapcraft/_baseplugin.py", line 183, in enable_cross_compilation
    'to a different target architecture'.format(self.name))
NotImplementedError: The plugin used by 'openra' does not support cross-compiling to a different target architecture