Skip to content

Commit

Permalink
fixup! feat: Add Cloudinit support using iso image (#294) (#298)
Browse files Browse the repository at this point in the history
  • Loading branch information
Manisha15 authored Oct 18, 2023
1 parent 55e22a1 commit d0ebba1
Showing 1 changed file with 47 additions and 21 deletions.
68 changes: 47 additions & 21 deletions app/helpers/proxmox_vm_cloudinit_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,38 +42,42 @@ def parse_server_cloudinit(args)
cloudinit_h
end

def create_cloudinit_iso(vm_name, configs)
ssh = Fog::SSH.new(URI.parse(fog_credentials[:proxmox_url]).host, fog_credentials[:proxmox_username].split('@')[0], { password: fog_credentials[:proxmox_password] })
def create_cloudinit_iso(vm_name, configs, ssh)
iso = File.join(default_iso_path, "#{vm_name.tr('.', '_')}_cloudinit.iso")
files = []
wd = create_temp_directory(ssh)

configs.each do |config|
begin
ssh.run([%({echo "#{config[1]}" >> "#{wd}/#{config[0]}"})])
rescue ::Foreman::Exception => e
logger.error("Error writing to the file #{config[0]}: #{e}")
raise e
config_file = ssh.run(%(echo "#{config[1]}" >> "#{wd}/#{config[0]}"))
unless config_file.first.status.zero?
delete_temp_dir(ssh, wd)
raise ::Foreman::Exception, "Failed to create file #{config[0]}: #{config_file.first.stdout}"
end
files.append(File.join(wd, config[0]))
end
raise Foreman::Exception, N_('ISO build failed') unless ssh.run(generate_iso_command(vm_name, files))
delete_config_files(wd)
generated_iso = ssh.run(generate_iso_command(iso, files))
unless generated_iso.first.status.zero?
delete_temp_dir(ssh, wd)
raise Foreman::Exception, N_("ISO build failed: #{generated_iso.first.stdout}")
end
delete_temp_dir(ssh, wd)
iso
end

def generate_iso_command(vm_name, files)
iso = File.join(default_iso_path, "#{vm_name}_cloudinit.iso")
arguments = ["genisoimage", "-output #{iso}", '-volid', 'cidata', '-joliet', '-rock']
logger.warn("iso image generation args: #{arguments}")
arguments.concat(files).join(' ')
def generate_iso_command(iso_file, config_files)
arguments = ["genisoimage", "-output #{iso_file}", '-volid', 'cidata', '-joliet', '-rock']
iso_command = arguments.concat(config_files).join(' ')
logger.debug("iso image generation args: #{iso_command}")
iso_command
end

def create_temp_directory(ssh)
res = ssh.run([%({mktemp -d})])
res = ssh.run("mktemp -d")
raise ::Foreman::Exception, "Could not create working directory to store cloudinit config data: #{res.first.stdout}." unless res.first.status.zero?
res.first.stdout.chomp
end

def delete_config_files(working_dir)
def delete_temp_dir(ssh, working_dir)
ssh.run("rm -rf #{working_dir}")
rescue Foreman::Exception => e
logger.warn("Could not delete directory for config files: #{e}. Please delete it manually at #{working_dir}")
Expand All @@ -83,12 +87,13 @@ def parse_cloudinit_config(args)
filenames = ["meta-data"]
config_data = ["instance-id: #{args[:name]}"]
user_data = args.delete(:user_data)

return args if user_data == ''
check_template_format(user_data)
ssh = vm_ssh

if user_data.include?('#network-config') && user_data.include?('#cloud-config')
config_data.concat(user_data.split('#network-config'))
filenames.append(['user-data', 'network-config'])
filenames.concat(['user-data', 'network-config'])
elsif user_data.include?('#network-config') && !user_data.include?('#cloud-config')
config_data.append(user_data.split('#network-config')[1])
filenames.append("network-config")
Expand All @@ -98,11 +103,11 @@ def parse_cloudinit_config(args)
end

return args if config_data.length == 1

configs = filenames.zip(config_data).to_h

iso = create_cloudinit_iso(args[:name], configs)
args.merge(attach_cloudinit_iso(args[:node_id], iso))
iso = create_cloudinit_iso(args[:name], configs, ssh)
args[:config_attributes]&.merge!(update_boot_order(args[:image_id]))
args.merge!(attach_cloudinit_iso(args[:node_id], iso))
end

def attach_cloudinit_iso(node, iso)
Expand All @@ -114,4 +119,25 @@ def attach_cloudinit_iso(node, iso)
def default_iso_path
"/var/lib/vz/template/iso"
end

def update_boot_order(image_id)
vm = find_vm_by_uuid(image_id)
return if vm.disks.nil?
disks = vm.disks.map { |disk| disk.split(":")[0] }.join(";")
{ boot: "order=" + disks }
end

def vm_ssh
ssh = Fog::SSH.new(URI.parse(fog_credentials[:proxmox_url]).host, fog_credentials[:proxmox_username].split('@')[0], { password: fog_credentials[:proxmox_password] })
ssh.run('ls') # test if ssh is successful
ssh
rescue StandardError => e
raise ::Foreman::Exception, "Unable to ssh into proxmox server: #{e}"
end

def check_template_format(user_data)
YAML.safe_load(user_data)
rescue StandardError => e
raise ::Foreman::Exception, "'User data kind' template provided could not be loaded, please check the format: #{e}"
end
end

0 comments on commit d0ebba1

Please sign in to comment.