memcached (openstack) is no longer in use
[mirror/dsa-puppet.git] / 3rdparty / modules / vswitch / lib / puppet / provider / vs_port / ovs_redhat.rb
1 require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppetx', 'redhat', 'ifcfg.rb'))
2
3 BASE = '/etc/sysconfig/network-scripts/ifcfg-'
4
5 # When not seedling from interface file
6 DEFAULT = {
7   'ONBOOT'        => 'yes',
8   'BOOTPROTO'     => 'dhcp',
9   'PEERDNS'       => 'no',
10   'NM_CONTROLLED' => 'no',
11   'NOZEROCONF'    => 'yes' }
12
13 Puppet::Type.type(:vs_port).provide(:ovs_redhat, :parent => :ovs) do
14   desc 'Openvswitch port manipulation for RedHat OSes family'
15
16   confine    :osfamily => :redhat
17   defaultfor :osfamily => :redhat
18
19   commands :ip     => 'ip'
20   commands :ifdown => 'ifdown'
21   commands :ifup   => 'ifup'
22   commands :vsctl  => 'ovs-vsctl'
23
24   def create
25     unless vsctl('list-ports',
26       @resource[:bridge]).include? @resource[:interface]
27       super
28     end
29
30     if interface_physical?
31       template = DEFAULT
32       extras   = nil
33
34       if link?
35         extras = dynamic_default if dynamic?
36         if File.exist?(BASE + @resource[:interface])
37           template = cleared(from_str(File.read(BASE + @resource[:interface])))
38         end
39       end
40
41       port = IFCFG::Port.new(@resource[:interface], @resource[:bridge])
42       if vlan?
43         port.set('VLAN' => 'yes')
44       end
45
46       if bonding?
47         port.set('BONDING_MASTER' => 'yes')
48         config = from_str(File.read(BASE + @resource[:interface]))
49         port.set('BONDING_OPTS' => config['BONDING_OPTS']) if config.has_key?('BONDING_OPTS')
50       end
51
52       port.save(BASE + @resource[:interface])
53
54       bridge = IFCFG::Bridge.new(@resource[:bridge], template)
55       bridge.set(extras) if extras
56       bridge.save(BASE + @resource[:bridge])
57
58       ifdown(@resource[:bridge])
59       ifdown(@resource[:interface])
60       ifup(@resource[:interface])
61       ifup(@resource[:bridge])
62     end
63   end
64
65   def exists?
66     if interface_physical?
67       super &&
68       IFCFG::OVS.exists?(@resource[:interface]) &&
69       IFCFG::OVS.exists?(@resource[:bridge])
70     else
71       super
72     end
73   end
74
75   def destroy
76     if interface_physical?
77       ifdown(@resource[:bridge])
78       ifdown(@resource[:interface])
79       IFCFG::OVS.remove(@resource[:interface])
80       IFCFG::OVS.remove(@resource[:bridge])
81     end
82     super
83   end
84
85   private
86
87   def bonding?
88     # To do: replace with iproute2 commands
89     if File.exists?("/proc/net/bonding/#{@resource[:interface]}")
90       return true
91     else
92       return false
93     end
94   rescue Errno::ENOENT
95     return false
96   end
97
98   def dynamic?
99     device = ''
100     device = ip('addr', 'show', @resource[:interface])
101     return device =~ /dynamic/ ? true : false
102   end
103
104   def link?
105     if File.read("/sys/class/net/#{@resource[:interface]}/operstate") =~ /up/
106       return true
107     else
108       return false
109     end
110   rescue Errno::ENOENT
111     return false
112   end
113
114   def dynamic_default
115     list = { 'OVSDHCPINTERFACES' => @resource[:interface] }
116     # Persistent MAC address taken from interface
117     bridge_mac_address = File.read("/sys/class/net/#{@resource[:interface]}/address").chomp
118     if bridge_mac_address != ''
119       list.merge!({ 'OVS_EXTRA' =>
120         "\"set bridge #{@resource[:bridge]} other-config:hwaddr=#{bridge_mac_address}\"" })
121     end
122     list
123   end
124
125   def interface_physical?
126     # OVS ports don't have entries in /sys/class/net
127     # Alias interfaces (ethX:Y) must use ethX entries
128     interface = @resource[:interface].sub(/:\d/, '')
129     ! Dir["/sys/class/net/#{interface}"].empty?
130   end
131
132   def from_str(data)
133     items = {}
134     data.each_line do |line|
135       if m = line.match(/^([A-Za-z_]*)=(.*)$/)
136         items.merge!(m[1] => m[2])
137       end
138     end
139     items
140   end
141
142   def cleared(data)
143     data.each do |key, value|
144       case key
145       when /vlan/i
146         data.delete(key)
147       when /bonding/i
148         data.delete(key)
149       end
150     end
151   end
152
153   def vlan?
154     if File.read('/proc/net/vlan/config') =~ /#{@resource[:interface]}/
155       return true
156     else
157       return false
158     end
159   rescue Errno::ENOENT
160     return false
161   end
162 end