[Ovirt-devel] [PATCH server] Replaced the config scripts with configuration encoding.

Darryl L. Pierce dpierce at redhat.com
Wed Oct 8 19:04:20 UTC 2008


Rather than sending the node a series of scripts that load
kernel modules, or are tightly coupled to tools like augeas,
this patch introduces an encoding scheme for data.

A line that begins with "kmod" describes a kernel module that
needs to be loaded. It will containing the module's name, an
optional alias for the module, and then the module options
if such are required.

A line that begins with "ifcfg" describes an network
interface. It will contain the mac address and interface name,
followed by all needed configuration values to bring the
interface up.

Signed-off-by: Darryl L. Pierce <dpierce at redhat.com>
---
 src/app/models/bonding.rb                          |    1 +
 src/lib/managed_node_configuration.rb              |   72 +++++++++------
 src/test/fixtures/bondings.yml                     |    8 ++-
 src/test/fixtures/bondings_nics.yml                |    8 ++
 src/test/fixtures/hosts.yml                        |   10 ++
 src/test/fixtures/nics.yml                         |   14 +++
 .../functional/managed_node_configuration_test.rb  |   94 ++++++++------------
 7 files changed, 118 insertions(+), 89 deletions(-)

diff --git a/src/app/models/bonding.rb b/src/app/models/bonding.rb
index 941e2cd..7bef2f8 100644
--- a/src/app/models/bonding.rb
+++ b/src/app/models/bonding.rb
@@ -38,6 +38,7 @@ class Bonding < ActiveRecord::Base
 
   belongs_to :host
   belongs_to :bonding_type
+  belongs_to :boot_type
 
   has_and_belongs_to_many :nics,
     :join_table  => 'bondings_nics',
diff --git a/src/lib/managed_node_configuration.rb b/src/lib/managed_node_configuration.rb
index 4ade235..8c8892b 100644
--- a/src/lib/managed_node_configuration.rb
+++ b/src/lib/managed_node_configuration.rb
@@ -23,36 +23,57 @@
 
 require 'stringio'
 
+# +ManagedNodeConfiguration+ generates a configuration file for an oVirt node
+# based on information about the hardware submitted by the node and the
+# configuration details held in the database.
+#
+# The configuration is returned as a series of encoded lines.
+#
+# For a kernel module, the formation of the line is as follows:
+#
+# kmod=[module name]|[module alias]|[module options]
+#
+# An example would be for loading the +bonding+ kernel module to setup a bonded
+# interface for load balancing. In this example, the bonded interface would be
+# named +failover0+ on the node:
+#
+# kmod=bonding|failover0|mode=2 miimon=100 downdelay=200
+#
+# For a network interface (including a bonded interface) an example would be:
+#
+# ifcfg=00:11:22:33:44|eth0|BOOTPROTO=dhcp|bridge=ovirtbr0|ONBOOT=yes
+#
+# In this line, the network interface +eth0+ has a hardware MAC address of
+# +00:11:22:33:44+. It will use DHCP for retrieving it's IP address details,
+# and will use the +ovirtbr0+ interface as a bridge.
+#
 class ManagedNodeConfiguration
   NIC_ENTRY_PREFIX='/files/etc/sysconfig/network-scripts'
 
   def self.generate(host, macs)
     result = StringIO.new
 
-    result.puts "#!/bin/bash"
     result.puts "# THIS FILE IS GENERATED!"
 
     # first process any bondings that're defined
     unless host.bondings.empty?
-      result.puts "cat <<\EOF > /var/tmp/pre-config-script"
-      result.puts "#!/bin/bash"
-      result.puts "# THIS FILE IS GENERATED!"
-
       host.bondings.each do |bonding|
-        result.puts "/sbin/modprobe bonding mode=#{bonding.bonding_type.mode}"
+        result.puts "bonding=#{bonding.interface_name}|mode=#{bonding.bonding_type.mode} miimon=100 downdelay=200"
       end
-
-      result.puts "EOF"
     end
 
     # now process the network interfaces  and bondings
-    result.puts "cat <<\EOF > /var/tmp/node-augtool"
 
     host.bondings.each do |bonding|
-      result.puts "rm #{NIC_ENTRY_PREFIX}/ifcfg-#{bonding.interface_name}"
-      result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{bonding.interface_name}/DEVICE #{bonding.interface_name}"
-      result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{bonding.interface_name}/IPADDR #{bonding.ip_addr}" if bonding.ip_addr
-      result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{bonding.interface_name}/ONBOOT yes"
+      entry = "ifcfg=none|#{bonding.interface_name}"
+
+      if bonding.ip_addr == nil || bonding.ip_addr.empty?
+        entry += "|BOOTPROTO=dhcp"
+      else
+        entry += "|BOOTPROTO=static|IPADDR=#{bonding.ip_addr}|NETMASK=#{bonding.netmask}|BROADCAST=#{bonding.broadcast}"
+      end
+
+      result.puts "#{entry}|ONBOOT=yes"
 
       bonding.nics.each do |nic|
         process_nic result, nic, macs, bonding
@@ -66,9 +87,6 @@ class ManagedNodeConfiguration
       end
     end
 
-    result.puts "save"
-    result.puts "EOF"
-
     result.string
   end
 
@@ -78,24 +96,18 @@ class ManagedNodeConfiguration
     iface_name = macs[nic.mac]
 
     if iface_name
-      result.puts "rm #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}"
-      result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/DEVICE #{iface_name}"
+      entry = "ifcfg=#{nic.mac}|#{iface_name}"
 
       if bonding
-        result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/MASTER #{bonding.interface_name}"
-        result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/SLAVE yes"
+        entry += "|MASTER=#{bonding.interface_name}|SLAVE=yes"
       else
-        result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/BOOTPROTO #{nic.boot_type.proto}"
-
-        if nic.boot_type.proto == 'static'
-          result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/IPADDR #{nic.ip_addr}"
-          result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/NETMASK #{nic.netmask}"
-          result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/BROADCAST #{nic.broadcast}"
-        end
+        entry += "|BOOTPROTO=#{nic.boot_type.proto}"
+        entry += "|IPADDR=#{nic.ip_addr}|NETMASK=#{nic.netmask}|BROADCAST=#{nic.broadcast}" if nic.boot_type.proto == 'static'
+        entry += "|BRIDGE=#{nic.bridge}" if nic.bridge
       end
-
-      result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/BRIDGE #{nic.bridge}"     if nic.bridge
-      result.puts "set #{NIC_ENTRY_PREFIX}/ifcfg-#{iface_name}/ONBOOT yes"
+      entry += "|ONBOOT=yes"
     end
+
+    result.puts entry if defined? entry
   end
 end
diff --git a/src/test/fixtures/bondings.yml b/src/test/fixtures/bondings.yml
index c2a47b5..7023e08 100644
--- a/src/test/fixtures/bondings.yml
+++ b/src/test/fixtures/bondings.yml
@@ -1,6 +1,6 @@
 mailservers_managed_node_bonding:
     name: Production Network
-    interface_name: bond0
+    interface_name: mailbonding0
     bonding_type_id: <%= Fixtures.identify(:link_aggregation_bonding_type) %>
     host_id: <%= Fixtures.identify(:mailservers_managed_node) %>
     ip_addr: 172.31.0.15
@@ -8,3 +8,9 @@ mailservers_managed_node_bonding:
     broadcast: 172.31.0.255
     arp_ping_address: 172.31.0.100
     arp_interval: 0
+
+mediaserver_managed_node_bonding:
+    name: Fileserver Network
+    interface_name: mediabonding0
+    bonding_type_id: <%= Fixtures.identify(:link_aggregation_bonding_type) %>
+    host_id: <%= Fixtures.identify(:mediaserver_managed_node) %>
diff --git a/src/test/fixtures/bondings_nics.yml b/src/test/fixtures/bondings_nics.yml
index 11a3d1a..607ff8b 100644
--- a/src/test/fixtures/bondings_nics.yml
+++ b/src/test/fixtures/bondings_nics.yml
@@ -5,3 +5,11 @@ mailservers_managed_node_bonding_nic_1:
 mailservers_managed_node_bonding_nic_2:
     bonding_id: <%= Fixtures.identify(:mailservers_managed_node_bonding) %>
     nic_id: <%= Fixtures.identify(:mailserver_nic_two) %>
+
+mediaservers_managed_node_bonding_nic_1:
+    bonding_id: <%= Fixtures.identify(:mediaserver_managed_node_bonding) %>
+    nic_id: <%= Fixtures.identify(:mediaserver_nic_one) %>
+
+mediaservers_managed_node_bonding_nic_2:
+    bonding_id: <%= Fixtures.identify(:mediaserver_managed_node_bonding) %>
+    nic_id: <%= Fixtures.identify(:mediaserver_nic_two) %>
diff --git a/src/test/fixtures/hosts.yml b/src/test/fixtures/hosts.yml
index 5b8af15..28282c2 100644
--- a/src/test/fixtures/hosts.yml
+++ b/src/test/fixtures/hosts.yml
@@ -125,3 +125,13 @@ buildserver_managed_node:
     is_disabled: 0
     hypervisor_type: 'kvm'
     hardware_pool_id: <%= Fixtures.identify(:prodops_pool) %>
+
+mediaserver_managed_node:
+    uuid: '6293acd9-2784-11dc-9387-001558c41534'
+    hostname: 'build.mynetwork.com'
+    arch: 'x86_64'
+    memory: 65536
+    is_disabled: 0
+    hypervisor_type: 'kvm'
+    hardware_pool_id: <%= Fixtures.identify(:prodops_pool) %>
+
diff --git a/src/test/fixtures/nics.yml b/src/test/fixtures/nics.yml
index ccf71d2..5b2cecc 100644
--- a/src/test/fixtures/nics.yml
+++ b/src/test/fixtures/nics.yml
@@ -78,3 +78,17 @@ buildserver_nic_two:
     broadcast: '172.31.0.255'
     host_id: <%= Fixtures.identify(:buildserver_managed_node) %>
     boot_type_id: <%= Fixtures.identify(:boot_type_static_ip) %>
+
+mediaserver_nic_one:
+    mac: '07:17:19:65:03:32'
+    usage_type: '1'
+    bandwidth: 100
+    host_id: <%= Fixtures.identify(:mediaserver_managed_node) %>
+    boot_type_id: <%= Fixtures.identify(:boot_type_dhcp) %>
+
+mediaserver_nic_two:
+    mac: '07:17:19:65:03:31'
+    usage_type: '1'
+    bandwidth: 100
+    host_id: <%= Fixtures.identify(:mediaserver_managed_node) %>
+    boot_type_id: <%= Fixtures.identify(:boot_type_dhcp) %>
diff --git a/src/test/functional/managed_node_configuration_test.rb b/src/test/functional/managed_node_configuration_test.rb
index b5a7ec5..fd2139e 100644
--- a/src/test/functional/managed_node_configuration_test.rb
+++ b/src/test/functional/managed_node_configuration_test.rb
@@ -36,6 +36,7 @@ class ManagedNodeConfigurationTest < Test::Unit::TestCase
     @host_with_ip_address = hosts(:ldapserver_managed_node)
     @host_with_multiple_nics = hosts(:buildserver_managed_node)
     @host_with_bondings = hosts(:mailservers_managed_node)
+    @host_with_dhcp_bondings = hosts(:mediaserver_managed_node)
   end
 
   # Ensures that network interfaces uses DHCP when no IP address is specified.
@@ -44,15 +45,8 @@ class ManagedNodeConfigurationTest < Test::Unit::TestCase
     nic = @host_with_dhcp_card.nics.first
 
     expected = <<-HERE
-#!/bin/bash
 # THIS FILE IS GENERATED!
-cat <<\EOF > /var/tmp/node-augtool
-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 #{nic.boot_type.proto}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/ONBOOT yes
-save
-EOF
+ifcfg=#{nic.mac}|eth0|BOOTPROTO=dhcp|ONBOOT=yes
     HERE
 
     result = ManagedNodeConfiguration.generate(
@@ -69,19 +63,8 @@ EOF
     nic = @host_with_ip_address.nics.first
 
     expected = <<-HERE
-#!/bin/bash
 # THIS FILE IS GENERATED!
-cat <<\EOF > /var/tmp/node-augtool
-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 #{nic.boot_type.proto}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/IPADDR #{nic.ip_addr}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/NETMASK #{nic.netmask}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BROADCAST #{nic.broadcast}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BRIDGE ovirtbr0
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/ONBOOT yes
-save
-EOF
+ifcfg=#{nic.mac}|eth0|BOOTPROTO=#{nic.boot_type.proto}|IPADDR=#{nic.ip_addr}|NETMASK=#{nic.netmask}|BROADCAST=#{nic.broadcast}|BRIDGE=#{nic.bridge}|ONBOOT=yes
     HERE
 
     result = ManagedNodeConfiguration.generate(
@@ -99,22 +82,9 @@ EOF
     nic2 = @host_with_multiple_nics.nics[1]
 
     expected = <<-HERE
-#!/bin/bash
 # THIS FILE IS GENERATED!
-cat <<\EOF > /var/tmp/node-augtool
-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 #{nic1.boot_type.proto}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/IPADDR #{nic1.ip_addr}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/NETMASK #{nic1.netmask}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/BROADCAST #{nic1.broadcast}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/ONBOOT yes
-rm /files/etc/sysconfig/network-scripts/ifcfg-eth1
-set /files/etc/sysconfig/network-scripts/ifcfg-eth1/DEVICE eth1
-set /files/etc/sysconfig/network-scripts/ifcfg-eth1/BOOTPROTO #{nic2.boot_type.proto}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth1/ONBOOT yes
-save
-EOF
+ifcfg=#{nic1.mac}|eth0|BOOTPROTO=#{nic1.boot_type.proto}|IPADDR=#{nic1.ip_addr}|NETMASK=#{nic1.netmask}|BROADCAST=#{nic1.broadcast}|ONBOOT=yes
+ifcfg=#{nic2.mac}|eth1|BOOTPROTO=#{nic2.boot_type.proto}|ONBOOT=yes
     HERE
 
     result = ManagedNodeConfiguration.generate(
@@ -137,30 +107,11 @@ EOF
     nic2 = bonding.nics[1]
 
     expected = <<-HERE
-#!/bin/bash
 # THIS FILE IS GENERATED!
-cat <<\EOF > /var/tmp/pre-config-script
-#!/bin/bash
-# THIS FILE IS GENERATED!
-/sbin/modprobe bonding mode=#{bonding.bonding_type.mode}
-EOF
-cat <<\EOF > /var/tmp/node-augtool
-rm /files/etc/sysconfig/network-scripts/ifcfg-#{bonding.interface_name}
-set /files/etc/sysconfig/network-scripts/ifcfg-#{bonding.interface_name}/DEVICE #{bonding.interface_name}
-set /files/etc/sysconfig/network-scripts/ifcfg-#{bonding.interface_name}/IPADDR 172.31.0.15
-set /files/etc/sysconfig/network-scripts/ifcfg-#{bonding.interface_name}/ONBOOT yes
-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/MASTER #{bonding.interface_name}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/SLAVE yes
-set /files/etc/sysconfig/network-scripts/ifcfg-eth0/ONBOOT yes
-rm /files/etc/sysconfig/network-scripts/ifcfg-eth1
-set /files/etc/sysconfig/network-scripts/ifcfg-eth1/DEVICE eth1
-set /files/etc/sysconfig/network-scripts/ifcfg-eth1/MASTER #{bonding.interface_name}
-set /files/etc/sysconfig/network-scripts/ifcfg-eth1/SLAVE yes
-set /files/etc/sysconfig/network-scripts/ifcfg-eth1/ONBOOT yes
-save
-EOF
+bonding=#{bonding.interface_name}|mode=#{bonding.bonding_type.mode} miimon=100 downdelay=200
+ifcfg=none|#{bonding.interface_name}|BOOTPROTO=static|IPADDR=#{bonding.ip_addr}|NETMASK=#{bonding.netmask}|BROADCAST=#{bonding.broadcast}|ONBOOT=yes
+ifcfg=#{nic1.mac}|eth0|MASTER=#{bonding.interface_name}|SLAVE=yes|ONBOOT=yes
+ifcfg=#{nic2.mac}|eth1|MASTER=#{bonding.interface_name}|SLAVE=yes|ONBOOT=yes
 HERE
 
     result = ManagedNodeConfiguration.generate(
@@ -173,4 +124,31 @@ HERE
     assert_equal expected, result
   end
 
+  # Ensures that the generated bonding supports DHCP boot protocol.
+  #
+  def test_generate_with_dhcp_bonding
+    bonding = @host_with_dhcp_bondings.bondings.first
+
+    bonding.ip_addr=nil
+    nic1 = bonding.nics[0]
+    nic2 = bonding.nics[1]
+
+    expected = <<-HERE
+# THIS FILE IS GENERATED!
+bonding=#{bonding.interface_name}|mode=#{bonding.bonding_type.mode} miimon=100 downdelay=200
+ifcfg=none|#{bonding.interface_name}|BOOTPROTO=dhcp|ONBOOT=yes
+ifcfg=#{nic1.mac}|eth0|MASTER=#{bonding.interface_name}|SLAVE=yes|ONBOOT=yes
+ifcfg=#{nic2.mac}|eth1|MASTER=#{bonding.interface_name}|SLAVE=yes|ONBOOT=yes
+HERE
+
+    result = ManagedNodeConfiguration.generate(
+      @host_with_dhcp_bondings,
+      {
+        "#{nic1.mac}" => 'eth0',
+        "#{nic2.mac}" => 'eth1'
+      })
+
+    assert_equal expected, result
+  end
+
 end
-- 
1.5.5.1




More information about the ovirt-devel mailing list