Skip to content

Commit

Permalink
Merge pull request #9 from snltd/fix/bhyve
Browse files Browse the repository at this point in the history
tweaks for bhyve
  • Loading branch information
snltd authored Oct 15, 2024
2 parents 3038724 + e33a135 commit 953bb1d
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
94 changes: 93 additions & 1 deletion lib/oozone/brand_installers/bhyve.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,99 @@ def create_volume(size, dataset)
def write_raw_image(src, dataset)
ds_target = "/dev/zvol/dsk/#{dataset}"
LOG.info("Copying #{src} to #{ds_target}")
execute!("/bin/pv #{src} > #{ds_target}")
execute!("/bin/cat #{src} >#{ds_target}")
end

def create_cloudinit_iso
img_dir = create_cloudinit_img_dir
create_cloudinit_iso_from_dir(
img_dir,
conf.metadata[:cloudinit_iso_file]
)
end

def fresh_cloudinit_iso_dir(cloudinit_iso_dir = nil)
cloudinit_iso_dir = cloudinit_tmp if cloudinit_iso_dir.nil?

if cloudinit_iso_dir.exist?
LOG.info("Flushing #{cloudinit_iso_dir}")
FileUtils.rm_rf(cloudinit_iso_dir)
end

Pathname.new(FileUtils.mkdir_p(cloudinit_iso_dir).first)
rescue StandardError
LOG.error "Cannot create cloud-init dir #{cloudinit_iso_dir}"
nil
end

# rubocop:disable Metrics/MethodLength
def cloudinit_src_dir(root_dir = Pathname.new('cloud-init'), zone = @zone)
instance_dir = cloudinit_dir(root_dir, zone)
common_dir = cloudinit_dir(root_dir, 'common')

if instance_dir.exist?
LOG.info "Using image-specific cloud-init config in #{instance_dir}"
instance_dir
elsif common_dir.exist?
LOG.info "Using common cloud-init config in #{common_dir}"
common_dir
else
LOG.error "No cloudinit dir. (Tried #{instance_dir}, #{common_dir}"
nil
end
rescue Errno::ENOENT
LOG.error "Failed to resolve #{root_dir}"
nil
end
# rubocop:enable Metrics/MethodLength

def create_cloudinit_img_dir(src_dir = nil, target_dir = nil)
src_dir ||= cloudinit_src_dir
target_dir = fresh_cloudinit_iso_dir(target_dir)

return if target_dir.nil? || src_dir.nil?

LOG.info("Constructing cloud-init CDROM in #{target_dir}")

src_dir.children.each do |f|
render_cloudinit_template(f, target_dir.join(f.basename))
end

target_dir
end

def create_cloudinit_iso_from_dir(src_dir, target_file)
cmd = "#{MKISOFS} -output #{target_file} -volid cidata " \
"-joliet -rock #{src_dir}/"

execute!(cmd)
end

private

def render_cloudinit_template(src, dest)
File.write(dest, ERB.new(File.read(src)).result_with_hash(erb_binding))
end

# Just to be explicit
def erb_binding
netconf = @conf.raw[:net].first
{
zone: @zone,
ip_address: netconf[:'allowed-address'],
gateway: netconf[:defrouter],
default_router: netconf[:defrouter]
}
rescue StandardError
raise 'Cannot parse network config for ERB binding'
end

def cloudinit_tmp
Pathname.new('/tmp').join(conf.metadata[:zone_name])
end

def cloudinit_dir(root_dir, zone_name)
root_dir.join(zone_name).realdirpath
end
end
end
Expand Down
9 changes: 9 additions & 0 deletions lib/oozone/commands/create.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def using_ansible?(conf)
end

# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def action_zone(zone_file)
conf = Oozone::ConfigLoader.new(zone_file)
zone_name = conf.metadata[:zone_name]
Expand All @@ -47,7 +48,9 @@ def action_zone(zone_file)
zone.boot
zone.wait_for_readiness
Oozone::Customizer.new(conf).customize!
remove_cloudinit_image(zone_name) if conf.metadata[:cloudinit]
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength

def install_or_clone
Expand All @@ -66,6 +69,12 @@ def leave_existing?(zone)
false
end
end

def remove_cloudinit_image(zone)
LOG.info('Removing cloud-init CD-ROM from zone')
execute!("#{ZONECFG} -z #{zone} 'remove attr name=cdrom'")
execute!("#{ZONECFG} -z #{zone} 'remove fs type=lofs'")
end
end
end
end
25 changes: 25 additions & 0 deletions lib/oozone/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,31 @@ def ready?
) == 'online'
end

# This is a horrible hack to watch a bhyve zone boot.
#
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def wait_for_readiness_console
log_name = "#{zone}-#{Time.now.strftime('%Y-%m-%d-%H:%M:%S')}-console.log"
LOG.info 'Waiting for zone to be ready'
File.open(Pathname.new('/var/log').join(log_name), 'w') do |log_file|
PTY.spawn("#{ZLOGIN} -C #{zone}") do |stdout, stdin, _thr|
stdout.each do |line|
log_file.write(line.gsub('s/\e\[[0-9;]*m(?:\e\[K)?', ''))

stdin.puts "\n" if line.include?('ttyS0')

if line.include?(' login:')
stdin.puts '~.'
return true
end
end
end
end
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength

# @return [String, Nil] maybe shouldn't be nil?
#
def state
Expand Down

0 comments on commit 953bb1d

Please sign in to comment.