Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add configuration management #17

Merged
merged 5 commits into from
Jan 15, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,32 @@ Tests on one orange pi zero show that the time from power on until a login
prompt on the serial console is about 1 minute.


Applying persistent configurations
----------------------------------

Custom configurations are saved as tar.gz archives in conf.d at the root of the
fat16 file system. After the start of userspace and before systemd is launched,
content in each archive is extracted in alphabetical order to /etc of the ramdisk,
so files in an archive towards the end of the list overwrite those from an earlier
archive in case of a filename conflict, and systemd will only see the final
(highest priority) configurations. For example:

/conf.d/00-tomesh-base.tar.gz
10-tomesh-wlan-mesh-top-gs07-rt5572.tar.gz
11-tomesh-wlan-hostap-tplink-tl-wn722n.tar.gz
50-node-config-save.tar.gz
90-user-custom-configs.tar.gz

This allows local mesh communities to customize nodes by distributing archives
of systemd.network configuration files, or any files that are to be read from
/etc. The user simply mounts the fat filesystem like a USB key and drops tar.gz
files into conf.d and backs them up across software updates.

If the node needs to save persistent configurations while running, such as
remembering a MAC address, it can save the current /etc directory into a
50-node-config-save.tar.gz archive by running `config_save`. The user may
also manually add configurations with higher priority archive names.

Test the Debian image using Qemu
--------------------------------

Expand Down
2 changes: 1 addition & 1 deletion debian/packages.d/README
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ customisations. These customisations are applied in several phases,
and each package that is found installed in the rescue system will
attempt to run its matching script during each phase.

Curently the phases are:
Currently the phases are:

"minimise"
During this phase, anything that can be removed to minimise the
Expand Down
39 changes: 39 additions & 0 deletions debian/packages.d/systemd.customise.add/init.d/20confd.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Apply configurations from conf.d
#
# Copyright (C) 2018 Benedict Lau <[email protected]>

CONFDIR=conf.d

try_partition() {
# Create file system node from partition
#mknod /dev/$1 b $2 $3 2>/dev/null
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hamishcoleman Works without this. Do we need?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strange - I'm confused as to what is creating the device nodes in that case - this is running on a system with an empty /dev and before udev has hotplugged anything

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was running the script manually so it wasn't tested at the correct state of OS startup

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, Doh!


# Mount partition as read-only
mount /dev/$1 /mnt -o ro

# Find conf.d in root of partition and extract in alphabetical order each
# tar.gz archive into the ramdisk /etc, overwriting any existing file
if [ -d "/mnt/$CONFDIR" ]; then
confs=$(find /mnt/$CONFDIR -name *.tar.gz)
for conf in $confs; do
echo Applying configurations from /dev/$1: $conf
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use "for conf in /mnt/$CONFDIR/*.tar.gz" ?

Using find will traverse subdirs and is not known to be sorted

tar --extract --gzip -f $conf -C /etc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tar will automatically detect the compression type - you can leave off "--gzip"

done
fi

# Unmount partition
umount /mnt
}

# Mount proc if not already mounted
#mount -t proc proc /proc
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hamishcoleman Works without this. Do we need?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strange, I dont know what would be mounting proc in this case - this is running before systemd has mounted any filesystems

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason. I am running this after all the systemd stuff

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You know, we could add a blockdevice to the qemu test environment and allow that to be used to simply test persistance


cat /proc/partitions | while read major minor size name; do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads conf.d from all partitions. I guess it's okay for now? It'll be a little weird if multiple partitions have configurations because tar archive order rule doesn't apply here cross partitions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could exit on first found - which has issues if the files are hard to overwrite. we could also collate all the tar files from all the partitions - but that has an unwanted increase in complexity.

by checking all partitions, we try to avoid painting ourselves into an unexpected corner

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither first found or collect sort seem better than current. They are just different but just as non-ideal. I suggest keeping it as is and discourage people from having two partitions with conf.d at root, and state current behaviour.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggested the collect-and-sort method as that is how a lot of things (like systemd) handle multiple sources of config overrides - its an annoying amount of additional work, but could be done if this ever becomes an issue

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On WINDOWS machines, only the FIRST partition is ever recognized OS on usb devices.

Unless you have some reason to put config on partition >2 you could just stick with partition 1 to make it most compatible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue still exists when there are multiple physical disks connected to the board

# Check each partition matching sd*[0-9] (e.g. sda1) or mmcblk*p* (e.g. mmcblk0p1)
case $name in
sd*[0-9]|mmcblk*p*)
echo Checking for configuration files on $name
try_partition $name $major $minor
;;
esac
done
35 changes: 35 additions & 0 deletions debian/scripts/usr/local/bin/config_save
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Save current configurations to partition containing conf.d
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hamishcoleman Where shall I place this file?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isnt really a well named place for non-debian customisations in the repo (I had some ideas, but it didnt come up enough to fix yet) - I think you found the debian/packages.d/systemd.customise.add/usr/local/sbin/ dir which should work for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't automatically run this right? And bin or sbin in this case? System never runs it, it's the administrator of the nodes that may use it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sbin is for tools that the administrator runs - so it is definitely sbin

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Local is a bit of a toss up for me. By definition it sorta applies sorta does not.

The /usr/local hierarchy is for use by the system administrator when installing software locally. It needs to be safe from being overwritten when the system software is updated. It may be used for programs and data that are shareable among a group of hosts, but not found in /usr.

Since were not "upgrading" we don't really need local?

#
# Copyright (C) 2018 Benedict Lau <[email protected]>

CONFDIR=conf.d

try_partition() {
# Create file system node from partition
#mknod /dev/$1 b $2 $3 2>/dev/null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as this is run from a booted system, it should not make nodes - udev will do that for us

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed


# Mount partition as read-write
mount /dev/$1 /mnt

# Find conf.d in root of partition and save current configurations in /etc
if [ -d "/mnt/$CONFDIR" ]; then
echo Saving configurations to /dev/$1: "/mnt/$CONFDIR/50-node-config-save.tar.gz"
tar --create --gzip -f 50-node-config-save.tar.gz -C /etc .
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, we probably want both the tar filename and the source files to be optional parameters - but dont complicate things right now

fi

# Unmount partition
umount /mnt
}

# Mount proc if not already mounted
#mount -t proc proc /proc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as this is running in a booted system, we should not be mounting proc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed


cat /proc/partitions | while read major minor size name; do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This writes to multiple partitions if they all have conf.d. We don't expect that to happen and it's probably not a big deal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dunno - I'd be wanting it to only save to one of them - perhaps exit after the first found. Perhaps allowing the device name to be given as an optional parameter

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added breaking after first found

# Check each partition matching sd*[0-9] (e.g. sda1) or mmcblk*p* (e.g. mmcblk0p1)
case $name in
sd*[0-9]|mmcblk*p*)
echo Checking for configuration directory on $name
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now we only write to partitions with a conf.d directory. We should include an empty conf.d in the fat16 we create alongside boot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the appropriate place to do this? Is there an obvious common Makefile?

try_partition $name $major $minor
;;
esac
done