Skip to content

Instantly share code, notes, and snippets.

@ohadlevy
Created November 12, 2010 20:29
Show Gist options
  • Save ohadlevy/674623 to your computer and use it in GitHub Desktop.
Save ohadlevy/674623 to your computer and use it in GitHub Desktop.
script to automate creation of machines, including dns, dhcp, tftp, foreman and puppet
#!/usr/bin/ruby
require "rubygems"
require "rest_client"
require "json"
require "uri"
fqdn = ARGV[0] || raise("Must define a fqdn")
mac = ARGV[1] || raise("Must define a mac")
start = Time.now
dhcp_server = "http://192.168.100.254:4567/dhcp"
tftp_server_ip = "192.168.100.254"
tftp_server = "http://#{tftp_server_ip}:4567"
dns_server = tftp_server
foreman_url = "http://192.168.100.254"
foreman_user = "admin"
foreman_pass = "changeme"
puppet_env = "production"
host_arch = "x86_64"
media_name = "Fedora Mirror"
# define defaults for restful connectivity to Foreman
@foreman = RestClient::Resource.new foreman_url,{ :user => foreman_user, :password => foreman_pass,
:headers => { :accept => :json, :content_type => :json }}
# fetch availavble networks on DHCP server
t=Time.now
print "fetching subnets from dhcp server via REST... "
networks= JSON.parse(RestClient.get("#{dhcp_server}/.json").body)
printf "done in %5.2f seconds\n", Time.now - t
# Use the first one
network = networks.first["network"]
puts "Selected #{network} Subnet"
print "checking if record already exists on #{network} subnet..."
t=Time.now
# find if the record already exists on the dhcp server
begin
record= JSON.parse(RestClient.get("#{dhcp_server}/#{network}/#{mac}.json").body)
rescue
record = nil
end
printf "done in %5.2f seconds\n", Time.now - t
if record
puts "skipping DHCP creation as record already exists"
ip = record["ip"]
else
t=Time.now
print "Checking for next unused IP Address on #{network}..."
# find the next free IP
ip = RestClient.get("#{dhcp_server}/#{network}/unused_ip").body
printf "done in %5.2f seconds\n", Time.now - t
print "About to create DHCP record using the free IP #{ip}..."
options = {
:network => network,
:ip => ip,
:mac => mac,
:name => fqdn,
:nextserver => tftp_server_ip,
:filename => "pxelinux.0"
}
t=Time.now
# create the DHCP reservation
RestClient.post "#{dhcp_server}/#{options[:network]}", options
printf "done in %5.2f seconds\n", Time.now - t
end
print "Creating DNS records..A.."
RestClient.post "#{dns_server}/dns", {:fqdn => fqdn, :value => ip}
print "done...PTR..."
RestClient.post "#{dns_server}/dns", {:fqdn => fqdn, :type => "PTR",
:value => ip.split(".").reverse.join(".") + ".in-addr.arpa" }
puts "done"
# Add the host to Foreman
#
#
def helper(url, title, args = %w{ name id })
t=Time.now
print "Asking Foreman for a(n) #{title}..."
hash = JSON.parse(@foreman[URI.escape(url)].get.body)
printf "done in %5.2f seconds\n", Time.now - t
hash = hash.is_a?(Array) ? hash.first[title] : hash[title]
args.collect {|arg| hash[arg]}
end
env, env_id = helper("/environments/#{puppet_env}", "environment")
#rhel5
os, os_id = helper("/operatingsystems/2", "operatingsystem")
#ubuntu
os, os_id = helper("/operatingsystems/3", "operatingsystem")
arch, arch_id = helper("/architectures/x86_64","architecture")
#redhat default
#media, media_id = helper("/medias/1","media")
# ubuntu default
media, media_id = helper("/medias/4","media")
domain, domain_id = helper("/domains/lab","domain")
# redhat default
#ptable, ptable_id = helper("/ptables","ptable")
# ubuntu default
ptable, ptable_id = helper("/ptables/2","ptable")
hostgroup, hostgroup_id = helper("/hostgroups/1", "hostgroup")
payload = {:host => {
:name => fqdn, :mac => mac, :ip => ip,
:environment_id => env_id, :architecture_id => arch_id, :domain_id => domain_id, :media_id => media_id,
:operatingsystem_id => os_id, :ptable_id => ptable_id,
:host_parameters_attributes => { Time.now.to_i => {:name => "activation_key", :value =>"123123xxxxxxx", :nested =>""}},
:hostgroup_id => hostgroup_id, :comment => "Added via Batch"
}}.to_json
begin
t=Time.now
print "Creating the Host at Foreman..."
@foreman["/hosts"].post payload
printf "done in %5.2f seconds\n", Time.now - t
rescue => e
warn "ERROR: #{e.response}"
end
# enable the host for installation
t=Time.now
print "Enabling Foreman to build the host..."
@foreman["/hosts/#{fqdn}/setBuild"].get.body
printf "done in %5.2f seconds\n", Time.now - t
#
# Create the TFTP setup
#
# First make sure the TFTP media is in place (kernel initrd)
#
#
puts "Setting up TFTP\n"
bootfiles_url = URI.escape("operatingsystems/#{os_id}/bootfiles?media=#{media}&architecture=#{arch}")
t=Time.now
print "asking Foreman for our PXE boot files..."
files = JSON.parse(@foreman[bootfiles_url].get.body)
printf "done in %5.2f seconds\n", Time.now - t
puts "asking our tftp server to fetch the following files"
files.each do |file|
file.each do |prefix, path|
t=Time.now
print "#{prefix} - #{path}..."
RestClient.post "#{tftp_server}/tftp/fetch_boot_file", {:prefix => prefix, :path => path}
printf "done in %5.2f seconds\n", Time.now - t
end
end
t=Time.now
print "quering Foreman for #{fqdn} TFTP configuation..."
config = @foreman["hosts/#{fqdn}/pxe_config"].get.body
printf "done in %5.2f seconds\n", Time.now - t
# TODO cleanup the entry after the machine sucsefully installed
# this will be done internally in foreman, so should not be a problem
#
t=Time.now
print "And asking our TFTP server to apply it..."
RestClient.post "#{tftp_server}/tftp/#{mac}", {:syslinux_config => config}
printf "done in %5.2f seconds\n", Time.now - t
puts
printf "Created everything in %5.2f seconds\n", Time.now - start
olevy@super:~/git/foreman(develop)$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment