lib/dcmgr/models/network.rb in wakame-vdc-dcmgr-11.06.0 vs lib/dcmgr/models/network.rb in wakame-vdc-dcmgr-11.12.0

- old
+ new

@@ -5,26 +5,10 @@ module Dcmgr::Models # IP network definitions. class Network < AccountResource taggable 'nw' - inheritable_schema do - String :ipv4_gw, :null=>false - Fixnum :prefix, :null=>false, :default=>24, :unsigned=>true - String :domain_name - String :dns_server - String :dhcp_server - String :metadata_server - Fixnum :metadata_server_port - Fixnum :bandwidth #in Mbit/s - Fixnum :vlan_lease_id, :null=>false, :default=>0 - Fixnum :nat_network_id - Text :description - index :nat_network_id - end - with_timestamps - module IpLeaseMethods def add_reserved(ipaddr, description=nil) model.create(:network_id=>model_object.id, :ipv4=>ipaddr, :alloc_type=>IpLease::TYPE_RESERVED, @@ -35,33 +19,70 @@ many_to_one :vlan_lease many_to_one :nat_network, :key => :nat_network_id, :class => self one_to_many :inside_networks, :key => :nat_network_id, :class => self + one_to_many :dhcp_range + many_to_one :physical_network + + def before_validation + self.link_interface ||= "br-#{self[:uuid]}" + super + end + def validate super + unless (1..31).include?(self.prefix.to_i) + errors.add(:prefix, "prefix must be 1-31: #{self.prefix}") + end + + network_addr = begin + IPAddress::IPv4.new("#{self.ipv4_network}/#{self.prefix}").network + rescue => e + errors.add(:ipv4_network, "Invalid IP address syntax: #{self.ipv4_network}") + end # validate ipv4 syntax - begin - IPAddress::IPv4.new("#{self.ipv4_gw}") - rescue => e - errors.add(:ipv4_gw, "Invalid IP address syntax: #{self.ipv4_gw}") + if self.ipv4_gw + begin + if !network_addr.include?(IPAddress::IPv4.new("#{self.ipv4_gw}")) + errors.add(:ipv4_gw, "Out of network address range: #{network_addr.to_s}") + end + rescue => e + errors.add(:ipv4_gw, "Invalid IP address syntax: #{self.ipv4_gw}") + end end + + if self.dhcp_server + begin + if !network_addr.include?(IPAddress::IPv4.new("#{self.dhcp_server}")) + errors.add(:dhcp_server, "Out of network address range: #{network_addr.to_s}") + end + rescue => e + errors.add(:dhcp_server, "Invalid IP address syntax: #{self.dhcp_server}") + end + end - unless (1..31).include?(self.prefix.to_i) - errors.add(:prefix, "prefix must be 1-31: #{self.prefix}") + if self.link_interface.size > 16 + errors.add(:link_interface, "Can not be the character lenth more than 16(=IF_NAMESIZ) ASCII characters.") end + end def to_hash h = super h.delete(:vlan_lease_id) h.merge({ :bandwidth_mark=>self[:id], :description=>description.to_s, :vlan_id => vlan_lease.nil? ? 0 : vlan_lease.tag_id, }) + if self.physical_network + h[:physical_network] = self.physical_network.to_hash + end + + h end def before_destroy #Make sure no other networks are natted to this one Network.filter(:nat_network_id => self[:id]).each { |n| @@ -76,33 +97,133 @@ super end def to_api_document - to_hash + to_hash.merge(:id=>self.canonical_uuid) end def nat_network Network.find(:id => self.nat_network_id) end - def ipaddress + def ipv4_ipaddress + IPAddress::IPv4.new("#{self.ipv4_network}/#{self.prefix}").network + end + + def ipv4_gw_ipaddress + return nil if self.ipv4_gw.nil? IPAddress::IPv4.new("#{self.ipv4_gw}/#{self.prefix}") end # check if the given IP addess is in the range of this network. # @param [String] ipaddr IP address def include?(ipaddr) ipaddr = ipaddr.is_a?(IPAddress::IPv4) ? ipaddr : IPAddress::IPv4.new(ipaddr) - self.ipaddress.network.include?(ipaddr) + self.ipv4_ipaddress.network.include?(ipaddr) end # register reserved IP address in this network def add_reserved(ipaddr) - add_ip_lease(:ipv4=>ipaddr, :type=>IpLease::TYPE_RESERVED) + raise "Out of subnet range: #{ipaddr} to #{self.ipv4_ipaddress}/#{self.prefix}" if !self.include?(ipaddr) + add_ip_lease(:ipv4=>ipaddr.to_s, :type=>IpLease::TYPE_RESERVED) end def available_ip_nums - self.ipaddress.hosts.size - self.ip_lease_dataset.count + self.ipv4_ipaddress.hosts.size - self.ip_lease_dataset.count + end + + def ipv4_u32_dynamic_range_array + ary=[] + dhcp_range_dataset.each { |r| + ary += (r.range_begin.to_u32 .. r.range_end.to_u32).to_a + } + ary + end + + def add_ipv4_dynamic_range(range_begin, range_end) + test_inclusion(*validate_range_args(range_begin, range_end)) { |range, op| + case op + when :coverbegin + range.range_end = range_begin + when :coverend + range.range_begin = range_end + when :inccur + range.destroy + end + range.save_changes + } + + self.add_dhcp_range(:range_begin=>range_begin.to_s, :range_end=>range_end.to_s) + + self + end + + def del_ipv4_dynamic_range(range_begin, range_end) + test_inclusion(*validate_range_args(range_begin, range_end)) { |range, op| + case op + when :coverbegin + range.range_end = range_begin + when :coverend + range.range_begin = range_end + when :inccur + range.destroy + when :incnew + t = range.range_end + range.range_end = range_begin + self.add_dhcp_range(:range_begin=>range_end, :range_end=>t) + end + range.save_changes + } + + self + end + + private + def validate_range_args(range_begin, range_end) + if range_begin.is_a?(IPAddress::IPv4) + raise "Different prefix length: range_begin" if range_begin.prefix != self.prefix + else + range_begin = IPAddress::IPv4.new("#{range_begin}/#{self.prefix}") + end + if range_end.is_a?(IPAddress::IPv4) + raise "Different prefix length: range_end" if range_end.prefix != self.prefix + else + range_end = IPAddress::IPv4.new("#{range_end}/#{self.prefix}") + end + if !(self.ipv4_ipaddress.include?(range_begin) && self.ipv4_ipaddress.include?(range_end)) + raise "Given address range is out of the subnet: #{self.ipv4_ipaddress} #{range_begin}-#{range_end}" + end + if range_begin > range_end + t = range_begin + range_begin = range_end + range_end = t + end + [range_begin, range_end] + end + + + def test_inclusion(range_begin, range_end, &blk) + dhcp_range_dataset.each { |r| + op = :outrange + if r.range_begin < range_begin && r.range_end > range_begin + # range_begin is in the range. + if r.range_end < range_end + op = :coverbegin + else + # new range is included in current range. + op = :incnew + end + elsif r.range_begin < range_end && r.range_end > range_end + # range_end is in the range. + if r.range_begin > range_begin + op = :coverend + end + elsif r.range_begin >= range_begin && r.range_end <= range_end + # current range is included in new range. + op = :inccur + end + blk.call(r, op) + } end end end