PageRenderTime 43ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ohai/plugins/network.rb

https://github.com/jmanero/ohai
Ruby | 173 lines | 111 code | 23 blank | 39 comment | 20 complexity | e4af1e0a82ec0c5cbd355480469121f6 MD5 | raw file
Possible License(s): Apache-2.0
  1. #
  2. # Author:: Adam Jacob (<adam@opscode.com>)
  3. # Copyright:: Copyright (c) 2008 Opscode, Inc.
  4. # License:: Apache License, Version 2.0
  5. #
  6. # Licensed under the Apache License, Version 2.0 (the "License");
  7. # you may not use this file except in compliance with the License.
  8. # You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. #
  18. require 'ipaddress'
  19. provides "network", "counters/network"
  20. network Mash.new unless network
  21. network[:interfaces] = Mash.new unless network[:interfaces]
  22. counters Mash.new unless counters
  23. counters[:network] = Mash.new unless counters[:network]
  24. require_plugin "hostname"
  25. require_plugin "#{os}::network"
  26. FAMILIES = {
  27. "inet" => "default",
  28. "inet6" => "default_inet6"
  29. }
  30. def sorted_ips(family = "inet")
  31. raise "bad family #{family}" unless [ "inet", "inet6" ].include? family
  32. # going to use that later to sort by scope
  33. scope_prio = [ "global", "site", "link", "host", "node", nil ]
  34. ipaddresses = []
  35. # ipaddresses going to hold #{family} ipaddresses and their scope
  36. Mash[network['interfaces']].each do |iface, iface_v|
  37. iface_v['addresses'].each do |addr, addr_v|
  38. next if addr_v.nil? or not addr_v.has_key? "family" or addr_v['family'] != family
  39. ipaddresses << {
  40. :ipaddress => addr_v["prefixlen"] ? IPAddress("#{addr}/#{addr_v["prefixlen"]}") : IPAddress("#{addr}/#{addr_v["netmask"]}"),
  41. :scope => addr_v["scope"].nil? ? nil : addr_v["scope"].downcase,
  42. :iface => iface
  43. }
  44. end
  45. end
  46. # sort ip addresses by scope, by prefixlen and then by ip address
  47. # 128 - prefixlen: longest prefixes first
  48. ipaddresses.sort_by do |v|
  49. [ ( scope_prio.index(v[:scope]) or 999999 ),
  50. 128 - v[:ipaddress].prefix.to_i,
  51. ( family == "inet" ? v[:ipaddress].to_u32 : v[:ipaddress].to_u128 )
  52. ]
  53. end
  54. end
  55. def find_ip(family = "inet")
  56. r=sorted_ips(family)
  57. # return if there isn't any #{family} address !
  58. return [ nil, nil ] if r.empty?
  59. # shortcuts to access default #{family} interface and gateway
  60. int_attr = FAMILIES[family] +"_interface"
  61. gw_attr = FAMILIES[family] + "_gateway"
  62. # If we have a default interface that has addresses,
  63. # populate the short-cut attributes
  64. if network[int_attr]
  65. # network[int_attr] exists, the choosen ip must be exist on this interface
  66. r = r.select do |v|
  67. v[:iface] == network[int_attr]
  68. end
  69. if r.empty?
  70. Ohai::Log.warn("[#{family}] no ip on #{network[int_attr]}")
  71. elsif network[gw_attr] and
  72. network["interfaces"][network[int_attr]] and
  73. network["interfaces"][network[int_attr]]["addresses"]
  74. if [ "0.0.0.0", "::" ].include? network[gw_attr]
  75. # link level default route
  76. Ohai::Log.debug("link level default #{family} route, picking ip from #{network[gw_attr]}")
  77. r = r.first
  78. else
  79. r = r.select do |v|
  80. network_contains_address(network[gw_attr], v[:ipaddress], v[:iface])
  81. end.first
  82. if r.nil?
  83. Ohai::Log.warn("[#{family}] no ipaddress/mask on #{network[int_attr]} matching the gateway #{network[gw_attr]}")
  84. else
  85. Ohai::Log.debug("[#{family}] Using default interface #{network[int_attr]} and default gateway #{network[gw_attr]} to set the default ip to #{r[:ipaddress]}")
  86. end
  87. end
  88. else
  89. # return the first ip address on network[int_attr]
  90. r = r.first
  91. end
  92. else
  93. r = r.first
  94. Ohai::Log.info("[#{family}] no default interface, picking the first ipaddress")
  95. end
  96. return [ nil, nil ] if r.nil? or r.empty?
  97. [ r[:ipaddress].to_s, r[:iface] ]
  98. end
  99. def find_mac_from_iface(iface)
  100. r = network["interfaces"][iface]["addresses"].select{|k,v| v["family"]=="lladdr"}
  101. r.nil? or r.first.nil? ? nil : r.first.first
  102. end
  103. def network_contains_address(address_to_match, ipaddress, iface)
  104. # address_to_match: String
  105. # ipaddress: IPAddress
  106. # iface: String
  107. if peer = network["interfaces"][iface]["addresses"][ipaddress.to_s][:peer]
  108. IPAddress(peer) == IPAddress(address_to_match)
  109. else
  110. ipaddress.include? IPAddress(address_to_match)
  111. end
  112. end
  113. # ipaddress, ip6address and macaddress can be set by the #{os}::network plugin
  114. # atm it is expected macaddress is set at the same time than ipaddress
  115. # if ipaddress is set and macaddress is nil, that means the interface
  116. # ipaddress is bound to has the NOARP flag
  117. results = {}
  118. # inet family is treated before inet6
  119. FAMILIES.keys.sort.each do |family|
  120. r = {}
  121. ( r["ip"], r["iface"] ) = find_ip(family)
  122. r["mac"] = find_mac_from_iface(r["iface"]) unless r["iface"].nil?
  123. # don't overwrite attributes if they've already been set by the "#{os}::network" plugin
  124. if family == "inet" and ipaddress.nil?
  125. if r["ip"].nil?
  126. Ohai::Log.warn("unable to detect ipaddress")
  127. # i don't issue this warning if r["ip"] exists and r["mac"].nil?
  128. # as it could be a valid setup with a NOARP default_interface
  129. Ohai::Log.warn("unable to detect macaddress")
  130. else
  131. ipaddress r["ip"]
  132. macaddress r["mac"]
  133. end
  134. elsif family == "inet6" and ip6address.nil?
  135. if r["ip"].nil?
  136. Ohai::Log.warn("unable to detect ip6address")
  137. else
  138. ip6address r["ip"]
  139. if r["mac"] and macaddress.nil? and ipaddress.nil?
  140. Ohai::Log.info("macaddress set to #{r["mac"]} from the ipv6 setup")
  141. macaddress r["mac"]
  142. end
  143. end
  144. end
  145. results[family] = r
  146. end
  147. if results["inet"]["iface"] and results["inet6"]["iface"] and
  148. results["inet"]["iface"] != results["inet6"]["iface"]
  149. Ohai::Log.info("ipaddress and ip6address are set from different interfaces (#{results["inet"]["iface"]} & #{results["inet6"]["iface"]}), macaddress has been set using the ipaddress interface")
  150. end