Home | Linux | NetworkManager |     Share This Page

Ruby Listing: configure.rb


Click here to download a plain-text version of this file.

#!/usr/bin/ruby -w

=begin
/***************************************************************************
 *   Copyright (C) 2008, Paul Lutus                                        *
 *                                                                         *
 *   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; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
=end

# routines to convert between dotted strings <-> integer IPs

def ip_to_int(ipstring)
   v = 0
   ipstring.split(".").reverse.each do |s|
      v = (v << 8) + (s.to_i)
   end
   return v
end

def int_to_ip(v)
   array = []
   n = 4
   begin
      array << (v % 0x100).to_s
      v >>= 8
   end while((n -= 1) > 0)
   return array.join(".")
end

# routine to convert string characters to int array
# used in SSID encoding

def string_to_int_array(s)
   return "[" + s.unpack("c*").join(",") + "]"
end

# check for the presence of a wireless NIC
# users may want to add to the short list of applicable NIC types
# or simply detect the word "wireless" and act accordingly

def has_wireless(sys)
   data = `ssh #{sys} /sbin/lspci`
   [ "2200","3945","4965" ].each do |wi|
      if(data =~ /Wireless\s*#{wi}/i)
         return true
      end
   end
   return false
end

# get a list of local network host names and IPs
# this could be replaced by any other way to
# create a hostname/IP hash

def get_ip_list(system_list)
   data = File.read("/etc/hosts")
   hash = {}
   system_list.each do |sys|
      addr = data.sub(%r{.*^([\d|\.]+)\s.*?#{sys}$.*}m,"\\1")
      hash[sys] = addr
   end
   return hash
end

# create a tagged type/value pair as a hash

def type_value(type,value)
   return { "type" => type, "value" => value }
end

# various data set constructors

def construct_ipv4_spec(ip,gateway,bits,dns_list,dns)
   hash = {}
   hash["addresses"] = type_value("list","[#{ip_to_int(ip)},#{bits},#{ip_to_int(gateway)}]")
   hash["dns"] = type_value("list",dns_list) if dns
   hash["method"] = type_value("string","manual")
   hash["name"] = type_value("string","ipv4")
   hash["routes"] = type_value("list","[]")
   return hash
end

def construct_connection_spec(id,autoconnect,type)
   hash = {}
   hash["autoconnect"] = type_value("booelan",autoconnect)
   hash["id"] = type_value("string",id)
   hash["type"] = type_value("string",type)
   hash["name"] = type_value("string","connection")
   return hash
end

def construct_wired_network_spec()
   hash = {}
   hash["duplex"] = type_value("string","full")
   hash["name"] = type_value("string","802-3-ethernet")
   return hash
end

def construct_wireless_network_spec(ssid,adhoc)
   hash = {}
   hash["mode"] = type_value("string",(adhoc)?"adhoc":"infrastructure")
   hash["name"] = type_value("string","802-11-wireless")
   hash["security"] = type_value("string","802-11-wireless-security")
   hash["ssid"] = type_value("list",string_to_int_array(ssid))
   return hash
end

def construct_wireless_security_spec(adhoc)
   hash = {}
   if(adhoc)
      hash["key-mgmt"] = type_value("string","none")
      hash["auth_alg"] = type_value("string","open")
   else
      hash["key-mgmt"] = type_value("string","wpa-psk")
   end
   hash["name"] = type_value("string","802-11-wireless-security")
   return hash
end

def construct_wired_tree(sys,ip,gateway,bits,dns_list)
   hash = {}
   hash["ipv4"] = construct_ipv4_spec(ip,gateway,bits,dns_list,true)
   hash["connection"] = construct_connection_spec("Wired eth0",true,"802-3-ethernet")
   hash["802-3-ethernet"] = construct_wired_network_spec()
   return hash
end

def construct_wireless_tree(sys,ssid,ip,gateway,bits,dns_list,adhoc)
   hash = {}
   hash["ipv4"] = construct_ipv4_spec(ip,gateway,bits,dns_list,!adhoc)
   hash["connection"] = construct_connection_spec("Wireless " + ssid,false,"802-11-wireless")
   hash["802-11-wireless"] = construct_wireless_network_spec(ssid,adhoc)
   hash["802-11-wireless-security"] = construct_wireless_security_spec(adhoc)
   return hash
end

# debugging routines that print out the entire data tree

def mktab(n)
   return "\t" * n
end

def show_tree(hash,tab = 0)
   hash.keys.sort.each do |key|
      if(hash[key].class == Hash)
         puts "#{mktab(tab)}#{key}"
         show_tree(hash[key],tab+1)
      else
         puts "#{mktab(tab)}#{key} = #{hash[key]}"
      end
   end
end

# build connection database

def build_database(system_list,addr_hash,wap_list,dns_list,gateway,bits)
   hash = {}
   system_list.each do |sys|
      hash[sys] = {}
      ip = addr_hash[sys]
      hash[sys]["Wired_eth0"] = construct_wired_tree(sys,ip,gateway,bits,dns_list)
      if(has_wireless(sys))
         wap_list.split("\s").each do |wap|
            hash[sys]["Wireless_" + wap] = construct_wireless_tree(sys,wap,ip,gateway,bits,dns_list,false)
         end
         hash[sys]["Wireless_pl-adhoc"] = construct_wireless_tree(sys,"pl-adhoc",ip,ip,bits,dns_list,true)
      end
   end
   return hash
end

# recursive tree traversal to build gconf definition paths

def program_system_recursive(list,hash,path,n)
   hash.keys.sort.each do |key|
      if(n < 2)
         list = program_system_recursive(list,hash[key],path + "/" + key,n+1)
      else
         type,value = hash[key]["type"],hash[key]["value"]
         type_str = "--type #{type}"
         type_str += " --list-type int" if(type =~ /list/)
         arg = "gconftool-2 #{type_str} --set #{path}/#{key} '#{value}'"
         print "."
         list += "#{arg};"
      end
   end
   return list
end

# construct the paths and program the gconf database

def program_network(tree,gcp)
   tree.keys.sort.each do |sys|
      # tell the user what's happening
      print "Programming #{sys} "
      # erase previous connection entries
      com_list = "gconftool-2 --recursive-unset #{gcp};"
      # create new entries as a data block
      com_list = program_system_recursive(com_list,tree[sys],gcp,0)
      puts ""
      # send the data block to the target machine
      `ssh #{sys} "#{com_list}"`
   end
end

# user actions

print "Okay to program network with NetworkManager data (y/N):"

reply = STDIN.readline.chomp

if(reply != "y")
   exit 0
end

# get a list of network host names
# again, any way to create a list of hostnames
# could be placed here

system_list=`sysnames.sh`.chomp.split("\s")

# create hash with hostname/IP key/value pairs

addr_hash = get_ip_list(system_list)

# local network specifications

gateway = "192.168.0.96"
dns1 = "xxx.xxx.xxx.xxx"
dns2 = "xxx.xxx.xxx.xxx"
dns3 = "xxx.xxx.xxx.xxx"
bits = "24"

dns_list = "[#{ip_to_int(dns1)},#{ip_to_int(dns2)},#{ip_to_int(dns3)}]"

# wireless access point SSIDs

wap_list= "pl-wireless-a pl-wireless-b pl-wireless-c"

# build the tree of connection data

data_tree = build_database(system_list,addr_hash,wap_list,dns_list,gateway,bits)

# debug display, normally commented out

# show_tree(data_tree)

# base GConf path for NetworkManager

gconf_path = "/system/networking/connections"

# traverse the network, programming each machine

program_network(data_tree,gconf_path)

puts "Done."

Home | Linux | NetworkManager |     Share This Page