class Macinbox::CLI
Constants
- DEFAULT_OPTION_VALUES
Public Class Methods
run!(argv)
click to toggle source
# File lib/macinbox/cli.rb, line 17 def self.run!(argv) begin self.new.start(argv) rescue Macinbox::Error => e Logger.error "Error: " + e.to_s exit 1 end exit 0 end
Public Instance Methods
check_for_sudo_root()
click to toggle source
# File lib/macinbox/cli.rb, line 192 def check_for_sudo_root if Process.uid != 0 or ENV["SUDO_USER"].nil? raise Macinbox::Error.new("script must be run as root with sudo") end end
parse_options(argv)
click to toggle source
# File lib/macinbox/cli/options.rb, line 31 def parse_options(argv) @options = DEFAULT_OPTION_VALUES @option_parser = OptionParser.new do |o| o.separator '' o.on( '--box-format FORMAT', 'Format of the box (default: vmware_desktop)') { |v| @options[:box_format] = v } o.separator '' o.on('-n', '--name NAME', 'Name of the box (default: macinbox)') { |v| @options[:box_name] = v } o.on('-d', '--disk SIZE', 'Size (GB) of the disk (default: 64)') { |v| @options[:disk_size] = v } o.on('-t', '--fstype TYPE', 'Type of FS on the disk (default: APFS)') { |v| @options[:fstype] = v } o.on('-m', '--memory SIZE', 'Size (MB) of the memory (default: 2048)') { |v| @options[:memory_size] = v } o.on('-c', '--cpu COUNT', 'Number of virtual cores (default: 2)') { |v| @options[:cpu_count] = v } o.on('-s', '--short NAME', 'Short name of the user (default: vagrant)') { |v| @options[:short_name] = v } o.on('-f', '--full NAME', 'Full name of the user (default: Vagrant)') { |v| @options[:full_name] = v } o.on('-p', '--password PASSWORD', 'Password of the user (default: vagrant)') { |v| @options[:password] = v } o.separator '' o.on( '--installer PATH', 'Path to the macOS installer app') { |v| @options[:installer_path] = File.absolute_path(v) } o.on( '--installer-dmg PATH', 'Path to a macOS installer app disk image') { |v| @options[:installer_dmg] = File.absolute_path(v) } o.on( '--vmware PATH', 'Path to the VMware Fusion app') { |v| @options[:vmware_path] = File.absolute_path(v) } o.on( '--parallels PATH', 'Path to the Parallels Desktop app') { |v| @options[:parallels_path] = File.absolute_path(v) } o.on( '--user-script PATH', 'Path to user script') { |v| @options[:user_script] = File.absolute_path(v) } o.separator '' o.on( '--no-auto-login', 'Disable auto login') { |v| @options[:auto_login] = v } o.on( '--no-skip-mini-buddy', 'Show the mini buddy on first login') { |v| @options[:skip_mini_buddy] = v } o.on( '--no-hidpi', 'Disable HiDPI resolutions') { |v| @options[:hidpi] = v } o.on( '--no-fullscreen', 'Display the virtual machine GUI in a window') { |v| @options[:fullsceen] = v } o.on( '--no-gui', 'Disable the GUI') { |v| @options[:gui] = v } o.separator '' o.on( '--use-qemu', 'Use qemu-img (vmware_desktop only)') { |v| @options[:use_qemu] = v } o.separator '' o.on( '--verbose', 'Enable verbose mode') { |v| $verbose = v } o.on( '--debug', 'Enable debug mode') { |v| $debug = $verbose = v } o.separator '' o.on('-v', '--version') { puts "macinbox #{Macinbox::VERSION}"; exit } o.on('-h', '--help') { puts o; exit } o.parse(argv) end @options[:full_name] ||= @options[:short_name].capitalize @options[:password] ||= @options[:short_name] end
start(argv)
click to toggle source
# File lib/macinbox/cli.rb, line 27 def start(argv) parse_options(argv) check_for_sudo_root collector = Collector.new(preserve_temp_dirs: $debug) collector.on_cleanup do STDERR.print TTY::Color::RESET STDERR.print TTY::Cursor::NORMAL end if @options[:installer_dmg] if !File.exists?(@options[:installer_dmg]) raise Macinbox::Error.new("Installer disk image not found: #{@options[:installer_dmg]}") end Logger.info "Attaching installer disk image..." installer_disk = VirtualDisk.new(@options[:installer_dmg]) collector.on_cleanup { installer_disk.detach! } installer_disk.attach installer_disk.mount @options[:installer_path] = Dir[installer_disk.mountpoint+'/*.app'].first end if not File.exists? @options[:installer_path] raise Macinbox::Error.new("Installer app not found: #{@options[:installer_path]}") end if not ["vmware_fusion", "vmware_desktop", "parallels", "virtualbox"].include? @options[:box_format] raise Macinbox::Error.new("Box format not supported: #{@options[:box_format]}") end if /^vmware_(fusion|desktop)$/ === @options[:box_format] unless File.exists?(@options[:vmware_path]) raise Macinbox::Error.new("VMware Fusion app not found: #{@options[:vmware_path]}") end vmware_version = Task.backtick %W[ defaults read #{@options[:vmware_path]}/Contents/Info.plist CFBundleShortVersionString ] @options[:vmware_major_version] = vmware_version.split(".")[0].to_i rescue 10 end if /^parallels$/ === @options[:box_format] && !File.exists?(@options[:parallels_path]) raise Macinbox::Error.new("Parallels Desktop app not found: #{@options[:parallels_path]}") end if /^virtualbox$/ === @options[:box_format] && !File.exists?('/usr/local/bin/VBoxManage') raise Macinbox::Error.new("VBoxManage not found: /usr/local/bin/VBoxManage") end if @options[:use_qemu] && !File.exists?('/usr/local/bin/qemu-img') raise Macinbox::Error.new("QEMU not found: /usr/local/bin/qemu-img") end if /^vmware_(fusion|desktop)$/ === @options[:box_format] && !@options[:use_qemu] && @options[:vmware_major_version] >= 11 fusion_is_not_running = false begin Task.run %W[ pgrep -q #{"^VMware Fusion$"} ] rescue fusion_is_not_running = true end if fusion_is_not_running || !File.exist?("/Library/PrivilegedHelperTools/com.vmware.DiskHelper") raise Macinbox::Error.new("VMware Fusion is not running and the workaround was not detected. See https://kb.vmware.com/s/article/65163 for more information, or try the --use-qemu option.") end end vagrant_home = ENV["VAGRANT_HOME"] if vagrant_home.nil? or vagrant_home.empty? vagrant_home = File.expand_path "~/.vagrant.d" end if !File.exist? vagrant_home raise Macinbox::Error.new("VAGRANT_HOME not found: #{vagrant_home}") end vagrant_boxes_dir = "#{vagrant_home}/boxes" if !File.exist? vagrant_boxes_dir Dir.mkdir vagrant_boxes_dir end root_temp_dir = Task.backtick %W[ /usr/bin/mktemp -d -t macinbox_root_temp ] user_temp_dir = Task.backtick %W[ /usr/bin/sudo -u #{ENV["SUDO_USER"]} /usr/bin/mktemp -d -t macinbox_user_temp ] collector.add_temp_dir root_temp_dir collector.add_temp_dir user_temp_dir ["TERM", "INT", "EXIT"].each do |signal| trap signal do trap signal, "SYSTEM_DEFAULT" unless signal == "EXIT" Process.waitall Logger.reset_depth if @success Logger.info "Cleaning up..." else STDERR.puts Logger.error "Cleaning up..." end collector.cleanup! Process.kill(signal, Process.pid) unless signal == "EXIT" end end @options[:image_path] = "macinbox.sparseimage" @options[:vmdk_path] = "macinbox.vmdk" @options[:hdd_path] = "macinbox.hdd" @options[:vdi_path] = "macinbox.vdi" @options[:box_path] = "macinbox.box" @options[:boxes_dir] = vagrant_boxes_dir @options[:collector] = collector Dir.chdir(root_temp_dir) do Logger.info "Checking macOS versions..." do @options[:macos_version] = Actions::CheckMacosVersions.new(@options).run end Logger.info "Creating image from installer..." do Actions::CreateImageFromInstaller.new(@options).run end case @options[:box_format] when /^vmware_(fusion|desktop)$/ Logger.info "Creating VMDK from image..." do Actions::CreateVMDKFromImage.new(@options).run end Logger.info "Creating box from VMDK..." do Actions::CreateBoxFromVMDK.new(@options).run end when /^parallels$/ Logger.info "Creating HDD from image..." do Actions::CreateHDDFromImage.new(@options).run end Logger.info "Creating box from HDD..." do Actions::CreateBoxFromHDD.new(@options).run end when /^virtualbox$/ Logger.info "Creating VDI from image..." do Actions::CreateVDIFromImage.new(@options).run end Logger.info "Creating box from VDI..." do Actions::CreateBoxFromVDI.new(@options).run end end Logger.info "Installing box..." do Actions::InstallBox.new(@options).run end end @success = true end