bin/box in system-builder-0.0.18 vs bin/box in system-builder-0.0.19

- old
+ new

@@ -1,52 +1,160 @@ #!/usr/bin/env ruby require 'optparse' +@options = {} OptionParser.new do |opts| opts.banner = <<-BANNER.gsub(/^ /,'') Box : manage box Usage: #{File.basename($0)} boot [options] Options are: BANNER opts.separator "" opts.on("-r", "--root=disk|iso", String, - "The support used to boot") { |arg| @root = arg } + "The support used to boot") { |arg| @options[:root] = arg } + opts.on("-t", "--target=<disk device>", String, + "The target to clone an image") { |arg| @options[:target] = arg } + opts.on("-i", "--image=<disk image>", String, + "The box image to be cloned") { |arg| @options[:image] = arg } + opts.on("-h", "--host=<host>", String, + "The host to be upgraded") { |arg| @options[:host] = arg } opts.on("-h", "--help", "Show this help message.") { puts opts; exit } opts.parse!(ARGV) @command = ARGV.shift - - unless @command == "boot" + + unless %w{boot clone upgrade}.include? @command puts opts; exit end end -qemu_options = [] +class BoxCommand -qemu_disks = [] + def boot(options = {}) + qemu_options = [] -case @root -when "iso" - qemu_options << "-cdrom dist/iso" - qemu_options << "--boot order=d" -else - qemu_disks << "dist/disk" -end + qemu_disks = [] -qemu_disks.push *Dir["dist/storage*"] + case options[:root] + when "iso" + qemu_options << "-cdrom dist/iso" + qemu_options << "--boot order=d" + else + qemu_disks << "dist/disk" + end -qemu_disks.each_with_index do |disk, index| - qemu_options << "-drive file=#{disk},if=ide,index=#{index+1},media=disk" -end + qemu_disks.push *Dir["dist/storage*"] -qemu_options << "-net nic -net vde,sock=/var/run/vde2/tap0.ctl" + qemu_disks.each_with_index do |disk, index| + qemu_options << "-drive file=#{disk},if=ide,index=#{index+1},media=disk" + end -ENV['QEMU_AUDIO_DRV']='alsa' + qemu_options << "-net nic -net vde,sock=/var/run/vde2/tap0.ctl" -qemu_command = "qemu -enable-kvm -m 512m -soundhw ac97 #{qemu_options.join(' ')}" + ENV['QEMU_AUDIO_DRV']='alsa' -puts "Run #{qemu_command}" -system qemu_command + qemu_command = "qemu -enable-kvm -m 512m -soundhw ac97 #{qemu_options.join(' ')}" + + puts "Run #{qemu_command}" + system qemu_command + end + + def clone(options = {}) + target = (options[:target] or "/dev/sdb") + disk_image = (options[:image] or "dist/disk") + partition = "#{target}1" + + if disk_image =~ /([a-z]+box)-(\d+-\d+)/ + # like pigebox-20101014-1155 + name = $1 + release = $2 + disk_image = "dist/#{name}-#{release}.disk" + sh "ssh dev.dbx.tryphon.priv cat /var/lib/buildbot/dist/#{name}/#{name}-#{release}.disk.gz | gunzip -c > #{disk_image}" unless File.exist?(disk_image) + end + + raise "Can't find #{disk_image}" unless File.exists?(disk_image) + + if partition_mount = mounts.assoc(partition) + partition_mount_point = partition_mount[1] + else + partition_mount_point = "/media/boot" + #sudo "mkdir #{partition_mount_point}" unless File.exist? partition_mount_point + #sudo "mount #{partition} #{partition_mount_point}" + end + + #unless File.exists? "#{partition_mount_point}/config.pp" + $stdout.write "Confirm you want install box image (#{disk_image}) in #{target} [y/N] :" + $stdout.flush + exit 1 unless $stdin.read(1).downcase == 'y' + #end + + if mounts.assoc(partition) + puts "Unmount #{target}" + exit 1 unless system "sudo umount #{partition}" + end + + puts "Install filesystem" + sh "echo ',,L,*' | sudo /sbin/sfdisk -f -uS #{target}" + sudo "mke2fs -j -L boot #{partition}" + + puts "Copy files" + sudo "mount #{partition} #{partition_mount_point}" + mount_disk_image_fs(disk_image) do |dir| + sudo "rsync -av #{dir}/ #{partition_mount_point}/" + end + sudo "umount #{partition_mount_point}" + + puts "Install extlinux" + sudo "mount #{partition} build/root/boot" + sudo "mount proc build/root/proc -t proc" + sudo "mount -o bind /dev build/root/dev" + + begin + sudo "chroot build/root /usr/bin/extlinux --install /boot" + ensure + sudo "umount build/root/proc" + sudo "umount build/root/boot" + sudo "umount build/root/dev" + end + + sudo "dd if=build/root/usr/lib/syslinux/mbr.bin of=#{target}" + end + + def sh(command) + puts "Run #{command}" + raise "command failed: '#{command}'" unless system command + end + + def sudo(command) + sh "sudo #{command}" + end + + def mounts + IO.readlines("/proc/mounts").map { |m| m.scan(/\S+/) } + end + + def mount_disk_image_fs(disk_image) + mount_dir = "/tmp/mount_boot_fs" + sh "mkdir -p /tmp/mount_boot_fs" + begin + sudo "mount -o loop,offset=#{64*512} #{disk_image} #{mount_dir}" + yield mount_dir + ensure + sudo "umount #{mount_dir}" + end + end + + def upgrade(options = {}) + host = options[:host] + raise "No specified host for upgrade, use --host" unless host + + sh "scp dist/latest.yml dist/upgrade.tar #{host}:/tmp/" + sh "ssh #{host} box-upgrade /tmp/upgrade.tar /tmp/latest.yml" + end + +end + +BoxCommand.new.send(@command, @options)