+ with_rootfs do |dir, devices|
+ puts "Override grub with host version..."
+ root_dev = "/dev/#{devices.first[/loop\d+/]}"
+ rootfs_uuid = dirs.find { |d| d.path == '/'}.fs_uuid
+ puts "New rootfs UUID=#{rootfs_uuid}"
+
+ system "rm", "-f", "#{dir}/etc/systemd/system/udev.service", "#{dir}/etc/systemd/system/systemd-udevd.service", "#{dir}/etc/udev/rules.d/70-persistent-net.rules"
+
+ puts "Rewrite fstab..."
+ File.open "#{dir}/etc/fstab", "w" do |f|
+ dirs.each_with_index do |di, idx|
+ f << %W(UUID=#{di.fs_uuid} #{di.path} ext4 defaults,noatime 0 #{di.path == '/' ? 1 : 2}).join("\t")
+ f << "\n"
+ end
+ end
+
+ system("chroot", dir, "apt-get", "-qy", "update")
+ if File.read("#{dir}/etc/debian_version").to_f >= 9.0
+ # Note: 2019-10-08 時点で Debian9 のカーネルバージョンに対応していないので、エラー回避のために既存のカーネルを全て削除し、強制的に jessie のカーネルをイントールする
+ system("rm", "-f", "#{dir}/var/lib/dpkg/info/linux-image-#{`uname -r`.chomp}.prerm")
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt", "remove", "--purge", "-y", "linux-image-*")
+ system("wget", "-O", "#{dir}/tmp/linux.deb", "http://security-cdn.debian.org/debian-security/pool/updates/main/l/linux/linux-image-3.16.0-10-amd64_3.16.81-1_amd64.deb") or raise "Failed to get jessie kernel"
+ system("chroot", dir, "dpkg", "-i", "/tmp/linux.deb")
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt", "install", "-f", "-y") or raise "Failed to install jessie kernel"
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt", "-y", "install", "isc-dhcp-client")
+ else
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt-get", "-y", "--allow-unauthenticated", "install", "linux-image-amd64", "isc-dhcp-client")
+ end
+
+ puts "Update grub..."
+ if File.exists? "#{dir}/var/lib/dpkg/info/grub-efi-amd64.list"
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt", "remove", "--purge", "-y", "grub-efi-amd64") or raise "Failed to purge grub-efi"
+ end
+ if !File.exists?("#{dir}/var/lib/dpkg/info/grub-pc.list") || !(File.exists?("#{dir}/usr/sbin/grub-bios-setup") || File.exists?("#{dir}/usr/sbin/grub-setup"))
+ system("chroot", dir, "apt-get", "-qy", "update") or raise "Failed to install grub-pc"
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt-get", "-y", "install", "grub-pc")
+ end
+ File.open "#{dir}/boot/grub/device.map", "w" do |f|
+ f.puts "(hd0)\t#{root_dev}"
+ end
+ system("chroot", dir, "grub-mkconfig", "-o", "/boot/grub/grub.cfg") or raise "grub-mkconfig fails."
+ system(*%W(grub-install --no-floppy --grub-mkdevicemap=#{dir}/boot/grub/device.map --root-directory=#{dir} #{root_dev})) or raise "grub-install failed."
+
+ unless Array(run_cmds).empty?
+ Array(run_cmds).each do |cmd|
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, *Array(cmd)) or raise "Failed to execute command (#{cmd}): #{$!}"
+ end
+ end
+
+ cfg = File.read "#{dir}/boot/grub/grub.cfg"
+ cfg.gsub! %r{mapper/loop\d+p}, "sda"
+ File.write "#{dir}/boot/grub/grub.cfg", cfg
+ end
+ end
+
+ def with_rootfs(&block)