Revert "Revert "oran-shell-release: release image for F""
[pti/rtp.git] / meta-starlingx / meta-stx-cloud / recipes-support / puppet / files / puppet-network / puppet-network-config-poky-provider.patch
1 diff -ruN a/lib/puppet/provider/network_config/interfaces.rb b/lib/puppet/provider/network_config/interfaces.rb
2 --- a/lib/puppet/provider/network_config/interfaces.rb  2020-04-14 15:30:26.488316830 +0800
3 +++ b/lib/puppet/provider/network_config/interfaces.rb  2020-04-14 15:30:11.388316418 +0800
4 @@ -14,7 +14,7 @@
5    desc "Debian interfaces style provider"
6  
7    confine    :osfamily => :debian
8 -  defaultfor :osfamily => :debian
9 +  defaultfor :operatingsystem => [:debian, :ubuntu]
10  
11    has_feature :provider_options
12    has_feature :hotpluggable
13 diff -ruN a/lib/puppet/provider/network_config/poky-stx.rb b/lib/puppet/provider/network_config/poky-stx.rb
14 --- a/lib/puppet/provider/network_config/poky-stx.rb    1970-01-01 08:00:00.000000000 +0800
15 +++ b/lib/puppet/provider/network_config/poky-stx.rb    2020-04-15 15:40:31.266687901 +0800
16 @@ -0,0 +1,310 @@
17 +require 'puppetx/filemapper'
18 +
19 +Puppet::Type.type(:network_config).provide(:pokystx) do
20 +  # Wind River Linux network_config interfaces provider.
21 +  #
22 +  # This provider uses the filemapper mixin to map the interfaces file to a
23 +  # collection of network_config providers, and back.
24 +  #
25 +  include PuppetX::FileMapper
26 +
27 +  desc "Poky starlingX interfaces style provider"
28 +
29 +  defaultfor :operatingsystem => :'poky-stx'
30 +
31 +  has_feature :provider_options
32 +  has_feature :hotpluggable
33 +
34 +  def select_file
35 +    '/var/run/interfaces.puppet'
36 +  end
37 +
38 +  def self.target_files
39 +    ['/var/run/interfaces.puppet']
40 +  end
41 +
42 +  class MalformedInterfacesError < Puppet::Error
43 +    def initialize(msg = nil)
44 +      msg = 'Malformed poky-stx interfaces file; cannot instantiate network_config resources' if msg.nil?
45 +      super
46 +    end
47 +  end
48 +
49 +  def self.raise_malformed
50 +    @failed = true
51 +    raise MalformedInterfacesError
52 +  end
53 +
54 +  class Instance
55 +
56 +    attr_reader :name
57 +
58 +    # Booleans
59 +    attr_accessor :onboot, :hotplug
60 +
61 +
62 +    # These fields are going to get rearranged to resolve issue 16
63 +    # https://github.com/adrienthebo/puppet-network/issues/16
64 +    attr_accessor :ipaddress, :netmask, :family, :method, :mtu
65 +
66 +    # Options hash
67 +    attr_reader :options
68 +
69 +    def initialize(name)
70 +      @name = name
71 +
72 +      @options = Hash.new {|hash, key| hash[key] = []}
73 +    end
74 +
75 +    def to_hash
76 +      h = {
77 +        :name      => @name,
78 +        :onboot    => @onboot,
79 +        :hotplug   => @hotplug,
80 +        :ipaddress => @ipaddress,
81 +        :netmask   => @netmask,
82 +        :family    => @family,
83 +        :method    => @method,
84 +        :mtu       => @mtu,
85 +        :options   => squeeze_options
86 +      }
87 +
88 +      h.inject({}) do |hash, (key, val)|
89 +        hash[key] = val unless val.nil?
90 +        hash
91 +      end
92 +    end
93 +
94 +    def squeeze_options
95 +      @options.inject({}) do |hash, (key, value)|
96 +        if value.size <= 1
97 +          hash[key] = value.pop
98 +        else
99 +          hash[key] = value
100 +        end
101 +
102 +      hash
103 +      end
104 +    end
105 +
106 +    class << self
107 +
108 +      def reset!
109 +        @interfaces = {}
110 +      end
111 +
112 +      # @return [Array<Instance>] All class instances
113 +      def all_instances
114 +        @interfaces ||= {}
115 +        @interfaces
116 +      end
117 +
118 +      def [](name)
119 +        if all_instances[name]
120 +          obj = all_instances[name]
121 +        else
122 +          obj = self.new(name)
123 +          all_instances[name] = obj
124 +        end
125 +
126 +        obj
127 +      end
128 +    end
129 +  end
130 +
131 +  def self.parse_file(filename, contents)
132 +    # Debian has a very irregular format for the interfaces file. The
133 +    # parse_file method is somewhat derived from the ifup executable
134 +    # supplied in the debian ifupdown package. The source can be found at
135 +    # http://packages.debian.org/squeeze/ifupdown
136 +
137 +
138 +    # The debian interfaces implementation requires global state while parsing
139 +    # the file; namely, the stanza being parsed as well as the interface being
140 +    # parsed.
141 +    status = :none
142 +    current_interface = nil
143 +
144 +    lines = contents.split("\n")
145 +    # TODO Join lines that end with a backslash
146 +
147 +    # Iterate over all lines and determine what attributes they create
148 +    lines.each do |line|
149 +
150 +      # Strip off any trailing comments
151 +      line.sub!(/#.*$/, '')
152 +
153 +      case line
154 +      when /^\s*#|^\s*$/
155 +        # Ignore comments and blank lines
156 +        next
157 +
158 +      when /^auto|^allow-auto/
159 +        # Parse out any auto sections
160 +        interfaces = line.split(' ')
161 +        interfaces.delete_at(0)
162 +
163 +        interfaces.each do |name|
164 +          Instance[name].onboot = true
165 +        end
166 +
167 +        # Reset the current parse state
168 +        current_interface = nil
169 +
170 +      when /^allow-hotplug/
171 +        # parse out allow-hotplug lines
172 +
173 +        interfaces = line.split(' ')
174 +        interfaces.delete_at(0)
175 +
176 +        interfaces.each do |name|
177 +          Instance[name].hotplug = true
178 +        end
179 +
180 +        # Don't reset Reset the current parse state
181 +      when /^iface/
182 +
183 +        # Format of the iface line:
184 +        #
185 +        # iface <iface> <family> <method>
186 +        # zero or more options for <iface>
187 +
188 +        if match = line.match(/^iface\s+(\S+)\s+(\S+)\s+(\S+)/)
189 +          name   = match[1]
190 +          family = match[2]
191 +          method = match[3]
192 +
193 +          # If an iface block for this interface has been seen, the file is
194 +          # malformed.
195 +          raise_malformed if Instance[name] and Instance[name].family
196 +
197 +          status = :iface
198 +          current_interface = name
199 +
200 +          # This is done automatically
201 +          #Instance[name].name   = name
202 +          Instance[name].family = family
203 +          Instance[name].method = method
204 +
205 +        else
206 +          # If we match on a string with a leading iface, but it isn't in the
207 +          # expected format, malformed blar blar
208 +          raise_malformed
209 +        end
210 +
211 +      when /^mapping/
212 +
213 +        # XXX dox
214 +        raise Puppet::DevError, "Debian interfaces mapping parsing not implemented."
215 +        status = :mapping
216 +
217 +      else
218 +        # We're currently examining a line that is within a mapping or iface
219 +        # stanza, so we need to validate the line and add the options it
220 +        # specifies to the known state of the interface.
221 +
222 +        case status
223 +        when :iface
224 +          if match = line.match(/(\S+)\s+(\S.*)/)
225 +            # If we're parsing an iface stanza, then we should receive a set of
226 +            # lines that contain two or more space delimited strings. Append
227 +            # them as options to the iface in an array.
228 +
229 +            key = match[1]
230 +            val = match[2]
231 +
232 +            name = current_interface
233 +
234 +            case key
235 +            when 'address'; Instance[name].ipaddress    = val
236 +            when 'netmask'; Instance[name].netmask      = val
237 +            when 'mtu';     Instance[name].mtu          = val
238 +            else            Instance[name].options[key] << val
239 +            end
240 +          else
241 +            raise_malformed
242 +          end
243 +        when :mapping
244 +          raise Puppet::DevError, "Debian interfaces mapping parsing not implemented."
245 +        when :none
246 +          raise_malformed
247 +        end
248 +      end
249 +    end
250 +
251 +    Instance.all_instances.map {|name, instance| instance.to_hash }
252 +  end
253 +
254 +  # Generate an array of sections
255 +  def self.format_file(filename, providers)
256 +    contents = []
257 +    contents << header
258 +
259 +    # Add onboot interfaces
260 +    if (auto_interfaces = providers.select {|provider| provider.onboot == true })
261 +      stanza = []
262 +      stanza << "auto " + auto_interfaces.map(&:name).sort.join(" ")
263 +      contents << stanza.join("\n")
264 +    end
265 +
266 +    # Build iface stanzas
267 +    providers.sort_by(&:name).each do |provider|
268 +      # TODO add validation method
269 +      raise Puppet::Error, "#{provider.name} does not have a method." if provider.method.nil?
270 +      raise Puppet::Error, "#{provider.name} does not have a family." if provider.family.nil?
271 +
272 +      stanza = []
273 +      if provider.method == :static and (not provider.ipaddress or provider.ipaddress == :absent)
274 +        stanza << %{iface #{provider.name} #{provider.family} manual}
275 +      else
276 +        stanza << %{iface #{provider.name} #{provider.family} #{provider.method}}
277 +      end
278 +
279 +      [
280 +        [:ipaddress, 'address'],
281 +        [:netmask,   'netmask'],
282 +        [:gateway,   'gateway'],
283 +        [:mtu,       'mtu'],
284 +      ].each do |(property, section)|
285 +        stanza << "    #{section} #{provider.send property}" if provider.send(property) and provider.send(property) != :absent
286 +      end
287 +
288 +      if provider.options and provider.options != :absent
289 +        provider.options.each_pair do |key_f, val|
290 +          key = key_f.gsub('_', '-')
291 +          if ['pre-up', 'up', 'post-up', 'down', 'pre-down', 'post-down'].include? key
292 +            if val.is_a? String
293 +              stanza << "    #{key} #{val}"
294 +            elsif val.is_a? Array
295 +              val.each { |entry| stanza << "    #{key} #{entry}" }
296 +            else
297 +              raise Puppet::Error, "#{self} options key #{key} expects a String or Array, got #{val.class}"
298 +            end
299 +          end
300 +          if key == 'SCOPE'
301 +            if val.is_a? String
302 +              stanza << "    #{val}"
303 +            else
304 +              raise Puppet::Error, "#{self} options key #{key} expects a String, got #{val.class}"
305 +            end
306 +          end
307 +        end
308 +      end
309 +
310 +      contents << stanza.join("\n")
311 +    end
312 +
313 +    contents.map {|line| line + "\n\n"}.join
314 +  end
315 +
316 +  def self.header
317 +    str = <<-HEADER
318 +# HEADER: This file is is being managed by puppet. Changes to
319 +# HEADER: interfaces that are not being managed by puppet will persist;
320 +# HEADER: however changes to interfaces that are being managed by puppet will
321 +# HEADER: be overwritten. In addition, file order is NOT guaranteed.
322 +# HEADER: Last generated at: #{Time.now}
323 +HEADER
324 +    str
325 +  end
326 +end