OSDN Git Service

Fix grub install condition.
[osdn-codes/image-creator.git] / create-image
index 8bf0092..04fe0ee 100755 (executable)
@@ -3,10 +3,11 @@ require 'pp'
 require 'shellwords'
 require 'tmpdir'
 require 'yaml'
+require 'json'
 
 class SyncDirDef
   DEFAULT_EXCLUDE = %w[/proc/* /sys/* /dev/mqueue /dev/hugepages /run/* /var/lib/os-prober/mount /swap /dev/shm/* /var/lib/lxcfs/*]
-  attr_accessor :path, :size, :exclude, :size, :srcpath, :fs_features, :device
+  attr_accessor :path, :size, :exclude, :size, :srcpath, :fs_features, :device, :fs_uuid
   def initialize(path: '/', size: 8, exclude: DEFAULT_EXCLUDE, srcpath: nil, fs_features: nil)
     @path = path
     @size = size.to_f
@@ -14,6 +15,7 @@ class SyncDirDef
     @srcpath = srcpath || path
     @fs_features = fs_features
     @device = nil
+    @fs_uuid = nil
   end
 end
 
@@ -48,13 +50,10 @@ class ImageCreator
     end
     system("parted", "-s", path, "mklabel", use_gpt ? 'gpt' : 'msdos') or raise "Failed to create partition label"
     system("parted", "-s", path, "mkpart", "primary", "1MiB", "#{size_gb * 1024 - 1}MiB") or raise "Failed to create partition"
-    if use_gpt
-      system("parted", "-s", path, "name", "1", di.path) or raise "Failed to set part label"
-    else
+    if !use_gpt
       system("parted", "-s", path, "set", "1", "boot", "on") or raise "Failed to set bios boot partition"
     end
-    puts "Image partition created."
-    #system "sfdisk", "-l", path
+    puts "Image partition has been created."
   end
   
   def with_loopdev &block
@@ -76,7 +75,8 @@ class ImageCreator
 
   def create_fs
     with_loopdev do |devices|
-      devices.each_with_index do |dev, index|
+      dirs.each_with_index do |di, index|
+        dev = di.device
         puts "Creating filesystem on #{dev}..."
         cmd = %w(mkfs.ext4 -q)
         di = dirs[index]
@@ -85,6 +85,8 @@ class ImageCreator
         end
         cmd << dev
         system(*cmd) or raise "Failed to create file system on #{dev}"
+        system "e2label", dev, di.path == '/' ? 'ROOT' : di.path[1..-1].tr('/', '-')
+        di.fs_uuid = `blkid -o value -s UUID #{di.device}`.chomp("\n")
       end
     end
   end
@@ -111,29 +113,29 @@ class ImageCreator
   def fix_boot
     puts "Fixing boot environments..."
     Dir.mktmpdir("ci-#{$$}-#{name}") do |dir|
-      system("cp", "-a", "/usr/lib/grub/i386-pc/boot.img", dir) or raise "Failed to copy boot.img"
-      coreimg = "#{dir}/core.img"
-      system("grub-mkimage", "-o", coreimg, "-O", "i386-pc", "-p", "(hd0,msdos1)/boot/grub", "biosdisk", "part_msdos", "ext2", "gzio", "xzio", "lzopio") or raise "Failed to create grub core image."
       with_loopdev do |devices|
-        root_dev = "/dev/#{devices.first[/loop\d+/]}"
         puts "Override grub with host version..."
-        system("grub-bios-setup", "-d", dir, root_dev) or raise "Failed to run grub-bios-setup"
-        fs_uuids = devices.map { |d| `blkid -o value -s UUID #{d}`.chomp("\n") }
-        rootfs_uuid = fs_uuids.first
+        root_dev = "/dev/#{devices.first[/loop\d+/]}"
+        rootfs_uuid = dirs.find { |d| d.path == '/'}.fs_uuid
         puts "New rootfs UUID=#{rootfs_uuid}"
         begin
           system("mount", devices.first, dir) or raise "Failed to mount #{devices.first} to #{dir}"
+          system("mount", "--bind", "/dev", "#{dir}/dev") or raise "Failed to mount /dev to #{dir}/dev"
+          system("mount", "--bind", "/proc", "#{dir}/proc") or raise "Failed to mount /proc to #{dir}/proc"
+
           dirs[1..-1].each_with_index do |di, idx|
             system "mkdir", "-p", "#{dir}#{di.path}"
             system("mount", di.device, "#{dir}#{di.path}") or raise "Failed to mount #{di.device} to #{dir}#{path}"
           end
 
+          system "rm", "-f", "#{dir}/etc/systemd/system/udev.service", "#{dir}/etc/systemd/system/systemd-udevd.service"
+
           puts "Rewrite fstab..."
           File.open "#{dir}/etc/fstab", "w" do |f|
-            devices.map.with_index { |d, idx|
-              f << %W(UUID=#{fs_uuids[idx]} #{dirs[idx].path} ext4 defaults,noatime 0 #{dirs[idx].path == '/' ? 1 : 2}).join("\t") 
+            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
 
           unless File.exists? "#{dir}/vmlinuz"
@@ -141,30 +143,19 @@ class ImageCreator
             system("chroot", dir, "apt-get", "-y", "install", "linux-image-amd64")
           end
 
-          puts "Update grub.cfg..."
-          system("mkdir", "-p", "#{dir}/boot/grub/i386-pc") or raise "Failed to create grub dir"
-          system("cp -a /usr/lib/grub/i386-pc/*.mod #{dir}/boot/grub/i386-pc/") or raise "Failed to copy grub modules"
-          if File.exists? "#{dir}/boot/grub/grub.cfg"
-            grubconf = File.read "#{dir}/boot/grub/grub.cfg"
-            if old_uuid = grubconf[/root=UUID=(\S+)/, 1]
-              File.write "#{dir}/boot/grub/grub.cfg", grubconf.gsub(/#{old_uuid}/, rootfs_uuid)
-            end
-          else
-            system("chroot", dir, "apt-get", "-qy", "update")
+          puts "Update grub..."
+          unless File.exists? "#{dir}/usr/sbin/grub-mkconfig"
+            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")
-            File.write "#{dir}/boot/grub/grub.cfg", <<-EOC
-              set timeout=5
-              insmod part_msdos
-              insmod ext2
-              insmod linux
-              search --no-floppy --fs-uuid --set=root #{rootfs_uuid}
-              menuentry 'Linux' {
-                linux   /vmlinuz root=UUID=#{rootfs_uuid} ro
-                initrd  /initrd.img
-              }
-            EOC
           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."
         ensure
+          system("umount", "#{dir}/dev")
+          system("umount", "#{dir}/proc")
           dirs.reverse[0..-2].each do |di, idx|
             system("umount", "#{dir}#{di.path}")
           end
@@ -174,14 +165,30 @@ class ImageCreator
     end
   end
 
+  def write_json
+    jdef = []
+    dirs.each_with_index do |dir, idx|
+      jdef.push({
+        "Description" => dir.path == '/' ? 'root' : dir.path[1..-1].tr('/', '-'),
+        "Format" => "raw",
+        "UserBucket" => {
+          "S3Bucket" => "Change-to-your-buket-name",
+          "S3Key" => "/src-disks/#{img_path_base}_#{idx}.img"
+        }
+      })
+    end
+    File.write "#{img_path_base}.json", JSON.pretty_generate(jdef)
+  end
+
+
   def run
     create_disk
     create_fs
     sync_dirs
     fix_boot
+    write_json
     puts "Image creation has been complated (#{name})"
   end
-
 end
 
 if $0 == __FILE__
@@ -192,6 +199,7 @@ if $0 == __FILE__
     if imgdef.kind_of?(Hash)
       name = imgdef['name']
       (imgdef['dirs'] || {}).each do |path, opts|
+        opts.kind_of?(Hash) or opts = {size: opts}
         dirs << SyncDirDef.new({path: path}.merge(opts.keys.map(&:to_sym).zip(opts.values).to_h))
       end
     else