Darryl L. Pierce
2008-Aug-18 20:48 UTC
[Ovirt-devel] [PATCH] Enables the generation of a configuration file for a managed node.
The configuration is generated from the contents of the nics table. The
managed node then downloads that configuration after completing the
identification and applies those changes.
What this needs is integration with the WUI itself, to generate the file
when the admin modifies the NIC for the host.
Signed-off-by: Darryl L. Pierce <dpierce at redhat.com>
---
ovirt-managed-node/src/gather.c | 2 +
ovirt-managed-node/src/ovirt-identify-node.h | 1 +
ovirt-managed-node/src/protocol.c | 3 +-
wui/src/host-browser/host-browser.rb | 582 ++++++++++----------
wui/src/host-browser/test-host-browser-identify.rb | 490 +++++++++--------
wui/src/lib/managed_node_configuration.rb | 58 ++
.../test/unit/managed_node_configuration_test.rb | 88 +++
7 files changed, 692 insertions(+), 532 deletions(-)
create mode 100644 wui/src/lib/managed_node_configuration.rb
create mode 100644 wui/src/test/unit/managed_node_configuration_test.rb
diff --git a/ovirt-managed-node/src/gather.c b/ovirt-managed-node/src/gather.c
index 39be6fd..7fa0992 100644
--- a/ovirt-managed-node/src/gather.c
+++ b/ovirt-managed-node/src/gather.c
@@ -205,6 +205,8 @@ get_nic_data(char *nic, nic_info_ptr nic_info)
interface libhal_device_get_property_string(hal_ctx, nic,
"net.interface",
&dbus_error);
+ snprintf(nic_info->interface_name, BUFFER_LENGTH, "%s",
interface);
+
bzero(&ifr, sizeof(struct ifreq));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
diff --git a/ovirt-managed-node/src/ovirt-identify-node.h
b/ovirt-managed-node/src/ovirt-identify-node.h
index c595891..b2814fa 100644
--- a/ovirt-managed-node/src/ovirt-identify-node.h
+++ b/ovirt-managed-node/src/ovirt-identify-node.h
@@ -67,6 +67,7 @@ typedef struct _nic_info {
char mac_address[BUFFER_LENGTH];
char bandwidth[BUFFER_LENGTH];
char ip_address[BUFFER_LENGTH];
+ char interface_name[BUFFER_LENGTH];
struct _nic_info* next;
} t_nic_info;
diff --git a/ovirt-managed-node/src/protocol.c
b/ovirt-managed-node/src/protocol.c
index 131bb38..d5c5fac 100644
--- a/ovirt-managed-node/src/protocol.c
+++ b/ovirt-managed-node/src/protocol.c
@@ -181,7 +181,8 @@ send_nic_details(void)
if (!(get_text("NICINFO?")) &&
(!send_value("MAC", current->mac_address)) &&
- (!send_value("BANDWIDTH", current->bandwidth))) {
+ (!send_value("BANDWIDTH", current->bandwidth))
&&
+ (!send_value("IFACE_NAME", current->interface_name)))
{
send_text("ENDNIC");
result = get_text("ACK NIC");
}
diff --git a/wui/src/host-browser/host-browser.rb
b/wui/src/host-browser/host-browser.rb
index 881b2ae..26981fd 100755
--- a/wui/src/host-browser/host-browser.rb
+++ b/wui/src/host-browser/host-browser.rb
@@ -39,361 +39,369 @@ $logfile = '/var/log/ovirt-wui/host-browser.log'
# about the node and then updates the list of active nodes for the WUI.
#
class HostBrowser
- attr_accessor :logfile
- attr_accessor :keytab_dir
- attr_accessor :keytab_filename
-
- def initialize(session)
- @session = session
- @log_prefix = "[#{session.peeraddr[3]}] "
- @keytab_dir = '/usr/share/ipa/html/'
- end
-
- # Ensures the conversation starts properly.
- #
- def begin_conversation
- puts "#{@log_prefix} Begin conversation" unless
defined?(TESTING)
- @session.write("HELLO?\n")
-
- response = @session.readline.chomp
- raise Exception.new("received #{response}, expected HELLO!")
unless response == "HELLO!"
- end
-
- # Retrieves the mode request from the remote system.
- #
- def get_mode
- puts "#{@log_prefix} Determining the runtime mode." unless
defined?(TESTING)
- @session.write("MODE?\n")
- response = @session.readline.chomp
- puts "#{@log_prefix} MODE=#{response}" unless
defined?(TESTING)
+ attr_accessor :logfile
+ attr_accessor :keytab_dir
+ attr_accessor :keytab_filename
+
+ def initialize(connection)
+ @connection = connection
+ @log_prefix = "[#{connection.peeraddr[3]}] "
+ @keytab_dir = '/usr/share/ipa/html/'
+ end
+
+ # Ensures the conversation starts properly.
+ #
+ def begin_conversation
+ puts "#{@log_prefix} Begin conversation" unless defined?(TESTING)
+ @connection.write("HELLO?\n")
+
+ response = @connection.readline.chomp
+ raise Exception.new("received #{response}, expected HELLO!")
unless response == "HELLO!"
+ end
+
+ # Retrieves the mode request from the remote system.
+ #
+ def get_mode
+ puts "#{@log_prefix} Determining the runtime mode." unless
defined?(TESTING)
+ @connection.write("MODE?\n")
+ response = @connection.readline.chomp
+ puts "#{@log_prefix} MODE=#{response}" unless defined?(TESTING)
+
+ response
+ end
+
+ # Requests node information from the remote system.
+ #
+ def get_remote_info
+ puts "#{@log_prefix} Begin remote info collection" unless
defined?(TESTING)
+ result = Hash.new
+ result['HOSTNAME'] = @connection.peeraddr[2]
+ result['IPADDR'] = @connection.peeraddr[3]
+
+ @connection.write("INFO?\n")
+
+ loop do
+ info = @connection.readline.chomp
+
+ puts "Received info='#{info}'"
+
+ break if info == "ENDINFO"
+
+ case info
+ when "CPU"
+ cpu = get_cpu_info
+ cpu_info = result['CPUINFO']
+
+ if(cpu_info == nil)
+ cpu_info = Array.new
+ result['CPUINFO'] = cpu_info
+ end
- response
- end
+ cpu_info << cpu
+
+ when "NIC"
+ nic = get_nic_info
+ nic_info = result['NICINFO']
- # Requests node information from the remote system.
- #
- def get_remote_info
- puts "#{@log_prefix} Begin remote info collection" unless
defined?(TESTING)
- result = Hash.new
- result['HOSTNAME'] = @session.peeraddr[2]
- result['IPADDR'] = @session.peeraddr[3]
+ if(nic_info == nil)
+ nic_info = Array.new
+ result['NICINFO'] = nic_info
+ end
- @session.write("INFO?\n")
+ nic_info << nic
+
+ else
+ raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
- loop do
- info = @session.readline.chomp
+ key, value = info.split("=")
- puts "Received info='#{info}'"
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- break if info == "ENDINFO"
+ @connection.write("ACK #{key}\n")
+ end
+ end
- case info
- when "CPU"
- cpu = get_cpu_info
- cpu_info = result['CPUINFO']
+ return result
+ end
- if(cpu_info == nil)
- cpu_info = Array.new
- result['CPUINFO'] = cpu_info
- end
+ # Extracts CPU details from the managed node.
+ #
+ def get_cpu_info
+ puts "Begin receiving CPU details"
- cpu_info << cpu
- when "NIC"
- nic = get_nic_info
- nic_info = result['NICINFO']
+ result = Hash.new
- if(nic_info == nil)
- nic_info = Array.new
- result['NICINFO'] = nic_info
- end
+ @connection.write("CPUINFO?\n")
- nic_info << nic
- else
+ loop do
+ info = @connection.readline.chomp
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ break if info == "ENDCPU"
- key, value = info.split("=")
+ raise Exception.new("ERRINFO! Excepted key=value : #{info}\n")
unless info =~ /[\w]+[\s]*=[\w]/
- puts "#{@log_prefix} ::Received - #{key}:#{value}"
unless defined?(TESTING)
- result[key] = value
+ key, value = info.split("=")
- @session.write("ACK #{key}\n")
- end
- end
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- return result
+ @connection.write("ACK #{key}\n")
end
- # Extracts CPU details from the managed node.
- #
- def get_cpu_info
- puts "Begin receiving CPU details"
+ @connection.write("ACK CPU\n");
- result = Hash.new
+ return result
+ end
- @session.write("CPUINFO?\n")
+ # Extracts NIC details from the managed node.
+ #
+ def get_nic_info
+ puts "Begin receiving NIC details"
- loop do
- info = @session.readline.chomp
+ result = Hash.new
- break if info == "ENDCPU"
+ @connection.write("NICINFO?\n")
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ loop do
+ info = @connection.readline.chomp
- key, value = info.split("=")
+ break if info == "ENDNIC"
- puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
- result[key] = value
+ raise Exception.new("ERRINFO! Excepted key=value : #{info}\n")
unless info =~ /[\w]+[\s]*=[\w]/
- @session.write("ACK #{key}\n")
- end
+ key, value = info.split("=")
- @session.write("ACK CPU\n");
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- return result
+ @connection.write("ACK #{key}\n")
end
- # Extracts NIC details from the managed node.
- #
- def get_nic_info
- puts "Begin receiving NIC details"
-
- result = Hash.new
-
- @session.write("NICINFO?\n")
+ @connection.write("ACK NIC\n");
+
+ return result
+ end
+
+ # Writes the supplied host information to the database.
+ #
+ def write_host_info(host_info)
+ ensure_present(host_info,'HOSTNAME')
+ ensure_present(host_info,'ARCH')
+ ensure_present(host_info,'MEMSIZE')
+ ensure_present(host_info,'CPUINFO')
+ ensure_present(host_info,'NICINFO')
+
+ cpu_info = host_info['CPUINFO']
+ nic_info = host_info['NICINFO']
+
+ cpu_info.each do |cpu|
+ ensure_present(cpu,'CPUNUM')
+ ensure_present(cpu,'CORENUM')
+ ensure_present(cpu,'NUMCORES')
+ ensure_present(cpu,'VENDOR')
+ ensure_present(cpu,'MODEL')
+ ensure_present(cpu,'FAMILY')
+ ensure_present(cpu,'CPUIDLVL')
+ ensure_present(cpu,'SPEED')
+ ensure_present(cpu,'CACHE')
+ ensure_present(cpu,'FLAGS')
+ end
+
+ nic_info.each do |nic|
+ ensure_present(nic, 'MAC')
+ ensure_present(nic, 'BANDWIDTH')
+ ensure_present(nic, 'IFACE_NAME')
+ end
- loop do
- info = @session.readline.chomp
+ puts "Searching for existing host record..." unless
defined?(TESTING)
+ host = Host.find(:first, :conditions => ["hostname = ?",
host_info['HOSTNAME']])
+
+ if host == nil
+ begin
+ puts "Creating a new record for
#{host_info['HOSTNAME']}..." unless defined?(TESTING)
+
+ host = Host.create(
+ "uuid" => host_info['UUID'],
+ "hostname" => host_info['HOSTNAME'],
+ "hypervisor_type" =>
host_info['HYPERVISOR_TYPE'],
+ "arch" => host_info['ARCH'],
+ "memory" => host_info['MEMSIZE'],
+ "is_disabled" => 0,
+ "hardware_pool" => HardwarePool.get_default_pool,
+ # Let host-status mark it available when it
+ # successfully connects to it via libvirt.
+ "state" => Host::STATE_UNAVAILABLE)
+ rescue Exception => error
+ puts "Error while creating record: #{error.message}" unless
defined?(TESTING)
+ end
+ else
+ host.uuid = host_info['UUID']
+ host.hostname = host_info['HOSTNAME']
+ host.arch = host_info['ARCH']
+ host.memory = host_info['MEMSIZE']
+ end
- break if info == "ENDNIC"
+ # delete an existing CPUs and create new ones based on the data
+ puts "Deleting any existing CPUs"
+ Cpu.delete_all(['host_id = ?', host.id])
+
+ puts "Saving new CPU records"
+ cpu_info.collect do |cpu|
+ detail = Cpu.new(
+ "cpu_number" => cpu['CPUNUM'],
+ "core_number" => cpu['CORENUM]'],
+ "number_of_cores" => cpu['NUMCORES'],
+ "vendor" => cpu['VENDOR'],
+ "model" => cpu['MODEL'],
+ "family" => cpu['FAMILY'],
+ "cpuid_level" => cpu['CPUIDLVL'],
+ "speed" => cpu['SPEED'],
+ "cache" => cpu['CACHE'],
+ "flags" => cpu['FLAGS'])
+
+ host.cpus << detail
+ end
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ # Update the NIC details for this host:
+ # -if the NIC exists, then update the IP address
+ # -if the NIC does not exist, create it
+ # -any nic not in this list is deleted
- key, value = info.split("=")
+ puts "Updating NIC records for the node"
+ nics = Array.new
- puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
- result[key] = value
+ host.nics.collect do |nic|
+ found = false
- @session.write("ACK #{key}\n")
+ nic_info.collect do |detail|
+ # if we have a match, then update the database and remove
+ # the received data to avoid creating a dupe later
+ if detail['MAC'] == nic.mac
+ nic_info.delete(detail)
end
+ end
- @session.write("ACK NIC\n");
-
- return result
+ # if the record wasn't found, then remove it from the database
+ unless found
+ host.nics.delete(nic)
+ nic.destroy
+ end
end
- # Writes the supplied host information to the database.
- #
- def write_host_info(host_info)
- ensure_present(host_info,'HOSTNAME')
- ensure_present(host_info,'ARCH')
- ensure_present(host_info,'MEMSIZE')
- ensure_present(host_info,'CPUINFO')
- ensure_present(host_info,'NICINFO')
-
- cpu_info = host_info['CPUINFO']
- nic_info = host_info['NICINFO']
-
- cpu_info.each do |cpu|
- ensure_present(cpu,'CPUNUM')
- ensure_present(cpu,'CORENUM')
- ensure_present(cpu,'NUMCORES')
- ensure_present(cpu,'VENDOR')
- ensure_present(cpu,'MODEL')
- ensure_present(cpu,'FAMILY')
- ensure_present(cpu,'CPUIDLVL')
- ensure_present(cpu,'SPEED')
- ensure_present(cpu,'CACHE')
- ensure_present(cpu,'FLAGS')
- end
+ # iterate over any nics left and create new records for them.
- puts "Searching for existing host record..." unless
defined?(TESTING)
- host = Host.find(:first, :conditions => ["hostname = ?",
host_info['HOSTNAME']])
-
- if host == nil
- begin
- puts "Creating a new record for
#{host_info['HOSTNAME']}..." unless defined?(TESTING)
-
- host = Host.create(
- "uuid" =>
host_info['UUID'],
- "hostname" =>
host_info['HOSTNAME'],
- "hypervisor_type" =>
host_info['HYPERVISOR_TYPE'],
- "arch" =>
host_info['ARCH'],
- "memory" =>
host_info['MEMSIZE'],
- "is_disabled" => 0,
- "hardware_pool" =>
HardwarePool.get_default_pool,
- # Let host-status mark it available when it
- # successfully connects to it via libvirt.
- "state" => Host::STATE_UNAVAILABLE)
- rescue Exception => error
- puts "Error while creating record: #{error.message}"
unless defined?(TESTING)
- end
- else
- host.uuid = host_info['UUID']
- host.hostname = host_info['HOSTNAME']
- host.arch = host_info['ARCH']
- host.memory = host_info['MEMSIZE']
- end
+ nic_info.collect do |nic|
+ puts "Creating a new nic..."
+ detail = Nic.new(
+ 'mac' => nic['MAC'],
+ 'bandwidth' => nic['BANDWIDTH'],
+ 'iface_name' => nic['IFACE_NAME'],
+ 'usage_type' => 1)
- # delete an existing CPUs and create new ones based on the data
- puts "Deleting any existing CPUs"
- Cpu.delete_all(['host_id = ?', host.id])
-
- puts "Saving new CPU records"
- cpu_info.collect do |cpu|
- detail = Cpu.new(
- "cpu_number" => cpu['CPUNUM'],
- "core_number" => cpu['CORENUM]'],
- "number_of_cores" => cpu['NUMCORES'],
- "vendor" => cpu['VENDOR'],
- "model" => cpu['MODEL'],
- "family" => cpu['FAMILY'],
- "cpuid_level" => cpu['CPUIDLVL'],
- "speed" => cpu['SPEED'],
- "cache" => cpu['CACHE'],
- "flags" => cpu['FLAGS'])
-
- host.cpus << detail
- end
-
- # Update the NIC details for this host:
- # -if the NIC exists, then update the IP address
- # -if the NIC does not exist, create it
- # -any nic not in this list is deleted
-
- puts "Updating NIC records for the node"
- nics = Array.new
-
- host.nics.collect do |nic|
- found = false
-
- nic_info.collect do |detail|
- # if we have a match, then update the database and remove
- # the received data to avoid creating a dupe later
- if detail['MAC'] == nic.mac
- nic_info.delete(detail)
- end
- end
-
- # if the record wasn't found, then remove it from the database
- unless found
- host.nics.delete(nic)
- nic.destroy
- end
- end
-
- # iterate over any nics left and create new records for them.
-
- nic_info.collect do |nic|
- puts "Creating a new nic..."
- detail = Nic.new(
- 'mac' => nic['MAC'],
- 'bandwidth' => nic['BANDWIDTH'],
- 'usage_type' => 1)
+ host.nics << detail
+ end
- host.nics << detail
- end
+ host.save!
- host.save!
+ return host
+ end
- return host
- end
+ # Creates a keytab if one is needed, returning the filename.
+ #
+ def create_keytab(hostname, ipaddress, krb5_arg = nil)
+ krb5 = krb5_arg || Krb5.new
- # Creates a keytab if one is needed, returning the filename.
- #
- def create_keytab(hostname, ipaddress, krb5_arg = nil)
- krb5 = krb5_arg || Krb5.new
+ default_realm = krb5.get_default_realm
+ libvirt_princ = 'libvirt/' + hostname + '@' + default_realm
+ outfile = ipaddress + '-libvirt.tab'
+ @keytab_filename = @keytab_dir + outfile
- default_realm = krb5.get_default_realm
- libvirt_princ = 'libvirt/' + hostname + '@' +
default_realm
- outfile = ipaddress + '-libvirt.tab'
- @keytab_filename = @keytab_dir + outfile
+ # TODO need a way to test this portion
+ unless (defined? TESTING) || File.exists?(@keytab_filename)
+ # TODO replace with Kr5Auth when it supports admin actions
+ puts "Writing keytab file: #{@keytab_filename}" unless
defined?(TESTING)
+ kadmin_local('addprinc -randkey ' + libvirt_princ)
+ kadmin_local('ktadd -k ' + @keytab_filename + ' ' +
libvirt_princ)
- # TODO need a way to test this portion
- unless (defined? TESTING) || File.exists?(@keytab_filename)
- # TODO replace with Kr5Auth when it supports admin actions
- puts "Writing keytab file: #{@keytab_filename}" unless
defined?(TESTING)
- kadmin_local('addprinc -randkey ' + libvirt_princ)
- kadmin_local('ktadd -k ' + @keytab_filename + ' ' +
libvirt_princ)
+ File.chmod(0644, at keytab_filename)
+ end
- File.chmod(0644, at keytab_filename)
- end
+ hostname = `hostname -f`.chomp
- hostname = `hostname -f`.chomp
+ @connection.write("KTAB
http://#{hostname}/ipa/config/#{outfile}\n")
- @session.write("KTAB
http://#{hostname}/ipa/config/#{outfile}\n")
+ response = @connection.readline.chomp
- response = @session.readline.chomp
+ raise Exception.new("ERRINFO! No keytab acknowledgement") unless
response == "ACK"
+ end
- raise Exception.new("ERRINFO! No keytab acknowledgement")
unless response == "ACK"
- end
+ # Ends the conversation, notifying the user of the key version number.
+ #
+ def end_conversation
+ puts "#{@log_prefix} Ending conversation" unless
defined?(TESTING)
- # Ends the conversation, notifying the user of the key version number.
- #
- def end_conversation
- puts "#{@log_prefix} Ending conversation" unless
defined?(TESTING)
+ @connection.write("BYE\n");
+ end
- @session.write("BYE\n");
- end
+ private
- private
+ # Private method to ensure that a required field is present.
+ #
+ def ensure_present(info,key)
+ raise Exception.new("ERROR! Missing '#{key}'...") if
info[key] == nil
+ end
- # Private method to ensure that a required field is present.
- #
- def ensure_present(info,key)
- raise Exception.new("ERROR! Missing '#{key}'...") if
info[key] == nil
- end
-
- # Executes an external program to support the keytab function.
- #
- def kadmin_local(command)
- system("/usr/kerberos/sbin/kadmin.local -q '" + command +
"'")
- end
+ # Executes an external program to support the keytab function.
+ #
+ def kadmin_local(command)
+ system("/usr/kerberos/sbin/kadmin.local -q '" + command +
"'")
+ end
end
def entry_point(server)
- while(session = server.accept)
- child = fork do
- remote = session.peeraddr[2]
-
- puts "Connected to #{remote}" unless defined?(TESTING)
-
- # This is needed because we just forked a new process
- # which now needs its own connection to the database.
- database_connect
+ while(session = server.accept)
+ child = fork do
+ remote = session.peeraddr[2]
- begin
- browser = HostBrowser.new(session)
+ puts "Connected to #{remote}" unless defined?(TESTING)
- browser.begin_conversation
- case browser.get_mode
- when "AWAKEN":
browser.create_keytab(remote,session.peeraddr[3])
- when "IDENTIFY":
browser.write_host_info(browser.get_remote_info)
- end
+ # This is needed because we just forked a new process
+ # which now needs its own connection to the database.
+ database_connect
- browser.end_conversation
- rescue Exception => error
- session.write("ERROR #{error.message}\n")
- puts "ERROR #{error.message}" unless
defined?(TESTING)
- end
+ begin
+ browser = HostBrowser.new(session)
- puts "Disconnected from #{remote}" unless
defined?(TESTING)
+ browser.begin_conversation
+ case browser.get_mode
+ when "AWAKEN":
browser.create_keytab(remote,session.peeraddr[3])
+ when "IDENTIFY":
browser.write_host_info(browser.get_remote_info)
end
- Process.detach(child)
+ browser.end_conversation
+ rescue Exception => error
+ session.write("ERROR #{error.message}\n")
+ puts "ERROR #{error.message}" unless defined?(TESTING)
+ end
+
+ puts "Disconnected from #{remote}" unless defined?(TESTING)
end
+
+ Process.detach(child)
+ end
end
unless defined?(TESTING)
- # The main entry point.
- #
- unless ARGV[0] == "-n"
- daemonize
- # redirect output to the log
- STDOUT.reopen $logfile, 'a'
- STDERR.reopen STDOUT
- end
-
- server = TCPServer.new("",12120)
- entry_point(server)
+ # The main entry point.
+ #
+ unless ARGV[0] == "-n"
+ daemonize
+ # redirect output to the log
+ STDOUT.reopen $logfile, 'a'
+ STDERR.reopen STDOUT
+ end
+
+ server = TCPServer.new("",12120)
+ entry_point(server)
end
diff --git a/wui/src/host-browser/test-host-browser-identify.rb
b/wui/src/host-browser/test-host-browser-identify.rb
index 7e672ce..e25497f 100755
--- a/wui/src/host-browser/test-host-browser-identify.rb
+++ b/wui/src/host-browser/test-host-browser-identify.rb
@@ -27,257 +27,259 @@ TESTING=true
require 'host-browser'
class TestHostBrowser < Test::Unit::TestCase
- def setup
- @session = flexmock('session')
- @session.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
-
- @browser = HostBrowser.new(@session)
- @browser.logfile = './unit-test.log'
-
- # default host info
- @host_info = {}
- @host_info['UUID'] = 'node1'
- @host_info['IPADDR'] = '192.168.2.2'
- @host_info['HOSTNAME'] = 'prod.corp.com'
- @host_info['ARCH'] = 'x86_64'
- @host_info['MEMSIZE'] = '16384'
- @host_info['DISABLED'] = '0'
-
- @host_info['NUMCPUS'] = '2'
-
- @host_info['CPUINFO'] = Array.new
- @host_info['CPUINFO'][0] = {}
- @host_info['CPUINFO'][0]['CPUNUM'] = '0'
- @host_info['CPUINFO'][0]['CORENUM'] = '0'
- @host_info['CPUINFO'][0]['NUMCORES'] = '2'
- @host_info['CPUINFO'][0]['VENDOR'] =
'GenuineIntel'
- @host_info['CPUINFO'][0]['MODEL'] = '15'
- @host_info['CPUINFO'][0]['FAMILY'] = '6'
- @host_info['CPUINFO'][0]['CPUIDLVL'] = '10'
- @host_info['CPUINFO'][0]['SPEED'] = '3'
- @host_info['CPUINFO'][0]['CACHE'] = '4096
kb'
- @host_info['CPUINFO'][0]['FLAGS'] = 'fpu vme de
pse tsc msr pae \
+ def setup
+ @connection = flexmock('connection')
+ @connection.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
+
+ @browser = HostBrowser.new(@connection)
+ @browser.logfile = './unit-test.log'
+
+ # default host info
+ @host_info = {}
+ @host_info['UUID'] = 'node1'
+ @host_info['IPADDR'] = '192.168.2.2'
+ @host_info['HOSTNAME'] = 'prod.corp.com'
+ @host_info['ARCH'] = 'x86_64'
+ @host_info['MEMSIZE'] = '16384'
+ @host_info['DISABLED'] = '0'
+
+ @host_info['NUMCPUS'] = '2'
+
+ @host_info['CPUINFO'] = Array.new
+ @host_info['CPUINFO'][0] = {}
+ @host_info['CPUINFO'][0]['CPUNUM'] = '0'
+ @host_info['CPUINFO'][0]['CORENUM'] = '0'
+ @host_info['CPUINFO'][0]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][0]['VENDOR'] =
'GenuineIntel'
+ @host_info['CPUINFO'][0]['MODEL'] = '15'
+ @host_info['CPUINFO'][0]['FAMILY'] = '6'
+ @host_info['CPUINFO'][0]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][0]['SPEED'] = '3'
+ @host_info['CPUINFO'][0]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][0]['FLAGS'] = 'fpu vme de pse
tsc msr pae \
mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
- @host_info['CPUINFO'][1] = {}
- @host_info['CPUINFO'][1]['CPUNUM'] = '1'
- @host_info['CPUINFO'][1]['CORENUM'] = '1'
- @host_info['CPUINFO'][1]['NUMCORES'] = '2'
- @host_info['CPUINFO'][1]['VENDOR'] =
'GenuineIntel'
- @host_info['CPUINFO'][1]['MODEL'] = '15'
- @host_info['CPUINFO'][1]['FAMILY'] = '6'
- @host_info['CPUINFO'][1]['CPUIDLVL'] = '10'
- @host_info['CPUINFO'][1]['SPEED'] = '3'
- @host_info['CPUINFO'][1]['CACHE'] = '4096
kb'
- @host_info['CPUINFO'][1]['FLAGS'] = 'fpu vme de
pse tsc msr pae \
+ @host_info['CPUINFO'][1] = {}
+ @host_info['CPUINFO'][1]['CPUNUM'] = '1'
+ @host_info['CPUINFO'][1]['CORENUM'] = '1'
+ @host_info['CPUINFO'][1]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][1]['VENDOR'] =
'GenuineIntel'
+ @host_info['CPUINFO'][1]['MODEL'] = '15'
+ @host_info['CPUINFO'][1]['FAMILY'] = '6'
+ @host_info['CPUINFO'][1]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][1]['SPEED'] = '3'
+ @host_info['CPUINFO'][1]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][1]['FLAGS'] = 'fpu vme de pse
tsc msr pae \
mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
- @host_info['NICINFO'] = Array.new
- @host_info['NICINFO'][0] = {}
- @host_info['NICINFO'][0]['MAC'] =
'00:11:22:33:44:55'
- @host_info['NICINFO'][0]['BANDWIDTH'] = '100'
-
- @host_info['NICINFO'][1] = {}
- @host_info['NICINFO'][1]['MAC'] =
'00:77:11:77:19:65'
- @host_info['NICINFO'][1]['BANDWIDTH'] = '100'
- end
-
- # Ensures that the server is satisfied if the remote system is
- # making a wakeup call.
- #
- def test_get_mode_with_awaken_request
-
@session.should_receive(:write).with("MODE?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"IDENTIFY\n" }
-
- result = @browser.get_mode()
-
- assert_equal "IDENTIFY", result, "method did not return
the right value"
- end
-
- # Ensures that, if an info field is missing a key, the server raises
- # an exception.
- #
- def test_get_info_with_missing_key
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"=value1\n" }
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that, if an info field is missing a value, the server raises
- # an exception.
- #
- def test_get_info_with_missing_value
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "key1=\n"
}
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that, if the server gets a poorly formed ending statement, it
- # raises an exception.
- #
- def test_get_info_with_invalid_end
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDIFNO\n" }
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that a well-formed transaction works as expected.
- #
- def test_get_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 4,info.keys.size, "Should contain four keys"
- assert info.include?("IPADDR")
- assert info.include?("HOSTNAME")
- assert info.include?("key1")
- assert info.include?("key2")
- end
-
- # Ensures that the server is fine when no UUID is present.
- #
- def test_write_host_info_with_missing_uuid
- @host_info['UUID'] = nil
-
- assert_nothing_raised { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the hostname is missing, the server
- # raises an exception.
- #
- def test_write_host_info_with_missing_hostname
- @host_info['HOSTNAME'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the architecture is missing, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_arch
- @host_info['ARCH'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the memory size is missing, the server raises an
- # exception.
- #
- def test_write_host_info_info_with_missing_memsize
- @host_info['MEMSIZE'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if no cpu info was available, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_cpuinfo
- @host_info['CPUINFO'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if no NIC info was available, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_nicinfo
- @host_info['NICINFO'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures the browser can properly parse the CPU details.
- #
- def test_parse_cpu_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?("CPUINFO")
- end
-
- # Ensures the browser can properly parse the CPU details of two CPUs.
- #
- def test_parse_cpu_info_with_two_entries
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
-
- # CPU 0
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
-
- # CPU 1
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key3=value3\n" }
- @session.should_receive(:write).with("ACK
key3\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key4=value4\n" }
- @session.should_receive(:write).with("ACK
key4\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
-
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?('CPUINFO')
- assert_equal 2, info['CPUINFO'].size, "Should contain
details for two CPUs"
- assert_not_nil info['CPUINFO'][0]['key1']
- assert_not_nil info['CPUINFO'][0]['key2']
- assert_not_nil info['CPUINFO'][1]['key3']
- assert_not_nil info['CPUINFO'][1]['key4']
- end
-
- # Ensures the browser can properly parse the details for a NIC.
- #
- def test_parse_nic_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "NIC\n" }
-
@session.should_receive(:write).with("NICINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDNIC\n" }
- @session.should_receive(:write).with("ACK
NIC\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?("NICINFO")
- end
+ @host_info['NICINFO'] = Array.new
+ @host_info['NICINFO'] << {
+ 'MAC' => '00:11:22:33:44:55',
+ 'BANDWIDTH' => '100',
+ 'IFACE_NAME' => 'eth0'}
+
+ @host_info['NICINFO'] << {
+ 'MAC' => '00:77:11:77:19:65',
+ 'BANDWIDTH' => '100',
+ 'IFACE_NAME' => 'eth01'}
+ end
+
+ # Ensures that the server is satisfied if the remote system is
+ # making a wakeup call.
+ #
+ def test_get_mode_with_awaken_request
+ @connection.should_receive(:write).with("MODE?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"IDENTIFY\n" }
+
+ result = @browser.get_mode()
+
+ assert_equal "IDENTIFY", result, "method did not return the
right value"
+ end
+
+ # Ensures that, if an info field is missing a key, the server raises
+ # an exception.
+ #
+ def test_get_info_with_missing_key
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"=value1\n" }
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that, if an info field is missing a value, the server raises
+ # an exception.
+ #
+ def test_get_info_with_missing_value
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "key1=\n"
}
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that, if the server gets a poorly formed ending statement, it
+ # raises an exception.
+ #
+ def test_get_info_with_invalid_end
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDIFNO\n" }
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that a well-formed transaction works as expected.
+ #
+ def test_get_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 4,info.keys.size, "Should contain four keys"
+ assert info.include?("IPADDR")
+ assert info.include?("HOSTNAME")
+ assert info.include?("key1")
+ assert info.include?("key2")
+ end
+
+ # Ensures that the server is fine when no UUID is present.
+ #
+ def test_write_host_info_with_missing_uuid
+ @host_info['UUID'] = nil
+
+ assert_nothing_raised { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the hostname is missing, the server
+ # raises an exception.
+ #
+ def test_write_host_info_with_missing_hostname
+ @host_info['HOSTNAME'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the architecture is missing, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_arch
+ @host_info['ARCH'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the memory size is missing, the server raises an
+ # exception.
+ #
+ def test_write_host_info_info_with_missing_memsize
+ @host_info['MEMSIZE'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if no cpu info was available, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_cpuinfo
+ @host_info['CPUINFO'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if no NIC info was available, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_nicinfo
+ @host_info['NICINFO'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures the browser can properly parse the CPU details.
+ #
+ def test_parse_cpu_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?("CPUINFO")
+ end
+
+ # Ensures the browser can properly parse the CPU details of two CPUs.
+ #
+ def test_parse_cpu_info_with_two_entries
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+
+ # CPU 0
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+
+ # CPU 1
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key3=value3\n" }
+ @connection.should_receive(:write).with("ACK
key3\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key4=value4\n" }
+ @connection.should_receive(:write).with("ACK
key4\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?('CPUINFO')
+ assert_equal 2, info['CPUINFO'].size, "Should contain details
for two CPUs"
+ assert_not_nil info['CPUINFO'][0]['key1']
+ assert_not_nil info['CPUINFO'][0]['key2']
+ assert_not_nil info['CPUINFO'][1]['key3']
+ assert_not_nil info['CPUINFO'][1]['key4']
+ end
+
+ # Ensures the browser can properly parse the details for a NIC.
+ #
+ def test_parse_nic_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "NIC\n" }
+
@connection.should_receive(:write).with("NICINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDNIC\n"
}
+ @connection.should_receive(:write).with("ACK
NIC\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?("NICINFO")
+ end
end
diff --git a/wui/src/lib/managed_node_configuration.rb
b/wui/src/lib/managed_node_configuration.rb
new file mode 100644
index 0000000..0bb34f0
--- /dev/null
+++ b/wui/src/lib/managed_node_configuration.rb
@@ -0,0 +1,58 @@
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+# +ManagedNodeConfiguration+ takes in the description for a managed node and,
+# from that, generates the configuration file that is consumed the next time
+# the managed node starts up.
+#
+
+require 'stringio'
+
+$: << File.join(File.dirname(__FILE__), "../dutils")
+$: << File.join(File.dirname(__FILE__), "../")
+
+class ManagedNodeConfiguration
+ @network_interfaces
+ @file = nil
+
+ attr_accessor :hostname
+
+ def initialize(host)
+ @host = host
+ end
+
+ NIC_ENTRY_PREFIX='/files/etc/sysconfig/network-scripts'
+
+ def generate
+ result = StringIO.new
+
+ @host.nics.each do |nic|
+ result.puts "rm #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}"
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/DEVICE
#{nic.iface_name}"
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/IPADDR
#{nic.ip_addr}" if nic.ip_addr
+ result.puts "set
#{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/BOOTPROTO dhcp" if
nic.ip_addr == nil
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/BRIDGE
#{nic.bridge}" if nic.bridge
+ end
+
+ result.puts "save"
+
+ result.string
+ end
+end
+
diff --git a/wui/src/test/unit/managed_node_configuration_test.rb
b/wui/src/test/unit/managed_node_configuration_test.rb
new file mode 100644
index 0000000..bfbfdac
--- /dev/null
+++ b/wui/src/test/unit/managed_node_configuration_test.rb
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+$:.unshift File.join(File.dirname(__FILE__),'..','lib')
+
+# require File.dirname(__FILE__) + '/../test/test_helper'
+require 'test/unit'
+require 'managed_node_configuration'
+require 'dutils'
+
+# Performs unit tests on the +ManagedNodeConfiguration+ class.
+#
+class ManagedNodeConfigurationTest < Test::Unit::TestCase
+ def setup
+ @host = Host.new
+ @config = ManagedNodeConfiguration.new(@host)
+ end
+
+
+ # Ensures that network interfaces uses DHCP when no IP address is specified.
+ #
+ def test_generate_with_no_ip_address
+ @host.nics << Nic.new(:iface_name => 'eth0')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BOOTPROTO dhcp
+save
+HERE
+
+ result = @config.generate
+
+ assert_equal expected, result
+ end
+
+ # Ensures that network interfaces use the IP address when it's provided.
+ #
+ def test_generate_with_ip_address
+ @host.nics << Nic.new(:iface_name => 'eth0', :ip_addr
=> '192.168.2.1')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/IPADDR 192.168.2.1
+save
+HERE
+
+ result = @config.generate
+
+ assert_equal expected, result
+ end
+
+ # Ensures the bridge is added to the configuration if one is defined.
+ #
+ def test_generate_with_bridge
+ @host.nics << Nic.new(:iface_name => 'eth0', :bridge =>
'ovirtbr0')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BOOTPROTO dhcp
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BRIDGE ovirtbr0
+save
+HERE
+
+ result = @config.generate
+
+ assert_equal expected, result
+ end
+
+end
--
1.5.5.1
Darryl L. Pierce
2008-Aug-19 15:26 UTC
[Ovirt-devel] [PATCH] Enables the generation of a configuration file for a managed node.
The configuration is generated from the contents of the nics table. The
managed node then downloads that configuration after completing the
identification and applies those changes.
Signed-off-by: Darryl L. Pierce <dpierce at redhat.com>
---
ovirt-managed-node/src/gather.c | 2 +
ovirt-managed-node/src/ovirt-identify-node.h | 1 +
ovirt-managed-node/src/protocol.c | 3 +-
wui/src/app/controllers/application.rb | 2 +-
wui/src/app/controllers/nic_controller.rb | 13 +-
wui/src/config/environment.rb | 2 +
wui/src/db/migrate/015_add_iface_name_to_nics.rb | 9 +
wui/src/host-browser/host-browser.rb | 582 ++++++++++----------
wui/src/host-browser/test-host-browser-identify.rb | 490 +++++++++--------
wui/src/lib/managed_node_configuration.rb | 49 ++
.../test/unit/managed_node_configuration_test.rb | 87 +++
11 files changed, 706 insertions(+), 534 deletions(-)
create mode 100644 wui/src/db/migrate/015_add_iface_name_to_nics.rb
create mode 100644 wui/src/lib/managed_node_configuration.rb
create mode 100644 wui/src/test/unit/managed_node_configuration_test.rb
diff --git a/ovirt-managed-node/src/gather.c b/ovirt-managed-node/src/gather.c
index 39be6fd..7fa0992 100644
--- a/ovirt-managed-node/src/gather.c
+++ b/ovirt-managed-node/src/gather.c
@@ -205,6 +205,8 @@ get_nic_data(char *nic, nic_info_ptr nic_info)
interface libhal_device_get_property_string(hal_ctx, nic,
"net.interface",
&dbus_error);
+ snprintf(nic_info->interface_name, BUFFER_LENGTH, "%s",
interface);
+
bzero(&ifr, sizeof(struct ifreq));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
diff --git a/ovirt-managed-node/src/ovirt-identify-node.h
b/ovirt-managed-node/src/ovirt-identify-node.h
index c595891..b2814fa 100644
--- a/ovirt-managed-node/src/ovirt-identify-node.h
+++ b/ovirt-managed-node/src/ovirt-identify-node.h
@@ -67,6 +67,7 @@ typedef struct _nic_info {
char mac_address[BUFFER_LENGTH];
char bandwidth[BUFFER_LENGTH];
char ip_address[BUFFER_LENGTH];
+ char interface_name[BUFFER_LENGTH];
struct _nic_info* next;
} t_nic_info;
diff --git a/ovirt-managed-node/src/protocol.c
b/ovirt-managed-node/src/protocol.c
index 131bb38..d5c5fac 100644
--- a/ovirt-managed-node/src/protocol.c
+++ b/ovirt-managed-node/src/protocol.c
@@ -181,7 +181,8 @@ send_nic_details(void)
if (!(get_text("NICINFO?")) &&
(!send_value("MAC", current->mac_address)) &&
- (!send_value("BANDWIDTH", current->bandwidth))) {
+ (!send_value("BANDWIDTH", current->bandwidth))
&&
+ (!send_value("IFACE_NAME", current->interface_name)))
{
send_text("ENDNIC");
result = get_text("ACK NIC");
}
diff --git a/wui/src/app/controllers/application.rb
b/wui/src/app/controllers/application.rb
index d653171..b27ddbe 100644
--- a/wui/src/app/controllers/application.rb
+++ b/wui/src/app/controllers/application.rb
@@ -35,7 +35,7 @@ class ApplicationController < ActionController::Base
before_filter :is_logged_in
def is_logged_in
- redirect_to (:controller => "login", :action =>
"login") unless get_login_user
+ redirect_to(:controller => "login", :action =>
"login") unless get_login_user
end
def get_login_user
diff --git a/wui/src/app/controllers/nic_controller.rb
b/wui/src/app/controllers/nic_controller.rb
index 85d4315..fef7c5b 100644
--- a/wui/src/app/controllers/nic_controller.rb
+++ b/wui/src/app/controllers/nic_controller.rb
@@ -18,9 +18,10 @@
# also available at http://www.gnu.org/copyleft/gpl.html.
class NicController < ApplicationController
+ after_filter :generate_configuration, :only => [:create, :edit, :update,
:destroy]
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
- :redirect_to => { :controller => 'dashboard' }
+ :redirect_to => { :controller => 'dashboard' }
def show
set_perms(@perm_obj)
@@ -44,8 +45,18 @@ class NicController < ApplicationController
def destroy
end
+
+ def generate_configuration
+ host = Host.find_by_id(params[:host_id])
+
+ File.open("#{MANAGED_NODE_CONFIGURATION_DIR}/#{host.hostname}",
"w") do |file|
+ # write the nic configuration
+ file.puts ManagedNodeConfiguration.generate(host)
+ end
+ end
private
+
#filter methods
def pre_new
flash[:notice] = 'Network Interfaces may not be edited via the web
UI'
diff --git a/wui/src/config/environment.rb b/wui/src/config/environment.rb
index ff6f6e8..57fd461 100644
--- a/wui/src/config/environment.rb
+++ b/wui/src/config/environment.rb
@@ -80,3 +80,5 @@ end
require 'gettext/rails'
gem 'cobbler'
require 'cobbler'
+
+MANAGED_NODE_CONFIGURATION_DIR = '/var/www/html/ovirt-cfgdb'
\ No newline at end of file
diff --git a/wui/src/db/migrate/015_add_iface_name_to_nics.rb
b/wui/src/db/migrate/015_add_iface_name_to_nics.rb
new file mode 100644
index 0000000..f1fb28d
--- /dev/null
+++ b/wui/src/db/migrate/015_add_iface_name_to_nics.rb
@@ -0,0 +1,9 @@
+class AddIfaceNameToNics < ActiveRecord::Migration
+ def self.up
+ add_column :nics, :iface_name, :string, :limit => 10
+ end
+
+ def self.down
+ remove_column :nics, :iface_name
+ end
+end
diff --git a/wui/src/host-browser/host-browser.rb
b/wui/src/host-browser/host-browser.rb
index 881b2ae..26981fd 100755
--- a/wui/src/host-browser/host-browser.rb
+++ b/wui/src/host-browser/host-browser.rb
@@ -39,361 +39,369 @@ $logfile = '/var/log/ovirt-wui/host-browser.log'
# about the node and then updates the list of active nodes for the WUI.
#
class HostBrowser
- attr_accessor :logfile
- attr_accessor :keytab_dir
- attr_accessor :keytab_filename
-
- def initialize(session)
- @session = session
- @log_prefix = "[#{session.peeraddr[3]}] "
- @keytab_dir = '/usr/share/ipa/html/'
- end
-
- # Ensures the conversation starts properly.
- #
- def begin_conversation
- puts "#{@log_prefix} Begin conversation" unless
defined?(TESTING)
- @session.write("HELLO?\n")
-
- response = @session.readline.chomp
- raise Exception.new("received #{response}, expected HELLO!")
unless response == "HELLO!"
- end
-
- # Retrieves the mode request from the remote system.
- #
- def get_mode
- puts "#{@log_prefix} Determining the runtime mode." unless
defined?(TESTING)
- @session.write("MODE?\n")
- response = @session.readline.chomp
- puts "#{@log_prefix} MODE=#{response}" unless
defined?(TESTING)
+ attr_accessor :logfile
+ attr_accessor :keytab_dir
+ attr_accessor :keytab_filename
+
+ def initialize(connection)
+ @connection = connection
+ @log_prefix = "[#{connection.peeraddr[3]}] "
+ @keytab_dir = '/usr/share/ipa/html/'
+ end
+
+ # Ensures the conversation starts properly.
+ #
+ def begin_conversation
+ puts "#{@log_prefix} Begin conversation" unless defined?(TESTING)
+ @connection.write("HELLO?\n")
+
+ response = @connection.readline.chomp
+ raise Exception.new("received #{response}, expected HELLO!")
unless response == "HELLO!"
+ end
+
+ # Retrieves the mode request from the remote system.
+ #
+ def get_mode
+ puts "#{@log_prefix} Determining the runtime mode." unless
defined?(TESTING)
+ @connection.write("MODE?\n")
+ response = @connection.readline.chomp
+ puts "#{@log_prefix} MODE=#{response}" unless defined?(TESTING)
+
+ response
+ end
+
+ # Requests node information from the remote system.
+ #
+ def get_remote_info
+ puts "#{@log_prefix} Begin remote info collection" unless
defined?(TESTING)
+ result = Hash.new
+ result['HOSTNAME'] = @connection.peeraddr[2]
+ result['IPADDR'] = @connection.peeraddr[3]
+
+ @connection.write("INFO?\n")
+
+ loop do
+ info = @connection.readline.chomp
+
+ puts "Received info='#{info}'"
+
+ break if info == "ENDINFO"
+
+ case info
+ when "CPU"
+ cpu = get_cpu_info
+ cpu_info = result['CPUINFO']
+
+ if(cpu_info == nil)
+ cpu_info = Array.new
+ result['CPUINFO'] = cpu_info
+ end
- response
- end
+ cpu_info << cpu
+
+ when "NIC"
+ nic = get_nic_info
+ nic_info = result['NICINFO']
- # Requests node information from the remote system.
- #
- def get_remote_info
- puts "#{@log_prefix} Begin remote info collection" unless
defined?(TESTING)
- result = Hash.new
- result['HOSTNAME'] = @session.peeraddr[2]
- result['IPADDR'] = @session.peeraddr[3]
+ if(nic_info == nil)
+ nic_info = Array.new
+ result['NICINFO'] = nic_info
+ end
- @session.write("INFO?\n")
+ nic_info << nic
+
+ else
+ raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
- loop do
- info = @session.readline.chomp
+ key, value = info.split("=")
- puts "Received info='#{info}'"
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- break if info == "ENDINFO"
+ @connection.write("ACK #{key}\n")
+ end
+ end
- case info
- when "CPU"
- cpu = get_cpu_info
- cpu_info = result['CPUINFO']
+ return result
+ end
- if(cpu_info == nil)
- cpu_info = Array.new
- result['CPUINFO'] = cpu_info
- end
+ # Extracts CPU details from the managed node.
+ #
+ def get_cpu_info
+ puts "Begin receiving CPU details"
- cpu_info << cpu
- when "NIC"
- nic = get_nic_info
- nic_info = result['NICINFO']
+ result = Hash.new
- if(nic_info == nil)
- nic_info = Array.new
- result['NICINFO'] = nic_info
- end
+ @connection.write("CPUINFO?\n")
- nic_info << nic
- else
+ loop do
+ info = @connection.readline.chomp
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ break if info == "ENDCPU"
- key, value = info.split("=")
+ raise Exception.new("ERRINFO! Excepted key=value : #{info}\n")
unless info =~ /[\w]+[\s]*=[\w]/
- puts "#{@log_prefix} ::Received - #{key}:#{value}"
unless defined?(TESTING)
- result[key] = value
+ key, value = info.split("=")
- @session.write("ACK #{key}\n")
- end
- end
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- return result
+ @connection.write("ACK #{key}\n")
end
- # Extracts CPU details from the managed node.
- #
- def get_cpu_info
- puts "Begin receiving CPU details"
+ @connection.write("ACK CPU\n");
- result = Hash.new
+ return result
+ end
- @session.write("CPUINFO?\n")
+ # Extracts NIC details from the managed node.
+ #
+ def get_nic_info
+ puts "Begin receiving NIC details"
- loop do
- info = @session.readline.chomp
+ result = Hash.new
- break if info == "ENDCPU"
+ @connection.write("NICINFO?\n")
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ loop do
+ info = @connection.readline.chomp
- key, value = info.split("=")
+ break if info == "ENDNIC"
- puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
- result[key] = value
+ raise Exception.new("ERRINFO! Excepted key=value : #{info}\n")
unless info =~ /[\w]+[\s]*=[\w]/
- @session.write("ACK #{key}\n")
- end
+ key, value = info.split("=")
- @session.write("ACK CPU\n");
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- return result
+ @connection.write("ACK #{key}\n")
end
- # Extracts NIC details from the managed node.
- #
- def get_nic_info
- puts "Begin receiving NIC details"
-
- result = Hash.new
-
- @session.write("NICINFO?\n")
+ @connection.write("ACK NIC\n");
+
+ return result
+ end
+
+ # Writes the supplied host information to the database.
+ #
+ def write_host_info(host_info)
+ ensure_present(host_info,'HOSTNAME')
+ ensure_present(host_info,'ARCH')
+ ensure_present(host_info,'MEMSIZE')
+ ensure_present(host_info,'CPUINFO')
+ ensure_present(host_info,'NICINFO')
+
+ cpu_info = host_info['CPUINFO']
+ nic_info = host_info['NICINFO']
+
+ cpu_info.each do |cpu|
+ ensure_present(cpu,'CPUNUM')
+ ensure_present(cpu,'CORENUM')
+ ensure_present(cpu,'NUMCORES')
+ ensure_present(cpu,'VENDOR')
+ ensure_present(cpu,'MODEL')
+ ensure_present(cpu,'FAMILY')
+ ensure_present(cpu,'CPUIDLVL')
+ ensure_present(cpu,'SPEED')
+ ensure_present(cpu,'CACHE')
+ ensure_present(cpu,'FLAGS')
+ end
+
+ nic_info.each do |nic|
+ ensure_present(nic, 'MAC')
+ ensure_present(nic, 'BANDWIDTH')
+ ensure_present(nic, 'IFACE_NAME')
+ end
- loop do
- info = @session.readline.chomp
+ puts "Searching for existing host record..." unless
defined?(TESTING)
+ host = Host.find(:first, :conditions => ["hostname = ?",
host_info['HOSTNAME']])
+
+ if host == nil
+ begin
+ puts "Creating a new record for
#{host_info['HOSTNAME']}..." unless defined?(TESTING)
+
+ host = Host.create(
+ "uuid" => host_info['UUID'],
+ "hostname" => host_info['HOSTNAME'],
+ "hypervisor_type" =>
host_info['HYPERVISOR_TYPE'],
+ "arch" => host_info['ARCH'],
+ "memory" => host_info['MEMSIZE'],
+ "is_disabled" => 0,
+ "hardware_pool" => HardwarePool.get_default_pool,
+ # Let host-status mark it available when it
+ # successfully connects to it via libvirt.
+ "state" => Host::STATE_UNAVAILABLE)
+ rescue Exception => error
+ puts "Error while creating record: #{error.message}" unless
defined?(TESTING)
+ end
+ else
+ host.uuid = host_info['UUID']
+ host.hostname = host_info['HOSTNAME']
+ host.arch = host_info['ARCH']
+ host.memory = host_info['MEMSIZE']
+ end
- break if info == "ENDNIC"
+ # delete an existing CPUs and create new ones based on the data
+ puts "Deleting any existing CPUs"
+ Cpu.delete_all(['host_id = ?', host.id])
+
+ puts "Saving new CPU records"
+ cpu_info.collect do |cpu|
+ detail = Cpu.new(
+ "cpu_number" => cpu['CPUNUM'],
+ "core_number" => cpu['CORENUM]'],
+ "number_of_cores" => cpu['NUMCORES'],
+ "vendor" => cpu['VENDOR'],
+ "model" => cpu['MODEL'],
+ "family" => cpu['FAMILY'],
+ "cpuid_level" => cpu['CPUIDLVL'],
+ "speed" => cpu['SPEED'],
+ "cache" => cpu['CACHE'],
+ "flags" => cpu['FLAGS'])
+
+ host.cpus << detail
+ end
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ # Update the NIC details for this host:
+ # -if the NIC exists, then update the IP address
+ # -if the NIC does not exist, create it
+ # -any nic not in this list is deleted
- key, value = info.split("=")
+ puts "Updating NIC records for the node"
+ nics = Array.new
- puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
- result[key] = value
+ host.nics.collect do |nic|
+ found = false
- @session.write("ACK #{key}\n")
+ nic_info.collect do |detail|
+ # if we have a match, then update the database and remove
+ # the received data to avoid creating a dupe later
+ if detail['MAC'] == nic.mac
+ nic_info.delete(detail)
end
+ end
- @session.write("ACK NIC\n");
-
- return result
+ # if the record wasn't found, then remove it from the database
+ unless found
+ host.nics.delete(nic)
+ nic.destroy
+ end
end
- # Writes the supplied host information to the database.
- #
- def write_host_info(host_info)
- ensure_present(host_info,'HOSTNAME')
- ensure_present(host_info,'ARCH')
- ensure_present(host_info,'MEMSIZE')
- ensure_present(host_info,'CPUINFO')
- ensure_present(host_info,'NICINFO')
-
- cpu_info = host_info['CPUINFO']
- nic_info = host_info['NICINFO']
-
- cpu_info.each do |cpu|
- ensure_present(cpu,'CPUNUM')
- ensure_present(cpu,'CORENUM')
- ensure_present(cpu,'NUMCORES')
- ensure_present(cpu,'VENDOR')
- ensure_present(cpu,'MODEL')
- ensure_present(cpu,'FAMILY')
- ensure_present(cpu,'CPUIDLVL')
- ensure_present(cpu,'SPEED')
- ensure_present(cpu,'CACHE')
- ensure_present(cpu,'FLAGS')
- end
+ # iterate over any nics left and create new records for them.
- puts "Searching for existing host record..." unless
defined?(TESTING)
- host = Host.find(:first, :conditions => ["hostname = ?",
host_info['HOSTNAME']])
-
- if host == nil
- begin
- puts "Creating a new record for
#{host_info['HOSTNAME']}..." unless defined?(TESTING)
-
- host = Host.create(
- "uuid" =>
host_info['UUID'],
- "hostname" =>
host_info['HOSTNAME'],
- "hypervisor_type" =>
host_info['HYPERVISOR_TYPE'],
- "arch" =>
host_info['ARCH'],
- "memory" =>
host_info['MEMSIZE'],
- "is_disabled" => 0,
- "hardware_pool" =>
HardwarePool.get_default_pool,
- # Let host-status mark it available when it
- # successfully connects to it via libvirt.
- "state" => Host::STATE_UNAVAILABLE)
- rescue Exception => error
- puts "Error while creating record: #{error.message}"
unless defined?(TESTING)
- end
- else
- host.uuid = host_info['UUID']
- host.hostname = host_info['HOSTNAME']
- host.arch = host_info['ARCH']
- host.memory = host_info['MEMSIZE']
- end
+ nic_info.collect do |nic|
+ puts "Creating a new nic..."
+ detail = Nic.new(
+ 'mac' => nic['MAC'],
+ 'bandwidth' => nic['BANDWIDTH'],
+ 'iface_name' => nic['IFACE_NAME'],
+ 'usage_type' => 1)
- # delete an existing CPUs and create new ones based on the data
- puts "Deleting any existing CPUs"
- Cpu.delete_all(['host_id = ?', host.id])
-
- puts "Saving new CPU records"
- cpu_info.collect do |cpu|
- detail = Cpu.new(
- "cpu_number" => cpu['CPUNUM'],
- "core_number" => cpu['CORENUM]'],
- "number_of_cores" => cpu['NUMCORES'],
- "vendor" => cpu['VENDOR'],
- "model" => cpu['MODEL'],
- "family" => cpu['FAMILY'],
- "cpuid_level" => cpu['CPUIDLVL'],
- "speed" => cpu['SPEED'],
- "cache" => cpu['CACHE'],
- "flags" => cpu['FLAGS'])
-
- host.cpus << detail
- end
-
- # Update the NIC details for this host:
- # -if the NIC exists, then update the IP address
- # -if the NIC does not exist, create it
- # -any nic not in this list is deleted
-
- puts "Updating NIC records for the node"
- nics = Array.new
-
- host.nics.collect do |nic|
- found = false
-
- nic_info.collect do |detail|
- # if we have a match, then update the database and remove
- # the received data to avoid creating a dupe later
- if detail['MAC'] == nic.mac
- nic_info.delete(detail)
- end
- end
-
- # if the record wasn't found, then remove it from the database
- unless found
- host.nics.delete(nic)
- nic.destroy
- end
- end
-
- # iterate over any nics left and create new records for them.
-
- nic_info.collect do |nic|
- puts "Creating a new nic..."
- detail = Nic.new(
- 'mac' => nic['MAC'],
- 'bandwidth' => nic['BANDWIDTH'],
- 'usage_type' => 1)
+ host.nics << detail
+ end
- host.nics << detail
- end
+ host.save!
- host.save!
+ return host
+ end
- return host
- end
+ # Creates a keytab if one is needed, returning the filename.
+ #
+ def create_keytab(hostname, ipaddress, krb5_arg = nil)
+ krb5 = krb5_arg || Krb5.new
- # Creates a keytab if one is needed, returning the filename.
- #
- def create_keytab(hostname, ipaddress, krb5_arg = nil)
- krb5 = krb5_arg || Krb5.new
+ default_realm = krb5.get_default_realm
+ libvirt_princ = 'libvirt/' + hostname + '@' + default_realm
+ outfile = ipaddress + '-libvirt.tab'
+ @keytab_filename = @keytab_dir + outfile
- default_realm = krb5.get_default_realm
- libvirt_princ = 'libvirt/' + hostname + '@' +
default_realm
- outfile = ipaddress + '-libvirt.tab'
- @keytab_filename = @keytab_dir + outfile
+ # TODO need a way to test this portion
+ unless (defined? TESTING) || File.exists?(@keytab_filename)
+ # TODO replace with Kr5Auth when it supports admin actions
+ puts "Writing keytab file: #{@keytab_filename}" unless
defined?(TESTING)
+ kadmin_local('addprinc -randkey ' + libvirt_princ)
+ kadmin_local('ktadd -k ' + @keytab_filename + ' ' +
libvirt_princ)
- # TODO need a way to test this portion
- unless (defined? TESTING) || File.exists?(@keytab_filename)
- # TODO replace with Kr5Auth when it supports admin actions
- puts "Writing keytab file: #{@keytab_filename}" unless
defined?(TESTING)
- kadmin_local('addprinc -randkey ' + libvirt_princ)
- kadmin_local('ktadd -k ' + @keytab_filename + ' ' +
libvirt_princ)
+ File.chmod(0644, at keytab_filename)
+ end
- File.chmod(0644, at keytab_filename)
- end
+ hostname = `hostname -f`.chomp
- hostname = `hostname -f`.chomp
+ @connection.write("KTAB
http://#{hostname}/ipa/config/#{outfile}\n")
- @session.write("KTAB
http://#{hostname}/ipa/config/#{outfile}\n")
+ response = @connection.readline.chomp
- response = @session.readline.chomp
+ raise Exception.new("ERRINFO! No keytab acknowledgement") unless
response == "ACK"
+ end
- raise Exception.new("ERRINFO! No keytab acknowledgement")
unless response == "ACK"
- end
+ # Ends the conversation, notifying the user of the key version number.
+ #
+ def end_conversation
+ puts "#{@log_prefix} Ending conversation" unless
defined?(TESTING)
- # Ends the conversation, notifying the user of the key version number.
- #
- def end_conversation
- puts "#{@log_prefix} Ending conversation" unless
defined?(TESTING)
+ @connection.write("BYE\n");
+ end
- @session.write("BYE\n");
- end
+ private
- private
+ # Private method to ensure that a required field is present.
+ #
+ def ensure_present(info,key)
+ raise Exception.new("ERROR! Missing '#{key}'...") if
info[key] == nil
+ end
- # Private method to ensure that a required field is present.
- #
- def ensure_present(info,key)
- raise Exception.new("ERROR! Missing '#{key}'...") if
info[key] == nil
- end
-
- # Executes an external program to support the keytab function.
- #
- def kadmin_local(command)
- system("/usr/kerberos/sbin/kadmin.local -q '" + command +
"'")
- end
+ # Executes an external program to support the keytab function.
+ #
+ def kadmin_local(command)
+ system("/usr/kerberos/sbin/kadmin.local -q '" + command +
"'")
+ end
end
def entry_point(server)
- while(session = server.accept)
- child = fork do
- remote = session.peeraddr[2]
-
- puts "Connected to #{remote}" unless defined?(TESTING)
-
- # This is needed because we just forked a new process
- # which now needs its own connection to the database.
- database_connect
+ while(session = server.accept)
+ child = fork do
+ remote = session.peeraddr[2]
- begin
- browser = HostBrowser.new(session)
+ puts "Connected to #{remote}" unless defined?(TESTING)
- browser.begin_conversation
- case browser.get_mode
- when "AWAKEN":
browser.create_keytab(remote,session.peeraddr[3])
- when "IDENTIFY":
browser.write_host_info(browser.get_remote_info)
- end
+ # This is needed because we just forked a new process
+ # which now needs its own connection to the database.
+ database_connect
- browser.end_conversation
- rescue Exception => error
- session.write("ERROR #{error.message}\n")
- puts "ERROR #{error.message}" unless
defined?(TESTING)
- end
+ begin
+ browser = HostBrowser.new(session)
- puts "Disconnected from #{remote}" unless
defined?(TESTING)
+ browser.begin_conversation
+ case browser.get_mode
+ when "AWAKEN":
browser.create_keytab(remote,session.peeraddr[3])
+ when "IDENTIFY":
browser.write_host_info(browser.get_remote_info)
end
- Process.detach(child)
+ browser.end_conversation
+ rescue Exception => error
+ session.write("ERROR #{error.message}\n")
+ puts "ERROR #{error.message}" unless defined?(TESTING)
+ end
+
+ puts "Disconnected from #{remote}" unless defined?(TESTING)
end
+
+ Process.detach(child)
+ end
end
unless defined?(TESTING)
- # The main entry point.
- #
- unless ARGV[0] == "-n"
- daemonize
- # redirect output to the log
- STDOUT.reopen $logfile, 'a'
- STDERR.reopen STDOUT
- end
-
- server = TCPServer.new("",12120)
- entry_point(server)
+ # The main entry point.
+ #
+ unless ARGV[0] == "-n"
+ daemonize
+ # redirect output to the log
+ STDOUT.reopen $logfile, 'a'
+ STDERR.reopen STDOUT
+ end
+
+ server = TCPServer.new("",12120)
+ entry_point(server)
end
diff --git a/wui/src/host-browser/test-host-browser-identify.rb
b/wui/src/host-browser/test-host-browser-identify.rb
index 7e672ce..e25497f 100755
--- a/wui/src/host-browser/test-host-browser-identify.rb
+++ b/wui/src/host-browser/test-host-browser-identify.rb
@@ -27,257 +27,259 @@ TESTING=true
require 'host-browser'
class TestHostBrowser < Test::Unit::TestCase
- def setup
- @session = flexmock('session')
- @session.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
-
- @browser = HostBrowser.new(@session)
- @browser.logfile = './unit-test.log'
-
- # default host info
- @host_info = {}
- @host_info['UUID'] = 'node1'
- @host_info['IPADDR'] = '192.168.2.2'
- @host_info['HOSTNAME'] = 'prod.corp.com'
- @host_info['ARCH'] = 'x86_64'
- @host_info['MEMSIZE'] = '16384'
- @host_info['DISABLED'] = '0'
-
- @host_info['NUMCPUS'] = '2'
-
- @host_info['CPUINFO'] = Array.new
- @host_info['CPUINFO'][0] = {}
- @host_info['CPUINFO'][0]['CPUNUM'] = '0'
- @host_info['CPUINFO'][0]['CORENUM'] = '0'
- @host_info['CPUINFO'][0]['NUMCORES'] = '2'
- @host_info['CPUINFO'][0]['VENDOR'] =
'GenuineIntel'
- @host_info['CPUINFO'][0]['MODEL'] = '15'
- @host_info['CPUINFO'][0]['FAMILY'] = '6'
- @host_info['CPUINFO'][0]['CPUIDLVL'] = '10'
- @host_info['CPUINFO'][0]['SPEED'] = '3'
- @host_info['CPUINFO'][0]['CACHE'] = '4096
kb'
- @host_info['CPUINFO'][0]['FLAGS'] = 'fpu vme de
pse tsc msr pae \
+ def setup
+ @connection = flexmock('connection')
+ @connection.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
+
+ @browser = HostBrowser.new(@connection)
+ @browser.logfile = './unit-test.log'
+
+ # default host info
+ @host_info = {}
+ @host_info['UUID'] = 'node1'
+ @host_info['IPADDR'] = '192.168.2.2'
+ @host_info['HOSTNAME'] = 'prod.corp.com'
+ @host_info['ARCH'] = 'x86_64'
+ @host_info['MEMSIZE'] = '16384'
+ @host_info['DISABLED'] = '0'
+
+ @host_info['NUMCPUS'] = '2'
+
+ @host_info['CPUINFO'] = Array.new
+ @host_info['CPUINFO'][0] = {}
+ @host_info['CPUINFO'][0]['CPUNUM'] = '0'
+ @host_info['CPUINFO'][0]['CORENUM'] = '0'
+ @host_info['CPUINFO'][0]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][0]['VENDOR'] =
'GenuineIntel'
+ @host_info['CPUINFO'][0]['MODEL'] = '15'
+ @host_info['CPUINFO'][0]['FAMILY'] = '6'
+ @host_info['CPUINFO'][0]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][0]['SPEED'] = '3'
+ @host_info['CPUINFO'][0]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][0]['FLAGS'] = 'fpu vme de pse
tsc msr pae \
mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
- @host_info['CPUINFO'][1] = {}
- @host_info['CPUINFO'][1]['CPUNUM'] = '1'
- @host_info['CPUINFO'][1]['CORENUM'] = '1'
- @host_info['CPUINFO'][1]['NUMCORES'] = '2'
- @host_info['CPUINFO'][1]['VENDOR'] =
'GenuineIntel'
- @host_info['CPUINFO'][1]['MODEL'] = '15'
- @host_info['CPUINFO'][1]['FAMILY'] = '6'
- @host_info['CPUINFO'][1]['CPUIDLVL'] = '10'
- @host_info['CPUINFO'][1]['SPEED'] = '3'
- @host_info['CPUINFO'][1]['CACHE'] = '4096
kb'
- @host_info['CPUINFO'][1]['FLAGS'] = 'fpu vme de
pse tsc msr pae \
+ @host_info['CPUINFO'][1] = {}
+ @host_info['CPUINFO'][1]['CPUNUM'] = '1'
+ @host_info['CPUINFO'][1]['CORENUM'] = '1'
+ @host_info['CPUINFO'][1]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][1]['VENDOR'] =
'GenuineIntel'
+ @host_info['CPUINFO'][1]['MODEL'] = '15'
+ @host_info['CPUINFO'][1]['FAMILY'] = '6'
+ @host_info['CPUINFO'][1]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][1]['SPEED'] = '3'
+ @host_info['CPUINFO'][1]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][1]['FLAGS'] = 'fpu vme de pse
tsc msr pae \
mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
- @host_info['NICINFO'] = Array.new
- @host_info['NICINFO'][0] = {}
- @host_info['NICINFO'][0]['MAC'] =
'00:11:22:33:44:55'
- @host_info['NICINFO'][0]['BANDWIDTH'] = '100'
-
- @host_info['NICINFO'][1] = {}
- @host_info['NICINFO'][1]['MAC'] =
'00:77:11:77:19:65'
- @host_info['NICINFO'][1]['BANDWIDTH'] = '100'
- end
-
- # Ensures that the server is satisfied if the remote system is
- # making a wakeup call.
- #
- def test_get_mode_with_awaken_request
-
@session.should_receive(:write).with("MODE?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"IDENTIFY\n" }
-
- result = @browser.get_mode()
-
- assert_equal "IDENTIFY", result, "method did not return
the right value"
- end
-
- # Ensures that, if an info field is missing a key, the server raises
- # an exception.
- #
- def test_get_info_with_missing_key
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"=value1\n" }
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that, if an info field is missing a value, the server raises
- # an exception.
- #
- def test_get_info_with_missing_value
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "key1=\n"
}
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that, if the server gets a poorly formed ending statement, it
- # raises an exception.
- #
- def test_get_info_with_invalid_end
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDIFNO\n" }
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that a well-formed transaction works as expected.
- #
- def test_get_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 4,info.keys.size, "Should contain four keys"
- assert info.include?("IPADDR")
- assert info.include?("HOSTNAME")
- assert info.include?("key1")
- assert info.include?("key2")
- end
-
- # Ensures that the server is fine when no UUID is present.
- #
- def test_write_host_info_with_missing_uuid
- @host_info['UUID'] = nil
-
- assert_nothing_raised { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the hostname is missing, the server
- # raises an exception.
- #
- def test_write_host_info_with_missing_hostname
- @host_info['HOSTNAME'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the architecture is missing, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_arch
- @host_info['ARCH'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the memory size is missing, the server raises an
- # exception.
- #
- def test_write_host_info_info_with_missing_memsize
- @host_info['MEMSIZE'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if no cpu info was available, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_cpuinfo
- @host_info['CPUINFO'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if no NIC info was available, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_nicinfo
- @host_info['NICINFO'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures the browser can properly parse the CPU details.
- #
- def test_parse_cpu_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?("CPUINFO")
- end
-
- # Ensures the browser can properly parse the CPU details of two CPUs.
- #
- def test_parse_cpu_info_with_two_entries
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
-
- # CPU 0
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
-
- # CPU 1
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key3=value3\n" }
- @session.should_receive(:write).with("ACK
key3\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key4=value4\n" }
- @session.should_receive(:write).with("ACK
key4\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
-
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?('CPUINFO')
- assert_equal 2, info['CPUINFO'].size, "Should contain
details for two CPUs"
- assert_not_nil info['CPUINFO'][0]['key1']
- assert_not_nil info['CPUINFO'][0]['key2']
- assert_not_nil info['CPUINFO'][1]['key3']
- assert_not_nil info['CPUINFO'][1]['key4']
- end
-
- # Ensures the browser can properly parse the details for a NIC.
- #
- def test_parse_nic_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "NIC\n" }
-
@session.should_receive(:write).with("NICINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDNIC\n" }
- @session.should_receive(:write).with("ACK
NIC\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?("NICINFO")
- end
+ @host_info['NICINFO'] = Array.new
+ @host_info['NICINFO'] << {
+ 'MAC' => '00:11:22:33:44:55',
+ 'BANDWIDTH' => '100',
+ 'IFACE_NAME' => 'eth0'}
+
+ @host_info['NICINFO'] << {
+ 'MAC' => '00:77:11:77:19:65',
+ 'BANDWIDTH' => '100',
+ 'IFACE_NAME' => 'eth01'}
+ end
+
+ # Ensures that the server is satisfied if the remote system is
+ # making a wakeup call.
+ #
+ def test_get_mode_with_awaken_request
+ @connection.should_receive(:write).with("MODE?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"IDENTIFY\n" }
+
+ result = @browser.get_mode()
+
+ assert_equal "IDENTIFY", result, "method did not return the
right value"
+ end
+
+ # Ensures that, if an info field is missing a key, the server raises
+ # an exception.
+ #
+ def test_get_info_with_missing_key
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"=value1\n" }
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that, if an info field is missing a value, the server raises
+ # an exception.
+ #
+ def test_get_info_with_missing_value
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "key1=\n"
}
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that, if the server gets a poorly formed ending statement, it
+ # raises an exception.
+ #
+ def test_get_info_with_invalid_end
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDIFNO\n" }
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that a well-formed transaction works as expected.
+ #
+ def test_get_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 4,info.keys.size, "Should contain four keys"
+ assert info.include?("IPADDR")
+ assert info.include?("HOSTNAME")
+ assert info.include?("key1")
+ assert info.include?("key2")
+ end
+
+ # Ensures that the server is fine when no UUID is present.
+ #
+ def test_write_host_info_with_missing_uuid
+ @host_info['UUID'] = nil
+
+ assert_nothing_raised { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the hostname is missing, the server
+ # raises an exception.
+ #
+ def test_write_host_info_with_missing_hostname
+ @host_info['HOSTNAME'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the architecture is missing, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_arch
+ @host_info['ARCH'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the memory size is missing, the server raises an
+ # exception.
+ #
+ def test_write_host_info_info_with_missing_memsize
+ @host_info['MEMSIZE'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if no cpu info was available, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_cpuinfo
+ @host_info['CPUINFO'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if no NIC info was available, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_nicinfo
+ @host_info['NICINFO'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures the browser can properly parse the CPU details.
+ #
+ def test_parse_cpu_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?("CPUINFO")
+ end
+
+ # Ensures the browser can properly parse the CPU details of two CPUs.
+ #
+ def test_parse_cpu_info_with_two_entries
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+
+ # CPU 0
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+
+ # CPU 1
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key3=value3\n" }
+ @connection.should_receive(:write).with("ACK
key3\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key4=value4\n" }
+ @connection.should_receive(:write).with("ACK
key4\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?('CPUINFO')
+ assert_equal 2, info['CPUINFO'].size, "Should contain details
for two CPUs"
+ assert_not_nil info['CPUINFO'][0]['key1']
+ assert_not_nil info['CPUINFO'][0]['key2']
+ assert_not_nil info['CPUINFO'][1]['key3']
+ assert_not_nil info['CPUINFO'][1]['key4']
+ end
+
+ # Ensures the browser can properly parse the details for a NIC.
+ #
+ def test_parse_nic_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "NIC\n" }
+
@connection.should_receive(:write).with("NICINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDNIC\n"
}
+ @connection.should_receive(:write).with("ACK
NIC\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?("NICINFO")
+ end
end
diff --git a/wui/src/lib/managed_node_configuration.rb
b/wui/src/lib/managed_node_configuration.rb
new file mode 100644
index 0000000..aa8c711
--- /dev/null
+++ b/wui/src/lib/managed_node_configuration.rb
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+# +ManagedNodeConfiguration+ takes in the description for a managed node and,
+# from that, generates the configuration file that is consumed the next time
+# the managed node starts up.
+#
+
+require 'stringio'
+
+$: << File.join(File.dirname(__FILE__), "../dutils")
+$: << File.join(File.dirname(__FILE__), "../")
+
+class ManagedNodeConfiguration
+ NIC_ENTRY_PREFIX='/files/etc/sysconfig/network-scripts'
+
+ def self.generate(host)
+ result = StringIO.new
+
+ host.nics.each do |nic|
+ result.puts "rm #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}"
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/DEVICE
#{nic.iface_name}"
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/IPADDR
#{nic.ip_addr}" if nic.ip_addr
+ result.puts "set
#{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/BOOTPROTO dhcp" if
nic.ip_addr == nil
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/BRIDGE
#{nic.bridge}" if nic.bridge
+ end
+
+ result.puts "save"
+
+ result.string
+ end
+end
+
diff --git a/wui/src/test/unit/managed_node_configuration_test.rb
b/wui/src/test/unit/managed_node_configuration_test.rb
new file mode 100644
index 0000000..01b3fe4
--- /dev/null
+++ b/wui/src/test/unit/managed_node_configuration_test.rb
@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+$:.unshift File.join(File.dirname(__FILE__),'..','lib')
+
+# require File.dirname(__FILE__) + '/../test/test_helper'
+require 'test/unit'
+require 'managed_node_configuration'
+require 'dutils'
+
+# Performs unit tests on the +ManagedNodeConfiguration+ class.
+#
+class ManagedNodeConfigurationTest < Test::Unit::TestCase
+ def setup
+ @host = Host.new
+ end
+
+
+ # Ensures that network interfaces uses DHCP when no IP address is specified.
+ #
+ def test_generate_with_no_ip_address
+ @host.nics << Nic.new(:iface_name => 'eth0')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BOOTPROTO dhcp
+save
+HERE
+
+ result = ManagedNodeConfiguration.generate @host
+
+ assert_equal expected, result
+ end
+
+ # Ensures that network interfaces use the IP address when it's provided.
+ #
+ def test_generate_with_ip_address
+ @host.nics << Nic.new(:iface_name => 'eth0', :ip_addr
=> '192.168.2.1')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/IPADDR 192.168.2.1
+save
+HERE
+
+ result = ManagedNodeConfiguration.generate @host
+
+ assert_equal expected, result
+ end
+
+ # Ensures the bridge is added to the configuration if one is defined.
+ #
+ def test_generate_with_bridge
+ @host.nics << Nic.new(:iface_name => 'eth0', :bridge =>
'ovirtbr0')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BOOTPROTO dhcp
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BRIDGE ovirtbr0
+save
+HERE
+
+ result = ManagedNodeConfiguration.generate @host
+
+ assert_equal expected, result
+ end
+
+end
--
1.5.5.1
Jim Meyering
2008-Aug-20 08:11 UTC
[Ovirt-devel] [PATCH] Enables the generation of a configuration file for a managed node.
"Darryl L. Pierce" <dpierce at redhat.com> wrote:> The configuration is generated from the contents of the nics table. The > managed node then downloads that configuration after completing the > identification and applies those changes. > > What this needs is integration with the WUI itself, to generate the file > when the admin modifies the NIC for the host.Hi Darryl, I was just glancing through this and stumbled up on what looks like a bug: ...> diff --git a/wui/src/host-browser/host-browser.rb b/wui/src/host-browser/host-browser.rb...> + # Update the NIC details for this host: > + # -if the NIC exists, then update the IP address > + # -if the NIC does not exist, create it > + # -any nic not in this list is deleted > > - key, value = info.split("=") > + puts "Updating NIC records for the node" > + nics = Array.new > > - puts "#{@log_prefix} ::Received - #{key}:#{value}" unless defined?(TESTING) > - result[key] = value > + host.nics.collect do |nic| > + found = false > > - @session.write("ACK #{key}\n") > + nic_info.collect do |detail| > + # if we have a match, then update the database and remove > + # the received data to avoid creating a dupe later > + if detail['MAC'] == nic.mac > + nic_info.delete(detail)I think you want to insert "found = true" here.> end > + end > > - @session.write("ACK NIC\n"); > - > - return result > + # if the record wasn't found, then remove it from the database > + unless found > + host.nics.delete(nic) > + nic.destroy > + end > end
Darryl L. Pierce
2008-Aug-20 13:10 UTC
[Ovirt-devel] [PATCH] Enables the generation of a configuration file for a managed node.
The configuration is generated from the contents of the nics table. The
managed node then downloads that configuration after completing the
identification and applies those changes.
Signed-off-by: Darryl L. Pierce <dpierce at redhat.com>
---
ovirt-managed-node/src/gather.c | 2 +
ovirt-managed-node/src/ovirt-identify-node.h | 1 +
ovirt-managed-node/src/protocol.c | 3 +-
wui/src/app/controllers/application.rb | 2 +-
wui/src/app/controllers/nic_controller.rb | 13 +-
wui/src/config/environment.rb | 2 +
wui/src/db/migrate/015_add_iface_name_to_nics.rb | 9 +
wui/src/host-browser/host-browser.rb | 583 ++++++++++----------
wui/src/host-browser/test-host-browser-awake.rb | 94 ----
wui/src/host-browser/test-host-browser-identify.rb | 283 ----------
wui/src/lib/managed_node_configuration.rb | 49 ++
wui/src/test/fixtures/nics.yml | 3 +
wui/src/test/unit/host_browser_awaken_test.rb | 96 ++++
wui/src/test/unit/host_browser_identify_test.rb | 304 ++++++++++
.../test/unit/managed_node_configuration_test.rb | 87 +++
15 files changed, 864 insertions(+), 667 deletions(-)
create mode 100644 wui/src/db/migrate/015_add_iface_name_to_nics.rb
delete mode 100755 wui/src/host-browser/test-host-browser-awake.rb
delete mode 100755 wui/src/host-browser/test-host-browser-identify.rb
create mode 100644 wui/src/lib/managed_node_configuration.rb
create mode 100755 wui/src/test/unit/host_browser_awaken_test.rb
create mode 100755 wui/src/test/unit/host_browser_identify_test.rb
create mode 100644 wui/src/test/unit/managed_node_configuration_test.rb
diff --git a/ovirt-managed-node/src/gather.c b/ovirt-managed-node/src/gather.c
index 39be6fd..7fa0992 100644
--- a/ovirt-managed-node/src/gather.c
+++ b/ovirt-managed-node/src/gather.c
@@ -205,6 +205,8 @@ get_nic_data(char *nic, nic_info_ptr nic_info)
interface libhal_device_get_property_string(hal_ctx, nic,
"net.interface",
&dbus_error);
+ snprintf(nic_info->interface_name, BUFFER_LENGTH, "%s",
interface);
+
bzero(&ifr, sizeof(struct ifreq));
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
diff --git a/ovirt-managed-node/src/ovirt-identify-node.h
b/ovirt-managed-node/src/ovirt-identify-node.h
index c595891..b2814fa 100644
--- a/ovirt-managed-node/src/ovirt-identify-node.h
+++ b/ovirt-managed-node/src/ovirt-identify-node.h
@@ -67,6 +67,7 @@ typedef struct _nic_info {
char mac_address[BUFFER_LENGTH];
char bandwidth[BUFFER_LENGTH];
char ip_address[BUFFER_LENGTH];
+ char interface_name[BUFFER_LENGTH];
struct _nic_info* next;
} t_nic_info;
diff --git a/ovirt-managed-node/src/protocol.c
b/ovirt-managed-node/src/protocol.c
index 131bb38..d5c5fac 100644
--- a/ovirt-managed-node/src/protocol.c
+++ b/ovirt-managed-node/src/protocol.c
@@ -181,7 +181,8 @@ send_nic_details(void)
if (!(get_text("NICINFO?")) &&
(!send_value("MAC", current->mac_address)) &&
- (!send_value("BANDWIDTH", current->bandwidth))) {
+ (!send_value("BANDWIDTH", current->bandwidth))
&&
+ (!send_value("IFACE_NAME", current->interface_name)))
{
send_text("ENDNIC");
result = get_text("ACK NIC");
}
diff --git a/wui/src/app/controllers/application.rb
b/wui/src/app/controllers/application.rb
index d653171..b27ddbe 100644
--- a/wui/src/app/controllers/application.rb
+++ b/wui/src/app/controllers/application.rb
@@ -35,7 +35,7 @@ class ApplicationController < ActionController::Base
before_filter :is_logged_in
def is_logged_in
- redirect_to (:controller => "login", :action =>
"login") unless get_login_user
+ redirect_to(:controller => "login", :action =>
"login") unless get_login_user
end
def get_login_user
diff --git a/wui/src/app/controllers/nic_controller.rb
b/wui/src/app/controllers/nic_controller.rb
index 85d4315..fef7c5b 100644
--- a/wui/src/app/controllers/nic_controller.rb
+++ b/wui/src/app/controllers/nic_controller.rb
@@ -18,9 +18,10 @@
# also available at http://www.gnu.org/copyleft/gpl.html.
class NicController < ApplicationController
+ after_filter :generate_configuration, :only => [:create, :edit, :update,
:destroy]
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
- :redirect_to => { :controller => 'dashboard' }
+ :redirect_to => { :controller => 'dashboard' }
def show
set_perms(@perm_obj)
@@ -44,8 +45,18 @@ class NicController < ApplicationController
def destroy
end
+
+ def generate_configuration
+ host = Host.find_by_id(params[:host_id])
+
+ File.open("#{MANAGED_NODE_CONFIGURATION_DIR}/#{host.hostname}",
"w") do |file|
+ # write the nic configuration
+ file.puts ManagedNodeConfiguration.generate(host)
+ end
+ end
private
+
#filter methods
def pre_new
flash[:notice] = 'Network Interfaces may not be edited via the web
UI'
diff --git a/wui/src/config/environment.rb b/wui/src/config/environment.rb
index ff6f6e8..57fd461 100644
--- a/wui/src/config/environment.rb
+++ b/wui/src/config/environment.rb
@@ -80,3 +80,5 @@ end
require 'gettext/rails'
gem 'cobbler'
require 'cobbler'
+
+MANAGED_NODE_CONFIGURATION_DIR = '/var/www/html/ovirt-cfgdb'
\ No newline at end of file
diff --git a/wui/src/db/migrate/015_add_iface_name_to_nics.rb
b/wui/src/db/migrate/015_add_iface_name_to_nics.rb
new file mode 100644
index 0000000..f1fb28d
--- /dev/null
+++ b/wui/src/db/migrate/015_add_iface_name_to_nics.rb
@@ -0,0 +1,9 @@
+class AddIfaceNameToNics < ActiveRecord::Migration
+ def self.up
+ add_column :nics, :iface_name, :string, :limit => 10
+ end
+
+ def self.down
+ remove_column :nics, :iface_name
+ end
+end
diff --git a/wui/src/host-browser/host-browser.rb
b/wui/src/host-browser/host-browser.rb
index 881b2ae..d3098ce 100755
--- a/wui/src/host-browser/host-browser.rb
+++ b/wui/src/host-browser/host-browser.rb
@@ -39,361 +39,370 @@ $logfile = '/var/log/ovirt-wui/host-browser.log'
# about the node and then updates the list of active nodes for the WUI.
#
class HostBrowser
- attr_accessor :logfile
- attr_accessor :keytab_dir
- attr_accessor :keytab_filename
-
- def initialize(session)
- @session = session
- @log_prefix = "[#{session.peeraddr[3]}] "
- @keytab_dir = '/usr/share/ipa/html/'
- end
-
- # Ensures the conversation starts properly.
- #
- def begin_conversation
- puts "#{@log_prefix} Begin conversation" unless
defined?(TESTING)
- @session.write("HELLO?\n")
-
- response = @session.readline.chomp
- raise Exception.new("received #{response}, expected HELLO!")
unless response == "HELLO!"
- end
-
- # Retrieves the mode request from the remote system.
- #
- def get_mode
- puts "#{@log_prefix} Determining the runtime mode." unless
defined?(TESTING)
- @session.write("MODE?\n")
- response = @session.readline.chomp
- puts "#{@log_prefix} MODE=#{response}" unless
defined?(TESTING)
+ attr_accessor :logfile
+ attr_accessor :keytab_dir
+ attr_accessor :keytab_filename
+
+ def initialize(connection)
+ @connection = connection
+ @log_prefix = "[#{connection.peeraddr[3]}] "
+ @keytab_dir = '/usr/share/ipa/html/'
+ end
+
+ # Ensures the conversation starts properly.
+ #
+ def begin_conversation
+ puts "#{@log_prefix} Begin conversation" unless defined?(TESTING)
+ @connection.write("HELLO?\n")
+
+ response = @connection.readline.chomp
+ raise Exception.new("received #{response}, expected HELLO!")
unless response == "HELLO!"
+ end
+
+ # Retrieves the mode request from the remote system.
+ #
+ def get_mode
+ puts "#{@log_prefix} Determining the runtime mode." unless
defined?(TESTING)
+ @connection.write("MODE?\n")
+ response = @connection.readline.chomp
+ puts "#{@log_prefix} MODE=#{response}" unless defined?(TESTING)
+
+ response
+ end
+
+ # Requests node information from the remote system.
+ #
+ def get_remote_info
+ puts "#{@log_prefix} Begin remote info collection" unless
defined?(TESTING)
+ result = Hash.new
+ result['HOSTNAME'] = @connection.peeraddr[2]
+ result['IPADDR'] = @connection.peeraddr[3]
+
+ @connection.write("INFO?\n")
+
+ loop do
+ info = @connection.readline.chomp
+
+ puts "Received info='#{info}'"
+
+ break if info == "ENDINFO"
+
+ case info
+ when "CPU"
+ cpu = get_cpu_info
+ cpu_info = result['CPUINFO']
+
+ if(cpu_info == nil)
+ cpu_info = Array.new
+ result['CPUINFO'] = cpu_info
+ end
- response
- end
+ cpu_info << cpu
+
+ when "NIC"
+ nic = get_nic_info
+ nic_info = result['NICINFO']
- # Requests node information from the remote system.
- #
- def get_remote_info
- puts "#{@log_prefix} Begin remote info collection" unless
defined?(TESTING)
- result = Hash.new
- result['HOSTNAME'] = @session.peeraddr[2]
- result['IPADDR'] = @session.peeraddr[3]
+ if(nic_info == nil)
+ nic_info = Array.new
+ result['NICINFO'] = nic_info
+ end
- @session.write("INFO?\n")
+ nic_info << nic
+
+ else
+ raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
- loop do
- info = @session.readline.chomp
+ key, value = info.split("=")
- puts "Received info='#{info}'"
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- break if info == "ENDINFO"
+ @connection.write("ACK #{key}\n")
+ end
+ end
- case info
- when "CPU"
- cpu = get_cpu_info
- cpu_info = result['CPUINFO']
+ return result
+ end
- if(cpu_info == nil)
- cpu_info = Array.new
- result['CPUINFO'] = cpu_info
- end
+ # Extracts CPU details from the managed node.
+ #
+ def get_cpu_info
+ puts "Begin receiving CPU details"
- cpu_info << cpu
- when "NIC"
- nic = get_nic_info
- nic_info = result['NICINFO']
+ result = Hash.new
- if(nic_info == nil)
- nic_info = Array.new
- result['NICINFO'] = nic_info
- end
+ @connection.write("CPUINFO?\n")
- nic_info << nic
- else
+ loop do
+ info = @connection.readline.chomp
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ break if info == "ENDCPU"
- key, value = info.split("=")
+ raise Exception.new("ERRINFO! Excepted key=value : #{info}\n")
unless info =~ /[\w]+[\s]*=[\w]/
- puts "#{@log_prefix} ::Received - #{key}:#{value}"
unless defined?(TESTING)
- result[key] = value
+ key, value = info.split("=")
- @session.write("ACK #{key}\n")
- end
- end
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- return result
+ @connection.write("ACK #{key}\n")
end
- # Extracts CPU details from the managed node.
- #
- def get_cpu_info
- puts "Begin receiving CPU details"
+ @connection.write("ACK CPU\n");
- result = Hash.new
+ return result
+ end
- @session.write("CPUINFO?\n")
+ # Extracts NIC details from the managed node.
+ #
+ def get_nic_info
+ puts "Begin receiving NIC details"
- loop do
- info = @session.readline.chomp
+ result = Hash.new
- break if info == "ENDCPU"
+ @connection.write("NICINFO?\n")
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ loop do
+ info = @connection.readline.chomp
- key, value = info.split("=")
+ break if info == "ENDNIC"
- puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
- result[key] = value
+ raise Exception.new("ERRINFO! Excepted key=value : #{info}\n")
unless info =~ /[\w]+[\s]*=[\w]/
- @session.write("ACK #{key}\n")
- end
+ key, value = info.split("=")
- @session.write("ACK CPU\n");
+ puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
+ result[key] = value
- return result
+ @connection.write("ACK #{key}\n")
end
- # Extracts NIC details from the managed node.
- #
- def get_nic_info
- puts "Begin receiving NIC details"
-
- result = Hash.new
-
- @session.write("NICINFO?\n")
+ @connection.write("ACK NIC\n");
+
+ return result
+ end
+
+ # Writes the supplied host information to the database.
+ #
+ def write_host_info(host_info)
+ ensure_present(host_info,'HOSTNAME')
+ ensure_present(host_info,'ARCH')
+ ensure_present(host_info,'MEMSIZE')
+ ensure_present(host_info,'CPUINFO')
+ ensure_present(host_info,'NICINFO')
+
+ cpu_info = host_info['CPUINFO']
+ nic_info = host_info['NICINFO']
+
+ cpu_info.each do |cpu|
+ ensure_present(cpu,'CPUNUM')
+ ensure_present(cpu,'CORENUM')
+ ensure_present(cpu,'NUMCORES')
+ ensure_present(cpu,'VENDOR')
+ ensure_present(cpu,'MODEL')
+ ensure_present(cpu,'FAMILY')
+ ensure_present(cpu,'CPUIDLVL')
+ ensure_present(cpu,'SPEED')
+ ensure_present(cpu,'CACHE')
+ ensure_present(cpu,'FLAGS')
+ end
+
+ nic_info.each do |nic|
+ ensure_present(nic, 'MAC')
+ ensure_present(nic, 'BANDWIDTH')
+ ensure_present(nic, 'IFACE_NAME')
+ end
- loop do
- info = @session.readline.chomp
+ puts "Searching for existing host record..." unless
defined?(TESTING)
+ host = Host.find(:first, :conditions => ["hostname = ?",
host_info['HOSTNAME']])
+
+ if host == nil
+ begin
+ puts "Creating a new record for
#{host_info['HOSTNAME']}..." unless defined?(TESTING)
+
+ host = Host.create(
+ "uuid" => host_info['UUID'],
+ "hostname" => host_info['HOSTNAME'],
+ "hypervisor_type" =>
host_info['HYPERVISOR_TYPE'],
+ "arch" => host_info['ARCH'],
+ "memory" => host_info['MEMSIZE'],
+ "is_disabled" => 0,
+ "hardware_pool" => HardwarePool.get_default_pool,
+ # Let host-status mark it available when it
+ # successfully connects to it via libvirt.
+ "state" => Host::STATE_UNAVAILABLE)
+ rescue Exception => error
+ puts "Error while creating record: #{error.message}" unless
defined?(TESTING)
+ end
+ else
+ host.uuid = host_info['UUID']
+ host.hostname = host_info['HOSTNAME']
+ host.arch = host_info['ARCH']
+ host.memory = host_info['MEMSIZE']
+ end
- break if info == "ENDNIC"
+ # delete an existing CPUs and create new ones based on the data
+ puts "Deleting any existing CPUs"
+ Cpu.delete_all(['host_id = ?', host.id])
+
+ puts "Saving new CPU records"
+ cpu_info.collect do |cpu|
+ detail = Cpu.new(
+ "cpu_number" => cpu['CPUNUM'],
+ "core_number" => cpu['CORENUM]'],
+ "number_of_cores" => cpu['NUMCORES'],
+ "vendor" => cpu['VENDOR'],
+ "model" => cpu['MODEL'],
+ "family" => cpu['FAMILY'],
+ "cpuid_level" => cpu['CPUIDLVL'],
+ "speed" => cpu['SPEED'],
+ "cache" => cpu['CACHE'],
+ "flags" => cpu['FLAGS'])
+
+ host.cpus << detail
+ end
- raise Exception.new("ERRINFO! Excepted key=value :
#{info}\n") unless info =~ /[\w]+[\s]*=[\w]/
+ # Update the NIC details for this host:
+ # -if the NIC exists, then update the IP address
+ # -if the NIC does not exist, create it
+ # -any nic not in this list is deleted
- key, value = info.split("=")
+ puts "Updating NIC records for the node"
+ nics = Array.new
- puts "#{@log_prefix} ::Received - #{key}:#{value}" unless
defined?(TESTING)
- result[key] = value
+ host.nics.collect do |nic|
+ found = false
- @session.write("ACK #{key}\n")
+ nic_info.collect do |detail|
+ # if we have a match, then update the database and remove
+ # the received data to avoid creating a dupe later
+ if detail['MAC'] == nic.mac
+ nic_info.delete(detail)
+ found = true
end
+ end
- @session.write("ACK NIC\n");
-
- return result
+ # if the record wasn't found, then remove it from the database
+ unless found
+ host.nics.delete(nic)
+ nic.destroy
+ end
end
- # Writes the supplied host information to the database.
- #
- def write_host_info(host_info)
- ensure_present(host_info,'HOSTNAME')
- ensure_present(host_info,'ARCH')
- ensure_present(host_info,'MEMSIZE')
- ensure_present(host_info,'CPUINFO')
- ensure_present(host_info,'NICINFO')
-
- cpu_info = host_info['CPUINFO']
- nic_info = host_info['NICINFO']
-
- cpu_info.each do |cpu|
- ensure_present(cpu,'CPUNUM')
- ensure_present(cpu,'CORENUM')
- ensure_present(cpu,'NUMCORES')
- ensure_present(cpu,'VENDOR')
- ensure_present(cpu,'MODEL')
- ensure_present(cpu,'FAMILY')
- ensure_present(cpu,'CPUIDLVL')
- ensure_present(cpu,'SPEED')
- ensure_present(cpu,'CACHE')
- ensure_present(cpu,'FLAGS')
- end
+ # iterate over any nics left and create new records for them.
- puts "Searching for existing host record..." unless
defined?(TESTING)
- host = Host.find(:first, :conditions => ["hostname = ?",
host_info['HOSTNAME']])
-
- if host == nil
- begin
- puts "Creating a new record for
#{host_info['HOSTNAME']}..." unless defined?(TESTING)
-
- host = Host.create(
- "uuid" =>
host_info['UUID'],
- "hostname" =>
host_info['HOSTNAME'],
- "hypervisor_type" =>
host_info['HYPERVISOR_TYPE'],
- "arch" =>
host_info['ARCH'],
- "memory" =>
host_info['MEMSIZE'],
- "is_disabled" => 0,
- "hardware_pool" =>
HardwarePool.get_default_pool,
- # Let host-status mark it available when it
- # successfully connects to it via libvirt.
- "state" => Host::STATE_UNAVAILABLE)
- rescue Exception => error
- puts "Error while creating record: #{error.message}"
unless defined?(TESTING)
- end
- else
- host.uuid = host_info['UUID']
- host.hostname = host_info['HOSTNAME']
- host.arch = host_info['ARCH']
- host.memory = host_info['MEMSIZE']
- end
+ nic_info.collect do |nic|
+ puts "Creating a new nic..."
+ detail = Nic.new(
+ 'mac' => nic['MAC'],
+ 'bandwidth' => nic['BANDWIDTH'],
+ 'iface_name' => nic['IFACE_NAME'],
+ 'usage_type' => 1)
- # delete an existing CPUs and create new ones based on the data
- puts "Deleting any existing CPUs"
- Cpu.delete_all(['host_id = ?', host.id])
-
- puts "Saving new CPU records"
- cpu_info.collect do |cpu|
- detail = Cpu.new(
- "cpu_number" => cpu['CPUNUM'],
- "core_number" => cpu['CORENUM]'],
- "number_of_cores" => cpu['NUMCORES'],
- "vendor" => cpu['VENDOR'],
- "model" => cpu['MODEL'],
- "family" => cpu['FAMILY'],
- "cpuid_level" => cpu['CPUIDLVL'],
- "speed" => cpu['SPEED'],
- "cache" => cpu['CACHE'],
- "flags" => cpu['FLAGS'])
-
- host.cpus << detail
- end
-
- # Update the NIC details for this host:
- # -if the NIC exists, then update the IP address
- # -if the NIC does not exist, create it
- # -any nic not in this list is deleted
-
- puts "Updating NIC records for the node"
- nics = Array.new
-
- host.nics.collect do |nic|
- found = false
-
- nic_info.collect do |detail|
- # if we have a match, then update the database and remove
- # the received data to avoid creating a dupe later
- if detail['MAC'] == nic.mac
- nic_info.delete(detail)
- end
- end
-
- # if the record wasn't found, then remove it from the database
- unless found
- host.nics.delete(nic)
- nic.destroy
- end
- end
-
- # iterate over any nics left and create new records for them.
-
- nic_info.collect do |nic|
- puts "Creating a new nic..."
- detail = Nic.new(
- 'mac' => nic['MAC'],
- 'bandwidth' => nic['BANDWIDTH'],
- 'usage_type' => 1)
+ host.nics << detail
+ end
- host.nics << detail
- end
+ host.save!
- host.save!
+ return host
+ end
- return host
- end
+ # Creates a keytab if one is needed, returning the filename.
+ #
+ def create_keytab(hostname, ipaddress, krb5_arg = nil)
+ krb5 = krb5_arg || Krb5.new
- # Creates a keytab if one is needed, returning the filename.
- #
- def create_keytab(hostname, ipaddress, krb5_arg = nil)
- krb5 = krb5_arg || Krb5.new
+ default_realm = krb5.get_default_realm
+ libvirt_princ = 'libvirt/' + hostname + '@' + default_realm
+ outfile = ipaddress + '-libvirt.tab'
+ @keytab_filename = @keytab_dir + outfile
- default_realm = krb5.get_default_realm
- libvirt_princ = 'libvirt/' + hostname + '@' +
default_realm
- outfile = ipaddress + '-libvirt.tab'
- @keytab_filename = @keytab_dir + outfile
+ # TODO need a way to test this portion
+ unless (defined? TESTING) || File.exists?(@keytab_filename)
+ # TODO replace with Kr5Auth when it supports admin actions
+ puts "Writing keytab file: #{@keytab_filename}" unless
defined?(TESTING)
+ kadmin_local('addprinc -randkey ' + libvirt_princ)
+ kadmin_local('ktadd -k ' + @keytab_filename + ' ' +
libvirt_princ)
- # TODO need a way to test this portion
- unless (defined? TESTING) || File.exists?(@keytab_filename)
- # TODO replace with Kr5Auth when it supports admin actions
- puts "Writing keytab file: #{@keytab_filename}" unless
defined?(TESTING)
- kadmin_local('addprinc -randkey ' + libvirt_princ)
- kadmin_local('ktadd -k ' + @keytab_filename + ' ' +
libvirt_princ)
+ File.chmod(0644, at keytab_filename)
+ end
- File.chmod(0644, at keytab_filename)
- end
+ hostname = `hostname -f`.chomp
- hostname = `hostname -f`.chomp
+ @connection.write("KTAB
http://#{hostname}/ipa/config/#{outfile}\n")
- @session.write("KTAB
http://#{hostname}/ipa/config/#{outfile}\n")
+ response = @connection.readline.chomp
- response = @session.readline.chomp
+ raise Exception.new("ERRINFO! No keytab acknowledgement") unless
response == "ACK"
+ end
- raise Exception.new("ERRINFO! No keytab acknowledgement")
unless response == "ACK"
- end
+ # Ends the conversation, notifying the user of the key version number.
+ #
+ def end_conversation
+ puts "#{@log_prefix} Ending conversation" unless
defined?(TESTING)
- # Ends the conversation, notifying the user of the key version number.
- #
- def end_conversation
- puts "#{@log_prefix} Ending conversation" unless
defined?(TESTING)
+ @connection.write("BYE\n");
+ end
- @session.write("BYE\n");
- end
+ private
- private
+ # Private method to ensure that a required field is present.
+ #
+ def ensure_present(info,key)
+ raise Exception.new("ERROR! Missing '#{key}'...") if
info[key] == nil
+ end
- # Private method to ensure that a required field is present.
- #
- def ensure_present(info,key)
- raise Exception.new("ERROR! Missing '#{key}'...") if
info[key] == nil
- end
-
- # Executes an external program to support the keytab function.
- #
- def kadmin_local(command)
- system("/usr/kerberos/sbin/kadmin.local -q '" + command +
"'")
- end
+ # Executes an external program to support the keytab function.
+ #
+ def kadmin_local(command)
+ system("/usr/kerberos/sbin/kadmin.local -q '" + command +
"'")
+ end
end
def entry_point(server)
- while(session = server.accept)
- child = fork do
- remote = session.peeraddr[2]
-
- puts "Connected to #{remote}" unless defined?(TESTING)
-
- # This is needed because we just forked a new process
- # which now needs its own connection to the database.
- database_connect
+ while(session = server.accept)
+ child = fork do
+ remote = session.peeraddr[2]
- begin
- browser = HostBrowser.new(session)
+ puts "Connected to #{remote}" unless defined?(TESTING)
- browser.begin_conversation
- case browser.get_mode
- when "AWAKEN":
browser.create_keytab(remote,session.peeraddr[3])
- when "IDENTIFY":
browser.write_host_info(browser.get_remote_info)
- end
+ # This is needed because we just forked a new process
+ # which now needs its own connection to the database.
+ database_connect
- browser.end_conversation
- rescue Exception => error
- session.write("ERROR #{error.message}\n")
- puts "ERROR #{error.message}" unless
defined?(TESTING)
- end
+ begin
+ browser = HostBrowser.new(session)
- puts "Disconnected from #{remote}" unless
defined?(TESTING)
+ browser.begin_conversation
+ case browser.get_mode
+ when "AWAKEN":
browser.create_keytab(remote,session.peeraddr[3])
+ when "IDENTIFY":
browser.write_host_info(browser.get_remote_info)
end
- Process.detach(child)
+ browser.end_conversation
+ rescue Exception => error
+ session.write("ERROR #{error.message}\n")
+ puts "ERROR #{error.message}" unless defined?(TESTING)
+ end
+
+ puts "Disconnected from #{remote}" unless defined?(TESTING)
end
+
+ Process.detach(child)
+ end
end
unless defined?(TESTING)
- # The main entry point.
- #
- unless ARGV[0] == "-n"
- daemonize
- # redirect output to the log
- STDOUT.reopen $logfile, 'a'
- STDERR.reopen STDOUT
- end
-
- server = TCPServer.new("",12120)
- entry_point(server)
+ # The main entry point.
+ #
+ unless ARGV[0] == "-n"
+ daemonize
+ # redirect output to the log
+ STDOUT.reopen $logfile, 'a'
+ STDERR.reopen STDOUT
+ end
+
+ server = TCPServer.new("",12120)
+ entry_point(server)
end
diff --git a/wui/src/host-browser/test-host-browser-awake.rb
b/wui/src/host-browser/test-host-browser-awake.rb
deleted file mode 100755
index 02e9146..0000000
--- a/wui/src/host-browser/test-host-browser-awake.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/ruby -Wall
-#
-# Copyright (C) 2008 Red Hat, Inc.
-# Written by Darryl L. Pierce <dpierce at redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301, USA. A copy of the GNU General Public License is
-# also available at http://www.gnu.org/copyleft/gpl.html.
-
-require File.dirname(__FILE__) + '/../test/test_helper'
-require 'test/unit'
-require 'flexmock/test_unit'
-
-TESTING=true
-
-require 'host-browser'
-
-# +TestHostBrowserAwaken+
-class TestHostBrowserAwaken < Test::Unit::TestCase
-
- def setup
- @session = flexmock('session')
- @session.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
-
- @krb5 = flexmock('krb5')
-
- @browser = HostBrowser.new(@session)
- @browser.logfile = './unit-test.log'
- @browser.keytab_dir = '/var/temp/'
- end
-
- # Ensures that the server raises an exception when it receives an
- # improper handshake response.
- #
- def test_begin_conversation_with_improper_response_to_greeting
- @session.should_receive(:write).with("HELLO?\n").once().returns {
|greeting| greeting.length }
- @session.should_receive(:readline).once().returns { "SUP?" }
-
- assert_raise(Exception) { @browser.begin_conversation }
- end
-
- # Ensures the server accepts a proper response from the remote system.
- #
- def test_begin_conversation
- @session.should_receive(:write).with("HELLO?\n").once().returns {
|greeting| greeting.length }
- @session.should_receive(:readline).once().returns { "HELLO!\n" }
-
- assert_nothing_raised(Exception) { @browser.begin_conversation }
- end
-
- # Ensures that the server is satisfied if the remote system is
- # making a wakeup call.
- #
- def test_get_mode_with_awaken_request
- @session.should_receive(:write).with("MODE?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "AWAKEN\n" }
-
- result = @browser.get_mode()
-
- assert_equal "AWAKEN", result, "method did not return the
right value"
- end
-
- # Ensures the host browser generates a keytab as expected.
- #
- def test_create_keytab
- @krb5.should_receive(:get_default_realm).once().returns {
"ovirt-test-realm" }
- servername = `hostname -f`.chomp
- @session.should_receive(:write).with("KTAB
http://#{servername}/ipa/config/127.0.0.1-libvirt.tab\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "ACK\n" }
-
- assert_nothing_raised(Exception) {
@browser.create_keytab('localhost','127.0.0.1', at krb5) }
- end
-
- # Ensures that, if a keytab is present and a key version number available,
- # the server ends the conversation by returning the key version number.
- #
- def test_end_conversation
- @session.should_receive(:write).with("BYE\n").once().returns {
|request| request.length }
-
- assert_nothing_raised(Exception) { @browser.end_conversation }
- end
-
-end
diff --git a/wui/src/host-browser/test-host-browser-identify.rb
b/wui/src/host-browser/test-host-browser-identify.rb
deleted file mode 100755
index 7e672ce..0000000
--- a/wui/src/host-browser/test-host-browser-identify.rb
+++ /dev/null
@@ -1,283 +0,0 @@
-#!/usr/bin/ruby -Wall
-#
-# Copyright (C) 2008 Red Hat, Inc.
-# Written by Darryl L. Pierce <dpierce at redhat.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-# MA 02110-1301, USA. A copy of the GNU General Public License is
-# also available at http://www.gnu.org/copyleft/gpl.html.
-
-require File.dirname(__FILE__) + '/../test/test_helper'
-require 'test/unit'
-require 'flexmock/test_unit'
-
-TESTING=true
-
-require 'host-browser'
-
-class TestHostBrowser < Test::Unit::TestCase
- def setup
- @session = flexmock('session')
- @session.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
-
- @browser = HostBrowser.new(@session)
- @browser.logfile = './unit-test.log'
-
- # default host info
- @host_info = {}
- @host_info['UUID'] = 'node1'
- @host_info['IPADDR'] = '192.168.2.2'
- @host_info['HOSTNAME'] = 'prod.corp.com'
- @host_info['ARCH'] = 'x86_64'
- @host_info['MEMSIZE'] = '16384'
- @host_info['DISABLED'] = '0'
-
- @host_info['NUMCPUS'] = '2'
-
- @host_info['CPUINFO'] = Array.new
- @host_info['CPUINFO'][0] = {}
- @host_info['CPUINFO'][0]['CPUNUM'] = '0'
- @host_info['CPUINFO'][0]['CORENUM'] = '0'
- @host_info['CPUINFO'][0]['NUMCORES'] = '2'
- @host_info['CPUINFO'][0]['VENDOR'] =
'GenuineIntel'
- @host_info['CPUINFO'][0]['MODEL'] = '15'
- @host_info['CPUINFO'][0]['FAMILY'] = '6'
- @host_info['CPUINFO'][0]['CPUIDLVL'] = '10'
- @host_info['CPUINFO'][0]['SPEED'] = '3'
- @host_info['CPUINFO'][0]['CACHE'] = '4096
kb'
- @host_info['CPUINFO'][0]['FLAGS'] = 'fpu vme de
pse tsc msr pae \
- mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
- fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
- bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
-
- @host_info['CPUINFO'][1] = {}
- @host_info['CPUINFO'][1]['CPUNUM'] = '1'
- @host_info['CPUINFO'][1]['CORENUM'] = '1'
- @host_info['CPUINFO'][1]['NUMCORES'] = '2'
- @host_info['CPUINFO'][1]['VENDOR'] =
'GenuineIntel'
- @host_info['CPUINFO'][1]['MODEL'] = '15'
- @host_info['CPUINFO'][1]['FAMILY'] = '6'
- @host_info['CPUINFO'][1]['CPUIDLVL'] = '10'
- @host_info['CPUINFO'][1]['SPEED'] = '3'
- @host_info['CPUINFO'][1]['CACHE'] = '4096
kb'
- @host_info['CPUINFO'][1]['FLAGS'] = 'fpu vme de
pse tsc msr pae \
- mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
- fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
- bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
-
- @host_info['NICINFO'] = Array.new
- @host_info['NICINFO'][0] = {}
- @host_info['NICINFO'][0]['MAC'] =
'00:11:22:33:44:55'
- @host_info['NICINFO'][0]['BANDWIDTH'] = '100'
-
- @host_info['NICINFO'][1] = {}
- @host_info['NICINFO'][1]['MAC'] =
'00:77:11:77:19:65'
- @host_info['NICINFO'][1]['BANDWIDTH'] = '100'
- end
-
- # Ensures that the server is satisfied if the remote system is
- # making a wakeup call.
- #
- def test_get_mode_with_awaken_request
-
@session.should_receive(:write).with("MODE?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"IDENTIFY\n" }
-
- result = @browser.get_mode()
-
- assert_equal "IDENTIFY", result, "method did not return
the right value"
- end
-
- # Ensures that, if an info field is missing a key, the server raises
- # an exception.
- #
- def test_get_info_with_missing_key
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"=value1\n" }
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that, if an info field is missing a value, the server raises
- # an exception.
- #
- def test_get_info_with_missing_value
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "key1=\n"
}
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that, if the server gets a poorly formed ending statement, it
- # raises an exception.
- #
- def test_get_info_with_invalid_end
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDIFNO\n" }
-
- assert_raise(Exception) { @browser.get_remote_info }
- end
-
- # Ensures that a well-formed transaction works as expected.
- #
- def test_get_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 4,info.keys.size, "Should contain four keys"
- assert info.include?("IPADDR")
- assert info.include?("HOSTNAME")
- assert info.include?("key1")
- assert info.include?("key2")
- end
-
- # Ensures that the server is fine when no UUID is present.
- #
- def test_write_host_info_with_missing_uuid
- @host_info['UUID'] = nil
-
- assert_nothing_raised { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the hostname is missing, the server
- # raises an exception.
- #
- def test_write_host_info_with_missing_hostname
- @host_info['HOSTNAME'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the architecture is missing, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_arch
- @host_info['ARCH'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if the memory size is missing, the server raises an
- # exception.
- #
- def test_write_host_info_info_with_missing_memsize
- @host_info['MEMSIZE'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if no cpu info was available, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_cpuinfo
- @host_info['CPUINFO'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures that, if no NIC info was available, the server raises an
- # exception.
- #
- def test_write_host_info_with_missing_nicinfo
- @host_info['NICINFO'] = nil
-
- assert_raise(Exception) { @browser.write_host_info(@host_info) }
- end
-
- # Ensures the browser can properly parse the CPU details.
- #
- def test_parse_cpu_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?("CPUINFO")
- end
-
- # Ensures the browser can properly parse the CPU details of two CPUs.
- #
- def test_parse_cpu_info_with_two_entries
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
-
- # CPU 0
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
-
- # CPU 1
- @session.should_receive(:readline).once().returns { "CPU\n" }
-
@session.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key3=value3\n" }
- @session.should_receive(:write).with("ACK
key3\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key4=value4\n" }
- @session.should_receive(:write).with("ACK
key4\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDCPU\n" }
- @session.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
-
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?('CPUINFO')
- assert_equal 2, info['CPUINFO'].size, "Should contain
details for two CPUs"
- assert_not_nil info['CPUINFO'][0]['key1']
- assert_not_nil info['CPUINFO'][0]['key2']
- assert_not_nil info['CPUINFO'][1]['key3']
- assert_not_nil info['CPUINFO'][1]['key4']
- end
-
- # Ensures the browser can properly parse the details for a NIC.
- #
- def test_parse_nic_info
-
@session.should_receive(:write).with("INFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns { "NIC\n" }
-
@session.should_receive(:write).with("NICINFO?\n").once().returns {
|request| request.length }
- @session.should_receive(:readline).once().returns {
"key1=value1\n" }
- @session.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"key2=value2\n" }
- @session.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDNIC\n" }
- @session.should_receive(:write).with("ACK
NIC\n").once().returns { |request| request.length }
- @session.should_receive(:readline).once().returns {
"ENDINFO\n" }
-
- info = @browser.get_remote_info
-
- assert_equal 3,info.keys.size, "Should contain four keys"
- assert info.include?("NICINFO")
- end
-
-end
diff --git a/wui/src/lib/managed_node_configuration.rb
b/wui/src/lib/managed_node_configuration.rb
new file mode 100644
index 0000000..aa8c711
--- /dev/null
+++ b/wui/src/lib/managed_node_configuration.rb
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+# +ManagedNodeConfiguration+ takes in the description for a managed node and,
+# from that, generates the configuration file that is consumed the next time
+# the managed node starts up.
+#
+
+require 'stringio'
+
+$: << File.join(File.dirname(__FILE__), "../dutils")
+$: << File.join(File.dirname(__FILE__), "../")
+
+class ManagedNodeConfiguration
+ NIC_ENTRY_PREFIX='/files/etc/sysconfig/network-scripts'
+
+ def self.generate(host)
+ result = StringIO.new
+
+ host.nics.each do |nic|
+ result.puts "rm #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}"
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/DEVICE
#{nic.iface_name}"
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/IPADDR
#{nic.ip_addr}" if nic.ip_addr
+ result.puts "set
#{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/BOOTPROTO dhcp" if
nic.ip_addr == nil
+ result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{nic.iface_name}/BRIDGE
#{nic.bridge}" if nic.bridge
+ end
+
+ result.puts "save"
+
+ result.string
+ end
+end
+
diff --git a/wui/src/test/fixtures/nics.yml b/wui/src/test/fixtures/nics.yml
index 008cfb7..c31714a 100644
--- a/wui/src/test/fixtures/nics.yml
+++ b/wui/src/test/fixtures/nics.yml
@@ -6,6 +6,7 @@ one:
usage_type: '1'
bandwidth: 100
host_id: 1
+ iface_name: eth0
two:
id: 2
mac: 'AA:BB:CC:DD:EE:FF'
@@ -13,6 +14,7 @@ two:
usage_type: '2'
bandwidth: 1000
host_id: 1
+ iface_name: eth1
three:
id: 3
mac: '00:FF:11:EE:22:DD'
@@ -20,3 +22,4 @@ three:
usage_type: '1'
bandwidth: 10
host_id: 2
+ iface_name: eth0
diff --git a/wui/src/test/unit/host_browser_awaken_test.rb
b/wui/src/test/unit/host_browser_awaken_test.rb
new file mode 100755
index 0000000..5340e01
--- /dev/null
+++ b/wui/src/test/unit/host_browser_awaken_test.rb
@@ -0,0 +1,96 @@
+#!/usr/bin/ruby -Wall
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+require File.dirname(__FILE__) + '/../test_helper'
+require 'test/unit'
+require 'flexmock/test_unit'
+
+TESTING=true
+
+require 'host-browser'
+
+# +HostBrowserAwakenTest+ ensures that the host-browser daemon works correctly
+# during the identify phase of operation.
+#
+class HostBrowserAwakenTest < Test::Unit::TestCase
+
+ def setup
+ @session = flexmock('session')
+ @session.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
+
+ @krb5 = flexmock('krb5')
+
+ @browser = HostBrowser.new(@session)
+ @browser.logfile = './unit-test.log'
+ @browser.keytab_dir = '/var/temp/'
+ end
+
+ # Ensures that the server raises an exception when it receives an
+ # improper handshake response.
+ #
+ def test_begin_conversation_with_improper_response_to_greeting
+ @session.should_receive(:write).with("HELLO?\n").once().returns {
|greeting| greeting.length }
+ @session.should_receive(:readline).once().returns { "SUP?" }
+
+ assert_raise(Exception) { @browser.begin_conversation }
+ end
+
+ # Ensures the server accepts a proper response from the remote system.
+ #
+ def test_begin_conversation
+ @session.should_receive(:write).with("HELLO?\n").once().returns {
|greeting| greeting.length }
+ @session.should_receive(:readline).once().returns { "HELLO!\n" }
+
+ assert_nothing_raised(Exception) { @browser.begin_conversation }
+ end
+
+ # Ensures that the server is satisfied if the remote system is
+ # making a wakeup call.
+ #
+ def test_get_mode_with_awaken_request
+ @session.should_receive(:write).with("MODE?\n").once().returns {
|request| request.length }
+ @session.should_receive(:readline).once().returns { "AWAKEN\n" }
+
+ result = @browser.get_mode()
+
+ assert_equal "AWAKEN", result, "method did not return the
right value"
+ end
+
+ # Ensures the host browser generates a keytab as expected.
+ #
+ def test_create_keytab
+ @krb5.should_receive(:get_default_realm).once().returns {
"ovirt-test-realm" }
+ servername = `hostname -f`.chomp
+ @session.should_receive(:write).with("KTAB
http://#{servername}/ipa/config/127.0.0.1-libvirt.tab\n").once().returns {
|request| request.length }
+ @session.should_receive(:readline).once().returns { "ACK\n" }
+
+ assert_nothing_raised(Exception) {
@browser.create_keytab('localhost','127.0.0.1', at krb5) }
+ end
+
+ # Ensures that, if a keytab is present and a key version number available,
+ # the server ends the conversation by returning the key version number.
+ #
+ def test_end_conversation
+ @session.should_receive(:write).with("BYE\n").once().returns {
|request| request.length }
+
+ assert_nothing_raised(Exception) { @browser.end_conversation }
+ end
+
+end
diff --git a/wui/src/test/unit/host_browser_identify_test.rb
b/wui/src/test/unit/host_browser_identify_test.rb
new file mode 100755
index 0000000..e43507c
--- /dev/null
+++ b/wui/src/test/unit/host_browser_identify_test.rb
@@ -0,0 +1,304 @@
+#!/usr/bin/ruby -Wall
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+require 'test/unit'
+require 'flexmock/test_unit'
+require 'dutils'
+
+TESTING=true
+
+require 'host-browser'
+
+# +HostBrowserIdentifyTest+ tests the host-browser server to ensure that it
+# works correctly during the identify mode of operation.
+#
+class HostBrowserIdentifyTest < Test::Unit::TestCase
+ def setup
+ @connection = flexmock('connection')
+ @connection.should_receive(:peeraddr).at_least.once.returns {
[nil,nil,nil,"192.168.2.255"] }
+
+ @browser = HostBrowser.new(@connection)
+ @browser.logfile = './unit-test.log'
+
+ # default host info
+ @host_info = {}
+ @host_info['UUID'] = 'node1'
+ @host_info['IPADDR'] = '192.168.2.2'
+ @host_info['HOSTNAME'] = 'prod.corp.com'
+ @host_info['ARCH'] = 'x86_64'
+ @host_info['MEMSIZE'] = '16384'
+ @host_info['DISABLED'] = '0'
+
+ @host_info['NUMCPUS'] = '2'
+
+ @host_info['CPUINFO'] = Array.new
+ @host_info['CPUINFO'][0] = {}
+ @host_info['CPUINFO'][0]['CPUNUM'] = '0'
+ @host_info['CPUINFO'][0]['CORENUM'] = '0'
+ @host_info['CPUINFO'][0]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][0]['VENDOR'] =
'GenuineIntel'
+ @host_info['CPUINFO'][0]['MODEL'] = '15'
+ @host_info['CPUINFO'][0]['FAMILY'] = '6'
+ @host_info['CPUINFO'][0]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][0]['SPEED'] = '3'
+ @host_info['CPUINFO'][0]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][0]['FLAGS'] = 'fpu vme de pse
tsc msr pae \
+ mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
+ fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
+ bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
+
+ @host_info['CPUINFO'][1] = {}
+ @host_info['CPUINFO'][1]['CPUNUM'] = '1'
+ @host_info['CPUINFO'][1]['CORENUM'] = '1'
+ @host_info['CPUINFO'][1]['NUMCORES'] = '2'
+ @host_info['CPUINFO'][1]['VENDOR'] =
'GenuineIntel'
+ @host_info['CPUINFO'][1]['MODEL'] = '15'
+ @host_info['CPUINFO'][1]['FAMILY'] = '6'
+ @host_info['CPUINFO'][1]['CPUIDLVL'] = '10'
+ @host_info['CPUINFO'][1]['SPEED'] = '3'
+ @host_info['CPUINFO'][1]['CACHE'] = '4096 kb'
+ @host_info['CPUINFO'][1]['FLAGS'] = 'fpu vme de pse
tsc msr pae \
+ mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx \
+ fxsr sse sse2 ss ht tm pbe nx lm constant_tsc arch_perfmon pebs \
+ bts pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr lahf_lm'
+
+ @host_info['NICINFO'] = Array.new
+ @host_info['NICINFO'] << {
+ 'MAC' => '00:11:22:33:44:55',
+ 'BANDWIDTH' => '100',
+ 'IFACE_NAME' => 'eth0'}
+
+ @host_info['NICINFO'] << {
+ 'MAC' => '00:77:11:77:19:65',
+ 'BANDWIDTH' => '100',
+ 'IFACE_NAME' => 'eth01'}
+ end
+
+ # Ensures that the server is satisfied if the remote system is
+ # making a wakeup call.
+ #
+ def test_get_mode_with_awaken_request
+ @connection.should_receive(:write).with("MODE?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"IDENTIFY\n" }
+
+ result = @browser.get_mode()
+
+ assert_equal "IDENTIFY", result, "method did not return the
right value"
+ end
+
+ # Ensures that, if an info field is missing a key, the server raises
+ # an exception.
+ #
+ def test_get_info_with_missing_key
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"=value1\n" }
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that, if an info field is missing a value, the server raises
+ # an exception.
+ #
+ def test_get_info_with_missing_value
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "key1=\n"
}
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that, if the server gets a poorly formed ending statement, it
+ # raises an exception.
+ #
+ def test_get_info_with_invalid_end
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDIFNO\n" }
+
+ assert_raise(Exception) { @browser.get_remote_info }
+ end
+
+ # Ensures that a well-formed transaction works as expected.
+ #
+ def test_get_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 4,info.keys.size, "Should contain four keys"
+ assert info.include?("IPADDR")
+ assert info.include?("HOSTNAME")
+ assert info.include?("key1")
+ assert info.include?("key2")
+ end
+
+ # Ensures that the server is fine when no UUID is present.
+ #
+ def test_write_host_info_with_missing_uuid
+ @host_info['UUID'] = nil
+
+ assert_nothing_raised { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the hostname is missing, the server
+ # raises an exception.
+ #
+ def test_write_host_info_with_missing_hostname
+ @host_info['HOSTNAME'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the architecture is missing, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_arch
+ @host_info['ARCH'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if the memory size is missing, the server raises an
+ # exception.
+ #
+ def test_write_host_info_info_with_missing_memsize
+ @host_info['MEMSIZE'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if no cpu info was available, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_cpuinfo
+ @host_info['CPUINFO'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if no NIC info was available, the server raises an
+ # exception.
+ #
+ def test_write_host_info_with_missing_nicinfo
+ @host_info['NICINFO'] = nil
+
+ assert_raise(Exception) { @browser.write_host_info(@host_info) }
+ end
+
+ # Ensures that, if a NIC is present that was already submitted, it
+ # doesn't get re-entered.
+ #
+ def test_write_host_info_with_duplicate_nic
+ # Values taken from the nics.yml fixture
+ @host_info['NICINFO'] << {
+ 'MAC' => '00:11:22:33:44:55',
+ 'BANDWIDTH' => '100',
+ 'IFACE_NAME' => 'eth0'
+ }
+
+ assert_nothing_raised { @browser.write_host_info(@host_info) }
+ assert_equal 3, Host.find_by_hostname('prod.corp.com').nics.size,
'Expected three NICs.'
+ end
+
+ # Ensures the browser can properly parse the CPU details.
+ #
+ def test_parse_cpu_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?("CPUINFO")
+ end
+
+ # Ensures the browser can properly parse the CPU details of two CPUs.
+ #
+ def test_parse_cpu_info_with_two_entries
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+
+ # CPU 0
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+
+ # CPU 1
+ @connection.should_receive(:readline).once().returns { "CPU\n" }
+
@connection.should_receive(:write).with("CPUINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key3=value3\n" }
+ @connection.should_receive(:write).with("ACK
key3\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key4=value4\n" }
+ @connection.should_receive(:write).with("ACK
key4\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDCPU\n"
}
+ @connection.should_receive(:write).with("ACK
CPU\n").once().returns { |request| request.length }
+
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?('CPUINFO')
+ assert_equal 2, info['CPUINFO'].size, "Should contain details
for two CPUs"
+ assert_not_nil info['CPUINFO'][0]['key1']
+ assert_not_nil info['CPUINFO'][0]['key2']
+ assert_not_nil info['CPUINFO'][1]['key3']
+ assert_not_nil info['CPUINFO'][1]['key4']
+ end
+
+ # Ensures the browser can properly parse the details for a NIC.
+ #
+ def test_parse_nic_info
+ @connection.should_receive(:write).with("INFO?\n").once().returns
{ |request| request.length }
+ @connection.should_receive(:readline).once().returns { "NIC\n" }
+
@connection.should_receive(:write).with("NICINFO?\n").once().returns {
|request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key1=value1\n" }
+ @connection.should_receive(:write).with("ACK
key1\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"key2=value2\n" }
+ @connection.should_receive(:write).with("ACK
key2\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns { "ENDNIC\n"
}
+ @connection.should_receive(:write).with("ACK
NIC\n").once().returns { |request| request.length }
+ @connection.should_receive(:readline).once().returns {
"ENDINFO\n" }
+
+ info = @browser.get_remote_info
+
+ assert_equal 3,info.keys.size, "Should contain four keys"
+ assert info.include?("NICINFO")
+ end
+end
diff --git a/wui/src/test/unit/managed_node_configuration_test.rb
b/wui/src/test/unit/managed_node_configuration_test.rb
new file mode 100644
index 0000000..01b3fe4
--- /dev/null
+++ b/wui/src/test/unit/managed_node_configuration_test.rb
@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# Written by Darryl L. Pierce <dpierce at redhat.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA. A copy of the GNU General Public License is
+# also available at http://www.gnu.org/copyleft/gpl.html.
+
+$:.unshift File.join(File.dirname(__FILE__),'..','lib')
+
+# require File.dirname(__FILE__) + '/../test/test_helper'
+require 'test/unit'
+require 'managed_node_configuration'
+require 'dutils'
+
+# Performs unit tests on the +ManagedNodeConfiguration+ class.
+#
+class ManagedNodeConfigurationTest < Test::Unit::TestCase
+ def setup
+ @host = Host.new
+ end
+
+
+ # Ensures that network interfaces uses DHCP when no IP address is specified.
+ #
+ def test_generate_with_no_ip_address
+ @host.nics << Nic.new(:iface_name => 'eth0')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BOOTPROTO dhcp
+save
+HERE
+
+ result = ManagedNodeConfiguration.generate @host
+
+ assert_equal expected, result
+ end
+
+ # Ensures that network interfaces use the IP address when it's provided.
+ #
+ def test_generate_with_ip_address
+ @host.nics << Nic.new(:iface_name => 'eth0', :ip_addr
=> '192.168.2.1')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/IPADDR 192.168.2.1
+save
+HERE
+
+ result = ManagedNodeConfiguration.generate @host
+
+ assert_equal expected, result
+ end
+
+ # Ensures the bridge is added to the configuration if one is defined.
+ #
+ def test_generate_with_bridge
+ @host.nics << Nic.new(:iface_name => 'eth0', :bridge =>
'ovirtbr0')
+
+ expected = <<HERE
+rm /files/etc/sysconfig/network-scripts/ifcfg-eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/DEVICE eth0
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BOOTPROTO dhcp
+set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BRIDGE ovirtbr0
+save
+HERE
+
+ result = ManagedNodeConfiguration.generate @host
+
+ assert_equal expected, result
+ end
+
+end
--
1.5.5.1