From bdd88f2ad262f23ca32e3f0c5d4ad78b7c9322d8 Mon Sep 17 00:00:00 2001
From: Gilles Dubreuil <gilles@redhat.com>
Date: Wed, 21 May 2014 10:13:00 +1000
Subject: [PATCH 2/2] Refacfored a more suitable ovs_redhat provider
- Added a helper class/library to handle ifcfg content
- Removed keep_ip and sleep parameters
Change-Id: I584fb1442de9a760b3a092f96cbfcbcd6776fdba
---
lib/puppet/provider/vs_bridge/ovs_redhat.rb | 54 ++++-------
lib/puppet/provider/vs_port/ovs_redhat.rb | 133 ++++++++++------------------
lib/puppet/type/vs_port.rb | 18 ----
lib/puppet_x/redhat/ifcfg.rb | 91 +++++++++++++++++++
4 files changed, 151 insertions(+), 145 deletions(-)
create mode 100644 lib/puppet_x/redhat/ifcfg.rb
diff --git a/lib/puppet/provider/vs_bridge/ovs_redhat.rb b/lib/puppet/provider/vs_bridge/ovs_redhat.rb
index 5495d12..e57597d 100644
--- a/lib/puppet/provider/vs_bridge/ovs_redhat.rb
+++ b/lib/puppet/provider/vs_bridge/ovs_redhat.rb
@@ -1,51 +1,27 @@
-require "puppet"
+require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x', 'redhat', 'ifcfg.rb'))
-Base="/etc/sysconfig/network-scripts/ifcfg-"
+Puppet::Type.type(:vs_bridge).provide(:ovs_redhat, :parent => :ovs) do
+ desc 'Openvswitch bridge manipulation for RedHat OSes family'
-Puppet::Type.type(:vs_bridge).provide(:ovs_redhat) do
- desc "Openvswitch bridge manipulation for RedHat family OSs"
-
- confine :osfamily => :redhat
+ confine :osfamily => :redhat
defaultfor :osfamily => :redhat
- optional_commands :vsctl => "/usr/bin/ovs-vsctl",
- :ip => "/sbin/ip"
-
- def exists?
- vsctl("br-exists", @resource[:name])
- rescue Puppet::ExecutionFailure
- return false
- end
+ commands :vsctl => 'ovs-vsctl'
def create
- vsctl("add-br", @resource[:name])
- ip("link", "set", @resource[:name], "up")
- external_ids = @resource[:external_ids] if @resource[:external_ids]
- end
-
- def destroy
- vsctl("del-br", @resource[:name])
- end
-
- def external_ids
- result = vsctl("br-get-external-id", @resource[:name])
- return result.split("\n").join(",")
- end
-
- def external_ids=(value)
- old_ids = _split(external_ids)
- new_ids = _split(value)
-
- new_ids.each_pair do |k,v|
- unless old_ids.has_key?(k)
- vsctl("br-set-external-id", @resource[:name], k, v)
- end
+ begin
+ super unless vsctl('br-exists', @resource[:name])
+ rescue Puppet::ExecutionFailure => e
+ super
end
+ IFCFG::Bridge.new(@resource[:name]).save
end
- private
+ def exists?
+ super && IFCFG::OVS.exists?(@resource[:name])
+ end
- def _split(string, splitter=",")
- return Hash[string.split(splitter).map{|i| i.split("=")}]
+ def destroy
+ super && IFCFG::OVS.remove(@resource[:name])
end
end
diff --git a/lib/puppet/provider/vs_port/ovs_redhat.rb b/lib/puppet/provider/vs_port/ovs_redhat.rb
index 6d43797..5a17897 100644
--- a/lib/puppet/provider/vs_port/ovs_redhat.rb
+++ b/lib/puppet/provider/vs_port/ovs_redhat.rb
@@ -1,105 +1,62 @@
-require "puppet"
+require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x', 'redhat', 'ifcfg.rb'))
-Puppet::Type.type(:vs_port).provide(:ovs_redhat) do
- desc "Openvswitch port manipulation for RedHat family OSs"
+Puppet::Type.type(:vs_port).provide(:ovs_redhat, :parent => :ovs) do
+ desc 'Openvswitch port manipulation for RedHat OSes family'
- confine :osfamily => :redhat
+ confine :osfamily => :redhat
defaultfor :osfamily => :redhat
- optional_commands :vsctl => "/usr/bin/ovs-vsctl",
- :sleep => "/bin/sleep"
-
- def exists?
- vsctl("list-ports", @resource[:bridge]).include? @resource[:interface]
- end
+ commands :grep => 'grep'
+ commands :ip => 'ip'
+ commands :ifdown => 'ifdown'
+ commands :ifup => 'ifup'
+ commands :vsctl => 'ovs-vsctl'
def create
- if @resource[:keep_ip]
- create_bridge_file
- create_physical_interface_file
- activate_port
+ begin
+ super unless vsctl('br-exists', @resource[:name])
+ rescue Puppet::ExecutionFailure => e
+ super
+ end
+ IFCFG::Port.new(@resource[:interface], @resource[:bridge]).save
+
+ if link?
+ if dynamic?
+ # Persistent MAC address
+ bridge_mac_address = nil
+ datapath_id = vsctl('get', 'bridge', @resource[:bridge], 'datapath_id')
+ bridge_mac_address = datapath_id[-14..-3].scan(/.{1,2}/).join(':') if datapath_id
+ IFCFG::BridgeDynamic.new(@resource[:bridge], @resource[:interface], bridge_mac_address).save
+ else
+ device = ip('addr', 'show', @resource[:interface])
+ cidr = device.to_s.match(/inet (\d*\.\d*\.\d*\.\d*\/\d*)/)[1]
+ IFCFG::BridgeStatic.new(@resource[:bridge], cidr).save
+ end
else
- vsctl("add-port", @resource[:bridge], @resource[:interface])
+ IFCFG::Bridge.new(@resource[:bridge]).save
end
- end
- def destroy
- vsctl("del-port", @resource[:bridge], @resource[:interface])
+ ifdown(@resource[:interface])
+ ifdown(@resource[:bridge])
+ ifup(@resource[:interface])
+ ifup(@resource[:bridge])
end
- private
-
- def activate_port
- atomic_operation="ifdown #{@resource[:interface]};
- ovs-vsctl add-port #{@resource[:bridge]} #{@resource[:interface]};
- ifup #{@resource[:interface]};
- ifup #{@resource[:bridge]}"
- system(atomic_operation)
- sleep(@resource[:sleep]) if @resource[:sleep]
- end
-
- def create_physical_interface_file
- file = File.open(Base + @resource[:interface], 'w+')
- file << "DEVICE=#{@resource[:interface]}\n"
- file << "DEVICETYPE=ovs\n"
- file << "TYPE=OVSPort\n"
- file << "BOOTPROTO=none\n"
- file << "OVS_BRIDGE=#{@resource[:bridge]}\n"
- file << "ONBOOT=yes\n"
- file.close
+ def exists?
+ super && IFCFG::OVS.exists?(@resource[:interface])
end
- def search(file_name, value)
- File.open(file_name) { |file|
- file.each_line { |line|
- match = value.match(line)
- return match[0] if match
- }
- }
+ def destroy
+ super && IFCFG::OVS.remove(@resource[:interface])
end
- def create_bridge_file
- bridge_file = File.open(Base + @resource[:bridge], 'w+')
- interface_file_name = Base + @resource[:interface]
-
- # Ultimately this to go to vs_bridge
- bridge_file << "DEVICE=#{@resource[:bridge]}\n"
- bridge_file << "TYPE=OVSBridge\n"
- bridge_file << "DEVICETYPE=ovs\n"
- bridge_file << "ONBOOT=yes\n"
- # End ultimately
-
- case search(interface_file_name, /bootproto=.*/i)
- when /dhcp/
- bridge_file << "OVSBOOTPROTO=dhcp\n"
- bridge_file << "OVSDHCPINTERFACES=#{@resource[:interface]}\n"
- when /static/, /none/
- bridge_file << "OVSBOOTPROTO=static\n"
+ def dynamic?
+ device = ''
+ device = ip('addr', 'show', @resource[:interface])
+ return device =~ /dynamic/ ? true : false
+ end
- ipaddr = search(interface_file_name, /ipaddr=.*/i)
- if ipaddr.class == String
- bridge_file << ipaddr + "\n"
- else
- raise RuntimeError, 'Undefined IP address'
- end
-
- mask = search(interface_file_name, /(prefix|netmask)=.*/i)
- if mask.class == String
- bridge_file << mask + "\n"
- else
- raise RuntimeError, 'Undefined netmask or prefix'
- end
- else
- raise RuntimeError, 'Undefined boot protocol'
- end
-
- # The idea here to have a fixed MAC address
- datapath_id = vsctl("get", "bridge", @resource[:bridge], 'datapath_id')
- bridge_mac_address = datapath_id[-14..-3].scan(/.{1,2}/).join(':') if datapath_id
-
- if bridge_mac_address
- bridge_file << "OVS_EXTRA=\"set bridge #{@resource[:bridge]} other-config:hwaddr=#{bridge_mac_address}\"\n"
- end
- bridge_file.close
+ def link?
+ grep('up', "/sys/class/net/#{@resource[:interface]}/operstate")
end
-end
\ No newline at end of file
+end
diff --git a/lib/puppet/type/vs_port.rb b/lib/puppet/type/vs_port.rb
index df4705e..8a4b913 100644
--- a/lib/puppet/type/vs_port.rb
+++ b/lib/puppet/type/vs_port.rb
@@ -25,24 +25,6 @@ Puppet::Type.newtype(:vs_port) do
end
end
- newparam(:keep_ip) do
- desc "True: keep physical interface's details and assign them to the bridge"
-
- defaultto false
- end
-
- newparam(:sleep) do
- desc "Waiting time, in seconds (0 by default), for network to sync after activating port, used with keep_ip only"
-
- defaultto '0'
-
- validate do |value|
- if value.to_i.class != Fixnum || value.to_i < 0
- raise ArgumentError, "sleep requires a positive integer"
- end
- end
- end
-
autorequire(:vs_bridge) do
self[:bridge] if self[:bridge]
end
diff --git a/lib/puppet_x/redhat/ifcfg.rb b/lib/puppet_x/redhat/ifcfg.rb
new file mode 100644
index 0000000..fe3a648
--- /dev/null
+++ b/lib/puppet_x/redhat/ifcfg.rb
@@ -0,0 +1,91 @@
+module IFCFG
+ class OVS
+ Base = '/etc/sysconfig/network-scripts/ifcfg-'
+
+ def self.remove(name)
+ File.delete(Base + name)
+ rescue Errno::ENOENT
+ end
+
+ def self.exists?(name)
+ File.exist?(Base + name)
+ end
+
+ def initialize(name)
+ @name = name
+ @device_type = 'ovs'
+ @onboot = 'yes'
+ end
+
+ def to_s
+ ifcfg = "DEVICE=#{@name}\n"
+ ifcfg << "DEVICETYPE=#{@device_type}\n"
+ ifcfg << "TYPE=#{@type}\n"
+ ifcfg << "ONBOOT=yes\n"
+ ifcfg << "OVSBOOTPROTO=#{@bootproto}\n"
+ end
+
+ def save
+ File.open(Base + @name, 'w+') { |file|
+ file << self.to_s
+ }
+ end
+ end
+
+ class Bridge < OVS
+ def initialize(name, bootproto = nil)
+ super(name)
+ @type = 'OVSBridge'
+ @bootproto = bootproto ? bootproto : 'none'
+ end
+ end
+
+ class BridgeDynamic < Bridge
+ def initialize(name, interface, bridge_mac_address=nil)
+ super(name, 'dhcp')
+ @interface = interface
+ @bridge_mac_address = bridge_mac_address
+ end
+
+ def to_s
+ ifcfg = super
+ ifcfg << "OVSDHCPINTERFACES=#{@interface}\n"
+ if @bridge_mac_address
+ ifcfg << "OVS_EXTRA=\"set bridge #{@name} other-config:hwaddr=#{@bridge_mac_address}\"\n"
+ end
+ ifcfg
+ end
+ end
+
+ class BridgeStatic < Bridge
+ def initialize(name, cidr)
+ super(name)
+ cidr.match('(.*)\/(.*)') { |m|
+ @ipaddr = m[1]
+ @prefix = m[2]
+ }
+ end
+
+ def to_s
+ ifcfg = super
+ if @cidr != ''
+ ifcfg << "IPADDR=#{@ipaddr}\n"
+ ifcfg << "PREFIX=#{@prefix}\n"
+ end
+ ifcfg
+ end
+ end
+
+ class Port < OVS
+ def initialize(name, bridge)
+ super(name)
+ @type = 'OVSPort'
+ @bridge = bridge
+ @bootproto = 'none'
+ end
+
+ def to_s
+ super + "OVS_BRIDGE=#{@bridge}\n"
+ end
+ end
+end
--
1.8.3.1