module Gogetit::Util

Public Instance Methods

check_ip_available(addresses, maas) click to toggle source
# File lib/gogetit/util.rb, line 241
def check_ip_available(addresses, maas)
  logger.info("Calling <#{__method__.to_s}>")
  # to do a ping test
  addresses.each do |ip|
    abort("#{ip} is already being used.") if ping_available?(ip)
  end
  # to check with MAAS
  ifaces = maas.ip_reserved?(addresses)
  abort("one of #{addresses.join(', ')} is already being used.") \
    unless ifaces
  return ifaces
end
generate_cloud_init_config(options, config, user_data = {}) click to toggle source
# File lib/gogetit/util.rb, line 265
    def generate_cloud_init_config(options, config, user_data = {})
      logger.info("Calling <#{__method__.to_s}>")

      if options[:'no-maas']
        # When there is no MAAS, containers should be able to resolve
        # their name with hosts file.
        user_data['manage_etc_hosts'] = true
      end

      # To add truested root CA certificates
      # https://cloudinit.readthedocs.io/en/latest/topics/examples.html
      # #configure-an-instances-trusted-ca-certificates
      #
      if config[:cloud_init_helper] && config[:cloud_init_helper][:ca_certs]
        user_data['ca-certs'] = {}
        certs = []

        config[:cloud_init_helper][:ca_certs].each do |ca|
          content = get_http_content(ca)
          certs.push(
            /^-----BEGIN CERTIFICATE-----.*-/m.match(content).to_s
          ) if content
        end

        user_data['ca-certs'] = { 'trusted' => certs }
      end

      # To get CA public key to be used for SSH authentication
      # https://cloudinit.readthedocs.io/en/latest/topics/examples.html
      # #writing-out-arbitrary-files
      if config[:cloud_init_helper] && config[:cloud_init_helper][:ssh_with_ca_signed_keys]
        user_data['write_files'] = []
        content = get_http_content(config[:cloud_init_helper][:ssh_with_ca_signed_keys][:ca_public_key_url])
        if content
          file = {
            'content'     => content.chop!,
            'path'        => config[:cloud_init_helper][:ssh_with_ca_signed_keys][:ca_public_key_path],
            'owner'       => config[:cloud_init_helper][:ssh_with_ca_signed_keys][:owner],
            'permissions' => config[:cloud_init_helper][:ssh_with_ca_signed_keys][:permissions]
          }
          user_data['write_files'].push(file)
          user_data['bootcmd'] = []
          user_data['bootcmd'].push(
            "cloud-init-per once ssh-ca-pub-key \
echo \"TrustedUserCAKeys #{file['path']}\" >> /etc/ssh/sshd_config"
          )
        end

        if config[:cloud_init_helper][:ssh_with_ca_signed_keys][:revocation_url]
          content = get_http_content(config[:cloud_init_helper][:ssh_with_ca_signed_keys][:revocation_url])
          if content
            user_data['bootcmd'].push(
              "cloud-init-per once download-key-revocation-list \
curl -o #{config[:cloud_init_helper][:ssh_with_ca_signed_keys][:revocation_path]} \
#{config[:cloud_init_helper][:ssh_with_ca_signed_keys][:revocation_url]}"
            )
            user_data['bootcmd'].push(
              "cloud-init-per once ssh-user-key-revocation-list \
echo \"RevokedKeys #{config[:cloud_init_helper][:ssh_with_ca_signed_keys][:revocation_path]}\" \
>> /etc/ssh/sshd_config"
            )
          end
        end
      end

      user_data.merge! (Hashie.stringify_keys config[:cloud_init])

      return user_data
    end
get_gateway(version) click to toggle source
# File lib/gogetit/util.rb, line 192
def get_gateway(version)
  IO.popen("ip -#{version.to_s} route").read.each_line do |route|
    if route.include? 'default'
      route.split[2]
    else
      'There is no get_gateway!'
      nil
    end
  end
end
get_http_content(url) click to toggle source
# File lib/gogetit/util.rb, line 48
def get_http_content(url)
  logger.info("Calling <#{__method__.to_s}> to get #{url}")

  uri = URI.parse(url)

  if is_port_open?(uri.host, uri.port)
    http = Net::HTTP.new(uri.host, uri.port)
    res = http.request_post(uri.path, nil)
    if res.code == "200"
      res.body
    else
      logger.error("Unable to reach the content of #{url}.")
      false
    end
  else
    logger.error("Unable to reach the server: #{uri.host} or port: #{uri.port}.")
    false
  end
end
get_provider_of(name, providers) click to toggle source
# File lib/gogetit/util.rb, line 16
def get_provider_of(name, providers)
  logger.info("Calling <#{__method__.to_s}> #{name}")
  if providers[:lxd].container_exists?(name)
    logger.info("It is a LXD container.")
    return 'lxd'
  elsif providers[:libvirt].domain_exists?(name)
    logger.info("It is a KVM domain.")
    return 'libvirt'
  else
    puts "#{name} is not found"
    return nil
  end
end
is_port_open?(ip, port) click to toggle source
# File lib/gogetit/util.rb, line 30
def is_port_open?(ip, port)
  logger.info("Calling <#{__method__.to_s}> to check #{ip}:#{port}")
  begin
    Timeout::timeout(1) do
      begin
        s = TCPSocket.new(ip, port)
        s.close
        return true
      rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, SocketError
        return false
      end
    end
  rescue Timeout::Error
  end

  return false
end
knife_bootstrap_chef(name, provider, config) click to toggle source
# File lib/gogetit/util.rb, line 68
def knife_bootstrap_chef(name, provider, config)
  logger.info("Calling <#{__method__.to_s}>")
  config[:chef][:target_environment] ||= '_default'
  if find_executable 'knife'
    if system('knife ssl check')
      install_cmd = "curl \
      -l #{config[:chef][:bootstrap][:install_script][provider.to_sym]} \
      | sudo bash -s --"
      knife_cmd = "knife bootstrap -y #{name} \
      --node-name #{name} \
      --ssh-user ubuntu \
      --sudo \
      --environment #{config[:chef][:target_environment]} \
      --bootstrap-install-command \"#{install_cmd}\"".gsub(/ * /, ' ')
      puts 'Bootstrapping with chef-server..'
      logger.info(knife_cmd)
      system(knife_cmd)
    end
  end
end
knife_bootstrap_zero(name, provider, config) click to toggle source
# File lib/gogetit/util.rb, line 89
def knife_bootstrap_zero(name, provider, config)
  logger.info("Calling <#{__method__.to_s}>")
  config[:chef][:target_environment] ||= '_default'
  if find_executable 'knife'
    knife_cmd = "knife zero bootstrap #{name} \
    --node-name #{name} \
    --ssh-user ubuntu \
    --sudo \
    --environment #{config[:chef][:target_environment]}".gsub(/ * /, ' ')
    puts 'Bootstrapping with chef-zero..'
    logger.info(knife_cmd)
    system(knife_cmd)
  end
end
knife_remove(name, options) click to toggle source
# File lib/gogetit/util.rb, line 104
def knife_remove(name, options)
  logger.info("Calling <#{__method__.to_s}>")
  if find_executable 'knife'
    if options[:chef]
      if system('knife ssl check')
        logger.info("With chef-server..")
        puts "Deleting node #{name}.."
        logger.info("knife node delete -y #{name}")
        system("knife node delete -y #{name}")
        puts "Deleting client #{name}.."
        logger.info("knife client delete -y #{name}")
        system("knife client delete -y #{name}")
      else
        abort('knife is not configured properly.')
      end
    elsif options[:zero]
      logger.info("With chef-zero..")
      puts "Deleting node #{name}.."
      logger.info("knife node delete -y #{name}")
      system("knife node delete -y #{name}")
      puts "Deleting client #{name}.."
      logger.info("knife client delete -y #{name}")
      system("knife client delete -y #{name}")
    end
  end
end
ping_available?(host) click to toggle source
# File lib/gogetit/util.rb, line 218
def ping_available?(host)
  # host can be both IP and ip_or_fqdn.
  logger.info("Calling <#{__method__.to_s}> for #{host}")
  `ping -c 1 -W 1 #{host}`
  $?.exitstatus == 0
end
run_command(cmd) click to toggle source
# File lib/gogetit/util.rb, line 11
def run_command(cmd)
  logger.info("Calling <#{__method__.to_s}> to run '#{cmd}'")
  system(cmd)
end
run_through_ssh(host, distro_name, commands) click to toggle source
# File lib/gogetit/util.rb, line 254
def run_through_ssh(host, distro_name, commands)
  logger.info("Calling <#{__method__.to_s}>")
  Net::SSH.start(host, distro_name) do |ssh|
    commands.each do |cmd|
      logger.info("'#{cmd}' is being executed..")
      output = ssh.exec!(cmd)
      puts output if output != ''
    end
  end
end
ssh_available?(ip_or_fqdn, user) click to toggle source
# File lib/gogetit/util.rb, line 225
def ssh_available?(ip_or_fqdn, user)
  logger.info("Calling <#{__method__.to_s}> for #{user}@#{ip_or_fqdn}")
  begin
    Net::SSH.start(
      ip_or_fqdn,
      user,
      :keys_only => true,
      :number_of_password_prompts => 0
    )
  rescue Exception => e
    puts e
    return false
  end
  true
end
update_databags(config) click to toggle source
# File lib/gogetit/util.rb, line 131
def update_databags(config)
  logger.info("Calling <#{__method__.to_s}>")
  data_bags_dir = "#{config[:chef][:chef_repo_root]}/data_bags"

  puts 'Listing databags..'
  databags_as_is = `knife data bag list`.split
  databags_to_be = Dir.entries(data_bags_dir) - ['.', '..']

  puts 'Checking databags to delete..'
  (databags_as_is - databags_to_be).each do |bag|
    puts "Deleting databag '#{bag}'.."
      answer = ask(
        'Do you really want to delete this?',
        :echo => true,
        :limited_to => ['y', 'n']
      )
      case answer
      when 'y'
        run_command("knife data bag delete -y #{bag}")
      when 'n'
        puts 'Keeping..'
      end
  end

  puts 'Checking databags to create..'
  (databags_to_be - databags_as_is).each do |bag|
    puts "Creating databag '#{bag}'.."
    run_command("knife data bag create #{bag}")
  end

  puts 'Checking items..'
  databags_to_be.each do |bag|
    items_as_is = `knife data bag show #{bag}`.split
    Dir.entries(data_bags_dir+'/'+bag).select do |file|
      /^.*\.json/.match(file)
    end.each do |item|
      item_file = data_bags_dir+'/'+bag+'/'+item
      item = item.gsub('.json', '')
      if JSON.parse(File.read(item_file))['vault']
        # We assumes you have configured 'mode' and 'admins' on your knife.rb
        if items_as_is.include? item
          run_command(
            "knife vault update #{bag} #{item} --json #{item_file}"\
            " --search '*:*'"
          )
        else
          run_command(
            "knife vault create #{bag} #{item} --json #{item_file}"\
            " --search '*:*'"
          )
        end
        run_command(
          "knife vault refresh #{bag} #{item} --clean-unknown-clients"
        )
      else
        run_command("knife data bag from file #{bag} #{item_file}")
      end
    end
  end
end
wait_until_available(ip_or_fqdn, distro_name) click to toggle source
# File lib/gogetit/util.rb, line 203
def wait_until_available(ip_or_fqdn, distro_name)
  logger.info("Calling <#{__method__.to_s}> for network connection..")
  until ping_available?(ip_or_fqdn)
    logger.info("Calling <#{__method__.to_s}> for ping to be ready..")
    sleep 3
  end
  logger.info("#{ip_or_fqdn} is now available to ping..")

  until ssh_available?(ip_or_fqdn, distro_name)
    logger.info("Calling <#{__method__.to_s}> for ssh to be ready..")
    sleep 3
  end
  logger.info("#{ip_or_fqdn} is now available to ssh..")
end