Bryan Kearney
2009-Jan-08 16:40 UTC
[Ovirt-devel] Installer Patch works off of earlier patches
This patch works off the earlier installer patches. It adds better validation, default value, and makes use of the ruby built in templating.
Bryan Kearney
2009-Jan-08 16:40 UTC
[Ovirt-devel] [PATCH server] Rework the installer to add validation, file generation by templates, and default values
--- installer/bin/ovirt-installer | 421 ++++++++++++++++++++++------------------- 1 files changed, 226 insertions(+), 195 deletions(-) diff --git a/installer/bin/ovirt-installer b/installer/bin/ovirt-installer index 84604ef..7ae789d 100755 --- a/installer/bin/ovirt-installer +++ b/installer/bin/ovirt-installer @@ -22,252 +22,283 @@ require 'socket' require 'fileutils' +require 'erb' -if File.exist?("/usr/sbin/sestatus") -sestatus = `/usr/sbin/sestatus` -if sestatus !~ /(Current mode: permissive|Current mode: disabled|SELinux status: disabled|SELinux status: permissive)/ -puts "SELinux enabled, please disable or set in permissive mode permanently by editing" -puts "/etc/selinux/config and rebooting" -exit -end -end - -FileUtils.mkdir_p("/usr/share/ace/appliances/ovirt") -config_file = File.new("/usr/share/ace/appliances/ovirt/ovirt.pp", "w") -config_file.write "import 'ovirt'\n" -config_file.write "import 'firewall'\n\n" -config_file.write "firewall::setup{'setup': status => 'disabled'}\n\n" - -mgmt_dev = "" -prov_dev = "" - -dev_ct = 0 -net_devs = `hal-find-by-capability --capability net` -net_devs.each_line{ |dev| -dev_ct = dev_ct + 1 -} - -if dev_ct == 0 -puts "Unable to install without a network interface" -exit +# +# Input output controls +# -else -puts "" -get_net_devs = `hal-find-by-capability --capability net` -puts "Below are the detected networking devices\n\n" -puts "mac address interface ip address" -net_devs.each_line{ |dev| -dev = dev.chomp -interface = `hal-get-property --udi #{dev} --key net.interface` -mac = `hal-get-property --udi #{dev} --key net.address` -ip = `ifconfig #{interface}` -ipaddr = ip.scan(/\s*inet addr:([\d.]+)/) -puts mac.chop + " : " + interface.chop + " : " + ipaddr.to_s if interface.chop != "lo" -} +# Basic read logic +def read_user_input(prompt) + print("\n#{prompt} ") + return gets.chomp end -if dev_ct > 1 -puts "\nDo you want separate management and provisioning networks? (y/n)" -sep_networks = gets.chomp -while sep_networks != "y" and sep_networks != "n" -puts "Invalid choice" -puts "Do you want separate management and provisioning networks? (y/n)" -sep_networks = gets.chomp +# prompt a user for a non-blank answer +def prompt_for_answer(prompt, options={}) + default = options[:default] + allow_blanks = options[:allow_blanks] ? options[:allow_blanks] : false + expression = options[:regex] + validate = !expression.nil? + + if !default.nil? + prompt = "#{prompt} [#{default}]" + end + + answer = read_user_input(prompt) + answer = default if (!default.nil? && answer == "") + + if (answer == "" and ! allow_blanks) + puts("Plese enter a value") + answer = prompt_for_answer(prompt, options) + end + + if (validate && answer !~ expression) + puts("That is not in the correct format") + answer = prompt_for_answer(prompt, options) + end + + return answer end -if sep_networks == "y" -while mgmt_dev == "" -puts "Input your management interface (example: eth0)" -mgmt_dev = gets.chomp +# Allow a user to enter a Yes/No +# And repeat the prompt until they do +def prompt_yes_no(prompt, options={}) + default = options[:default] + + if default.nil? + prompt = "#{prompt} (y/n)" + else + prompt = "#{prompt} [#{default}]" + end + answer = read_user_input(prompt) + answer = default if (!default.nil? && answer == "") + answer = answer.downcase() + while answer != "y" and answer != "n" + puts("Invalid choice") + answer = read_user_input(prompt).downcase() + end + + return answer end -while prov_dev == "" -puts "Input your provisioning interface, this may also be your management interface (example: eth1)" -prov_dev = gets.chomp +# +# The real script begins here +# + +# These regular expressions will be used to +# validate the user input +IP = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ +THREE_OCTETS = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){2}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ +FQDN = /(?=^.{1,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)/ +IP_OR_FQDN = /(?=^.{1,254}$)(^((?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$)/ +OCTET = /^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/ + +# Print a friendly welcome message +welcome = "This installer will configure the ovirt installation based on a series\n\ +of questions. When complete, you will be asked to install oVirt or\n\ +do the installation manually. Would you like to continue?" + +if (prompt_yes_no(welcome, :default => "y") == "n") + exit(0) end -elsif sep_networks == "n" -while mgmt_dev == "" -puts "Input your management/provisioning interface (example: eth1)" -mgmt_dev = gets.chomp -prov_dev = mgmt_dev -end + +if File.exist?("/usr/sbin/sestatus") + sestatus = `/usr/sbin/sestatus` + if sestatus !~ /(Current mode: permissive|Current mode: disabled|SELinux status: disabled|SELinux status: permissive)/ + puts "SELinux enabled, please disable or set in permissive mode permanently by editing" + puts "/etc/selinux/config and rebooting" + exit + end end -elsif dev_ct == 1 -while mgmt_dev == "" -puts "\nOnly one networking device detected" -puts "Input your management/provisioning interface (example: eth1)" -mgmt_dev = gets.chomp -prov_dev = mgmt_dev -puts "Need Management interface" +# Networking Configuration +dev_ct = 0 +net_devs = `hal-find-by-capability --capability net` +net_devs.each_line do |dev| + dev_ct = dev_ct + 1 end + +if dev_ct == 0 + puts "Unable to install without a network interface" + exit +else + puts "" + get_net_devs = `hal-find-by-capability --capability net` + puts "Below are the detected networking devices\n\n" + puts "mac address interface ip address" + net_devs.each_line do |dev| + dev = dev.chomp + interface = `hal-get-property --udi #{dev} --key net.interface` + mac = `hal-get-property --udi #{dev} --key net.address` + ip = `ifconfig #{interface}` + ipaddr = ip.scan(/\s*inet addr:([\d.]+)/) + puts mac.chop + " : " + interface.chop + " : " + ipaddr.to_s if interface.chop != "lo" + end end -puts "Enter the hostname of the oVirt management server (example: management.example.com)" -ovirt_host = gets.chomp +mgmt_dev = prompt_for_answer("Enter your management interface (example: eth0):") +prov_dev = prompt_for_answer("Enter your provisioning interface, this may also be your management interface:", :default => mgmt_dev) + +sep_networks = (mgmt_dev == prov_dev) ? "n" : "y" + +ovirt_host = prompt_for_answer("Enter the hostname of the oVirt management server (example: management.example.com):", :regex => IP_OR_FQDN) ipa_host = ovirt_host -puts "\nUse this system's dns servers (y/n)" +# DNS Configuration +puts "\nThe following DNS servers were found:" File.open('/etc/resolv.conf').each_line{ |line| line = line.chomp -puts line if line =~ /nameserver/ and line !~ /nameserver 127.0.0.1/ + puts line if line =~ /nameserver/ and line !~ /nameserver 127.0.0.1/ } -dns_servers = gets.chomp - -while dns_servers != "y" and dns_servers != "n" -puts "Invalid choice" -dns_servers = gets.chomp -end +dns_servers = prompt_yes_no("Use this systems's dns servers?") mgmt_ip = `ifconfig #{mgmt_dev}` mgmt_ipaddr= mgmt_ip.scan(/\s*inet addr:([\d.]+)/) prov_ip = `ifconfig #{prov_dev}` prov_ipaddr= prov_ip.scan(/\s*inet addr:([\d.]+)/) -config_file.write "# dns configuration\n" -config_file.write "$mgmt_ipaddr = '#{mgmt_ipaddr}'\n" -config_file.write "$prov_ipaddr = '#{prov_ipaddr}'\n" -config_file.write "$ovirt_host = '#{ovirt_host}'\n" -config_file.write "$ipa_host = '#{ipa_host}'\n\n" - -if dns_servers == "n" -config_file.write "dns::bundled{setup: mgmt_ipaddr=> $mgmt_ipaddr, prov_ipaddr=> $prov_ipaddr, mgmt_dev => '#{mgmt_dev}', prov_dev => '#{prov_dev}'}\n\n" -end - if dns_servers == "y" -config_file.write "dns::remote{setup: mgmt_ipaddr=> $mgmt_ipaddr, prov_ipaddr=> $prov_ipaddr, mgmt_dev => '#{mgmt_dev}', prov_dev => '#{prov_dev}'}\n\n" -host_lookup = Socket.getaddrinfo(ipa_host,nil) -hostip = host_lookup[1][3] -if hostip.to_s != mgmt_ipaddr.to_s -puts "Reverse dns lookup for #{ipa_host} failed, exiting" -exit -end -end - -puts "Does you provisioning network already have dhcp? (y/n)" -dhcp_setup = gets.chomp -while dhcp_setup != "y" and dhcp_setup != "n" -puts "Invalid choice" -dhcp_setup = gets.chomp + host_lookup = Socket.getaddrinfo(ipa_host,nil) + hostip = host_lookup[1][3] + if hostip.to_s != mgmt_ipaddr.to_s + puts "Reverse dns lookup for #{ipa_host} failed, exiting" + exit + end end +# DHCP Configuration +dhcp_setup = prompt_yes_no("Does your provisioning network already have dhcp?") if dhcp_setup == "n" - -puts "DHCP Configuration\n" -config_file.write "# dhcp configuration\n" -dhcp_interface = prov_dev -config_file.write "$dhcp_interface = '#{dhcp_interface}'\n" - -puts "Enter the first 3 octets of the dhcp network you wish to use (example: 192.168.50)" -dhcp_network = gets.chomp -config_file.write "$dhcp_network = '#{dhcp_network}'\n" - -puts "Enter the dhcp pool start address (example: 3)" -dhcp_start = gets.chomp -config_file.write "$dhcp_start = '#{dhcp_start}'\n" - -puts "Enter the dhcp pool end addess (example: 100)" -dhcp_stop = gets.chomp -config_file.write "$dhcp_stop = '#{dhcp_stop}'\n" - -puts "Enter the dhcp domain you wish to use (example: example.com)" -dhcp_domain = gets.chomp -config_file.write "$dhcp_domain = '#{dhcp_domain}'\n" - -config_file.write "$ntp_server = '#{mgmt_ipaddr}'\n\n" - -puts "Provide pxe/tftp capability? (y/n)" -tftp_setup = gets.chomp - -if sep_networks == "y" -prov_ip = `ifconfig #{prov_dev}` -prov_dns_server = prov_ip.scan(/\s*inet addr:([\d.]+)/) -config_file.write "$prov_dns_server = '#{prov_dns_server}'\n" - -puts "Enter the network gateway for your provisioning network (example: 192.168.50.254)" -prov_network_gateway = gets.chomp -config_file.write "$prov_network_gateway = '#{prov_network_gateway}'\n" -end + dhcp_interface = prov_dev + dhcp_network = prompt_for_answer("Enter the first 3 octets of the dhcp network you wish to use (example: 192.168.50):", :regex => THREE_OCTETS) + dhcp_start = prompt_for_answer("Enter the dhcp pool start address (example: 3):", :regex => OCTET) + dhcp_stop = prompt_for_answer("Enter the dhcp pool end addess (example: 100):", :regex => OCTET) + dhcp_domain = prompt_for_answer("Enter the dhcp domain you wish to use (example: example.com):", :regex => IP_OR_FQDN) + tftp_setup = prompt_yes_no("Provide pxe/tftp capability?") + + if sep_networks == "y" + prov_ip = `ifconfig #{prov_dev}` + prov_dns_server = prov_ip.scan(/\s*inet addr:([\d.]+)/) + prov_network_gateway = prompt_for_answer("Enter the network gateway for your provisioning network (example: 192.168.50.254):", :regex => IP_OR_FQDN) + end end # Cobbler Configuration -puts "Do you have a cobbler already that you wish to use? (y/n)" -cobbler_setup = gets.chomp - -while cobbler_setup != "y" and cobbler_setup != "n" -puts "Invalid choice" -cobbler_setup = gets.chomp -end - -cobbler_config = "n" +cobbler_setup = prompt_yes_no("Do you have a cobbler already that you wish to use?") if cobbler_setup == "y" -puts "Enter the hostname of your cobbler server" -cobbler_hostname = gets.chomp -puts "Enter your cobbler username" -cobbler_user_name= gets.chomp -puts "Enter your cobbler user password" -cobbler_user_password = gets.chomp - + cobbler_hostname = prompt_for_answer("Enter the hostname of your cobbler server:", :regex => IP_OR_FQDN) elsif cobbler_setup == "n" -cobbler_hostname = "localhost" -puts "We will setup a cobbler instance, please provide the following information" -puts "Enter your cobbler username" -cobbler_user_name= gets.chomp -puts "Enter your cobbler user password" -cobbler_user_password = gets.chomp + cobbler_hostname = "localhost" + puts "\nWe will setup a cobbler instance, please provide the following information" end -config_file.write "# cobbler configuration\n" -config_file.write "$cobbler_hostname = '#{cobbler_hostname}'\n" -config_file.write "$cobbler_user_name = '#{cobbler_user_name}'\n" -config_file.write "$cobbler_user_password = '#{cobbler_user_password}'\n\n" - +cobbler_user_name= prompt_for_answer("Enter your cobbler username:") +cobbler_user_password = prompt_for_answer("Enter your cobbler user password:") # Postgres Configuration -puts "Enter a password for the ovirt postgres account" db_username = "ovirt" -db_password = gets.chomp -config_file.write "# postgres configuration\n" -config_file.write "$db_username = '#{db_username}'\n" -config_file.write "$db_password = '#{db_password}'\n\n" +db_password = prompt_for_answer("Enter a password for the ovirt postgres account:") # FreeIPA Configuration -config_file.write "# FreeIPA configuration\n" -puts "Enter your realm name (example: example.com)" -realm_name = gets.chomp -config_file.write "$realm_name = '#{realm_name}'\n" -puts "\nEnter an administrator password for FreeIPA " -puts "*** This will also be you ovirtadmin password for the web management login ***\n\n" -freeipa_password = gets.chomp -config_file.write "$freeipa_password = '#{freeipa_password}'\n" +realm_name = prompt_for_answer("Enter your realm name (example: example.com):", :regex => FQDN) + +freeipa_password = prompt_for_answer("NOTE: The following pasword will also be you ovirtadmin password for the web management login\n\ +Enter an administrator password for FreeIPA:") ldap_dn = "cn=ipaConfig,cn=etc," ldap_dn_temp = realm_name.split(".") ldap_dn_temp.each do |i| -ldap_dn += "dc=#{i}," + ldap_dn += "dc=#{i}," end ldap_dn = ldap_dn.chop -config_file.write "$ldap_dn = '#{ldap_dn}'\n\n" -if cobbler_setup == "y" -config_file.write "include cobbler::remote\n" -elsif cobbler_setup == "n" -config_file.write "include cobbler::bundled\n" -end +# +# Use ERB to spit out the puppet file whcih is used by ace. +# -if dhcp_setup == "n" -config_file.write "include dhcp::bundled\n" -end +# Create the template +template = <<END_OF_TEMPLATE +# Configurations script generated by ovirt-installer +# at <%= Time.now().to_s() %> +# -if tftp_setup == "y" -config_file.write "include tftp::bundled\n" -end +import 'ovirt' +import 'firewall' +firewall::setup{'setup': + status => 'disabled' +} + +#DNS Configuration +$mgmt_ipaddr = '<%= mgmt_ipaddr %>' +$prov_ipaddr = '<%= prov_ipaddr %>' +$ovirt_host = '<%= ovirt_host %>' +$ipa_host = '<%= ipa_host %>' + +<% if dns_servers == "n" %> +dns::bundled{setup: +<% else %> +dns::remote{ +<% end %> + mgmt_ipaddr=> $mgmt_ipaddr, + prov_ipaddr=> $prov_ipaddr, + mgmt_dev => '<%= mgmt_dev %>', + prov_dev => '<%= prov_dev %>' +} + +# DHCP Configuration +<% if dhcp_setup == "n" %> +$dhcp_interface = '<%= dhcp_interface %>' +$dhcp_network = '<%= dhcp_network %>' +$dhcp_start = '<%= dhcp_start %>' +$dhcp_stop = '<%= dhcp_stop %>' +$dhcp_domain = '<%= dhcp_domain %>' +$ntp_server = '<%= mgmt_ipaddr %>' +<% if tftp_setup == "y" %> +include tftp::bundled +<% end %> +<% if sep_networks == "y" %> +$prov_dns_server = '<%= prov_dns_server %>' +$prov_network_gateway = '<%= prov_network_gateway %>' +<% end %> +<% end %> + + +# Cobbler configuration +$cobbler_hostname = '<%= cobbler_hostname %>' +$cobbler_user_name = '<%= cobbler_user_name %>' +$cobbler_user_password = '<%= cobbler_user_password %>' + +# Postgres Configuration +$db_username = '<%= db_username %>' +$db_password = '<%= db_password %>' + +# FreeIPA configuration +$realm_name = '<%= realm_name %>' +$freeipa_password = '<%= freeipa_password %>' +$ldap_dn = '<%= ldap_dn %>' + +<% if cobbler_setup == "n" %> +include cobbler::bundled +<% else %> +include cobbler::remote +<% end %> +<% if dhcp_setup == "n" %> +include dhcp::bundled +<% end %> +include postgres::bundled +include freeipa::bundled +include ovirt::setup +END_OF_TEMPLATE + +# Generate the file and output it. +FileUtils.mkdir_p("/usr/share/ace/appliances/ovirt") +config_file = File.new("/usr/share/ace/appliances/ovirt/ovirt.pp", "w") +config_file.write(ERB.new(template, 0, "%>").result) +config_file.close() -config_file.write "include postgres::bundled\n" -config_file.write "include freeipa::bundled\n" -config_file.write "include ovirt::setup\n" -config_file.close -puts "\n\nTo start the installation run: ace install ovirt" +# Give a friendly reminder about what to do next +puts "\nTo start the installation run: ace install ovirt" -- 1.6.0.6