small fixes. splited in task{...}.
This commit is contained in:
parent
068bbc95b6
commit
090b011853
|
@ -11,14 +11,27 @@ end
|
||||||
|
|
||||||
class Pathname
|
class Pathname
|
||||||
def self.which cmd
|
def self.which cmd
|
||||||
ENV['PATH'].each do |path|
|
ENV['PATH'].split(':').each do |path|
|
||||||
path = Pathname.new( path) + cmd
|
path = Pathname.new( path) + cmd
|
||||||
return path if path.executable?
|
return path if path.executable?
|
||||||
end
|
end
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Base
|
class Base
|
||||||
|
def task name, &exe
|
||||||
|
STDERR.puts "\e[30;1m***\e[0m #{name} \e[30;1m#{'*' * [0,80-name.length].max}\e[0m"
|
||||||
|
if yield
|
||||||
|
STDERR.puts "\e[32;1m---\e[0m #{name} \e[32;1m#{'-' * [0,80-name.length].max}\e[0m\n"
|
||||||
|
else
|
||||||
|
STDERR.puts "\e[35;1m---\e[0m #{name} \e[35;1m#{'-' * [0,80-name.length].max}\e[0m\n"
|
||||||
|
end
|
||||||
|
rescue Object
|
||||||
|
STDERR.puts "\n\e[31;1m|||\e[0m #{name} \e[31;1m#{'|' * [0,80-name.length].max}\e[0m\n"
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
|
||||||
def self.run *args, &exe
|
def self.run *args, &exe
|
||||||
new( *args).instance_eval &exe
|
new( *args).instance_eval &exe
|
||||||
end
|
end
|
||||||
|
@ -105,9 +118,10 @@ class Base
|
||||||
STDERR.print "\e[0m"
|
STDERR.print "\e[0m"
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_program cmd
|
def check_programm cmd
|
||||||
path = Pathname.which cmd
|
path = Pathname.which cmd
|
||||||
raise Error, "#{cmd} not found." unless path&.executable?
|
raise ProgrammError, "#{cmd} not found." unless path&.executable?
|
||||||
|
path
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :sh, :mounted, :looped, :base, :dest, :vgname
|
attr_reader :sh, :mounted, :looped, :base, :dest, :vgname
|
||||||
|
@ -118,10 +132,10 @@ class Base
|
||||||
end
|
end
|
||||||
|
|
||||||
%w[kpartx parted rsync lvm lvs pvs vgs mkfs.xfs mkfs.vfat dmsetup losetup lsblk blkid].each do |cmd|
|
%w[kpartx parted rsync lvm lvs pvs vgs mkfs.xfs mkfs.vfat dmsetup losetup lsblk blkid].each do |cmd|
|
||||||
check_program cmd
|
check_programm cmd
|
||||||
end
|
end
|
||||||
@qemu_bin_src = check_program 'qemu-arm-static'
|
@qemu_bin_src = check_programm 'qemu-arm-static'
|
||||||
raise Error, "@qemu-arm-static not found. Please install qemu-user-static" unless @qemu_bin_srci&.executable?
|
raise ProgrammError, "qemu-arm-static not found. Please install qemu-user-static" unless @qemu_bin_src&.executable?
|
||||||
|
|
||||||
if :ask == @password
|
if :ask == @password
|
||||||
v = b = nil
|
v = b = nil
|
||||||
|
@ -159,7 +173,7 @@ Settings:
|
||||||
hostname: #{@hostname || '(default)'}
|
hostname: #{@hostname || '(default)'}
|
||||||
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 partx kpartx sync rsync xz gzip bzip2 zip tar bash dpkg apt]
|
||||||
sh.def_system_commands *%i[losetup 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 :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]
|
||||||
|
@ -182,7 +196,7 @@ EOF
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on '-bIMAGE', '--baseimage=IMAGE', 'Write image to IMAGE. Device or file' do |v|
|
opts.on '-bIMAGE', '--baseimage=IMAGE', 'Read image from IMAGE. Device or file' do |v|
|
||||||
@baseimage = v
|
@baseimage = v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -364,6 +378,25 @@ EOF
|
||||||
dest.root.join( 'etc/hostname').write "#{hostname}\n"
|
dest.root.join( 'etc/hostname').write "#{hostname}\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
FSTabMountEntry =
|
||||||
|
Struct.new :spec, :file, :type, :ops, :freq, :passno do
|
||||||
|
def to_a() [spec, file, type, ops, freq||0, passno||0] end
|
||||||
|
def to_s() to_a.join ' ' end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_fstab content
|
||||||
|
cnt = {}
|
||||||
|
content = content.each do |ent|
|
||||||
|
cnt[ent.file.to_s] = ent.to_s
|
||||||
|
end
|
||||||
|
dest.root.join( 'etc/fstab').replace_i do |f|
|
||||||
|
f.each_line.flat_map do |l|
|
||||||
|
mp = l.split( /\s+/)[1]
|
||||||
|
cnt.delete( mp) || l
|
||||||
|
end + cnt.values
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def install_packages_from_dir *paths
|
def install_packages_from_dir *paths
|
||||||
paths.each do |pkgs|
|
paths.each do |pkgs|
|
||||||
next unless pkgs.directory?
|
next unless pkgs.directory?
|
||||||
|
|
|
@ -15,34 +15,45 @@ 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
|
alias link make_link
|
||||||
File.symlink to.to_s, to_s
|
alias symlink make_symlink
|
||||||
end
|
|
||||||
|
|
||||||
def link to
|
def replace_i &e
|
||||||
File.link to.to_s, to_s
|
changed = false
|
||||||
end
|
|
||||||
|
|
||||||
def replace_i
|
|
||||||
open 'r+' do |f|
|
open 'r+' do |f|
|
||||||
lines = yield f
|
old = f.readlines
|
||||||
f.truncate 0
|
|
||||||
f.pos = 0
|
f.pos = 0
|
||||||
f.puts lines
|
lines = yield f
|
||||||
|
changed = lines != old
|
||||||
|
if changed
|
||||||
|
f.truncate 0
|
||||||
|
f.pos = 0
|
||||||
|
f.puts lines
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
not changed
|
||||||
end
|
end
|
||||||
|
|
||||||
def sed_i **replaces, &e
|
def sed_i **replaces, &e
|
||||||
|
changed = false
|
||||||
open 'r+' do |f|
|
open 'r+' do |f|
|
||||||
lines = f.each_line.flat_map {|l| yield l.chomp, replaces }
|
lines =
|
||||||
f.truncate 0
|
f.each_line.flat_map do |l|
|
||||||
f.pos = 0
|
yield( l.chomp, replaces).tap {|r| changed = true unless l == r }
|
||||||
f.puts lines
|
end
|
||||||
replaces.each {|_,rls| f.puts rls }
|
changed = true unless replaces.empty?
|
||||||
|
if changed
|
||||||
|
f.truncate 0
|
||||||
|
f.pos = 0
|
||||||
|
f.puts lines
|
||||||
|
replaces.each {|_,rls| f.puts rls }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
not changed
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
class XPathname < Pathname
|
class XPathname < Pathname
|
||||||
%i[/ + join].each do |meth|
|
%i[/ + join].each do |meth|
|
||||||
define_method meth do |*n|
|
define_method meth do |*n|
|
||||||
|
@ -50,44 +61,53 @@ class XPathname < Pathname
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[unlink read].each do |meth|
|
%i[unlink read mkdir mkpath].each do |meth|
|
||||||
define_method meth do |*a, &e|
|
define_method meth do
|
||||||
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m"
|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m"
|
||||||
super *a, &e
|
super()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[replace_i sed_i].each do |meth|
|
%i[replace_i sed_i].each do |meth|
|
||||||
define_method meth do |*a, &e|
|
define_method meth do |*a, **o, &e|
|
||||||
STDERR.puts "\e[1;36mpatching \e[1;35m#{self}\e[0m"
|
STDERR.print "\e[1;36mpatching \e[1;35m#{self}\e[0m"
|
||||||
super *a, &e
|
begin
|
||||||
|
r = super *a, **o, &e
|
||||||
|
STDERR.puts "\r\e[#{r ? "1;32" : "33"}mpatching \e[1;35m#{self}\e[0m"
|
||||||
|
rescue Object
|
||||||
|
STDERR.puts "\r\e[1;31mpatching \e[1;35m#{self}\e[0m"
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
r
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[link rename symlink].each do |meth|
|
def rename dest
|
||||||
define_method meth do |*a, &e|
|
STDERR.puts "\e[1;36mrename \e[1;35m#{self}\e[0m -> \e[1;35m#{dest}\e[0m"
|
||||||
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m -> #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
|
super dest
|
||||||
super *a, &e
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[move copy].each do |meth|
|
def move src
|
||||||
define_method meth do |*a, &e|
|
STDERR.puts "\e[1;36mmove \e[1;35m#{self}\e[0m <- \e[1;35m#{dest}\e[0m"
|
||||||
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m <- #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
|
super src
|
||||||
super *a, &e
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%i[make_link make_symlink].each do |meth|
|
def copy src, **opts
|
||||||
name = meth.to_s.sub /\Amake_/, ''
|
STDERR.puts "\e[1;36mcopy \e[1;35m#{self}\e[0m <- \e[1;35m#{src}\e[0m"
|
||||||
define_method meth do |*a, &e|
|
super src, **opts
|
||||||
STDERR.puts "\e[1;36m#{name} \e[1;35m#{self}\e[0m -> #{a.map{|x|"\e[1;35m#{x}\e[0m"}.join ', '}"
|
end
|
||||||
super *a, &e
|
|
||||||
|
%i[link symlink].each do |meth|
|
||||||
|
define_method meth do |dest|
|
||||||
|
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m -> \e[1;35m#{dest}\e[0m"
|
||||||
|
super dest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
alias link make_link
|
||||||
|
alias symlink make_symlink
|
||||||
|
|
||||||
%i[write].each do |meth|
|
%i[write].each do |meth|
|
||||||
define_method meth do |*a, &e|
|
define_method meth do |*a, **o, &e|
|
||||||
STDERR.puts "\e[1;36m#{meth} \e[1;35m#{self}\e[0m \e[1;35m#{a[0][0...128].inspect}\e[0m"
|
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
|
super *a, &e
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,50 @@
|
||||||
require 'to_lvm_xfs'
|
require 'to_lvm_xfs'
|
||||||
|
|
||||||
class Raspbian < Base
|
class Raspbian < Base
|
||||||
|
Sizes = {
|
||||||
|
'' => 1,
|
||||||
|
'b' => 1,
|
||||||
|
's' => 512,
|
||||||
|
'k' => 1024,
|
||||||
|
'm' => 1024*1024,
|
||||||
|
'g' => 1024*1024*1024,
|
||||||
|
't' => 1024*1024*1024*1024,
|
||||||
|
'p' => 1024*1024*1024*1024*1024,
|
||||||
|
'e' => 1024*1024*1024*1024*1024*1024,
|
||||||
|
}
|
||||||
|
|
||||||
|
Volume = Struct.new :sh, :name, :device, :mountpoint, :builder_mp, :size do
|
||||||
|
def uuid() sh.fs_uuid device end
|
||||||
|
def type() sh.fs_type device end
|
||||||
|
|
||||||
|
def to_fstab_entry
|
||||||
|
FSTabMountEntry.new "UUID=#{uuid}", mountpoint, type, 'defaults,noatime', nil, nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def initialize *args
|
def initialize *args
|
||||||
@vgname = "raspi_#{SecureRandom.urlsafe_base64 5}"
|
@vgname = "raspi_#{SecureRandom.urlsafe_base64 5}"
|
||||||
|
@volumes = { root: ['/', '4.2G'], home: ['/home', '100M'] }
|
||||||
super *args
|
super *args
|
||||||
|
@vgpath = XPathname.new( '/dev') + @vgname
|
||||||
|
|
||||||
|
STDERR.printf "Volumes:\n"
|
||||||
|
vols = {}
|
||||||
|
@volumes.each do |name, (mp, size)|
|
||||||
|
mp = XPathname.new( mp).cleanpath
|
||||||
|
vols[mp.to_s] = Volume.new sh, name.to_s, @vgpath+name.to_s, mp, dest.root + mp.to_s[1..-1], size
|
||||||
|
STDERR.printf "%13s: %s (%s)\n", name, mp, size
|
||||||
|
end
|
||||||
|
@volumes = vols
|
||||||
|
end
|
||||||
|
|
||||||
|
def getopts opts
|
||||||
|
super opts
|
||||||
|
opts.on '-vNAME', '--volume=NAME', 'Creates additional volume name:mountpoint=size or overwrites defaults.' do |v|
|
||||||
|
m = %r<\A([0-9a-z_-]+):(/[0-9a-z/_-]*)=([0-9.]+[%a-z]?)\z>i.match v
|
||||||
|
fail "Volume expected in format: \"name:mountpoint=size\"" unless m
|
||||||
|
@volumes[m[1].to_sym] = [XPathname.new( m[2]).cleanpath, m[3]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def build
|
def build
|
||||||
|
@ -16,182 +57,207 @@ class Raspbian < Base
|
||||||
r = sh.losetup_list
|
r = sh.losetup_list
|
||||||
unless r.empty? or r['loopdevices']
|
unless r.empty? or r['loopdevices']
|
||||||
r['loopdevices'].each do |lo|
|
r['loopdevices'].each do |lo|
|
||||||
d "File #{dest.image} used as loop-device back-file",
|
fail "File #{dest.image} used as loop-device back-file" if +dest.image == +XPathname.new( lo['back-file'])
|
||||||
+dest.image != +XPathname.new(lo['back-file'])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
when dest.image.blockdev?, dest.image.chardev?
|
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]
|
fail "Device #{l[:name]} mounted at #{l[:mountpoint]}" if l[:mountpoint]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sleep 5
|
task "Mount base image #{base.image}" do
|
||||||
|
sh.partx -:u, base.image if base.image.blockdev?
|
||||||
|
|
||||||
d "Base image does not exist", base.image.exist?
|
fail "Base image does not exist" unless base.image.exist?
|
||||||
base_parts = kpartx base.image
|
base_parts = kpartx base.image
|
||||||
d "two partitions in base expected, got: #{base_parts.inspect}", 2 == base_parts.length
|
fail "two partitions in base expected, got: #{base_parts.inspect}" unless 2 == base_parts.length
|
||||||
mount base_parts[1], base.root, -:oro
|
mount base_parts[1], base.root, -:oro
|
||||||
mount base_parts[0], base.root+'boot', -:oro
|
mount base_parts[0], base.root+'boot', -:oro
|
||||||
|
end
|
||||||
|
|
||||||
dest.image.open 'w' do |f|
|
dest.image.open 'w' do |f|
|
||||||
|
size =
|
||||||
|
@volumes.inject 136*1024*1024 do |s, (_n, vol)|
|
||||||
|
m = /\A([0-9.]+)([bBsSkKmMgGtTpPeE]?)\z/i.match vol.size
|
||||||
|
fail "invalid size: #{vol.size}" unless m
|
||||||
|
s + m[1].to_f * Sizes[m[2].downcase]
|
||||||
|
end
|
||||||
f << 0.chr*4096
|
f << 0.chr*4096
|
||||||
f.pos = 4.8*1024*1024*1024-1
|
f.pos = size - 1
|
||||||
f.putc 0.chr
|
f.putc 0.chr
|
||||||
end
|
end
|
||||||
sh.parted dest.image, *%w[--
|
task "Partitioning destination image #{dest.image}" do
|
||||||
mklabel msdos
|
sh.parted dest.image, *%w[--
|
||||||
mkpart primary fat32 4MB 132MB
|
mklabel msdos
|
||||||
mkpart primary ext2 132MB -1s
|
mkpart primary fat32 4MB 132MB
|
||||||
set 2 LVM on
|
mkpart primary ext2 132MB -1s
|
||||||
print]
|
set 2 LVM on
|
||||||
|
print]
|
||||||
|
sh.partx -:u, dest.image if dest.image.blockdev?
|
||||||
|
end
|
||||||
|
|
||||||
*dest_parts =
|
*dest_parts =
|
||||||
begin
|
begin
|
||||||
lsblk( dest.image).select do |l|
|
lsblk( dest.image).select do |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| XPathname.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
|
||||||
d "two partitions in destination expected", 2 == dest_parts.length
|
fail "two partitions in destination expected" unless 2 == dest_parts.length
|
||||||
dest_parts[0].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
task "Prepare boot-partition #{dest_parts[0]} and lvm #{dest_parts[1]}" do
|
||||||
dest_parts[1].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
dest_parts[0].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
||||||
sh.vgscan '--cache'
|
dest_parts[1].open( 'w') {|f| f << 0.chr*4*1024*1024 }
|
||||||
vgpath = XPathname.new( '/dev') + vgname
|
sh.vgscan '--cache'
|
||||||
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
|
@volumes.each {|_name, vol| sh.lvcreate "-n#{vol.name}", "-L#{vol.size}", vgname }
|
||||||
sh.lvcreate -:nhome, '-L100M', vgname
|
sh.vgchange -:ae, vgname
|
||||||
sh.vgchange -:ae, vgname
|
sh.mkvfat -:nboot, dest_parts[0]
|
||||||
sh.mkvfat -:nboot, dest_parts[0]
|
@volumes.each {|_name, vol| sh.mkxfs "-L#{vol.name}", vol.device }
|
||||||
sh.mkxfs -:Lroot, vgpath+'root'
|
end
|
||||||
sh.mkxfs -:Lhome, vgpath+'home'
|
|
||||||
mount vgpath+'root', dest.root
|
|
||||||
addmp = {run_udev: dest.root+'run/udev'}
|
addmp = {run_udev: dest.root+'run/udev'}
|
||||||
%i[home boot dev proc sys].each do |n|
|
task "Mount all filesystems" do
|
||||||
d = addmp[n] = dest.root+n.to_s
|
mount @vgpath+'root', dest.root
|
||||||
d.mkdir
|
(%i[boot dev proc sys]).each do |n|
|
||||||
end
|
d = addmp[n] = dest.root+n.to_s
|
||||||
mount vgpath+'home', addmp[:home]
|
d.mkdir
|
||||||
mount dest_parts[0], addmp[:boot]
|
end
|
||||||
|
mount dest_parts[0], addmp[:boot]
|
||||||
|
mount '/dev', addmp[:dev], --:bind
|
||||||
|
mount 'proc', addmp[:proc], -:tproc
|
||||||
|
mount 'sysfs', addmp[:sys], -:tsysfs
|
||||||
|
|
||||||
mount '/dev', addmp[:dev], --:bind
|
@volumes.each do |_name, vol|
|
||||||
mount 'proc', addmp[:proc], -:tproc
|
path = vol.builder_mp
|
||||||
mount 'sysfs', addmp[:sys], -:tsysfs
|
next if dest.root == path || addmp.values.include?( path)
|
||||||
|
path.mkdir
|
||||||
sh.rsync_all "#{base.root}/", dest.root
|
mount @vgpath+vol.name, path
|
||||||
|
end
|
||||||
install_authorized_keys
|
|
||||||
rename_user
|
|
||||||
|
|
||||||
(dest.root+'etc'+'fstab').replace_i do |f|
|
|
||||||
replace = {
|
|
||||||
'/' => "UUID=#{sh.fs_uuid vgpath+'root'} / xfs defaults,noatime 0 0",
|
|
||||||
'/boot' => "UUID=#{sh.fs_uuid dest_parts[0]} /boot vfat defaults 1 1",
|
|
||||||
'/home' => "UUID=#{sh.fs_uuid vgpath+'home'} /home xfs defaults,noatime 1 1",
|
|
||||||
}
|
|
||||||
f.each_line.flat_map do |l|
|
|
||||||
mp = l.split( /\s+/)[1]
|
|
||||||
replace.delete( mp) || l
|
|
||||||
end + replace.values
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(addmp[:boot]+'config.txt').replace_i do |f|
|
task "Copy raspbian from base to dest" do
|
||||||
replace = {
|
sh.rsync_all "#{base.root}/", dest.root
|
||||||
'pi4' => { initramfs: 'initramfs initrd7l.img followkernel', },
|
end
|
||||||
'pi3' => { initramfs: 'initramfs initrd7.img followkernel', },
|
|
||||||
'pi2' => { initramfs: 'initramfs initrd7.img followkernel', },
|
task "Prepare users" do
|
||||||
'pi1' => { initramfs: 'initramfs initrd.img followkernel', },
|
install_authorized_keys
|
||||||
'pi0' => { initramfs: 'initramfs initrd.img followkernel', },
|
rename_user
|
||||||
}
|
end
|
||||||
blocks = [nil]
|
|
||||||
content = Hash.new {|h,block| h[block] = [] }
|
task "Prepare /etc and /boot" do
|
||||||
block = nil
|
update_fstab @volumes.map { |_name, vol| vol.to_fstab_entry } +
|
||||||
f.each_line do |l|
|
[ FSTabMountEntry.new( "UUID=#{sh.fs_uuid( dest_parts[0])}", '/boot', 'vfat', 'defaults', 1, 1)]
|
||||||
l.chomp!
|
|
||||||
case l
|
addmp[:boot].join( 'config.txt').replace_i do |f|
|
||||||
when /\A\[([^\]]*)\]\z/
|
replace = {
|
||||||
block = $1
|
'pi4' => { initramfs: 'initramfs initrd8.img followkernel', arm_64bit: 'arm_64bit=1' },
|
||||||
blocks.push block
|
'pi3' => { initramfs: 'initramfs initrd7l.img followkernel', },
|
||||||
when /\Ainitramfs /
|
'pi2' => { initramfs: 'initramfs initrd7.img followkernel', },
|
||||||
l = replace[block].delete :initramfs
|
'pi1' => { initramfs: 'initramfs initrd.img followkernel', },
|
||||||
|
'pi0' => { initramfs: 'initramfs initrd.img followkernel', },
|
||||||
|
}
|
||||||
|
blocks = [nil]
|
||||||
|
content = Hash.new {|h,block| h[block] = [] }
|
||||||
|
block = nil
|
||||||
|
f.each_line do |l|
|
||||||
|
l.chomp!
|
||||||
|
case l
|
||||||
|
when /\A\[([^\]]*)\]\z/
|
||||||
|
block = $1
|
||||||
|
blocks.push block
|
||||||
|
when /\Ainitramfs /
|
||||||
|
l = replace[block].delete :initramfs
|
||||||
|
end
|
||||||
|
content[block].push l
|
||||||
end
|
end
|
||||||
content[block].push l
|
replace.each {|block, rpl| content[block] += rpl.values + [''] unless rpl.empty? }
|
||||||
|
blocks.flat_map {|block| content[block] }
|
||||||
end
|
end
|
||||||
replace.each {|block, rpl| content[block] += rpl.values + [''] unless rpl.empty? }
|
|
||||||
blocks.flat_map {|block| content[block] }
|
|
||||||
end
|
|
||||||
|
|
||||||
(addmp[:boot]+'ssh').write ''
|
addmp[:boot].join( 'ssh').write ''
|
||||||
|
|
||||||
(addmp[:boot]+'cmdline.txt').replace_i do |f|
|
addmp[:boot].join( 'cmdline.txt').replace_i do |f|
|
||||||
lines = f.readlines
|
lines = f.readlines
|
||||||
d "Only one line in cmdline.txt expected", 1 == lines.length
|
fail "Only one line in cmdline.txt expected" unless 1 == lines.length
|
||||||
opts = {}
|
opts = {}
|
||||||
lines[0].split( ' ').each do |line|
|
lines[0].split( ' ').each do |line|
|
||||||
/^([^=]*)(?:=(.*))?/ =~ line
|
/^([^=]*)(?:=(.*))?/ =~ line
|
||||||
opts[$1.to_sym] = $2
|
opts[$1.to_sym] = $2
|
||||||
|
end
|
||||||
|
opts[:root] = @vgpath+'root'
|
||||||
|
opts[:rootfstype] = :xfs
|
||||||
|
opts.delete :init
|
||||||
|
opts.map {|k,v| v ? "#{k}=#{v}" : "#{k}" }.join(' ')
|
||||||
end
|
end
|
||||||
opts[:root] = vgpath+'root'
|
|
||||||
opts[:rootfstype] = :xfs
|
|
||||||
opts.delete :init
|
|
||||||
opts.map {|k,v| v ? "#{k}=#{v}" : "#{k}" }.join(' ')
|
|
||||||
end
|
|
||||||
|
|
||||||
(dest.root+'etc').chdir do
|
dest.root.join( 'etc').chdir do
|
||||||
XPathname.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.copy @qemu_bin_src, preserve: true
|
set_hostname
|
||||||
|
end
|
||||||
|
|
||||||
preload, preload_x = dest.root+'etc/ld.so.preload', dest.root+'etc/ld.so.preload.tp'
|
preload, preload_x = dest.root+'etc/ld.so.preload', dest.root+'etc/ld.so.preload.tp'
|
||||||
preload.rename preload_x
|
task "Prepare to chroot to raspbian" do
|
||||||
|
@qemu_bin.copy @qemu_bin_src, preserve: true
|
||||||
|
|
||||||
ish = sh.chroot( dest.root).chdir( '/')
|
preload.rename preload_x
|
||||||
ish.apt :update
|
|
||||||
ish.apt :upgrade, -:y
|
|
||||||
ish.apt :update
|
|
||||||
|
|
||||||
# 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
|
end
|
||||||
|
|
||||||
set_hostname
|
task "update, upgrade and install" do
|
||||||
|
ish = sh.chroot( dest.root).chdir( '/')
|
||||||
|
ish.apt :update
|
||||||
|
ish.apt :upgrade, -:y
|
||||||
|
ish.apt :update
|
||||||
|
|
||||||
install_packages_from_dir(
|
install_packages_from_dir(
|
||||||
XPathname.new( $0).expand_path.dirname + 'raspbian-files',
|
XPathname.new( $0).expand_path.dirname + 'raspbian-files',
|
||||||
XPathname.new( 'files')
|
XPathname.new( 'files')
|
||||||
)
|
)
|
||||||
|
|
||||||
# generates implicite initramfs
|
# We mount /run/udev for lvm-scanning - vgs / vgcfgbackup need it to connect to udev.
|
||||||
ish.system *%w[dpkg-reconfigure raspberrypi-kernel]
|
addmp[:run_udev].mkdir
|
||||||
|
mount '/run/udev', addmp[:run_udev], --:bind
|
||||||
|
|
||||||
preload_x.rename preload
|
# prevent installing exim by installing nullmailer
|
||||||
@qemu_bin.unlink
|
#ish.apt *%w[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 *%w[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
|
||||||
|
|
||||||
|
# strange error while generating initramfs;
|
||||||
|
# it want to delete this directory, but it does not exist.
|
||||||
|
#overlays = dest.root + 'usr/share/rpikernelhack/overlays'
|
||||||
|
#overlays.mkpath
|
||||||
|
#overlays.join( '.keep').write ''
|
||||||
|
|
||||||
|
# generates implicite initramfs
|
||||||
|
ish.system *%w[dpkg-reconfigure raspberrypi-kernel]
|
||||||
|
end
|
||||||
|
|
||||||
|
task "Reverse hacking for chrooting" do
|
||||||
|
preload_x.rename preload
|
||||||
|
@qemu_bin.unlink
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Binary file not shown.
Loading…
Reference in a new issue