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/*]
begin
system("mount", dev, mount_point) or raise "Failed to mount file system #{dev} on #{mount_point}"
puts "Copying #{src_host}:#{di.srcpath} to #{dev}..."
- system("rsync", "-azHSAX", "--numeric-ids", "--info=progress2", "#{src_host}:#{di.srcpath}/", "#{mount_point}/", *((["--exclude"] * di.exclude.size).zip(di.exclude).flatten)) or raise "rsync fails"
+ unless system("rsync", "-azHSAX", "--numeric-ids", "--info=progress2", "#{src_host}:#{di.srcpath}/", "#{mount_point}/", *((["--exclude"] * di.exclude.size).zip(di.exclude).flatten))
+ warn "rsync exit with error, file transfer may not be completed."
+ end
ensure
system("umount", mount_point)
File.directory?(mount_point) and
end
end
- unless File.exists? "#{dir}/vmlinuz"
- system("chroot", dir, "apt-get", "-qy", "update")
- system("chroot", dir, "apt-get", "-y", "install", "linux-image-amd64")
+ 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"
+ else
+ system({'DEBIAN_FRONTEND' => 'noninteractive'}, "chroot", dir, "apt-get", "-y", "install", "linux-image-amd64")
end
puts "Update grub..."
- unless File.exists? "#{dir}/boot/grub/grub.cfg"
+ 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")
end
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" => ENV.fetch("S3_BUCKET", "osdn-base-images"),
+ "S3Key" => "#{ENV.fetch("S3_KEY_PREFIX", "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__
+ require 'optparse'
+
+ opts = ARGV.getopts('l:', 'limit:', 'skip:')
+ limit_pat = opts['limit'] || opts['l']
+ limit_pat and
+ limit_pat = Regexp.new(limit_pat)
+
list = YAML.load_file(ARGV[0] || 'image-list.yml')
list.each do |imgdef|
name = nil
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
name = imgdef
end
+ if limit_pat
+ limit_pat.match?(name) or next
+ end
dirs.empty? and dirs << SyncDirDef.new
ImageCreator.new(name, dirs).run
end