[Ovirt-devel] [PATCH server] Rework the installer to add validation, file generation by templates, and default values

Bryan Kearney bkearney at redhat.com
Thu Jan 8 16:40:41 UTC 2009


---
 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




More information about the ovirt-devel mailing list