• R/O
  • HTTP
  • SSH
  • HTTPS

image-creator: 提交

KVM host image creator.


Commit MetaInfo

修订版e2302b08a354c8084fd8586d5dc2d32c8a3f12a6 (tree)
时间2019-09-24 17:23:11
作者Tatsuki Sugiura <sugi@nemu...>
CommiterTatsuki Sugiura

Log Message

Change to use mbr for boot disk, split dirs for each disk.

更改概述

差异

--- a/create-image
+++ b/create-image
@@ -6,75 +6,77 @@ require 'yaml'
66
77 class SyncDirDef
88 DEFAULT_EXCLUDE = %w[/proc/* /sys/* /dev/mqueue /dev/hugepages /run/* /var/lib/os-prober/mount /swap /dev/shm/* /var/lib/lxcfs/*]
9- attr_accessor :path, :size, :exclude, :size, :srcpath, :fs_features
9+ attr_accessor :path, :size, :exclude, :size, :srcpath, :fs_features, :device
1010 def initialize(path: '/', size: 8, exclude: DEFAULT_EXCLUDE, srcpath: nil, fs_features: nil)
1111 @path = path
1212 @size = size.to_f
1313 @exclude = (DEFAULT_EXCLUDE + [*exclude]).uniq
1414 @srcpath = srcpath || path
1515 @fs_features = fs_features
16+ @device = nil
1617 end
1718 end
1819
19-
2020 class ImageCreator
21- attr_accessor :name, :dirs, :src_host
21+ attr_accessor :name, :dirs, :src_host, :img_path_base
22+ MiB = 1024 ** 2
23+ GiB = 1024 ** 3
2224
2325 def initialize(name, dirs, src_host: nil)
2426 @name = name
2527 @dirs = dirs
2628 @src_host = src_host || name
29+ @img_path_base = "#{name}_#{Time.now.strftime '%FT%T%z'}"
2730 end
2831
29- def size
30- @size and return @size
31- @size = 3 * (1024**2) # alignment + BIOS boot partition + gap
32- dirs.each do |di|
33- @size += di.size * (1024**3)
34- end
35- @size
32+ def imgpath(idx)
33+ "#{img_path_base}_#{idx}.img"
3634 end
3735
38- def imgpath
39- @imgpath ||= "#{name}_#{Time.now.strftime '%FT%T%z'}.img"
36+ def create_disk
37+ dirs.each_with_index do |di, idx|
38+ _create_disk imgpath(idx), di, idx != 0
39+ end
4040 end
4141
42- def create_disk
43- raise "Disk image #{imgpath} is already exists!" if File.exists? imgpath
44- puts "Creating disk image #{imgpath} (#{'%5.2f' % (size.to_f/(1024**3))} GiB)..."
45- last_mb = 1
46- File.open(imgpath, "w") do |f|
47- f.truncate size
42+ def _create_disk path, di, use_gpt = false
43+ size_gb = di.size
44+ raise "Disk image #{path} is already exists!" if File.exists? path
45+ puts "Creating disk image #{path} (#{'%5.2f' % size_gb.to_f} GiB)..."
46+ File.open(path, "w") do |f|
47+ f.truncate(size_gb * GiB)
4848 end
49- system("parted", "-s", imgpath, "mklabel", "gpt") or raise "Failed to create partition label"
50- system("parted", "-s", imgpath, "mkpart", "primary", "#{last_mb}MiB", "#{last_mb+1}MiB") or raise "Failed to create boot partition"
51- system("parted", "-s", imgpath, "set", "1", "bios_grub", "on") or raise "Failed to set bios boot partition"
52- last_mb += 1
53- dirs.each do |di|
54- system("parted", "-s", imgpath, "mkpart", "primary", "#{last_mb}MiB", "#{di.size * 1024 + last_mb}MiB") or raise "Failed to create partition: #{l}"
55- last_mb += di.size * 1024
49+ system("parted", "-s", path, "mklabel", use_gpt ? 'gpt' : 'msdos') or raise "Failed to create partition label"
50+ system("parted", "-s", path, "mkpart", "primary", "1MiB", "#{size_gb * 1024 - 1}MiB") or raise "Failed to create partition"
51+ if use_gpt
52+ system("parted", "-s", path, "name", "1", di.path) or raise "Failed to set part label"
53+ else
54+ system("parted", "-s", path, "set", "1", "boot", "on") or raise "Failed to set bios boot partition"
5655 end
5756 puts "Image partition created."
58- #system "sfdisk", "-l", imgpath
57+ #system "sfdisk", "-l", path
5958 end
6059
6160 def with_loopdev &block
6261 begin
63- system("kpartx", "-as", imgpath) or raise "Failed to map loop device"
64- maplines = `kpartx -l #{Shellwords.escape imgpath}`.split("\n")
6562 devices = []
66- maplines.each do |map|
67- devices << "/dev/mapper/#{map[/loop\d+p\d+/]}"
63+ dirs.each_with_index do |di, idx|
64+ system("kpartx", "-as", imgpath(idx)) or raise "Failed to map loop device"
65+ di.device = "/dev/mapper/" + `kpartx -l #{Shellwords.escape imgpath(idx)}`.split("\n").first[/loop\d+p\d+/]
66+ devices << di.device
6867 end
69- yield devices, maplines.first[%r{/dev/loop\d+}]
68+ yield devices
7069 ensure
71- system "kpartx", "-d", imgpath, err: "/dev/null"
70+ dirs.each_with_index do |di, idx|
71+ system "kpartx", "-d", imgpath(idx), err: "/dev/null"
72+ di.device = nil
73+ end
7274 end
7375 end
7476
7577 def create_fs
76- with_loopdev do |devices, root|
77- devices[1..-1].each_with_index do |(dev, _), index|
78+ with_loopdev do |devices|
79+ devices.each_with_index do |dev, index|
7880 puts "Creating filesystem on #{dev}..."
7981 cmd = %w(mkfs.ext4 -q)
8082 di = dirs[index]
@@ -88,8 +90,8 @@ class ImageCreator
8890 end
8991
9092 def sync_dirs
91- with_loopdev do |devices, root|
92- devices[1..-1].each_with_index do |dev, idx|
93+ with_loopdev do |devices|
94+ devices.each_with_index do |dev, idx|
9395 di = dirs[idx]
9496 mount_point = "/mnt/ci-#{$$}-#{name}-#{idx}"
9597 system("mkdir", "-p", mount_point)
@@ -111,20 +113,28 @@ class ImageCreator
111113 Dir.mktmpdir("ci-#{$$}-#{name}") do |dir|
112114 system("cp", "-a", "/usr/lib/grub/i386-pc/boot.img", dir) or raise "Failed to copy boot.img"
113115 coreimg = "#{dir}/core.img"
114- system("grub-mkimage", "-o", coreimg, "-O", "i386-pc", "-p", "(hd0,gpt2)/boot/grub", "biosdisk", "part_gpt", "ext2", "gzio", "xzio", "lzopio") or raise "Failed to create grub core image."
115- with_loopdev do |devices, root|
116+ 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."
117+ with_loopdev do |devices|
118+ root_dev = "/dev/#{devices.first[/loop\d+/]}"
116119 puts "Override grub with host version..."
117- system("grub-bios-setup", "-d", dir, root) or raise "Failed to run grub-bios-setup"
118- rootfs_uuid=`blkid -o value -s UUID #{devices[1]}`.chomp("\n")
120+ system("grub-bios-setup", "-d", dir, root_dev) or raise "Failed to run grub-bios-setup"
121+ fs_uuids = devices.map { |d| `blkid -o value -s UUID #{d}`.chomp("\n") }
122+ rootfs_uuid = fs_uuids.first
119123 puts "New rootfs UUID=#{rootfs_uuid}"
120124 begin
121- system("mount", devices[1], dir)
125+ system("mount", devices.first, dir) or raise "Failed to mount #{devices.first} to #{dir}"
126+ dirs[1..-1].each_with_index do |di, idx|
127+ system "mkdir", "-p", "#{dir}#{di.path}"
128+ system("mount", di.device, "#{dir}#{di.path}") or raise "Failed to mount #{di.device} to #{dir}#{path}"
129+ end
122130
123131 puts "Rewrite fstab..."
124- fstab = File.read "#{dir}/etc/fstab"
125- fstab.gsub!(%r{^(UUID=|/)\S+(\s+/\s+)}, "UUID=#{rootfs_uuid}\\2")
126- fstab.gsub!(%r{^(\S+\s+\S+\s+\S+\s+sw(?=\b))}, '#\1')
127- File.write "#{dir}/etc/fstab", fstab
132+ File.open "#{dir}/etc/fstab", "w" do |f|
133+ devices.map.with_index { |d, idx|
134+ f << %W(UUID=#{fs_uuids[idx]} #{dirs[idx].path} ext4 defaults,noatime 0 #{dirs[idx].path == '/' ? 1 : 2}).join("\t")
135+ f << "\n"
136+ }
137+ end
128138
129139 unless File.exists? "#{dir}/vmlinuz"
130140 system("chroot", dir, "apt-get", "-qy", "update")
@@ -144,7 +154,7 @@ class ImageCreator
144154 system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt-get", "-y", "install", "grub-pc")
145155 File.write "#{dir}/boot/grub/grub.cfg", <<-EOC
146156 set timeout=5
147- insmod part_gpt
157+ insmod part_msdos
148158 insmod ext2
149159 insmod linux
150160 search --no-floppy --fs-uuid --set=root #{rootfs_uuid}
@@ -155,6 +165,9 @@ class ImageCreator
155165 EOC
156166 end
157167 ensure
168+ dirs.reverse[0..-2].each do |di, idx|
169+ system("umount", "#{dir}#{di.path}")
170+ end
158171 system("umount", dir)
159172 end
160173 end
Show on old repository browser