Mohammed Morsi
2009-Nov-03 22:47 UTC
[Ovirt-devel] [PATCH server] suggest ip address for nics/bondings on edit host/vm network forms
Provides a mechanism to generate ip addresses for static networks and prefill the 'ip address' fields of the host and vm networking forms w/ the first suggested ip. --- src/app/controllers/vm_controller.rb | 2 +- src/app/models/ip_address.rb | 52 +++++++++++++++++++++++++++++++++ src/app/models/network.rb | 11 +++++++ src/app/models/physical_network.rb | 6 ++++ src/app/models/vlan.rb | 6 ++++ src/app/services/host_service.rb | 2 + src/app/views/host/edit_network.rhtml | 4 ++- src/test/unit/ip_address_test.rb | 17 +++++++++++ src/test/unit/network_test.rb | 19 ++++++++++++ 9 files changed, 117 insertions(+), 2 deletions(-) diff --git a/src/app/controllers/vm_controller.rb b/src/app/controllers/vm_controller.rb index 9860843..c4ad7ce 100644 --- a/src/app/controllers/vm_controller.rb +++ b/src/app/controllers/vm_controller.rb @@ -193,7 +193,7 @@ class VmController < ApplicationController networks.each{ |net| nnic = Nic.new(:mac => Nic::gen_mac, :network => net) if(net.boot_type.proto == 'static') - nnic.ip_addresses << IpAddress.new(:address => '127.0.0.1') # FIXME + nnic.ip_addresses << IpAddress.new(:address => net.gen_address) end @nics.push nnic } diff --git a/src/app/models/ip_address.rb b/src/app/models/ip_address.rb index 13f5d19..2909e4e 100644 --- a/src/app/models/ip_address.rb +++ b/src/app/models/ip_address.rb @@ -17,6 +17,8 @@ # MA 02110-1301, USA. A copy of the GNU General Public License is # also available at http://www.gnu.org/copyleft/gpl.html. +require 'ipaddr' + # +IpAddress+ is the base class for all address related classes. # class IpAddress < ActiveRecord::Base @@ -35,4 +37,54 @@ class IpAddress < ActiveRecord::Base raise ArgumentError("Invalid type #{params[:type]}") end end + + # get the range of valid addresses for this network address + def range + # exclude the gateway and broadcast addresses + # associated w/ this ip address + sgatewayi = IPAddr.new(gateway).to_i + sbcasti = IPAddr.new(broadcast).to_i + + addresses = [] + _numeric_range.each { |i| # this can be a big performance hit + # depending on your network / mask + unless i == sgatewayi || i == sbcasti + addresses.push IPAddr.new(i, Socket::AF_INET).to_s + end + } + + addresses + end + + # get first available address for this network address given list + # of addresses already used + def first_available_address(used_addresses) + # exclude the gateway and broadcast addresses + # associated w/ this ip address + sgatewayi = IPAddr.new(gateway).to_i + sbcasti = IPAddr.new(broadcast).to_i + + _numeric_range.each { |i| + ip = IPAddr.new(i, Socket::AF_INET).to_s + unless i == sgatewayi || i == sbcasti || used_addresses.include?(ip) + return ip + end + } + + nil + end + + private + # internal helper method, get the range of numeric addresses for this + # network address + def _numeric_range + return [] unless network_id != nil + netaddress_ip = IPAddr.new(address) + netmask_ip = IPAddr.new(netmask) + firstaddress = netaddress_ip.to_i + 1 + lastaddress = netaddress_ip.to_i + (~netmask_ip).to_i - 1 + (firstaddress...lastaddress+1) + end + + end diff --git a/src/app/models/network.rb b/src/app/models/network.rb index 22e5692..c9d5d84 100644 --- a/src/app/models/network.rb +++ b/src/app/models/network.rb @@ -42,5 +42,16 @@ class Network < ActiveRecord::Base end end + # return true / false if network has statically assigned ips + def is_static? + !boot_type.nil? && boot_type.proto == "static" + end + + # generate an ip address for this network based on the + # associated IpAddress and specified array of addreses already used + def gen_address(used_addresses = []) + return nil if ip_addresses.nil? || ip_addresses.size == 0 + ip_addresses[0].first_available_address(used_addresses) + end end diff --git a/src/app/models/physical_network.rb b/src/app/models/physical_network.rb index f50eeff..17a325e 100644 --- a/src/app/models/physical_network.rb +++ b/src/app/models/physical_network.rb @@ -20,4 +20,10 @@ class PhysicalNetwork < Network def is_destroyable? nics.empty? end + + # generate an ip address for this network based on associated ip and + # addresses already associated w/ nics + def gen_address + super(nics.collect { |n| n.ip_address}) + end end diff --git a/src/app/models/vlan.rb b/src/app/models/vlan.rb index e34dddc..ca80dfc 100644 --- a/src/app/models/vlan.rb +++ b/src/app/models/vlan.rb @@ -26,6 +26,12 @@ class Vlan < Network bondings.empty? && nics.empty? end + # generate an ip address for this network based on associated ip and + # addresses already associated w/ bondings/nics + def gen_address + super(bondings.collect { |b| b.ip_address } + nics.collect { |n| n.ip_address}) + end + protected def validate # ensure that any assigned nics only belong to vms, not hosts diff --git a/src/app/services/host_service.rb b/src/app/services/host_service.rb index 3b59f0e..e6b2810 100644 --- a/src/app/services/host_service.rb +++ b/src/app/services/host_service.rb @@ -73,6 +73,8 @@ module HostService def svc_modify(id) lookup(id, Privilege::MODIFY) @networks = Network.find(:all) + @suggested_ips = {} + @networks.each { |n| @suggested_ips[n.id] = n.gen_address } @bonding_types = BondingType.find(:all) end diff --git a/src/app/views/host/edit_network.rhtml b/src/app/views/host/edit_network.rhtml index 1154595..2b22a7c 100644 --- a/src/app/views/host/edit_network.rhtml +++ b/src/app/views/host/edit_network.rhtml @@ -241,6 +241,7 @@ jnet.static_ip = <%= rnet.boot_type.proto == 'static' %>; jnet.boot_type = "<%= rnet.boot_type.proto %>"; jnet.selected = false; + jnet.suggested_ip = "<%= @suggested_ips[rnet.id] %>"; networks.push(jnet); <% } %> @@ -380,7 +381,8 @@ div.children("input").removeAttr("disabled"); // grab value of address field from device - address = device ? device.ip_address : ""; + address = (device && (device.ip_address != "")) ? + device.ip_address : network.suggested_ip; div.children("input").val(address); // for non-static networks disable/hide ip address textbox diff --git a/src/test/unit/ip_address_test.rb b/src/test/unit/ip_address_test.rb index 89972ad..f0aa96b 100644 --- a/src/test/unit/ip_address_test.rb +++ b/src/test/unit/ip_address_test.rb @@ -17,4 +17,21 @@ class IpAddressTest < ActiveSupport::TestCase # this networking is in flux. Revisit this test once that stabilizes. flunk "Ip Address must be associated with network, nic, or bonding" unless @ip_address.valid? end + + def test_ip_address_range + ipv4addr = IpV4Address.new :address => '1.2.3.0', + :netmask => '255.255.255.0', + :gateway => '1.2.3.1', + :broadcast => '1.2.3.255', + :network_id => 5 + + range = ipv4addr.range + + assert_equal 253, range.size + assert !range.include?("1.2.3.1") + assert !range.include?("1.2.3.255") + (2...255).each { |i| + assert range.include?("1.2.3." + i.to_s) + } + end end diff --git a/src/test/unit/network_test.rb b/src/test/unit/network_test.rb index 73ea7eb..e9aa0d6 100644 --- a/src/test/unit/network_test.rb +++ b/src/test/unit/network_test.rb @@ -66,4 +66,23 @@ class NetworkTest < ActiveSupport::TestCase vl.bondings.push Bonding.new flunk "Vlan with bondings should not be destroyable" if vl.is_destroyable? end + + def test_gen_physical_net_address + net = networks :static_physical_network_one + addr = net.gen_address + + assert net.ip_addresses[0].address != addr + assert net.ip_addresses[0].netmask != addr + assert net.ip_addresses[0].broadcast != addr + assert net.ip_addresses[0].gateway != addr + net.nics.each { |nic| + assert nic.ip_address != addr + } + + addri = IPAddr.new(addr).to_i + naddri = IPAddr.new(net.ip_addresses[0].address).to_i + baddri = naddri + (~IPAddr.new(net.ip_addresses[0].netmask)).to_i + assert addri > naddri + assert addri < baddri + end end -- 1.6.2.5
Maybe Matching Threads
- [PATCH server] new host networking wui
- [PATCH server] permit many-to-many vms / networks relationship
- [PATCH server] use service layer for Network controller.
- [PATCH server] Add of a button destroy for disabled hosts.
- [PATCH server] consolidated network & routing info ui's