# frozen_string_literal: true require 'log4r' module VagrantPlugins module ProviderZone module Action # This is used to package the VM into a box class Package def initialize(app, env) @logger = Log4r::Logger.new('vagrant_zones::action::import') @app = app @executor = Executor::Exec.new @pfexec = if Process.uid.zero? '' elsif system('sudo -v') 'sudo' else 'pfexec' end env['package.output'] ||= 'package.box' end def execute(*cmd, **opts, &block) @executor.execute(*cmd, **opts, &block) end def call(env) @machine = env[:machine] @driver = @machine.provider.driver name = @machine.name boxname = env['package.output'] brand = @machine.provider_config.brand kernel = @machine.provider_config.kernel vcc = @machine.provider_config.vagrant_cloud_creator boxshortname = @machine.provider_config.boxshortname raise "#{boxname}: Already exists" if File.exist?(boxname) ## Create Snapshot tmp_dir = "#{Dir.pwd}/_tmp_package" Dir.mkdir(tmp_dir) datasetpath = "#{@machine.provider_config.boot['array']}/#{@machine.provider_config.boot['dataset']}/#{name}" t = Time.new d = '-' c = ':' datetime = %(#{t.year}#{d}#{t.month}#{d}#{t.day}#{d}#{t.hour}#{c}#{t.min}#{c}#{t.sec}) snapshot_create(datasetpath, datetime, env[:ui], @machine.provider_config) snapshot_send(datasetpath, "#{tmp_dir}/box.zss", datetime, env[:ui], @machine.provider_config) ## snapshot_delete(datasetpath, env[:ui], datetime) # Package VM extra = '' ## Include User Extra Files @tmp_include = "#{tmp_dir}/_include" if env['package.include'] extra = './_include' Dir.mkdir(@tmp_include) env['package.include'].each do |f| env[:ui].info("Including user file: #{f}") FileUtils.cp(f, @tmp_include) end end ## Include Vagrant file if env['package.vagrantfile'] extra = './_include' Dir.mkdir(@tmp_include) unless File.directory?(@tmp_include) env[:ui].info('Including user Vagrantfile') FileUtils.cp(env['package.vagrantfile'], "#{@tmp_include}/Vagrantfile") end ## Create the Metadata and Vagrantfile Dir.chdir(tmp_dir) File.write('./metadata.json', metadata_content(brand, kernel, vcc, boxshortname)) File.write('./Vagrantfile', vagrantfile_content(brand, kernel, datasetpath)) ## Create the Box file assemble_box(boxname, extra) FileUtils.mv("#{tmp_dir}/#{boxname}", "../#{boxname}") Dir.chdir('../') FileUtils.rm_rf(tmp_dir) env[:ui].info("Box created, You can now add the box: 'vagrant box add #{boxname} --nameofnewbox'") @app.call(env) end def snapshot_create(datasetpath, datetime, uii, config) uii.info('Creating a Snapshot of the box.') result = execute(true, "#{@pfexec} zfs snapshot -r #{datasetpath}/boot@vagrant_box#{datetime}") uii.info("#{@pfexec} zfs snapshot -r #{datasetpath}/boot@vagrant_box#{datetime}") if result.zero? && config.debug end def snapshot_delete(datasetpath, uii, datetime) result = execute(true, "#{@pfexec} zfs destroy -r -f #{datasetpath}/boot@vagrant_box#{datetime}") uii.info("#{@pfexec} zfs destroy -r -f #{datasetpath}/boot@vagrant_box#{datetime}") if result.zero? && config.debug end def snapshot_send(datasetpath, destination, datetime, uii, config) uii.info('Sending Snapshot to ZFS Send Stream image.') result = execute(true, "#{@pfexec} zfs send #{datasetpath}/boot@vagrant_box#{datetime} > #{destination}") puts "#{@pfexec} zfs send -r #{datasetpath}/boot@vagrant_box#{datetime} > #{destination}" if result.zero? && config.debug end def metadata_content(brand, _kernel, vcc, boxshortname) <<-ZONEBOX { "provider": "zone", "format": "zss", "brand": "#{brand}", "url": "https://app.vagrantup.com/#{vcc}/boxes/#{boxshortname}" } ZONEBOX end def vagrantfile_content(brand, _kernel, datasetpath) <<-ZONEBOX Vagrant.configure('2') do |config| config.vm.provider :zone do |zone| zone.brand = "#{brand}" zone.datasetpath = "#{datasetpath}" end end user_vagrantfile = File.expand_path('../_include/Vagrantfile', __FILE__) load user_vagrantfile if File.exists?(user_vagrantfile) ZONEBOX end def assemble_box(boxname, extra) `tar -cvzEf "#{boxname}" ./metadata.json ./Vagrantfile ./box.zss #{extra}` end end end end end