bin/box in system-builder-0.0.23 vs bin/box in system-builder-0.0.26
- old
+ new
@@ -1,8 +1,9 @@
#!/usr/bin/env ruby
require 'optparse'
+require 'tmpdir'
@options = {}
OptionParser.new do |opts|
opts.banner = <<-BANNER.gsub(/^ /,'')
Box : manage box
@@ -20,10 +21,18 @@
"The box image to be cloned") { |arg| @options[:image] = arg }
opts.on("-o", "--host=<host>", String,
"The host to be upgraded") { |arg| @options[:host] = arg }
opts.on("-s", "--skip-format",
"Skip partitionning and formatting") { |arg| @options[:skip_format] = true }
+ opts.on("-e", "--external-extlinux",
+ "Don't use extlinux provided by image") { |arg| @options[:external_extlinux] = true }
+ opts.on("-b", "--name=<box name>", String,
+ "The box name") { |arg| @options[:name] = arg }
+ opts.on("-m", "--mac-index=<index>", Integer,
+ "An numeric index uses to choose mac") { |arg| @options[:mac_index] = arg }
+ opts.on("-n", "--dry-run",
+ "Dry run mode") { |arg| @options[:dry_run] = true }
opts.on("-h", "--help",
"Show this help message.") { puts opts; exit }
opts.parse!(ARGV)
@command = ARGV.shift
@@ -31,131 +40,175 @@
unless %w{boot clone upgrade}.include? @command
puts opts; exit
end
end
+module SystemTools
+
+ def sh(command)
+ puts "* #{command}"
+ unless @dry_run
+ raise "command failed: '#{command}'" unless system command
+ end
+ end
+
+ def sudo(command)
+ sh "sudo #{command}"
+ end
+
+end
+
class BoxCommand
+ include SystemTools
def boot(options = {})
qemu_options = []
qemu_disks = []
+ dist_dir = ["dist", options[:name]].compact.join("/")
+
case options[:root]
when "iso"
- qemu_options << "-cdrom dist/iso"
+ qemu_options << "-cdrom #{dist_dir}/iso"
qemu_options << "--boot order=d"
else
- qemu_disks << "dist/disk"
+ qemu_disks << "#{dist_dir}/disk"
end
- qemu_disks.push *Dir["dist/storage*"]
+ qemu_disks.push *Dir["#{dist_dir}/storage*"]
qemu_disks.each_with_index do |disk, index|
qemu_options << "-drive file=#{disk},if=ide,index=#{index+1},media=disk"
end
- qemu_options << "-net nic -net vde,sock=/var/run/vde2/tap0.ctl"
+ mac_address_index = (options[:mac_index] or 0)
+ mac_address = "52:54:00:12:34:#{56+mac_address_index}"
+
+ qemu_options << "-net nic,macaddr=#{mac_address} -net vde,sock=/var/run/vde2/tap0.ctl"
+ memory = (ENV['MEMORY'] or "512")
+
ENV['QEMU_AUDIO_DRV']='alsa'
- qemu_command = "qemu -enable-kvm -m 512m -soundhw ac97 #{qemu_options.join(' ')}"
+ qemu_command = "qemu -enable-kvm -m #{memory}m -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"
- tmpdir = "/tmp/dist"
+ class Cloner
+ include SystemTools
- sh "[ -d #{tmpdir} ]||mkdir #{tmpdir}"
- if disk_image =~ /([a-z]+box)-(\d+-\d+)/
- # like pigebox-20101014-1155
- name = $1
- release = $2
- disk_image = "#{tmpdir}/#{name}-#{release}.disk"
- sh "ssh dev.tryphon.priv cat /var/lib/buildbot/dist/#{name}/#{name}-#{release}.disk.gz | gunzip -c > #{disk_image}" unless File.exist?(disk_image)
+ attr_accessor :target, :image, :dry_run, :skip_format, :external_extlinux
+
+ def initialize(options = {})
+ options = { :target => "/dev/sdb", :image => "dist/disk" }.merge options
+ options.each { |k,v| send "#{k}=", v }
end
- raise "Can't find #{disk_image}" unless File.exists?(disk_image)
+ def partition
+ "#{target}1"
+ end
- #if partition_mount = mounts.assoc(partition)
- # partition_mount_point = partition_mount[1]
- #else
- partition_mount_point = "#{tmpdir}/boot"
- #sudo "mkdir #{partition_mount_point}" unless File.exist? partition_mount_point
- #sudo "mount #{partition} #{partition_mount_point}"
- #end
+ def mounts
+ IO.readlines("/proc/mounts").map { |m| m.scan(/\S+/) }
+ 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
+ def mount(volume, options = {}, &block)
+ name = File.basename(volume)
- if mounts.assoc(partition)
- puts "Unmount #{target}"
- exit 1 unless system "sudo umount #{partition}"
+ unless target = options.delete(:target)
+ Dir.mktmpdir("#{name}-") do |target|
+ mount volume, {:target => target}.merge(options), &block
+ end
+ return
+ end
+
+ name = File.basename(volume)
+ mount_options = options.collect do |pair|
+ [ pair - [true] ].join('=')
+ end.join(',')
+
+ mount_options = "-o #{mount_options}" unless mount_options.empty?
+
+ begin
+ sudo "mount #{mount_options} #{volume} #{target}"
+ yield target
+ ensure
+ sudo "umount #{target}"
+ end
end
- unless options[:skip_format]
- puts "Formatting filesystem"
- sh "echo ',,L,*' | sudo /sbin/sfdisk -f -uS #{target}"
- sh "grep -q #{partition} /proc/mounts && sudo umount #{partition} || true"
- sudo "mke2fs -L boot #{partition}"
+ def mount_image
+ mount(image, :loop => true, :offset => 64*512) do |mount_dir|
+ yield mount_dir
+ end
end
- sh "[ -d #{partition_mount_point} ]||mkdir #{partition_mount_point}"
-
- puts "Copy files"
- sudo "mount #{partition} #{partition_mount_point}"
- mount_disk_image_fs(disk_image) do |dir|
- sudo "rsync -av #{dir}/ #{partition_mount_point}/"
+ def chroot(root, command)
+ sudo "mount proc #{root}/proc -t proc"
+ sudo "mount -o bind /dev #{root}/dev"
+
+ begin
+ sudo "chroot #{root} #{command}"
+ ensure
+ sudo "umount #{root}/proc"
+ sudo "umount #{root}/dev"
+ end
end
- sudo "umount #{partition_mount_point}"
- puts "Install extlinux"
- sudo "mount #{partition} #{partition_mount_point}"
- #sudo "mount proc #{partition_mount_point}/proc -t proc"
- #sudo "mount -o bind /dev #{partition_mount_point}/dev"
+ def clone
+ puts "Dry run mode" if dry_run
+ confirm
+ format unless skip_format
+ copy
+ extlinux
+ end
- begin
- #sudo "chroot #{tmpdir} /usr/bin/extlinux --install /boot"
- sudo "/usr/sbin/extlinux --install #{partition_mount_point}"
- ensure
- #sudo "umount #{tmpdir}/proc"
- #sudo "umount #{tmpdir}/dev"
- sudo "umount #{partition_mount_point}"
+ def extlinux
+ mount(partition) do |partition_mount|
+ if external_extlinux
+ sudo "extlinux --install #{partition_mount}"
+ else
+ mount("#{partition_mount}/filesystem.squashfs", :loop => true) do |root|
+ mount(partition_mount, :bind => true, :target => "#{root}/boot") do
+ chroot root, "extlinux --install /boot"
+ end
+ end
+ end
+ end
+
+ # Required ?
+ # sudo "dd if=/usr/lib/syslinux/mbr.bin of=#{target}"
end
- sudo "dd if=/usr/lib/syslinux/mbr.bin of=#{target}"
- end
+ def copy
+ puts "Copy files"
+ mount_image do |image_mount|
+ mount(partition) do |partition_mount|
+ sudo "rsync -av #{image_mount}/ #{partition_mount}/"
+ end
+ end
+ end
- def sh(command)
- puts "Run #{command}"
- raise "command failed: '#{command}'" unless system command
- end
+ def format
+ puts "Formatting filesystem"
+ sh "echo ',,L,*' | sudo /sbin/sfdisk -f -uS #{target}"
+ sh "grep -q #{partition} /proc/mounts && sudo umount #{partition} || true"
+ sudo "mke2fs -j -L boot #{partition}"
+ end
- def sudo(command)
- sh "sudo #{command}"
- end
+ def confirm
+ $stdout.write "Confirm you want install box image (#{image}) in #{target} [y/N] :"
+ $stdout.flush
+ exit 1 unless $stdin.read(1).downcase == 'y'
+ 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 "[ -d #{mount_dir} ]||mkdir -p #{mount_dir}"
- begin
- sudo "mount -o loop,offset=#{64*512} #{disk_image} #{mount_dir}"
- yield mount_dir
- ensure
- sudo "umount #{mount_dir}"
- end
+ def clone(options = {})
+ Cloner.new(options).clone
end
def upgrade(options = {})
host = options[:host]
raise "No specified host for upgrade, use --host" unless host