Merge pull request #9 from morphis/improve-snap-pkg

Improve snap pkg
This commit is contained in:
Simon Fels 2016-12-06 08:05:39 +01:00 • committed by GitHub
commit 0887abe263
13 changed files with 124 additions and 176 deletions

4
.gitignore vendored
View file

@ -1,2 +1,6 @@
build*/ build*/
parts/
stage/
prime/
*.snap
CMakeLists.txt.user CMakeLists.txt.user

View file

@ -27,6 +27,53 @@ For more details have a look at the following documentation pages:
* The Android "qemud" multiplexing daemon (https://goo.gl/DeYa5J) * The Android "qemud" multiplexing daemon (https://goo.gl/DeYa5J)
* Android Qemud services (https://goo.gl/W8Lx6t) * Android Qemud services (https://goo.gl/W8Lx6t)
## Installation
Anbox is available as a snap in the public Ubuntu Store. Currently it
is only available in the edge channel and requires to be installed in
devmode as we don't have proper confinement for it in place yet.
Additionally you need to manually load the binder and ashmem kernel
drivers everytime as we build them out-of-tree with a hack as this
isn't officially supported. Before you start anbox you always need
to execute
$ cd anbox
$ scripts/load-kmods.sh
Anbox can be installed from the Ubuntu Store with
$ snap install --edge --devmode anbox
Afterwards run it with
$ anbox
After the first installation the container management service needs
a few minutes to setup the container the first time before it is
available.
Applications can be launched via the launch subcommand of the anbox
binary. For example
$ anbox launch --package com.android.settings
## Build from source
To build the Anbox runtime itself there is nothing special to know
about. We're using cmake as build system.
$ mkdir build
$ cd build
$ cmake ..
$ make
That will build the whole stack. A simple
$ make install
will install the necessary bits into your system.
## Copyright and Licensing ## Copyright and Licensing
Anbox reuses code from other projects like the Android Qemu emulator Anbox reuses code from other projects like the Android Qemu emulator

View file

@ -1,27 +0,0 @@
#!/bin/sh
set -e
set -x
if [ ! -e android-rootfs.tar ] ; then
echo "ERROR: Missing Android rootfs package!"
exit 1
fi
./cross-compile-chroot.sh -a armhf -d vivid
if [ -e click ] ; then
rm -rf click
fi
mkdir click
cp data/manifest.json click/
cp data/apparmor.json click/
cp data/anbox.desktop click/
(cd click ; tar xf ../android-rootfs.tar ; mv rootfs android-rootfs)
cp build-armhf-vivid/src/anbox click/
cp build-armhf-vivid/src/anbox-container click/
(cd click ; click build .)

View file

@ -23,34 +23,6 @@ function prepare_filesystem() {
chown system:system /dev/$f chown system:system /dev/$f
chmod 0666 /dev/$f chmod 0666 /dev/$f
done done
if [ ! -e /.anbox_setup_done ] ; then
echo "Fixing up all permissions ..."
# Fixup permissions of the android binaries in /system
while read line
do
file=`echo $line | cut -d' ' -f 1`
user=`echo $line | cut -d' ' -f 2`
group=`echo $line | cut -d' ' -f 3`
mode=`echo $line | cut -d' ' -f 4`
# Avoid changing symlinks
if [ ! -h /$file ] ; then
chmod $mode /$file
chown -h $user:$group /$file
fi
done < "/filesystem_config.txt"
# Additional ones not listed in the config generated from the build
for f in qemu_pipe qemu_trace goldfish_pipe ; do
[ ! -e /dev/$f ] && continue
chown system:system /dev/$f
chmod 0666 /dev/$f
done
echo "Setup done!"
echo $VERSION > /.anbox_setup_done
fi
} }
prepare_filesystem & prepare_filesystem &

View file

@ -5,27 +5,56 @@
# Other than that nothing should ever modify the content of the # Other than that nothing should ever modify the content of the
# rootfs. # rootfs.
ROOTFS_PATH=$SNAP_COMMON/var/lib/anbox/rootfs DATA_PATH=$SNAP_COMMON/var/lib/anbox
ROOTFS_VERSION=1 ROOTFS_PATH=$DATA_PATH/rootfs
RAMDISK_PATH=$DATA_PATH/ramdisk
INITRD=$SNAP/ramdisk.img
SYSTEM_IMG=$SNAP/system.img
ANDROID_DATA_PATH=$DATA_PATH/android-data
if [ ! -e $ROOTFS_PATH ] || [ "$ROOTFS_VERSION" != "$(cat $ROOTFS_PATH/.version)" ] ; then if [ ! -e $INITRD ]; then
rm -rf $ROOTFS_PATH echo "ERROR: boot ramdisk does not exist"
echo "Copying rootfs into $ROOTFS_PATH .." exit 1
mkdir -p $ROOTFS_PATH
tar xf $SNAP/android-rootfs.tar -C $ROOTFS_PATH/ --strip-components=1
echo $ROOTFS_VERSION > $ROOTFS_PATH/.version
fi fi
# Load binder and ashmem kernel drivers. This will just horrible break if [ ! -e $SYSTEM_IMG ]; then
# if kernel versions are changing ... echo "ERROR: system image does not exist"
insmod $SNAP/binder_linux.ko || true exit 1
chmod 666 /dev/binder fi
insmod $SNAP/ashmem_linux.ko || true
chmod 666 /dev/ashmem # Extract ramdisk content instead of trying to bind mount the
# cpio image file to allow modifications.
rm -Rf $RAMDISK_PATH
mkdir -p $RAMDISK_PATH
cd $RAMDISK_PATH
cat $INITRD | gzip -d | cpio -i
# FIXME those things should be fixed in the build process
chmod +x $RAMDISK_PATH/anbox-init.sh
# Setup the read-only rootfs
mkdir -p $ROOTFS_PATH
mount -o bind,ro $RAMDISK_PATH $ROOTFS_PATH
mount -o loop,ro $SYSTEM_IMG $ROOTFS_PATH/system
# ... but we keep /data in the read/write space
mkdir -p $ANDROID_DATA_PATH
mount -o bind $ANDROID_DATA_PATH $ROOTFS_PATH/data
# Make sure our setup path for the container rootfs # Make sure our setup path for the container rootfs
# is present as lxc is statically configured for # is present as lxc is statically configured for
# this path. # this path.
mkdir -p $SNAP_COMMON/lxc mkdir -p $SNAP_COMMON/lxc
exec $SNAP/bin/anbox-wrapper.sh container-manager # We start the bridge here as long as a oneshot service unit is not
# possible. See snapcraft.yaml for further details.
$SNAP/bin/anbox-bridge.sh start
$SNAP/usr/sbin/aa-exec -p unconfined -- $SNAP/bin/anbox-wrapper.sh container-manager
pid=$!
waitpid $pid
$SNAP/bin/anbox-bridge.sh stop
umount $ROOTFS_PATH/system
umount $ROOTFS_PATH/data

View file

@ -1,11 +0,0 @@
#!/bin/bash
$SNAP/bin/lxc-attach \
--lxcpath=$SNAP_COMMON/var/lib/anbox/containers \
--name default \
--clear-env \
--set-var PATH=/system/bin:/system/sbin:/system/xbin \
--set-var ANDROID_DATA=/data \
--set-var ANDROID_ROOT=/system \
-- \
/system/bin/sh

View file

@ -1,2 +0,0 @@
#!/system/bin/sh
echo "Dummy iptables wrapper"

View file

@ -1,60 +0,0 @@
#!/bin/bash
set -e
set -x
basepath=/home/phablet/android-box
rootfs=$basepath/rootfs
rootfs_overrides=$basepath/overrides
ramdisk=$basepath/ramdisk.img
systemdisk=$basepath/system.img
init_cmd="/init"
if [ "$1" = "shell" ] ; then
init_cmd=/system/bin/sh
fi
if [ -d $rootfs ] ; then
sudo umount --recursive $rootfs || true
rm -rf $rootfs
fi
mkdir -p $rootfs
sudo mount -t tmpfs none $rootfs
(cd $rootfs ; cat $ramdisk | gzip -d | cpio -i)
mkdir -p $rootfs/dev/pts
sudo mount -o ro,loop $systemdisk $rootfs/system
if [ -d "$rootfs_overrides" ] ; then
for f in `ls $rootfs_overrides` ; do
if [ "$f" = "system" ] ; then
for f2 in `find $rootfs_overrides/system -type f` ; do
real_path=`echo $f2 | sed -e s:$rootfs_overrides::g`
sudo mount -o bind $f2 $rootfs/$real_path
done
else
cp $rootfs_overrides/$f $rootfs
fi
done
fi
/home/phablet/bwrap \
--ro-bind $rootfs / \
--bind /home/phablet/android-box/iptables-wrapper /system/bin/iptables \
--bind /home/phablet/android-box/iptables-wrapper /system/bin/ip6tables \
--dev /dev \
--proc /proc \
--tmpfs /data \
--unshare-user \
--unshare-ipc \
--unshare-pid \
--unshare-net \
--unshare-uts \
--uid 0 \
--gid 0 \
--setenv PATH /system/bin:/system/sbin:/system/xbin \
--chdir / \
$init_cmd
sudo umount --recursive $rootfs
rm -rf $rootfs

View file

@ -1,16 +0,0 @@
#!/bin/bash
# We need to put the rootfs somewhere where we can modify some
# parts of the content on first boot (namely file permissions).
# Other than that nothing should ever modify the content of the
# rootfs.
ROOTFS_PATH=$SNAP_COMMON/var/lib/anbox/rootfs
if [ -d $ROOTFS_PATH ] ; then
rm -rf $ROOTFS_PATH
fi
echo "Copying rootfs into $ROOTFS_PATH .."
mkdir -p $ROOTFS_PATH
tar xf $SNAP/android-rootfs.tar -C $ROOTFS_PATH/ --strip-components=1

View file

@ -1,3 +0,0 @@
#!/bin/bash
exec /bin/bash $@

View file

@ -10,21 +10,24 @@ grade: devel
apps: apps:
anbox: anbox:
command: bin/anbox-wrapper.sh run command: bin/anbox-wrapper.sh
container-manager: container-manager:
command: bin/container-manager.sh command: bin/container-manager.sh
daemon: simple daemon: simple
bridge: # FIXME: a oneshot unit with start/stop commands needs also RemainAfterExit=yes
command: bin/anbox-bridge.sh start # but this isn't supported by snapd yet. See LP #1647169 for details.
stop-command: bin/anbox-bridge.sh stop # bridge:
daemon: oneshot # command: bin/anbox-bridge.sh start
# stop-command: bin/anbox-bridge.sh stop
# daemon: oneshot
parts: parts:
android-rootfs: android:
plugin: copy plugin: copy
source: . source: .
files: files:
android-rootfs.tar: android-rootfs.tar system.img: system.img
ramdisk.img: ramdisk.img
anbox-common: anbox-common:
plugin: copy plugin: copy
source: . source: .
@ -36,6 +39,10 @@ parts:
- bin/anbox-bridge.sh - bin/anbox-bridge.sh
- bin/anbox-wrapper.sh - bin/anbox-wrapper.sh
- bin/container-manager.sh - bin/container-manager.sh
apparmor:
plugin: nil
stage-packages:
- apparmor
lxc: lxc:
source: git://github.com/morphis/lxc source: git://github.com/morphis/lxc
source-branch: snappy-support source-branch: snappy-support

View file

@ -113,9 +113,11 @@ void LxcContainer::start(const Configuration &configuration) {
"lxc.logfile", "lxc.logfile",
utils::string_format("%s/container.log", config::log_path()).c_str()); utils::string_format("%s/container.log", config::log_path()).c_str());
set_config_item("lxc.network.type", "veth"); if (fs::exists("/sys/class/net/anboxbr0")) {
set_config_item("lxc.network.flags", "up"); set_config_item("lxc.network.type", "veth");
set_config_item("lxc.network.link", "anboxbr0"); set_config_item("lxc.network.flags", "up");
set_config_item("lxc.network.link", "anboxbr0");
}
#if 0 #if 0
// Android uses namespaces as well so we have to allow nested namespaces for LXC // Android uses namespaces as well so we have to allow nested namespaces for LXC
@ -136,9 +138,12 @@ void LxcContainer::start(const Configuration &configuration) {
if (fs::is_directory(bind_mount.first)) create_type = "dir"; if (fs::is_directory(bind_mount.first)) create_type = "dir";
auto target_path = bind_mount.second; auto target_path = bind_mount.second;
// LXC wants target paths relative to the container rootfs so // The target path needs to be absolute and pointing to the right
// prividing an absolute path doesn't work. // location inside the target rootfs as otherwise we get problems
if (utils::string_starts_with(target_path, "/")) target_path.erase(0, 1); // when running in confined environments like snap's.
if (!utils::string_starts_with(target_path, "/"))
target_path = std::string("/") + target_path;
target_path = config::rootfs_path() + target_path;
set_config_item( set_config_item(
"lxc.mount.entry", "lxc.mount.entry",

View file

@ -42,7 +42,10 @@ Daemon::Daemon()
} }
int Daemon::Run(const std::vector<std::string> &arguments) try { int Daemon::Run(const std::vector<std::string> &arguments) try {
return cmd.run({std::cin, std::cout, arguments}); auto argv = arguments;
if (arguments.size() == 0)
argv = {"run"};
return cmd.run({std::cin, std::cout, argv});
} catch (std::exception &err) { } catch (std::exception &err) {
ERROR("%s", err.what()); ERROR("%s", err.what());
return EXIT_FAILURE; return EXIT_FAILURE;