next level

This commit is contained in:
Denis Knauf 2018-12-25 21:33:57 +01:00
parent 3eb91f4708
commit ec88e37571
9 changed files with 591 additions and 5 deletions

86
activate.rb Executable file
View file

@ -0,0 +1,86 @@
#!/usr/bin/env ruby
require 'pathname'
$: << Pathname.new($0).expand_path.dirname+'lib'
require 'base'
require 'active_support/all'
require 'json'
class Tivate < Base
def initialize
super
sh.alias_command :lsblk_json, *%w[lsblk --json --fs], return: :string
end
def listing *devices, reverse: nil, only_fs: nil, &exe
return to_enum( __method__, *devices, reverse: reverse, only_fs: only_fs) unless block_given?
return nil if devices.empty?
reverse = false if reverse.nil?
only_fs = false if only_fs.nil?
l =
lambda do |e|
case e['fstype']
when 'LVM2_member'
e[:isfs] = false
yield e if not only_fs and not reverse
(e['children']||[]).each &l
yield e if not only_fs and reverse
when *%w[ext2 ext3 ext4 xfs]
e[:isfs] = true
yield e
end
end
devices.each do |dev|
if dev.exist?
data = JSON.parse sh.lsblk_json( dev)
data['blockdevices'].each &l
end
end
end
end
cmd = Pathname.new $0
case ARGV[0]
when '-h', '--help'
puts <<EOF
Usage: activate.rb -h | image # provides all filesystem of an image as devices
deactivate.rb -h | image # umounts and deprovitions devices
EOF
end
image = Pathname.new ARGV[0]
case cmd.basename( '.rb').to_s.downcase.to_sym
when :activate
Tivate.run do
raise "Image «#{image}» does not exist" unless image.exist?
devs = kpartx image
listing *devs do |dev|
if 'LVM2_member' == dev['fstype']
vgname = get_vgname_of_pv( "/dev/mapper/#{dev['name']}").to_a[0]
sh.vgchange -:ay, vgname, return: :string
end
end
listing *devs do |dev|
if dev[:isfs]
puts "/dev/mapper/#{dev['name']}"
end
end
end
when :deactivate
Tivate.run do
raise "Image «#{image}» does not exist" unless image.exist?
devs = lpartx image
listing *devs, reverse: true do |dev|
sh.umount dev['mountpoint'] if dev['mountpoint']
if 'LVM2_member' == dev['fstype']
vgname = get_vgname_of_pv( "/dev/mapper/#{dev['name']}").to_a[0]
sh.vgchange -:an, vgname
end
end
departx image
end
else
raise "activate or deactivate?"
end

229
armbian2.rb Executable file
View file

@ -0,0 +1,229 @@
#!/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
super
chs = [?a..?z, ?A..?Z].map(&:to_a).flatten
@vgname = "armbian_#{5.times.map{chs[rand(chs.length)]}.join}"
d "Destination image «#{dest.image}» in use!", dest.kpartxed?
end
# read from input, write to output
# input|output can be:
# Pathname: opens file and use it as IO
# String: reads from/writes to like an IO (->StringIO)
# IO: use it directly
# obs|ibs|bs: blocksizes (if ibs|obs not given, bs will be used, else 512)
# from: set input-block-position to from
# skip: skip next X blocks from current position
# at: set output-block-position to to
# seek: seek to next X blocks from current position
def dd input, output, from: nil, skip: nil, at: nil, seek: nil, bs: nil, ibs: nil, obs: nil
case input
when Pathname
input.open 'r' do |f|
return __method__( f, output, pos: pos, seek: seek)
end
when String
StringIO.open input do |f|
return __method__( f, output, pos: pos, seek: seek)
end
when IO
case output
when Pathname
output.open 'w' do |f|
return __method__( input, f, pos: pos, seek: seek)
end
when String
StringIO.open output, 'w' do |f|
return __method__( input, f, pos: pos, seek: seek)
end
when IO
ibs ||= bs || 512
obs ||= bs || 512
input.pos = from*ibs if from
input.pos += skip*ibs if skip
output.pos = at*obs if at
output.pos += seek*obs if seek
output.write input.read( count ? count*ibs : nil)
end
else
raise ArgumentError, "input for dd must be a String, IO or Pathname"
end
end
def run
mkmppaths
d "Base image does not exist", base.image.exist?
base_parts = base.kpartx
d "two (root-)partition in base expected, got: #{base_parts.inspect}", 1 == base_parts.length
mount base_parts[0], base.root, -:oro
msg 'prepare image', dest.image
dest.image.open 'w' do |f|
f.truncate 0
f.pos = 0
f.write 0.chr*4.megabytes
f.pos = 1.5.gigabytes+128.megabytes+4.megabytes-1
f.putc 0.chr
end
# partitions for: /boot (128MiBi), LVM
sh.parted dest.image, '--',
*%w[mklabel msdos],
*%w[mkpart primary ext2 4MB 132MB],
*%w[mkpart primary ext2 132MB -4MB],
*%w[set 1 boot on],
*%w[set 2 LVM on],
*%w[print]
ubootdir = base.root + 'usr' + 'lib' + 'linux-u-boot-dev-odroidxu4_5.34.171103_armhf'
if false
sh.bash -:ec, <<-EOF.gsub( /^\t{4}/, '').sub( /\n$/m, '')
echo "hallo welt"
BRANCH=dev
source ./build/config/sources/odroidxu4.conf
dd() {
echo dd "$*" >&2
command dd "$@"
}
write_uboot_platform #{ubootdir.to_s.shellescape} #{dest.image.to_s.shellescape}
EOF
else
msg 'install u-boot', dest.image, ubootdir
dest.image.open 'r+' do |f|
msg ' apply', ubootdir+'bl1.bin.hardkernel'
f.pos = 1*Sector
b = (ubootdir+'bl1.bin.hardkernel').read
f.write b
msg ' apply', ubootdir+'bl2.bin.hardkernel.720k_uboot'
f.pos = 31*Sectors
f.write (ubootdir+'bl2.bin.hardkernel.720k_uboot').read
msg ' apply', ubootdir+'u-boot-dtb.bin'
f.pos = 63*Sectors
f.write (ubootdir+'u-boot-dtb.bin').read
msg ' apply', ubootdir+'tzsw.bin.hardkernel'
f.pos = 1503*Sectors
f.write (ubootdir+'tzsw.bin.hardkernel').read
msg ' clear', 'u-boot env'
f.pos = 2015*Sectors
f.write 0.chr*32*Sectors
end
end
dest_parts = dest.kpartx
d "two partitions in destination expected", 2 == dest_parts.length
#root = MP.new self, dest_parts[1], dest.root
#home = MP.new self, nil, dest.root+'home'
#boot = MP.new self, dest_parts[0], dest.root+'boot'
vgpath = Pathname.new( '/dev') + vgname
root = MP.new self, vgpath + 'root', dest.root
#home = MP.new self, vgpath + 'home', dest.root+'home'
boot = MP.new self, dest_parts[0], dest.root+'boot'
#swap = MP.new self, vgpath + 'swap', 'none'
sh.pvcreate dest_parts[1]
sh.vgcreate vgname, dest_parts[1]
sh.lvcreate -:nroot, '-L1.5G', vgname
#sh.lvcreate -:nhome, '-L120M', vgname
#sh.lvcreate -:nswap, '-L10M', vgname
activate_vg vgname
sh.mkext4fs boot.dev
sh.mkxfs root.dev
#sh.mkxfs home.dev
#sh.mkswap swap.dev
root.mount
#home.mp.mkdir
#home.mount
boot.mp.mkdir
boot.mount
exclude = %w[boot/dtb-*
boot/uInitrd-* boot/vmlinuz-* boot/initrd.img-*
boot/config-* boot/System.map-*
etc/systemd/system/basic.target.wants/resize2fs.service
etc/systemd/system/sysinit.target.wants/log2ram.service
etc/rc?.d/*resize2fs
root/.not_logged_in_yet etc/profile.d/check_first_login.sh
].flat_map {|e| ['--exclude', e] } #"#{base.root}#{e}"] }
sh.rsync_all *exclude, "#{base.root}/", root.mp
msg 'create symlink', boot.mp+'boot', '->', '.'
(boot.mp+'boot').make_symlink '.'
manipulate_file boot.mp+'boot.ini' do |file, &push|
file.each_line do |l|
case l.chomp!
when /^ *setenv +rootdev +/
push.call "setenv rootdev \"UUID=#{root.uuid}\""
when /^ *setenv +rootfstype +/
push.call "setenv rootfstype \"#{root.fstype}\""
else
push.call l
end
end
end
manipulate_file root.mp+'etc'+'initramfs-tools'+'initramfs.conf' do |file, &push|
file.each_line do |l|
case l.chomp!
when /^COMPRESS=/
push.call 'COMPRESS=xz'
when /^# *COMPRESS=/
push.call l, 'COMPRESS=xz'
else
push.call l
end
end
end
manipulate_file root.mp+'etc'+'fstab' do |file, &push|
file.each_line do |l|
case l.chomp!
when /^ *#/
push.call l
when /^\s*(\S+)\s+\/\s+()/
push.call "UUID=#{root.uuid} / #{root.fstype} defaults,noatime,nodiratime,errors=remount-ro 0 1"
when /^\s*\/var\/swap\s+/
# skip
else
push.call l
end
end
#push.call "UUID=#{swap.uuid} none #{swap.fstype} sw 0 0"
push.call "UUID=#{boot.uuid} /boot #{boot.fstype} defaults 0 0"
#push.call "UUID=#{home.uuid} /home #{home.fstype} defaults,errors=remount-ro 0 0"
end
sh.tar -:C, root.mp, -:xf, 'files.tar' if File.exists? 'files.tar'
rescue ProgrammError
err $!
raise
ensure
STDERR.puts "="*80
umount_all ignore_exceptions: true
deactivate_all_vgs ignore_exceptions: true
capsulated_rescue { sh.sync }
capsulated_rescue { dest.departx }
capsulated_rescue { base.departx }
capsulated_rescue { sh.sync }
end
end
Armbian2LVM_XFS.new.run

1
deactivate.rb Symbolic link
View file

@ -0,0 +1 @@
activate.rb

View file

@ -1,6 +1,6 @@
require 'to_lvm_xfs'
class Raspibian < Base
class Raspbian < Base
def initialize *args
@vgname = "raspi_#{SecureRandom.urlsafe_base64 5}"
super *args
@ -57,13 +57,17 @@ class Raspibian < Base
sh.mkxfs -:Lhome, vgpath+'home'
mount vgpath+'root', dest.root
addmp = {}
%i[home boot].each do |n|
%i[home boot dev proc sys].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]
mount '/dev', addmp[:dev], --:bind
mount 'proc', addmp[:proc], -:tproc
mount 'sysfs', addmp[:sys], -:tsysfs
sh.rsync_all "#{base.root}/", dest.root
#sh.rsync *%w[kernel7.img initrd7.img], addmp[:boot]
@ -143,7 +147,7 @@ class Raspibian < Base
msg :copy, "/usr/bin/qemu-arm-static"
qemu_bin.copy '/usr/bin/qemu-arm-static', preserve: true
ish = sh.chroot dest.root
ish = sh.chroot( dest.root).chdir( '/')
ish.apt :update
ish.apt :upgrade, -:y
ish.apt :update

View file

@ -87,7 +87,6 @@ class Sh
else Fork
end
cl.new do
Dir.chdir @shell.opts[:pwd] if @shell.opts[:pwd]
cmd = @command.to_s
$0 = cmd
#STDERR.printf "\n|\n| %p\n|\n", cmd: cmd, args: @args
@ -101,6 +100,10 @@ class Sh
STDERR.printf "\e[1;34mchroot(%s)\e[0m ", opts[:chroot].to_s
Dir.chroot opts[:chroot].to_s
end
if @shell.opts[:pwd]
STDERR.printf "%s ", @shell.opts[:pwd]
Dir.chdir @shell.opts[:pwd]
end
#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",
opts[:return] ? '<=' : '#',

Binary file not shown.

View file

@ -4,4 +4,4 @@ require 'pathname'
$: << Pathname.new($0).expand_path.dirname+'lib'
require 'to_lvm_xfs/raspbian'
Raspian.new(*ARGV).run
Raspbian.new(*ARGV).run

132
raspbian2lvm_xfs.sh Normal file
View file

@ -0,0 +1,132 @@
#!/usr/bin/env bash
die() {
>&2 printf '\e[1;31mdied: '"$*"'\e[0m\n'
all_umounts
exit 1
}
l() {
>&2 printf '\e[1m'"$*"'\e[0m\n'
}
d() {
>&2 printf '\e[1;34m# '"$*"'\e[0m\n'
"$@" || die "$*"
}
baseimg="$1"
unpack_zip() {
zip -p "$1" > "$2"
}
unzip_xz() {
xz -d < "$1" > "$2"
}
unpack_bzip2() {
bzip2 -d < "$1" > "$2"
}
unpack_gzip() {
gzip -d < "$1" > "$2"
}
unpack_plain() {
ln -sf "$1" "$2"
}
all_umounts() {
umount base/root
umount base/boot
umount dest/root
umount dest/boot
vgchange -an raspi
kpartx -d dest/image
kpartx -d base/image
}
pii_mounts() {
local dir="${1:-murks}"
local img="${2:-$dir/image}"
set -- `kpartx -l "$img" | sed -e 's/ : .*//'`
local bootdev="/dev/mapper/$1"
local rootdev="/dev/mapper/$2"
[ -e "$bootdev" -a -e "$rootdev" ] || die "Cannot find devs [$bootdev] [$rootdev]"
d mount "$bootdev" "$dir/boot"
d mount "$rootdev" "$dir/root"
}
pii_mkfs() {
local img="${1:-murks}"
set -- `kpartx -l "$img" | sed -e 's/ : .*//'`
local bootdev="/dev/mapper/$1"
local rootdev="/dev/mapper/$2"
[ -e "$bootdev" -a -e "$rootdev" ] || die "Cannot find devs [$bootdev] [$rootdev]"
l format destination-boot
d mkfs.fat -n boot -F 32 "$bootdev"
l format destination-root
d mkfs.xfs -L root "$rootdev"
}
case "$baseimg" in
*.zip) alias unpack=d\ unpack_zip ;;
*.xz) alias unpack=d\ unpack_xz ;;
*.bz2) alias unpack=d\ unpack_bz2 ;;
*.gz) alias unpack=d\ unpack_gz ;;
*) alias unpack=d\ unpack_plain ;;
esac
# let's go...
d mkdir -p base/root base/boot dest/root dest/boot
l setup base-image-access
#[ -e base/image ] && die "base/image already exists"
#unpack "$baseimg" base/image
d kpartx -sar base/image
l mount base-partitions
pii_mounts base
l create destination image
d dd if=/dev/zero of=dest/image seek=$((4800*256-1)) count=1 bs=4096
d parted dest/image -- \
mklabel msdos \
mkpart primary fat32 4MB 132MB \
mkpart primary lvm 133MB -1s \
set 2 lba off \
print
d kpartx -sa dest/image
pii_mkfs dest/image
d parted dest/image print
l mount destination-partitions
pii_mounts dest
l install it
d rsync -aHAX base/boot/ dest/boot/
d rsync -aHAX base/root/ dest/root/
d rsync kernel7.img initrd7.img dest/boot
if grep -q '^initramfs ' dest/boot/config.txt
then
d sed -i -e 's!^initramfs .*!initramfs initrd7.img followkernel!' dest/boot/config.txt
else
l "# echo initramfs initrd7.img followkernel >> dest/boot/config.txt"
echo initramfs initrd7.img followkernel >> dest/boot/config.txt || die "echo initramfs initrd7.img followkernel >> dest/boot/config.txt"
fi
d sed -i -e 's!\<root=[^ ]*!root=/dev/raspi/root!;s!\<rootfstype=[^ ]*!rootfstype=xfs!;s!\<init=[^ ]* *!!' dest/boot/cmdline.txt
d touch dest/boot/ssh
l setup initramfs for updates in future
d sed -i -e 's!^COMPRESS=!COMPRESS=xz!' dest/root/etc/initramfs-tools/initramfs.conf
l deactivate resize2fs-init-script
d rm dest/root/etc/rc*.d/*resize2fs_once
l change user pi to deac
d sed -i -e 's!^pi:.*!deac:x:1000:1000:Denis Knauf,,,:/home/deac:/bin/bash!' dest/root/etc/passwd
d sed -i -e 's!^pi:.*!deac:$6$aZRhIfbP$6ELyvhfjXP2wiIuq5gIsDPFXFWM1E8KwGhKFWKtFwJZ8CLwHXmZECzpxslwLbvgtYCScTZBJBTjp.hVjd6.2l1:16958:0:99999:7:::!' dest/root/etc/shadow
d sed -i -e 's!\<pi\>!deac!' dest/root/etc/group
d mv dest/root/home/pi dest/root/home/deac
all_umounts

131
raspbian2xfs.sh Normal file
View file

@ -0,0 +1,131 @@
#!/usr/bin/env bash
die() {
>&2 printf '\e[1;31mdied: '"$*"'\e[0m\n'
all_umounts
exit 1
}
l() {
>&2 printf '\e[1m'"$*"'\e[0m\n'
}
d() {
>&2 printf '\e[1;34m# '"$*"'\e[0m\n'
"$@" || die "$*"
}
baseimg="$1"
unpack_zip() {
zip -p "$1" > "$2"
}
unzip_xz() {
xz -d < "$1" > "$2"
}
unpack_bzip2() {
bzip2 -d < "$1" > "$2"
}
unpack_gzip() {
gzip -d < "$1" > "$2"
}
unpack_plain() {
ln -sf "$1" "$2"
}
all_umounts() {
umount base/root
umount base/boot
umount dest/root
umount dest/boot
kpartx -d dest/image
kpartx -d base/image
}
pii_mounts() {
local dir="${1:-murks}"
local img="${2:-$dir/image}"
set -- `kpartx -l "$img" | sed -e 's/ : .*//'`
local bootdev="/dev/mapper/$1"
local rootdev="/dev/mapper/$2"
[ -e "$bootdev" -a -e "$rootdev" ] || die "Cannot find devs [$bootdev] [$rootdev]"
d mount "$bootdev" "$dir/boot"
d mount "$rootdev" "$dir/root"
}
pii_mkfs() {
local img="${1:-murks}"
set -- `kpartx -l "$img" | sed -e 's/ : .*//'`
local bootdev="/dev/mapper/$1"
local rootdev="/dev/mapper/$2"
[ -e "$bootdev" -a -e "$rootdev" ] || die "Cannot find devs [$bootdev] [$rootdev]"
l format destination-boot
d mkfs.fat -n boot -F 32 "$bootdev"
l format destination-root
d mkfs.xfs -L root "$rootdev"
}
case "$baseimg" in
*.zip) alias unpack=d\ unpack_zip ;;
*.xz) alias unpack=d\ unpack_xz ;;
*.bz2) alias unpack=d\ unpack_bz2 ;;
*.gz) alias unpack=d\ unpack_gz ;;
*) alias unpack=d\ unpack_plain ;;
esac
# let's go...
d mkdir -p base/root base/boot dest/root dest/boot
l setup base-image-access
#[ -e base/image ] && die "base/image already exists"
#unpack "$baseimg" base/image
d kpartx -sar base/image
l mount base-partitions
pii_mounts base
l create destination image
d dd if=/dev/zero of=dest/image seek=$((4800*256-1)) count=1 bs=4096
d parted dest/image -- \
mklabel msdos \
mkpart primary fat32 4MB 132MB \
mkpart primary xfs 133MB -1s \
set 2 lba off \
print
d kpartx -sa dest/image
pii_mkfs dest/image
d parted dest/image print
l mount destination-partitions
pii_mounts dest
l install it
d rsync -aHAX base/boot/ dest/boot/
d rsync -aHAX base/root/ dest/root/
d rsync kernel7.img initrd7.img dest/boot
if grep -q '^initramfs ' dest/boot/config.txt
then
d sed -i -e 's!^initramfs !initramfs initrd7.img followkernel!' dest/boot/config.txt
else
l "# echo initramfs initrd7.img followkernel >> dest/boot/config.txt"
echo initramfs initrd7.img followkernel >> dest/boot/config.txt || die "echo initramfs initrd7.img followkernel >> dest/boot/config.txt"
fi
d sed -i -e 's!\<root=[^ ]*!root=LABEL=root!;s!\<rootfstype=[^ ]*!rootfstype=xfs!;s!\<init=[^ ]* *!!' dest/boot/cmdline.txt
d touch dest/boot/ssh
l setup initramfs for updates in future
d sed -i -e 's!^COMPRESS=!COMPRESS=xz!' dest/root/etc/initramfs-tools/initramfs.conf
l deactivate resize2fs-init-script
d rm dest/root/etc/rc*.d/*resize2fs_once
l change user pi to deac
d sed -i -e 's!^pi:.*!deac:x:1000:1000:Denis Knauf,,,:/home/deac:/bin/bash!' dest/root/etc/passwd
d sed -i -e 's!^pi:.*!deac:$6$aZRhIfbP$6ELyvhfjXP2wiIuq5gIsDPFXFWM1E8KwGhKFWKtFwJZ8CLwHXmZECzpxslwLbvgtYCScTZBJBTjp.hVjd6.2l1:16958:0:99999:7:::!' dest/root/etc/shadow
d sed -i -e 's!\<pi\>!deac!' dest/root/etc/group
d mv dest/root/home/pi dest/root/home/deac
all_umounts