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)