tolvmxfs/armbian2lvm_xfs.rb

156 lines
3.8 KiB
Ruby
Executable File

#!/usr/bin/env ruby
require 'pathname'
$: << Pathname.new($0).expand_path.dirname+'lib'
require 'base'
require 'active_support/all'
Sector = Sectors = 512
class Armbian2LVM_XFS < Base
def initialize vgname = nil
super
chs = [?a..?z, ?A..?Z].map(&:to_a).flatten
@vgname = vgname || "armbian_#{5.times.map{chs[rand(chs.length)]}.join}"
end
def remove_all_partitions_from image
o = `parted -ms #{image.to_s.shellescape} print`
d "Cannot determine partitions in dest-image #{image}", 0 == $?
o.split( "\n")[2..-1].each do
sh.parted image, :rm, 1
end
end
def run
mkmppaths
d "Base image does not exist", base.image.exist?
base_parts = kpartx base.image
d "two (root-)partition in base expected, got: #{base_parts.inspect}", 1 == base_parts.length
mount -:oro, base_parts[0], base.root
# creates an image
dest.image.open 'w' do |f|
#f.pos = 1*Sector
## copy first 4mb from base-image because of u-boot
#f.write base.image.read( 4.megabytes-Sector, Sector)
f.pos = 1.6.gigabytes-1
f.putc 0.chr
end
# partitions for: /boot (128MiBi), LVM
sh.parted dest.image, *%w[--
mklabel msdos
mkpart primary ext2 4MB 132MB
mkpart primary ext2 132MB -1s
set 2 LVM on
print]
sh.bash -:ec, <<-EOF.gsub( /^\t{3}/, '').sub( /\n$/m, '')
BRANCH=dev
source ./build/config/sources/odroidxu4.conf
write_uboot_platform base/root/usr/lib/linux-u-boot-dev-odroidxu4_5.34.171103_armhf dest/base
EOF
dest_parts = kpartx dest.image
d "two partitions in destination expected", 2 == dest_parts.length
vgpath = Pathname.new( '/dev') + vgname
sh.pvcreate dest_parts[1]
sh.vgcreate vgname, dest_parts[1]
sh.lvcreate -:nroot, '-L1.1G', vgname
sh.lvcreate -:nhome, '-L100M', vgname
sh.vgchange -:ae, vgname
sh.mkext4fs dest_parts[0]
sh.mkxfs vgpath+'root'
sh.mkxfs vgpath+'home'
mount vgpath+'root', dest.root
addmp = {}
%i[home boot].each do |n|
d = addmp[n] = dest.root+n.to_s
d.mkdir
end
mount vgpath+'home', addmp[:home]
mount dest_parts[0], addmp[:boot]
sh.rsync_all "#{base.root}/", dest.root
(addmp[:boot]+'boot').make_symlink '.' # boot -> .
(addmp[:boot]+'boot.ini').open 'r+' do |f|
replace = {
rootdev: "setenv rootdev \"#{vgpath+'root'}\"",
rootfstype: "setenv rootfstype \"xfs\"",
}
lines =
f.each_line.map do |l|
l.chomp!
case l
when /^setenv rootdev /
replace.delete :rootdev
when /^setenv rootfstype /
replace.delete :rootfstype
else
l.gsub ' /boot/', ' /'
end
end
f.truncate 0
f.pos = 0
f.puts *lines
d "boot.ini had no entry for: #{replace.keys}", replace.empty?
end
(dest.root+'etc'+'fstab').open 'r+' do |f|
replace = {
'/' => "#{vgpath+'root'} / xfs defaults,noatime 0 0",
'/boot' => "#{dest_parts[0]} /boot ext4 defaults,noatime 0 0",
'/home' => "#{vgpath+'home'} /home xfs defaults,noatime 0 0",
}
lines =
f.each_line.flat_map do |l|
mp = l.split( /\s+/)[1]
replace.delete( mp) || l
end
lines += replace.values
f.truncate 0
f.pos = 0
f.puts lines
end
(dest.root+'etc'+'initramfs-tools'+'initramfs.conf').open 'r+' do |f|
lines =
f.each_line.flat_map do |l|
l.chomp!
case l
when /^COMPRESS=/
'COMPRESS=xz'
when /^# *COMPRESS=/
[l, 'COMPRESS=xz']
else
l
end
end
f.truncate 0
f.pos = 0
f.puts lines
end
sh.tar -:C, dest.root, -:xf, 'files.tar' if File.exists? 'files.tar'
rescue ProgrammError
err $!
raise
ensure
STDERR.puts "="*80
umount_all ignore_exceptions: true
sh.vgchange -:an, vgname rescue Object
sh.sync rescue Object
departx dest.image rescue Object
departx base.image rescue Object
sh.sync rescue Object
STDERR.puts "="*80
end
end
Armbian2LVM_XFS.new(*ARGV).run