Outils pour utilisateurs

Outils du site


tuto_a20-olinuxino-micro_generation_d_un_rootfs_ubuntu_14.04_minimal_a_l_aide_de_live-build

Génération d'un "rootfs" Ubuntu 14.04 minimal a l'aide de live-build pour la carte A20-OLinuXino


Introduction

Suite a l'article précédent (Génération d'image à base du noyau 3.4.90+ et Ubuntu Core pour la carte A20-OLinuXino), je vous propose de construire un rootfs Ubuntu 14.04 pour la carte A20-OLinuXino. Bien entendu, cette procedure reste applicable, dans les grands principes, pour les autres cartes basés sur un ARMv7, telle que la Raspberry Pi.

Pour la petite histoire, j'en suis venu à devoir me contruire ce rootfs, car bien que la procedure ai fonctionné et que ma carte se soit bien connecté au reseau, il m'etait impossible de me connecter dessus ; Le rootfs Ubuntu Core n'embarque pas de serveur SSH, et je ne possede pas de convertisseur USB-RS232 TTL en 3.3V. Je me suis donc penché sur la generation d'un tel “rootfs”.

On ne parle plus vraiment de rootfs. dans la mesure ou les outils les generant (rootstock, notamment) sont devenus obseletes ; mais plutot de systemes “Live”. Il apparait que dans les fait, pour les systemes debian et derivés, il s'agit toujours d'une surcouche a debootstrap…

Comme toujours, vous pouvez retrouver l'integralité du projet sur le GitHub : https://github.com/spelle/Ubuntu-14.04-LTS-ARMHF-Minimal-SSH.

Bonne lecture !


Prérequis

Sur une distribution *buntu 14.04 LTS Trusty Tahr, il convient d'installer les packages suivants :

$ sudo apt-get install live-build qemu-system-arm

debootstrap etant une dependance sera aussi deployé.

Il convient aussi d'ajouter les depots linaro ainsi que le package qemu-user-static :

$ sudo add-apt-repository ppa:linaro-maintainers/tools
$ sudo apt-get update
$ sudo apt-get install qemu-user-static

Afin de travailler de maniere organisée, il est possible de se mettre à l'aise dans un espace de travail. Tout le monde travaillant selon sa methode, cette etape est facultative :

$ cd Workspaces
$ mkdir workspace-Olimex
$ cd worspace-Olimex
$ mkdir Ubuntu-14.04-LTS-ARMHF-Minimal-SSH
$ cd Ubuntu-14.04-LTS-ARMHF-Minimal-SSH

le retour de la commande “pwd” devrait donner ceci :

$ pwd
/home/<user>/Workspaces/workspace-Olimex/Ubuntu-14.04-LTS-ARMHF-Minimal-SSH

Il peut etre utile pour la suite de se placer en tant que super-utilisateur.

$ sudo su

Image minimale

Donc pour commencer, et à la vue de ce qui se fait par ailleurs, puisque la génération se fait en deux etapes, le ”lb_config” suivi du ”lb_build”, nous allons créer un fichier “configure” avec le code suivant :

configure
#!/bin/sh
 
set -e
 
echo "I: create configuration"
export LB_BOOTSTRAP_INCLUDE="apt-transport-https gnupg"
lb config \
 --apt-indices none \
 --apt-secure false \
 --architectures armhf \
 --archive-areas 'main universe' \
 --binary-filesystem ext3 \
 --binary-images tar \
 --bootappend-live "hostname=a20-olinuxino username=olimex" \
 --bootstrap-qemu-arch armhf \
 --bootstrap-qemu-static /usr/bin/qemu-arm-static \
 --cache false \
 --chroot-filesystem none \
 --compression gzip \
 --bootstrap-flavour minimal \
 --distribution trusty \
 --gzip-options '-9 --rsyncable' \
 --iso-publisher 'Me Myself and I' \
 --iso-volume 'ARMHF Ubuntu 14.04' \
 --linux-flavours none \
 --linux-packages none \
 --mode ubuntu \
 --security false \
 --system normal
 
echo "I: done"

On crée ensuite le fichier Makefile comme suit :

Makefile
#!/bin/sh
LOGFILE=lb-build.log
 
all:
	set -e; sudo lb build 2>&1 | tee $(LOGFILE)
 
clean:
	sudo lb clean --purge ; sudo rm -rf {config,local,$(LOGFILE)}

Il est d'ors-et-deja possible de proceder a la génération du systeme live decrit dans le configure. Le systeme resutant sera un systeme minimal (–bootstrap-flavour minimal) pour une architecture ARMHF (–architectures armhf), le tout etant une ubuntu Trusty (–mode ubuntu & –distribution trusty) .


Customizations

Tout ceci est bien joli. Mais a y bien regarder, nous ne sommes pas plus avancés. Il n'y a toujours pas de serveur SSH sur ce rootfs ! Nous allons y Remedier.

Commencons par créer un repertoire ”customization” :

$ mkdir customization
$ cd customization

Au sein de ce repertoire, trois autres repertoires se trouvent present : “hooks”, “includes”, et “package-lists”

Il conviendra de modifier le configure afin qu'il prenne en compte les customizations en ajoutant les lignes suivantes :

echo "I: copy customization"
cp -rf customization/* config/

Hook it up !

En anglais, un “hook” c'est un “crochet”. Rappellez vous du capitaine Hook dans Peter Pan… Et oui…

Ce repertoire peut donc contenir de scripts qui seront exécutés pour eventuellement modifier notre rootfs. Ils ont pour extension .chroot car ils sont executés apres qu'un chroot n'ait été fait. Les chemin de fichier qu'il viennent modifier sont donc les chemin ”cibles”.

Le premier hook vise a créer un utilisateur et renseigner le mot de passe. L'utilisateur sera ”olimex” avec pour mot de passe ”olimex”.

hooks/01-setup_user_olimex.chroot
#!/bin/sh  
 
echo "I: create olimex user"
adduser --gecos olimex --disabled-login olimex
 
echo "I: set olimex user password"
echo "olimex:olimex" | chpasswd

Le second hook consiste a ajouter notre utilisateur ”olimex” aux differents groupes auquel on souhaite le voir etre ajouté.

hooks/02-add_olimex_to_groups.chroot
#!/bin/sh -x 
 
DEFGROUPS="admin,adm,dialout,cdrom,plugdev,audio,dip,video"
 
/bin/egrep  -i "^admin" /etc/group
if [ $? -eq 0 ]; then
   echo "User admin exists in /etc/group"
else
   echo "User admin does not exists in /etc/group must create"
   groupadd admin
fi
/bin/egrep  -i "^dialout" /etc/group
if [ $? -eq 0 ]; then
   echo "User dialout exists in /etc/group"
else
   echo "User dialout does not exists in /etc/group must create"
   groupadd dialout
fi
/bin/egrep  -i "^cdrom" /etc/group
if [ $? -eq 0 ]; then
   echo "User cdrom exists in /etc/group"
else
   echo "User cdrom does not exists in /etc/group must create"
   groupadd cdrom 
fi
/bin/egrep  -i "^plugdev" /etc/group
if [ $? -eq 0 ]; then
   echo "User plugdev exists in /etc/group"
else
   echo "User plugdev does not exists in /etc/group must create"
   groupadd plugdev
fi
/bin/egrep  -i "^audio" /etc/group
if [ $? -eq 0 ]; then
   echo "User audio exists in /etc/group"
else
   echo "User audio does not exists in /etc/group must create"
   groupadd audio
fi
/bin/egrep  -i "^dip" /etc/group
if [ $? -eq 0 ]; then
   echo "User dip exists in /etc/group"
else
   echo "User dip does not exists in /etc/group must create"
   groupadd dip
fi
/bin/egrep  -i "^video" /etc/group
if [ $? -eq 0 ]; then
   echo "User video exists in /etc/group"
else
   echo "User video does not exists in /etc/group must create"
   groupadd video
fi
/bin/egrep  -i "^adm" /etc/group
if [ $? -eq 0 ]; then
   echo "User adm exists in /etc/group"
else
   echo "User adm does not exists in /etc/group must create"
   groupadd adm
fi
 
echo "I: add olimex to ($DEFGROUPS) groups"
usermod -a -G ${DEFGROUPS} olimex

Le troisieme hook consiste a attribuer des droits super-utilisateur a notre utilisateur ”olimex”.

hooks/03-check_sudoers_for_admin.chroot
#!/bin/sh 
 
# check to make sure sudoers file has ref for admin
ADMINEXISTS="$(awk '$1 == "%admin" { print $1 }' /etc/sudoers)"
if [ -z "$ADMINEXISTS" ]; then
  # append admin entry to sudoers
  echo "# Members of the admin group may gain root privileges" >> /etc/sudoers
  echo "%admin  ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
fi
 
# make sure that NOPASSWD is set for %admin
# expecially in the case that we didn't add it to /etc/sudoers
# just blow the %admin line away and force it to be NOPASSWD
sed -i -e '
/\%admin/ c \
%admin  ALL = (ALL) NOPASSWD: ALL
' /etc/sudoers

Le quatrieme hook renseigne le fichier /etc/fstab de la maniere qu'on le souhaite.

hooks/04-fstab.chroot
echo "# /etc/fstab: static file system information." > /etc/fstab
echo "#" >> /etc/fstab
echo "# <file system> <mount point>   <type>  <options>       <dump>  <pass>" >> /etc/fstab
echo "/dev/root      /               ext4     noatime,errors=remount-ro 0 1" >> /etc/fstab
echo "tmpfs          /run/shm        tmpfs    defaults                  0 0" >> /etc/fstab
echo "tmpfs          /tmp            tmpfs    defaults                  0 0" >> /etc/fstab
echo "tmpfs          /var/tmp        tmpfs    defaults                  0 0" >> /etc/fstab%            

Le cinquieme hook procede de meme avec le fichier /etc/network/interfaces

hooks/05-network-interfaces.chroot
echo "" >> /etc/network/interfaces
echo "auto lo" >> /etc/network/interfaces
echo "iface lo inet loopback" >> /etc/network/interfaces
echo "auto eth0" >> /etc/network/interfaces
echo "iface eth0 inet dhcp" >> /etc/network/interfaces

Voila pour les Hooks !

Includes

Dans le repertoire includes, on y place les differents fichiers que l'on souhaite voir etre copiés tel quels sur le systeme hote.

En passant, plutot que de faire des hooks pour le /etc/fstab et le /etc/network/interfaces, on aurait pu le faire via les includes.

Voici donc les fichiers presents dans le ”includes.chroot”.

includes.chroot/etc/default/locale
LANG=C.UTF-8
includes.chroot/etc/hostname
a20-olinuxino
includes.chroot/etc/hosts
127.0.0.1	localhost
::1		localhost ip6-localhost ip6-loopback
fe00::0		ip6-localnet
ff00::0		ip6-mcastprefix
ff02::1		ip6-allnodes
ff02::2		ip6-allrouters
127.0.1.1       a20-olinuxino
includes.chroot/etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
 
# Generate the SSH keys if non-existent
test -f /etc/ssh/ssh_host_dsa_key || dpkg-reconfigure openssh-server
 
exit 0

package-lists

Le troisieme et dernier repertoire de notre “customization” ne contient qu'un fichier :

package-lists/a20-olinuxino-packages.list.chroot
# Packages needed for A20-OLinuXino
isc-dhcp-server
openssh-server
sudo

Génération du rootfs

La Génération se fait simplement :

$ ./configure
I: create configuration
[2014-07-14 15:43:45] lb_config --apt-indices none --apt-secure false --architectures armhf --archive-areas main universe --binary-filesystem ext3 --binary-images tar --bootappend-live hostname=a20-olinuxino username=olimex --bootstrap-qemu-arch armhf --bootstrap-qemu-static /usr/bin/qemu-arm-static --cache false --chroot-filesystem none --compression gzip --bootstrap-flavour minimal --distribution trusty --gzip-options -9 --rsyncable --iso-publisher Me Myself and I --iso-volume ARMHF Ubuntu 14.04 --linux-flavours none --linux-packages none --mode ubuntu --security false --system normal
P: Considering defaults defined in /etc/live/build.conf
P: Creating config tree for a ubuntu/armhf system
I: copy customization
I: done
$ make
[...]

A la fin de la génération, nous avons le resultat suivant :

% la
total 96776
drwxrwxr-x 10 nuptse nuptse     4096 juil. 14 16:06 ./
drwxrwxr-x  7 nuptse nuptse     4096 juil. 14 13:54 ../
drwxrwxr-x  2 nuptse nuptse     4096 juil. 14 15:43 auto/
drwxr-xr-x 20 root   root       4096 juil. 14 16:05 binary/
-rw-r--r--  1 root   root     550593 juil. 14 16:05 binary.contents
-rw-r--r--  1 root   root       5519 juil. 14 16:05 binary.packages
-rw-r--r--  1 root   root   98387955 juil. 14 16:05 binary-tar.tar.gz
drwxrwxr-x  2 nuptse nuptse     4096 juil. 14 16:06 .build/
drwxr-xr-x  4 root   root       4096 juil. 14 15:53 cache/
drwxr-xr-x 20 root   root       4096 juil. 14 16:05 chroot/
-rw-r--r--  1 root   root          0 juil. 14 16:02 chroot.headers
-rw-r--r--  1 root   root       5519 juil. 14 16:02 chroot.packages.install
-rw-r--r--  1 root   root       5519 juil. 14 16:03 chroot.packages.live
drwxrwxr-x 19 nuptse nuptse     4096 juil. 14 15:43 config/
-rwxrwxr-x  1 nuptse nuptse     1175 juil. 14 15:03 configure*
drwxrwxr-x  5 nuptse nuptse     4096 juil. 14 11:48 customization/
-rw-rw-r--  1 nuptse nuptse    76790 juil. 14 16:06 lb-build.log
drwxrwxr-x  4 nuptse nuptse     4096 juil. 14 15:43 local/
-rwxrwxr-x  1 nuptse nuptse      153 juil. 14 11:45 Makefile*

Deploiement

Le déploiement de notre rootfs ne pose a priori pas de problèmes. Il suffit de reprendre le tutoriel précédent (Génération d'image à base du noyau 3.4.90+ et Ubuntu Core pour la carte A20-OLinuXino) à partir du paragraphe ”Deploiement du rootfs”.

Le contenu du rootfs est présent dans le répertoire binary.

$ sudo umount /dev/mmcblk0p*
$ sudo mkfs.etx3 /dev/mmcblk0p2
$ sudo mount /dev/mmcblk0p2 /mnt/mmcblk
$ sudo tar xzvf --strip=1 --wildcards binary-tar.tar.gz binary/* -C /mnt/mmcblk
$ cd ..
$ cd ubuntu_core_3.4.90+
$ sudo rm -rf /mnt/mmcblk/lib/modules/*
zsh: sure you want to delete all the files in /mnt/mmcblk/lib/modules [yn]? y
$ sudo rm -rf /mnt/mmcblk/lib/firmware/
$ sudo cp -rfv linux-sunxi/out/lib/modules/3.4.90+/ /mnt/mmcblk/lib/modules/
$ sudo cp -rfv linux-sunxi/out/lib/firmware/ /mnt/mmcblk/lib/
$ sync
$ sudo umount /dev/mmcblk 

Mise en route

Après avoir déployé notre rootfs sur la carte µSD, il convient de l’insérer dans le logement prévu pour sur la A20-OLinuXino.

Il convient aussi de s'assurer que l'interface ethernet est bien connectée au réseau, et qu'un serveur DHCP sera en mesure d'attribuer une addresse IP a la carte.

Une fois ceci fait, il est possible d'ouvrir une session SSH à destination de la carte et procéder a son exploitation.


Remarques, Propositions d'améliorations, Questions

Vous pouvez poster vos remarques, propositions d’amélioration, et questions sur le forum, dans la discussion prévue a cet effet : http://fablab-robert-houdin.org/fablab/phpBB-3.0.11-fr/phpBB3/viewtopic.php?f=5&t=45


Notes

Les packages listés sont les packages minimaux. J'ai depuis lors ajouter les packages suivants : zsh, git, aptitude, vim, wget, curl, ntpdate, dialog.

J'ai aussi procédé à la configuration de mon editeur de texte favori : vim, tel que decrit ici : https://github.com/spelle/dotVIM


Bibliographie

tuto_a20-olinuxino-micro_generation_d_un_rootfs_ubuntu_14.04_minimal_a_l_aide_de_live-build.txt · Dernière modification: 2014/07/19 18:46 par spelle