Guest User

Untitled

a guest
May 20th, 2018
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.48 KB | None | 0 0
  1. require 'puppet/provider/parsedfile'
  2. require 'erb'
  3.  
  4. Puppet::Type.type(:interface).provide(:redhat) do
  5. desc "Manage network interfaces on Red Hat operating systems. This provider
  6. parses and generates configuration files in ``/etc/sysconfig/network-scripts``."
  7.  
  8. INTERFACE_DIR = "/etc/sysconfig/network-scripts"
  9. confine :exists => INTERFACE_DIR
  10. defaultfor :operatingsystem => [:fedora, :centos, :redhat]
  11.  
  12. # Create the setter/gettor methods to match the model.
  13. mk_resource_methods
  14.  
  15. @templates = {}
  16.  
  17. # Register a template.
  18. def self.register_template(name, string)
  19. @templates[name] = ERB.new(string)
  20. end
  21.  
  22. # Retrieve a template by name.
  23. def self.template(name)
  24. @templates[name]
  25. end
  26.  
  27. register_template :alias, <<-ALIAS
  28. DEVICE=<%= self.device %>
  29. ONBOOT=<%= self.on_boot %>
  30. BOOTPROTO=none
  31. IPADDR=<%= self.name %>
  32. NETMASK=<%= self.netmask %>
  33. BROADCAST=
  34. ALIAS
  35.  
  36.  
  37. register_template :normal, <<-LOOPBACKDUMMY
  38. DEVICE=<%= self.device %>
  39. ONBOOT=<%= self.on_boot %>
  40. BOOTPROTO=static
  41. IPADDR=<%= self.name %>
  42. NETMASK=<%= self.netmask %>
  43. BROADCAST=
  44. LOOPBACKDUMMY
  45.  
  46. # maximum number of dummy interfaces
  47. @max_dummies = 10
  48.  
  49. # maximum number of aliases per interface
  50. @max_aliases_per_iface = 10
  51.  
  52. @@dummies = []
  53. @@aliases = Hash.new { |hash, key| hash[key] = [] }
  54.  
  55. # calculate which dummy interfaces are currently already in
  56. # use prior to needing to call self.next_dummy later on.
  57. def self.instances
  58. # parse all of the config files at once
  59. Dir.glob("%s/ifcfg-*" % INTERFACE_DIR).collect do |file|
  60. record = parse(file)
  61.  
  62. # store the existing dummy interfaces
  63. @@dummies << record[:ifnum] if (record[:interface_type] == :dummy and ! @@dummies.include?(record[:ifnum]))
  64.  
  65. @@aliases[record[:interface]] << record[:ifnum] if record[:interface_type] == :alias
  66.  
  67. new(record)
  68. end
  69. end
  70.  
  71. # return the next avaliable dummy interface number, in the case where
  72. # ifnum is not manually specified
  73. def self.next_dummy
  74. @max_dummies.times do |i|
  75. unless @@dummies.include?(i.to_s)
  76. @@dummies << i.to_s
  77. return i.to_s
  78. end
  79. end
  80. end
  81.  
  82. # return the next available alias on a given interface, in the case
  83. # where ifnum if not manually specified
  84. def self.next_alias(interface)
  85. @max_aliases_per_iface.times do |i|
  86. unless @@aliases[interface].include?(i.to_s)
  87. @@aliases[interface] << i.to_s
  88. return i.to_s
  89. end
  90. end
  91. end
  92.  
  93. # base the ifnum, for dummy / loopback interface in linux
  94. # on the last octect of the IP address
  95.  
  96. # Parse the existing file.
  97. def self.parse(file)
  98. instance = new()
  99. return instance unless FileTest.exist?(file)
  100.  
  101. File.readlines(file).each do |line|
  102. if line =~ /^(\w+)=(.+)$/
  103. instance.send($1.downcase + "=", $2)
  104. end
  105. end
  106.  
  107. return instance
  108. end
  109.  
  110. # Prefetch our interface list, yo.
  111. def self.prefetch(resources)
  112. instances.each do |prov|
  113. if resource = resources[prov.name]
  114. resource.provider = prov
  115. end
  116. end
  117. end
  118.  
  119. def create
  120. self.class.resource_type.validproperties.each do |property|
  121. if value = @resource.should(property)
  122. @property_hash[property] = value
  123. end
  124. end
  125. @property_hash[:name] = @resource.name
  126.  
  127. return (@resource.class.name.to_s + "_created").intern
  128. end
  129.  
  130. def destroy
  131. File.unlink(file_path)
  132. end
  133.  
  134. def exists?
  135. FileTest.exist?(file_path)
  136. end
  137.  
  138. # generate the content for the interface file, so this is dependent
  139. # on whether we are adding an alias to a real interface, or a loopback
  140. # address (also dummy) on linux. For linux it's quite involved, and we
  141. # will use an ERB template
  142. def generate
  143. itype = self.interface_type == :alias ? :alias : :normal
  144. self.class.template(itype).result(binding)
  145. end
  146.  
  147. # Where should the file be written out?
  148. # This defaults to INTERFACE_DIR/ifcfg-<namevar>, but can have a
  149. # more symbolic name by setting interface_desc in the type.
  150. def file_path
  151. if resource and val = resource[:interface_desc]
  152. desc = val
  153. else
  154. desc = self.name
  155. end
  156.  
  157. self.fail("Could not get name for interface") unless desc
  158.  
  159. if self.interface_type == :alias
  160. return File.join(INTERFACE_DIR, "ifcfg-" + self.interface + ":" + desc)
  161. else
  162. return File.join(INTERFACE_DIR, "ifcfg-" + desc)
  163. end
  164. end
  165.  
  166. # Use the device value to figure out all kinds of nifty things.
  167. def device=(value)
  168. case value
  169. when /:/:
  170. @property_hash[:interface], @property_hash[:ifnum] = value.split(":")
  171. @property_hash[:interface_type] = :alias
  172. when /^dummy/:
  173. @property_hash[:interface_type] = :loopback
  174. @property_hash[:interface] = "dummy"
  175.  
  176. # take the number of the dummy interface, as this is used
  177. # when working out whether to call next_dummy when dynamically
  178. # creating these
  179. @property_hash[:ifnum] = value.sub("dummy",'')
  180.  
  181. @@dummies << @property_hash[:ifnum].to_s unless @@dummies.include?(@property_hash[:ifnum].to_s)
  182. else
  183. @property_hash[:interface_type] = :normal
  184. @property_hash[:interface] = value
  185. end
  186. end
  187.  
  188. # create the device name, so this based on the IP, and interface + type
  189. def device
  190. case @resource.should(:interface_type)
  191. when :loopback
  192. @property_hash[:ifnum] ||= self.class.next_dummy
  193. return "dummy" + @property_hash[:ifnum]
  194. when :alias
  195. @property_hash[:ifnum] ||= self.class.next_alias(@resource[:interface])
  196. return @resource[:interface] + ":" + @property_hash[:ifnum]
  197. end
  198. end
  199.  
  200. # Set the name to our ip address.
  201. def ipaddr=(value)
  202. @property_hash[:name] = value
  203. end
  204.  
  205. # whether the device is to be brought up on boot or not. converts
  206. # the true / false of the type, into yes / no values respectively
  207. # writing out the ifcfg-* files
  208. def on_boot
  209. case @property_hash[:onboot].to_s
  210. when "true"
  211. return "yes"
  212. when "false"
  213. return "no"
  214. else
  215. return "neither"
  216. end
  217. end
  218.  
  219. # Mark whether the interface should be started on boot.
  220. def on_boot=(value)
  221. # translate whether we come up on boot to true/false
  222. case value.downcase
  223. when "yes":
  224. @property_hash[:onboot] = :true
  225. else
  226. @property_hash[:onboot] = :false
  227. end
  228. end
  229.  
  230. # Write the new file out.
  231. def flush
  232. # Don't flush to disk if we're removing the config.
  233. return if self.ensure == :absent
  234.  
  235. @property_hash.each do |name, val|
  236. if val == :absent
  237. raise ArgumentError, "Propety %s must be provided" % val
  238. end
  239. end
  240.  
  241. File.open(file_path, "w") do |f|
  242. f.puts generate()
  243. end
  244. end
  245.  
  246. def prefetch
  247. @property_hash = self.class.parse(file_path)
  248. end
  249. end
Add Comment
Please, Sign In to add comment