fixes first boot kernel-issues
This commit is contained in:
parent
ec88e37571
commit
6aee21c7ca
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.*.sw[po]
|
3
README.adoc
Normal file
3
README.adoc
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
= Dependencies =
|
||||||
|
|
||||||
|
sudo aptitude install git kpartx ruby qemu-system-arm qemu-user-static
|
91
init.sh
Normal file
91
init.sh
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
Usage() {
|
||||||
|
>&2 echo "Usage: $0 hostname [vgname]"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
>&2 echo "died: $*"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
msg() {
|
||||||
|
>&2 printf '\e[34;1m%s\e[0m\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_exists() {
|
||||||
|
true && lvs --noheadings --options lv_name "$1"
|
||||||
|
case $? in
|
||||||
|
0) return 0 ;;
|
||||||
|
5) return 1 ;;
|
||||||
|
*) die "Error while determining, if lv «$1» exists" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
alias blkuuid="blkid -ovalue -sUUID" blkfstype="blkid -ovalue -sTYPE"
|
||||||
|
|
||||||
|
[ X = X"$1" ] && Usage
|
||||||
|
[ X-h = X"$1" ] && Usage
|
||||||
|
[ X--help = X"$1" ] && Usage
|
||||||
|
|
||||||
|
hostname="$1"
|
||||||
|
#vgname="${2:-${hostname}sd}"
|
||||||
|
disc="/dev/mmcblk1"
|
||||||
|
pvpath="${disc}p2"
|
||||||
|
|
||||||
|
echo "Hostname: «$hostname»"
|
||||||
|
#echo "VG-name: «$vgname»"
|
||||||
|
echo
|
||||||
|
|
||||||
|
msg "Install needed tools..."
|
||||||
|
apt update
|
||||||
|
apt install -y lvm2 xfsprogs
|
||||||
|
|
||||||
|
msg "Set Hostname «$hostname»..."
|
||||||
|
oldhostname=`cat /etc/hostname`
|
||||||
|
sed -i -e "s/$oldhostname/$hostname/g" /etc/hosts
|
||||||
|
echo "$hostname" > /etc/hostname
|
||||||
|
|
||||||
|
vgname="`pvs --noheadings --options vg_name "$pvpath" | sed -e 's/^ *//'`"
|
||||||
|
# renaming does not work, because blockdevices will not be created.
|
||||||
|
# vgknodes, vgscan --mknodes tested.
|
||||||
|
#if [ "X$oldvgname" = "X$vgname" ]
|
||||||
|
#then
|
||||||
|
# msg "VG already named «$vgname»."
|
||||||
|
#else
|
||||||
|
# msg "Rename VG in «$vgname»..."
|
||||||
|
# vgrename "$oldvgname" "$vgname"
|
||||||
|
#fi
|
||||||
|
|
||||||
|
msg "Expand PV «$pvpath»..."
|
||||||
|
parted -ms "$disc" -- resizepart 2 -4MB print
|
||||||
|
pvresize "$pvpath"
|
||||||
|
|
||||||
|
msg "Expand root-LV..."
|
||||||
|
lvextend -rL4G "$vgname/root"
|
||||||
|
|
||||||
|
if lv_exists "$vgname/swap"
|
||||||
|
then
|
||||||
|
msg "LV «swap» already exists."
|
||||||
|
else
|
||||||
|
msg "Prepare swap-LV..."
|
||||||
|
lvcreate -nswap -L2G "$vgname"
|
||||||
|
mkswap "/dev/$vgname/swap"
|
||||||
|
echo "UUID=`blkuuid /dev/$vgname/swap` swap swap sw 0 0" >>/etc/fstab
|
||||||
|
fi
|
||||||
|
|
||||||
|
if lv_exists "$vgname/home"
|
||||||
|
then
|
||||||
|
msg "LV «home» already exists"
|
||||||
|
else
|
||||||
|
msg "Prepare home-LV..."
|
||||||
|
lvcreate -nhome -L4G "$vgname"
|
||||||
|
mkfs.xfs "/dev/$vgname/home"
|
||||||
|
echo "UUID=`blkuuid /dev/$vgname/home` /home xfs defaults 0 0" >>/etc/fstab
|
||||||
|
fi
|
||||||
|
|
||||||
|
msg "Install Updates..."
|
||||||
|
apt dist-upgrade -y
|
||||||
|
|
||||||
|
msg "ok"
|
|
@ -32,7 +32,7 @@ class Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def lpartx image
|
def lpartx image
|
||||||
mapper = Pathname.new '/dev/mapper'
|
mapper = XPathname.new '/dev/mapper'
|
||||||
lines = sh.kpartx( -:al, image, return: :lines)[0..-1]
|
lines = sh.kpartx( -:al, image, return: :lines)[0..-1]
|
||||||
if lines.grep( /^loop deleted/).empty?
|
if lines.grep( /^loop deleted/).empty?
|
||||||
lines.map do |line|
|
lines.map do |line|
|
||||||
|
@ -138,16 +138,17 @@ Settings:
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
sh.def_system_commands *%i[echo sed mount umount kpartx sync rsync xz gzip bzip2 zip tar bash dpkg apt]
|
sh.def_system_commands *%i[echo sed mount umount kpartx sync rsync xz gzip bzip2 zip tar bash dpkg apt]
|
||||||
sh.def_system_commands *%i[dmsetup lvcreate vgcreate pvcreate vgchange mkswap vgscan]
|
sh.def_system_commands *%i[losetup dmsetup lvcreate vgcreate pvcreate vgchange mkswap vgscan]
|
||||||
|
sh.alias_command :losetup_list, *%w[losetup --list --json], return: :json, could_be_empty: true
|
||||||
sh.alias_command :pvs, *%w[pvs --noheadings]
|
sh.alias_command :pvs, *%w[pvs --noheadings]
|
||||||
sh.alias_command :blkid, 'blkid', return: :line
|
sh.alias_command :blkid, 'blkid', return: :line
|
||||||
sh.alias_command :lsblk, *%w[lsblk --noheadings --paths --list], return: :lines
|
sh.alias_command :lsblk, *%w[lsblk --noheadings --paths --list], return: :lines
|
||||||
sh.alias_command :parted, *%w[parted -ms]
|
sh.alias_command :parted, *%w[parted --machine --script]
|
||||||
sh.alias_command :mkxfs, *%w[mkfs.xfs -f]
|
sh.alias_command :mkxfs, *%w[mkfs.xfs -f]
|
||||||
sh.alias_command :mkext2fs, *%w[mkfs.ext2]
|
sh.alias_command :mkext2fs, *%w[mkfs.ext2]
|
||||||
sh.alias_command :mkext4fs, *%w[mkfs.ext4]
|
sh.alias_command :mkext4fs, *%w[mkfs.ext4]
|
||||||
sh.alias_command :mkvfat, *%w[mkfs.vfat]
|
sh.alias_command :mkvfat, *%w[mkfs.vfat]
|
||||||
sh.alias_command :rsync_all, *%w[rsync -aHAX]
|
sh.alias_command :rsync_all, *%w[rsync --archive --hard-links --acls --xattrs]
|
||||||
sh.alias_command :mount_ro, *%w[mount -oro]
|
sh.alias_command :mount_ro, *%w[mount -oro]
|
||||||
sh.alias_command :fs_uuid, *%w[blkid -o value -s UUID], return: :line
|
sh.alias_command :fs_uuid, *%w[blkid -o value -s UUID], return: :line
|
||||||
sh.alias_command :fs_type, *%w[blkid -o value -s TYPE], return: :line
|
sh.alias_command :fs_type, *%w[blkid -o value -s TYPE], return: :line
|
||||||
|
@ -188,19 +189,20 @@ EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on '-aAUTHKEYS', '--auth-keys=AUTHKEYS', 'SSH-Keys for user' do |f|
|
opts.on '-aAUTHKEYS', '--auth-keys=AUTHKEYS', 'SSH-Keys for user' do |f|
|
||||||
f = Pathname.new f
|
f = XPathname.new f
|
||||||
d "#{f} not found.", f.exist?
|
d "#{f} not found.", f.exist?
|
||||||
@authorized_keys = f
|
@authorized_keys = f
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on '-AAUTHKEYS', '--root-auth-keys=AUTHKEYS', 'SSH-Keys for root' do |f|
|
opts.on '-AAUTHKEYS', '--root-auth-keys=AUTHKEYS', 'SSH-Keys for root' do |f|
|
||||||
f = Pathname.new f
|
f = XPathname.new f
|
||||||
d "#{f} not found.", f.exist?
|
d "#{f} not found.", f.exist?
|
||||||
@root_authorized_keys = f
|
@root_authorized_keys = f
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
|
nok = false
|
||||||
build
|
build
|
||||||
|
|
||||||
qemu_bin = dest.root + "usr/bin/qemu-arm-static"
|
qemu_bin = dest.root + "usr/bin/qemu-arm-static"
|
||||||
|
@ -210,10 +212,11 @@ EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue ProgrammError
|
rescue ProgrammError
|
||||||
|
nok = true
|
||||||
err $!
|
err $!
|
||||||
raise
|
raise
|
||||||
ensure
|
ensure
|
||||||
STDERR.puts "="*80
|
STDERR.puts "\e[1;36m#{"<"*80}\e[0m"
|
||||||
umount_all ignore_exceptions: true
|
umount_all ignore_exceptions: true
|
||||||
umount dest.root, -:R rescue Object
|
umount dest.root, -:R rescue Object
|
||||||
umount base.root, -:R rescue Object
|
umount base.root, -:R rescue Object
|
||||||
|
@ -222,7 +225,7 @@ EOF
|
||||||
departx dest.image rescue Object
|
departx dest.image rescue Object
|
||||||
departx base.image rescue Object
|
departx base.image rescue Object
|
||||||
sh.sync rescue Object
|
sh.sync rescue Object
|
||||||
STDERR.puts "="*80
|
STDERR.puts "\e[1;#{nok ? 31: 36}m#{">"*80}\e[0m"
|
||||||
end
|
end
|
||||||
|
|
||||||
def activate_vg vgname
|
def activate_vg vgname
|
||||||
|
@ -283,66 +286,61 @@ EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def ssh_copy_id_local src, home, uid, gid = nil
|
def ssh_copy_id_local src, home, uid, gid = nil
|
||||||
akf = home+'.ssh/authorized_keys'
|
akfile = home+'.ssh/authorized_keys'
|
||||||
akd = akf.dirname
|
akdir = akfile.dirname
|
||||||
akd.mkdir
|
akdir. mkdir
|
||||||
akd.chown uid, gid
|
akdir. chown uid, gid
|
||||||
akd.chmod 0700
|
akdir. chmod 0700
|
||||||
akf.copy src
|
akfile.copy src
|
||||||
akf.chown uid, gid
|
akfile.chown uid, gid
|
||||||
akf.chmod 0600
|
akfile.chmod 0600
|
||||||
end
|
end
|
||||||
|
|
||||||
def rename_user
|
def install_authorized_keys
|
||||||
ssh_copy_id_local @authorized_keys, dest.root+'home/pi', 1000, 1000 if @authorized_keys
|
ssh_copy_id_local @authorized_keys, dest.root+'home/pi', 1000, 1000 if @authorized_keys
|
||||||
ssh_copy_id_local @root_authorized_keys, dest.root+'root', 0, 0 if @root_authorized_keys
|
ssh_copy_id_local @root_authorized_keys, dest.root+'root', 0, 0 if @root_authorized_keys
|
||||||
|
end
|
||||||
|
|
||||||
if @username
|
def rename_user username = nil, password: nil, old: nil
|
||||||
dest.root.join( 'etc/passwd').replace_i do |f|
|
username ||= @username
|
||||||
f.each_line.flat_map do |l|
|
old ||= 'pi'
|
||||||
user, pwd, uid, gid, name, home, shell = l.split( ':')
|
password ||= @password
|
||||||
user, home = @username, "/home/#{@username}" if 'pi' == user
|
|
||||||
|
if username and old != username
|
||||||
|
dest.root.join( 'etc/passwd').sed_i do |l|
|
||||||
|
user, pwd, uid, gid, name, home, shell = l.split( ':', 7)
|
||||||
|
user, home = username, "/home/#{username}" if old == user
|
||||||
[user, pwd, uid, gid, name, home, shell].join ':'
|
[user, pwd, uid, gid, name, home, shell].join ':'
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
dest.root.join( 'etc/group').replace_i do |f|
|
dest.root.join( 'etc/group').sed_i do |l|
|
||||||
f.each_line.flat_map do |l|
|
group, pwd, gid, users = l.split( ':', 4)
|
||||||
group, pwd, gid, users = l.split( ':')
|
group = username if old == group
|
||||||
group = @username if 'pi' == group
|
users = users.split( ',').map {|user| old == user ? username : user }
|
||||||
users = users.split( ',').map {|user| 'pi' == user ? @username : user }
|
|
||||||
[group, pwd, gid, users.join( ',')].join ':'
|
[group, pwd, gid, users.join( ',')].join ':'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
dest.root.join( 'home', old).rename dest.root.join( 'home', username)
|
||||||
end
|
end
|
||||||
|
|
||||||
dest.root.join( 'home/pi').rename dest.root.join( 'home', @username)
|
if password or username
|
||||||
end
|
dest.root.join( 'etc/shadow').sed_i do |l|
|
||||||
|
user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved = l.split( ':', 9)
|
||||||
if @password or @username
|
if old == user
|
||||||
dest.root.join( 'etc/shadow').replace_i do |f|
|
crypt = password if password
|
||||||
f.each_line.flat_map do |l|
|
user = username if username
|
||||||
user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved = l.split( ':')
|
|
||||||
if 'pi' == user
|
|
||||||
crypt = @password if @password
|
|
||||||
user = @username if @username
|
|
||||||
end
|
end
|
||||||
[user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved].join ':'
|
[user, crypt, lastchange, minage, maxage, warn, inact, expiry, reserved].join ':'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def set_hostname hostname = nil
|
def set_hostname hostname = nil
|
||||||
hostname = @hostname
|
hostname ||= @hostname
|
||||||
return if hostname.nil? or hostname.empty?
|
return if hostname.nil? or hostname.empty?
|
||||||
msg :patch, 'etc/hosts', 'set hostname to', hostname
|
msg "setting hostname", hostname
|
||||||
dest.root.join( 'etc/hosts').replace_i do |f|
|
dest.root.join( 'etc/hosts').sed_i {|l| l.gsub /\<raspberrypi\>/, hostname }
|
||||||
f.each_line.map {|l| l.gsub /\<raspberrypi\>/, hostname }
|
dest.root.join( 'etc/hostname').write "#{hostname}\n"
|
||||||
end
|
|
||||||
msg :write, hostname, :to, 'etc/hostname'
|
|
||||||
dest.root.join( 'etc/hostname').open 'w' do |f|
|
|
||||||
f.puts hostname
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_packages_from_dir *paths
|
def install_packages_from_dir *paths
|
||||||
|
@ -368,7 +366,7 @@ EOF
|
||||||
|
|
||||||
def install_deb path
|
def install_deb path
|
||||||
#sh.dpkg '--unpack', '--force-architecture', pn, chroot: dest.root
|
#sh.dpkg '--unpack', '--force-architecture', pn, chroot: dest.root
|
||||||
adeb = Pathname.new( 'var/cache/apt/archives')+path.basename.to_s
|
adeb = XPathname.new( 'var/cache/apt/archives')+path.basename.to_s
|
||||||
dest.root.join( adeb.to_s).copy path
|
dest.root.join( adeb.to_s).copy path
|
||||||
sh.dpkg -:i, adeb, chroot: dest.root
|
sh.dpkg -:i, adeb, chroot: dest.root
|
||||||
#msg :unpack, path
|
#msg :unpack, path
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
require 'pathname'
|
require 'pathname'
|
||||||
|
|
||||||
class Pathname
|
class Pathname
|
||||||
alias +@ to_s
|
def +@
|
||||||
|
expand_path.to_s
|
||||||
|
end
|
||||||
|
|
||||||
def chdir &exe
|
def chdir &exe
|
||||||
Dir.chdir self.to_s, &exe
|
Dir.chdir self.to_s, &exe
|
||||||
|
@ -13,6 +15,14 @@ class Pathname
|
||||||
FileUtils.copy_file src.to_s, self.to_s, **opts
|
FileUtils.copy_file src.to_s, self.to_s, **opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def symlink to
|
||||||
|
File.symlink to.to_s, to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def link to
|
||||||
|
File.link to.to_s, to_s
|
||||||
|
end
|
||||||
|
|
||||||
def replace_i
|
def replace_i
|
||||||
open 'r+' do |f|
|
open 'r+' do |f|
|
||||||
lines = yield f
|
lines = yield f
|
||||||
|
@ -21,6 +31,67 @@ class Pathname
|
||||||
f.puts lines
|
f.puts lines
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sed_i **replaces, &e
|
||||||
|
open 'r+' do |f|
|
||||||
|
lines = f.each_line.flat_map {|l| yield l.chomp, replaces }
|
||||||
|
f.truncate 0
|
||||||
|
f.pos = 0
|
||||||
|
f.puts lines
|
||||||
|
replaces.each {|_,rls| f.puts rls }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class XPathname < Pathname
|
||||||
|
%i[/ + join].each do |meth|
|
||||||
|
define_method meth do |*n|
|
||||||
|
XPathname.new "#{super *n}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%i[unlink read].each do |meth|
|
||||||
|
define_method meth do |*a, &e|
|
||||||
|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m"
|
||||||
|
super *a, &e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%i[replace_i sed_i].each do |meth|
|
||||||
|
define_method meth do |*a, &e|
|
||||||
|
STDERR.puts "\e[1;36mpatching \e[1;35m#{self}\e[0m"
|
||||||
|
super *a, &e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%i[link rename symlink].each do |meth|
|
||||||
|
define_method meth do |*a, &e|
|
||||||
|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m -> #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
|
||||||
|
super *a, &e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%i[move copy].each do |meth|
|
||||||
|
define_method meth do |*a, &e|
|
||||||
|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m <- #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
|
||||||
|
super *a, &e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%i[make_link make_symlink].each do |meth|
|
||||||
|
name = meth.to_s.sub /\Amake_/, ''
|
||||||
|
define_method meth do |*a, &e|
|
||||||
|
STDERR.puts "\e[1;36m#{name} \e[1;35m#{self}\e[0m -> #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
|
||||||
|
super *a, &e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
%i[write].each do |meth|
|
||||||
|
define_method meth do |*a, &e|
|
||||||
|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m \e[1;35m#{a[0][0...128].inspect}\e[0m"
|
||||||
|
super *a, &e
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Symbol
|
class Symbol
|
||||||
|
|
|
@ -10,9 +10,23 @@ class Raspbian < Base
|
||||||
ENV['LANG'] = 'C'
|
ENV['LANG'] = 'C'
|
||||||
mkmppaths
|
mkmppaths
|
||||||
|
|
||||||
|
case
|
||||||
|
when !dest.image.exist?
|
||||||
|
when dest.image.file?
|
||||||
|
r = sh.losetup_list
|
||||||
|
unless r.empty? or r['loopdevices']
|
||||||
|
r['loopdevices'].each do |lo|
|
||||||
|
d "File #{dest.image} used as loop-device back-file",
|
||||||
|
+dest.image != +XPathname.new(lo['back-file'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
when dest.image.blockdev?, dest.image.chardev?
|
||||||
lsblk( dest.image).each do |l|
|
lsblk( dest.image).each do |l|
|
||||||
d "Device #{l[:name]} mounted at #{l[:mountpoint]}", ! l[:mountpoint]
|
d "Device #{l[:name]} mounted at #{l[:mountpoint]}", ! l[:mountpoint]
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
|
||||||
d "Base image does not exist", base.image.exist?
|
d "Base image does not exist", base.image.exist?
|
||||||
base_parts = kpartx base.image
|
base_parts = kpartx base.image
|
||||||
|
@ -38,7 +52,7 @@ class Raspbian < Base
|
||||||
STDERR.puts l
|
STDERR.puts l
|
||||||
sh.dmsetup :remove, File.basename(l[:name]) if 'lvm' == l[:type]
|
sh.dmsetup :remove, File.basename(l[:name]) if 'lvm' == l[:type]
|
||||||
l[:name].start_with?( dest.image.to_s) and 'part' == l[:type]
|
l[:name].start_with?( dest.image.to_s) and 'part' == l[:type]
|
||||||
end.map {|l| Pathname.new l[:name] }.sort
|
end.map {|l| XPathname.new l[:name] }.sort
|
||||||
rescue Sh::ProcessError
|
rescue Sh::ProcessError
|
||||||
kpartx dest.image
|
kpartx dest.image
|
||||||
end
|
end
|
||||||
|
@ -46,8 +60,8 @@ class Raspbian < Base
|
||||||
dest_parts[0].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
dest_parts[0].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
||||||
dest_parts[1].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
dest_parts[1].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
||||||
sh.vgscan '--cache'
|
sh.vgscan '--cache'
|
||||||
vgpath = Pathname.new( '/dev') + vgname
|
vgpath = XPathname.new( '/dev') + vgname
|
||||||
sh.pvcreate '-ff', dest_parts[1]
|
sh.pvcreate -:ff, dest_parts[1]
|
||||||
sh.vgcreate vgname, dest_parts[1]
|
sh.vgcreate vgname, dest_parts[1]
|
||||||
sh.lvcreate -:nroot, '-L4.2G', vgname
|
sh.lvcreate -:nroot, '-L4.2G', vgname
|
||||||
sh.lvcreate -:nhome, '-L100M', vgname
|
sh.lvcreate -:nhome, '-L100M', vgname
|
||||||
|
@ -56,7 +70,7 @@ class Raspbian < Base
|
||||||
sh.mkxfs -:Lroot, vgpath+'root'
|
sh.mkxfs -:Lroot, vgpath+'root'
|
||||||
sh.mkxfs -:Lhome, vgpath+'home'
|
sh.mkxfs -:Lhome, vgpath+'home'
|
||||||
mount vgpath+'root', dest.root
|
mount vgpath+'root', dest.root
|
||||||
addmp = {}
|
addmp = {run_udev: dest.root+'run/udev'}
|
||||||
%i[home boot dev proc sys].each do |n|
|
%i[home boot dev proc sys].each do |n|
|
||||||
d = addmp[n] = dest.root+n.to_s
|
d = addmp[n] = dest.root+n.to_s
|
||||||
d.mkdir
|
d.mkdir
|
||||||
|
@ -69,11 +83,10 @@ class Raspbian < Base
|
||||||
mount 'sysfs', addmp[:sys], -:tsysfs
|
mount 'sysfs', addmp[:sys], -:tsysfs
|
||||||
|
|
||||||
sh.rsync_all "#{base.root}/", dest.root
|
sh.rsync_all "#{base.root}/", dest.root
|
||||||
#sh.rsync *%w[kernel7.img initrd7.img], addmp[:boot]
|
|
||||||
|
|
||||||
|
install_authorized_keys
|
||||||
rename_user
|
rename_user
|
||||||
|
|
||||||
msg :patch, 'etc/fstab'
|
|
||||||
(dest.root+'etc'+'fstab').replace_i do |f|
|
(dest.root+'etc'+'fstab').replace_i do |f|
|
||||||
replace = {
|
replace = {
|
||||||
'/' => "UUID=#{sh.fs_uuid vgpath+'root'} / xfs defaults,noatime 0 0",
|
'/' => "UUID=#{sh.fs_uuid vgpath+'root'} / xfs defaults,noatime 0 0",
|
||||||
|
@ -86,25 +99,34 @@ class Raspbian < Base
|
||||||
end + replace.values
|
end + replace.values
|
||||||
end
|
end
|
||||||
|
|
||||||
msg :patch, 'boot/config.txt'
|
|
||||||
(addmp[:boot]+'config.txt').replace_i do |f|
|
(addmp[:boot]+'config.txt').replace_i do |f|
|
||||||
replace = {
|
replace = {
|
||||||
initramfs: 'initramfs initrd7.img followkernel',
|
'pi4' => { initramfs: 'initramfs initrd7l.img followkernel', },
|
||||||
|
'pi3' => { initramfs: 'initramfs initrd7.img followkernel', },
|
||||||
|
'pi2' => { initramfs: 'initramfs initrd7.img followkernel', },
|
||||||
|
'pi1' => { initramfs: 'initramfs initrd.img followkernel', },
|
||||||
|
'pi0' => { initramfs: 'initramfs initrd.img followkernel', },
|
||||||
}
|
}
|
||||||
f.each_line.flat_map do |l|
|
blocks = [nil]
|
||||||
|
content = Hash.new {|h,block| h[block] = [] }
|
||||||
|
block = nil
|
||||||
|
f.each_line do |l|
|
||||||
l.chomp!
|
l.chomp!
|
||||||
case l
|
case l
|
||||||
when /^initramfs /
|
when /\A\[([^\]]*)\]\z/
|
||||||
replace.delete :initramfs
|
block = $1
|
||||||
else l
|
blocks.push block
|
||||||
|
when /\Ainitramfs /
|
||||||
|
l = replace[block].delete :initramfs
|
||||||
end
|
end
|
||||||
end + replace.values
|
content[block].push l
|
||||||
|
end
|
||||||
|
replace.each {|block, rpl| content[block] += rpl.values + [''] unless rpl.empty? }
|
||||||
|
blocks.flat_map {|block| content[block] }
|
||||||
end
|
end
|
||||||
|
|
||||||
msg :touch, 'boot/ssh'
|
(addmp[:boot]+'ssh').write ''
|
||||||
(addmp[:boot]+'ssh').open('w') {|f|}
|
|
||||||
|
|
||||||
msg :patch, 'boot/cmdline.txt'
|
|
||||||
(addmp[:boot]+'cmdline.txt').replace_i do |f|
|
(addmp[:boot]+'cmdline.txt').replace_i do |f|
|
||||||
lines = f.readlines
|
lines = f.readlines
|
||||||
d "Only one line in cmdline.txt expected", 1 == lines.length
|
d "Only one line in cmdline.txt expected", 1 == lines.length
|
||||||
|
@ -119,46 +141,58 @@ class Raspbian < Base
|
||||||
opts.map {|k,v| v ? "#{k}=#{v}" : "#{k}" }.join(' ')
|
opts.map {|k,v| v ? "#{k}=#{v}" : "#{k}" }.join(' ')
|
||||||
end
|
end
|
||||||
|
|
||||||
msg :patch, 'etc/initramfs-tools/initramfs.conf'
|
|
||||||
dest.root.join( 'etc/initramfs-tools/initramfs.conf').replace_i do |f|
|
|
||||||
f.each_line.flat_map do |l|
|
|
||||||
l.chomp!
|
|
||||||
case l
|
|
||||||
when /^COMPRESS=/
|
|
||||||
'COMPRESS=xz'
|
|
||||||
when /^# *COMPRESS=/
|
|
||||||
[l, 'COMPRESS=xz']
|
|
||||||
else
|
|
||||||
l
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
set_hostname
|
|
||||||
|
|
||||||
msg :unlinking, 'etc/rc*.d/*resize2fs_once'
|
|
||||||
(dest.root+'etc').chdir do
|
(dest.root+'etc').chdir do
|
||||||
Pathname.glob( 'rc*.d/*resize2fs_once').each do |fn|
|
XPathname.glob( 'rc*.d/*resize2fs_once').each do |fn|
|
||||||
fn.unlink
|
fn.unlink
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
qemu_bin = dest.root.join 'usr/bin/qemu-arm-static'
|
qemu_bin = dest.root.join 'usr/bin/qemu-arm-static'
|
||||||
msg :copy, "/usr/bin/qemu-arm-static"
|
|
||||||
qemu_bin.copy '/usr/bin/qemu-arm-static', preserve: true
|
qemu_bin.copy '/usr/bin/qemu-arm-static', preserve: true
|
||||||
|
|
||||||
|
preload, preload_x = dest.root+'etc/ld.so.preload', dest.root+'etc/ld.so.preload.tp'
|
||||||
|
preload.rename preload_x
|
||||||
|
|
||||||
ish = sh.chroot( dest.root).chdir( '/')
|
ish = sh.chroot( dest.root).chdir( '/')
|
||||||
ish.apt :update
|
ish.apt :update
|
||||||
ish.apt :upgrade, -:y
|
ish.apt :upgrade, -:y
|
||||||
ish.apt :update
|
ish.apt :update
|
||||||
ish.apt :install, -:y, :lvm2, :xfsprogs
|
|
||||||
|
# We mount /run/udev for lvm-scanning - vgs / vgcfgbackup need it to connect to udev.
|
||||||
|
addmp[:run_udev].mkdir
|
||||||
|
mount '/run/udev', addmp[:run_udev], --:bind
|
||||||
|
|
||||||
|
# prevent installing exim by installing nullmailer
|
||||||
|
#ish.apt :install, -:y, :lvm2, :xfsprogs, :nullmailer, :dracut
|
||||||
|
#dest.root.join( 'etc/dracut.conf.d/10-denkn.conf').open 'w' do |f|
|
||||||
|
# f.puts 'add_modules+="lvm"'
|
||||||
|
# f.puts 'add_drivers+="dm-mod xfs"'
|
||||||
|
# f.puts 'compress="xz"'
|
||||||
|
#end
|
||||||
|
|
||||||
|
ish.apt :install, -:y, :lvm2, :xfsprogs, 'initramfs-tools'
|
||||||
|
dest.root.join( 'etc/initramfs-tools/initramfs.conf').replace_i do |f|
|
||||||
|
replace = { compress: 'COMPRESS=xz', }
|
||||||
|
f.each_line.flat_map do |l|
|
||||||
|
case l.chomp!
|
||||||
|
when /^COMPRESS=/ then replace.delete :compress
|
||||||
|
when /^# *COMPRESS=/ then [l, replace.delete( :compress)]
|
||||||
|
else l
|
||||||
|
end
|
||||||
|
end + replace.values
|
||||||
|
end
|
||||||
|
|
||||||
|
set_hostname
|
||||||
|
|
||||||
install_packages_from_dir(
|
install_packages_from_dir(
|
||||||
Pathname.new($0).expand_path.dirname+'raspbian-files',
|
XPathname.new( $0).expand_path.dirname + 'raspbian-files',
|
||||||
Pathname.new('files')
|
XPathname.new( 'files')
|
||||||
)
|
)
|
||||||
|
|
||||||
# generates implicite initramfs
|
# generates implicite initramfs
|
||||||
ish.system *%w[dpkg-reconfigure raspberrypi-kernel]
|
ish.system *%w[dpkg-reconfigure raspberrypi-kernel]
|
||||||
|
|
||||||
|
preload_x.rename preload
|
||||||
|
qemu_bin.unlink
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
require 'forwardable'
|
require 'forwardable'
|
||||||
require 'shellwords'
|
require 'shellwords'
|
||||||
require 'socket'
|
require 'socket'
|
||||||
|
require 'json'
|
||||||
|
|
||||||
class Sh
|
class Sh
|
||||||
class ForkError < RuntimeError
|
class ForkError < RuntimeError
|
||||||
|
@ -99,13 +100,14 @@ class Sh
|
||||||
if opts[:chroot]
|
if opts[:chroot]
|
||||||
STDERR.printf "\e[1;34mchroot(%s)\e[0m ", opts[:chroot].to_s
|
STDERR.printf "\e[1;34mchroot(%s)\e[0m ", opts[:chroot].to_s
|
||||||
Dir.chroot opts[:chroot].to_s
|
Dir.chroot opts[:chroot].to_s
|
||||||
|
Dir.chdir '/'
|
||||||
end
|
end
|
||||||
if @shell.opts[:pwd]
|
if @shell.opts[:dir]
|
||||||
STDERR.printf "%s ", @shell.opts[:pwd]
|
STDERR.printf "%s ", @shell.opts[:dir]
|
||||||
Dir.chdir @shell.opts[:pwd]
|
Dir.chdir @shell.opts[:dir]
|
||||||
end
|
end
|
||||||
#STDERR.puts "\e[0m#{opts[:return] ? '<=' : '#'} \e[33m#{cmd.shellescape} \e[35m#{usable_args.shelljoin}\e[0m"
|
#STDERR.puts "\e[0m#{opts[:return] ? '<=' : '#'} \e[33m#{cmd.shellescape} \e[35m#{usable_args.shelljoin}\e[0m"
|
||||||
STDERR.printf "\e[0m%s \e[33m%s \e[35m%s\e[0m\n",
|
STDERR.printf "\e[30;1m%s \e[0;33m%s \e[1;35m%s\e[0m\n",
|
||||||
opts[:return] ? '<=' : '#',
|
opts[:return] ? '<=' : '#',
|
||||||
cmd.shellescape,
|
cmd.shellescape,
|
||||||
usable_args.shelljoin
|
usable_args.shelljoin
|
||||||
|
@ -132,7 +134,19 @@ class Sh
|
||||||
when :string
|
when :string
|
||||||
opts[:mode], exe = :io, lambda( &:read)
|
opts[:mode], exe = :io, lambda( &:read)
|
||||||
when :line
|
when :line
|
||||||
opts[:mode], exe = :io, lambda{|f|f.read.chomp}
|
opts[:mode], exe = :io, lambda {|f| f.read.chomp }
|
||||||
|
when :json
|
||||||
|
opts[:mode] = :io
|
||||||
|
if opts[:could_be_empty]
|
||||||
|
exe = lambda do |f|
|
||||||
|
r = f.read
|
||||||
|
r.empty? ? [] : JSON.parse( r)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
exe = lambda {|f| JSON.parse f.read }
|
||||||
|
end
|
||||||
|
when :jsonl
|
||||||
|
opts[:mode], exe = :io, lambda {|f| f.each_line.map {|l| JSON.parse l } }
|
||||||
end
|
end
|
||||||
r = f = fork **opts
|
r = f = fork **opts
|
||||||
begin
|
begin
|
||||||
|
|
|
@ -7,13 +7,13 @@ class Image
|
||||||
@dir =
|
@dir =
|
||||||
case dir
|
case dir
|
||||||
when Pathname then dir
|
when Pathname then dir
|
||||||
when String then Pathname.new dir
|
when String then XPathname.new dir
|
||||||
else raise ArgumentError, "Pathname for dir expected"
|
else raise ArgumentError, "Pathname for dir expected"
|
||||||
end
|
end
|
||||||
@image =
|
@image =
|
||||||
case image
|
case image
|
||||||
when Pathname then image
|
when Pathname then image
|
||||||
when String then Pathname.new image
|
when String then XPathname.new image
|
||||||
when nil then @dir+'image'
|
when nil then @dir+'image'
|
||||||
else raise ArgumentError, "Pathname for image expected"
|
else raise ArgumentError, "Pathname for image expected"
|
||||||
end
|
end
|
||||||
|
@ -21,7 +21,7 @@ class Image
|
||||||
@root =
|
@root =
|
||||||
case root
|
case root
|
||||||
when Pathname then root
|
when Pathname then root
|
||||||
when String then Pathname.new root
|
when String then XPathname.new root
|
||||||
when nil then @dir+'root'
|
when nil then @dir+'root'
|
||||||
else raise ArgumentError, "Path for root must be Pathname, String or MP, if given"
|
else raise ArgumentError, "Path for root must be Pathname, String or MP, if given"
|
||||||
end
|
end
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue