[Ovirt-devel] [PATCH server] suggest ip address for nics/bondings on edit host/vm network forms
Mohammed Morsi
mmorsi at redhat.com
Tue Nov 3 22:47:03 UTC 2009
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
More information about the ovirt-devel
mailing list