From 6da29b468613e5163f224df2b1fc7706b49a7277 Mon Sep 17 00:00:00 2001 From: Stanislav Makar Date: Thu, 3 Dec 2015 16:19:50 +0000 Subject: [PATCH] Fix restoring lnx2lnx patch after reboot on CentOS7/RHEL7 Change-Id: I148edd31b83e761184a3135570c9b20b8527896c Closes-bug: #1522481 --- .../l23network/files/centos_ifup-pre-local | 5 + .../provider/l23_stored_config_centos.rb | 48 ++++- .../lib/puppet/provider/l2_patch/lnx.rb | 8 +- .../manifests/l2/centos_upndown_scripts.pp | 6 + .../ifcfg-br1 | 6 + .../ifcfg-br2 | 6 + .../ifcfg-p_33470efd-0 | 4 + .../ifcfg-p_33470efd-1 | 4 + .../pre-up-ifcfg-p_33470efd-0 | 2 + .../pre-up-ifcfg-p_33470efd-1 | 2 + .../lnx_centos7__lnx2lnx_patch__spec.rb | 184 ++++++++++++++++++ 11 files changed, 267 insertions(+), 8 deletions(-) create mode 100644 deployment/puppet/l23network/files/centos_ifup-pre-local create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br1 create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br2 create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-0 create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-1 create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-0 create mode 100644 deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-1 create mode 100644 deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec.rb diff --git a/deployment/puppet/l23network/files/centos_ifup-pre-local b/deployment/puppet/l23network/files/centos_ifup-pre-local new file mode 100644 index 0000000000..09a472dcf0 --- /dev/null +++ b/deployment/puppet/l23network/files/centos_ifup-pre-local @@ -0,0 +1,5 @@ +#!/bin/sh +SCRIPT="/etc/sysconfig/network-scripts/pre-up-$1" +if [[ -x $SCRIPT ]] ; then +. $SCRIPT +fi diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb index 5c69593425..6b86255b1d 100644 --- a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos.rb @@ -48,6 +48,7 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ :bond_downdelay => 'downdelay', :ethtool => 'ETHTOOL_OPTS', :routes => 'ROUTES', + :jacks => 'JACKS', } end def property_mappings @@ -129,6 +130,12 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ hash.delete('PREFIX') end + # reading preup file for patch if it exists + if preup_content = self.read_file("#{self.script_directory}/pre-up-ifcfg-#{dirty_iface_name}") and !preup_content.empty? + hash['JACKS'] = preup_content + hash['TYPE'] = 'Patch' + end + hash.delete('DEVICETYPE') if hash['DEVICETYPE'] # Do extra actions if ovs2lnx patch cord @@ -261,6 +268,18 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ return rv end + def self.mangle__jacks(data) + #data should be + #ip link add p_3911f6cc-0 type veth peer name p_3911f6cc-1\nip link set up dev p_3911f6cc-1 + rv = [] + p "parse jacks #{data}" + data.split("\n").each do | line | + jacks = line.scan(/ip\s+link\s+add\s+([\w\-]+)\s+type\s+veth\s+peer\s+name\s+([\w\-]+)/).flatten + rv = jacks if !jacks.empty? + end + return rv + end + ### # Hash to file def self.format_file(filename, providers) @@ -316,6 +335,14 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ self.remove_line_from_file('/etc/sysconfig/network', /GATEWAY.*/) end + #writing the pre-up file for patch + if pairs['TYPE'].to_s == 'Patch' and pairs['JACKS'] + patch_pre_up_filename = "#{self.script_directory}/pre-up-ifcfg-#{provider.name}" + self.write_file(patch_pre_up_filename, pairs['JACKS']) + pairs.delete('TYPE') + pairs.delete('JACKS') + end + pairs.each_pair do |key, val| content << "#{key}=#{val}" if ! val.nil? end @@ -326,12 +353,19 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ end def self.read_file(file) - File.read file + content = '' + content = File.read(file) if File.exist?(file) + return content end def self.write_file(file, content) - File.open(file, 'w') do |fp| - fp.write content + debug("write_file(): writing the file #{file} \nwith content:\n#{content}") + begin + File.open(file, 'w') do |writing_file| + writing_file.write content.to_s + end + rescue + raise Puppet::Error, "write_file(): file #{file} can not be written!" end end @@ -425,5 +459,13 @@ class Puppet::Provider::L23_stored_config_centos < Puppet::Provider::L23_stored_ return rv end + def self.unmangle__jacks(provider, data) + rv = [] + rv << "ip link add #{data[0]} type veth peer name #{data[1]}" + rv << "ip link set up dev #{data[1]}" + rv.join("\n") + end + + end # vim: set ts=2 sw=2 et : diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_patch/lnx.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_patch/lnx.rb index 871d0c6678..5d3181578d 100644 --- a/deployment/puppet/l23network/lib/puppet/provider/l2_patch/lnx.rb +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_patch/lnx.rb @@ -29,7 +29,7 @@ Puppet::Type.type(:l2_patch).provide(:lnx, :parent => Puppet::Provider::Lnx_base found_peer = jacks.select{|j| j[:ifindex]==jack[:peer_ifindex]} next if found_peer.empty? peer = found_peer[0] - _bridges = [jack[:bridge], peer[:bridge]].sort + _bridges = [jack[:bridge], peer[:bridge]] _tails = ([jack[:bridge], peer[:bridge]] == _bridges ? [jack[:name], peer[:name]] : [peer[:name], jack[:name]]) if _bridges.include? nil _name = "patch__raw__#{_tails[0]}--#{_tails[1]}" @@ -70,7 +70,7 @@ Puppet::Type.type(:l2_patch).provide(:lnx, :parent => Puppet::Provider::Lnx_base _br = _bridges.fetch(br_name, {}) #todo: sv: re-design for call method from bridge provider if _br[:br_type].to_s == 'lnx' - self.class.iproute(['link', 'set', 'dev', @resource[:jacks][i], 'master', br_name ]) + self.class.brctl(['addif', br_name, @resource[:jacks][i]]) elsif _br[:br_type].to_s == 'ovs' fail("lnx2ovs patchcord '#{patch_name}' is not implemented yet, use ovs2lnx for this purpose!") #self.class.ovs_vsctl(['--may-exist', 'add-port', br_name, @resource[:jacks][i]]) @@ -92,9 +92,7 @@ Puppet::Type.type(:l2_patch).provide(:lnx, :parent => Puppet::Provider::Lnx_base debug("FLUSH properties: #{@property_flush}") if !['', 'absent'].include? @property_flush[:mtu].to_s # 'absent' is a synonym 'do-not-touch' for MTU - @property_hash[:jacks].uniq.each do |iface| - self.class.set_mtu(iface, @property_flush[:mtu]) - end + @property_hash[:jacks].each { |iface| self.class.set_mtu(iface, @property_flush[:mtu]) } if @property_hash[:jacks] end #todo: /sv: make ability of change bridges for RAW patchcords @property_hash = resource.to_hash diff --git a/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp b/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp index 9babb2f948..6b6e03b356 100644 --- a/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp +++ b/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp @@ -12,5 +12,11 @@ class l23network::l2::centos_upndown_scripts { mode => '0755', content => template('l23network/centos_ifdown-local.erb'), } -> + file {'/sbin/ifup-pre-local': + ensure => present, + owner => 'root', + mode => '0755', + source => 'puppet:///modules/l23network/centos_ifup-pre-local', + } -> anchor { 'l23network::l2::centos_upndown_scripts': } } diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br1 b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br1 new file mode 100644 index 0000000000..fdaed7cce1 --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br1 @@ -0,0 +1,6 @@ +BOOTPROTO=none +IPADDR=192.168.88.2 +DEVICE=br1 +ONBOOT=yes +TYPE=Bridge +PREFIX=24 diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br2 b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br2 new file mode 100644 index 0000000000..1f831c68b4 --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-br2 @@ -0,0 +1,6 @@ +BOOTPROTO=none +IPADDR=192.168.99.2 +DEVICE=br2 +ONBOOT=yes +TYPE=Bridge +PREFIX=24 diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-0 b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-0 new file mode 100644 index 0000000000..3c7413aa0e --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-0 @@ -0,0 +1,4 @@ +BOOTPROTO=none +DEVICE=p_33470efd-0 +ONBOOT=yes +BRIDGE=br1 diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-1 b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-1 new file mode 100644 index 0000000000..cd4dfd463b --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/ifcfg-p_33470efd-1 @@ -0,0 +1,4 @@ +BOOTPROTO=none +DEVICE=p_33470efd-1 +ONBOOT=yes +BRIDGE=br2 diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-0 b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-0 new file mode 100644 index 0000000000..5bbf711261 --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-0 @@ -0,0 +1,2 @@ +ip link add p_33470efd-0 type veth peer name p_33470efd-1 +ip link set up dev p_33470efd-1 diff --git a/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-1 b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-1 new file mode 100644 index 0000000000..5bbf711261 --- /dev/null +++ b/deployment/puppet/l23network/spec/fixtures/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec/pre-up-ifcfg-p_33470efd-1 @@ -0,0 +1,2 @@ +ip link add p_33470efd-0 type veth peer name p_33470efd-1 +ip link set up dev p_33470efd-1 diff --git a/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec.rb b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec.rb new file mode 100644 index 0000000000..891dfa6a25 --- /dev/null +++ b/deployment/puppet/l23network/spec/unit/puppet/provider/l23_stored_config/lnx_centos7__lnx2lnx_patch__spec.rb @@ -0,0 +1,184 @@ +require 'spec_helper' + +resources_map = { + :'br1' => { + :name => "br1", + :onboot => "yes", + :method => "static", + :if_type => "bridge", + :ipaddr => "192.168.88.2/24", + :provider => "lnx_centos7", + }, + :'br2' => { + :name => "br2", + :onboot => "yes", + :method => "static", + :if_type => "bridge", + :ipaddr => "192.168.99.2/24", + :provider => "lnx_centos7", + }, + :'p_33470efd-0' => { + :name => 'p_33470efd-0', + :if_type => 'patch', + :bridge => ["br1"], + :jacks => ['p_33470efd-0', 'p_33470efd-1'], + :provider => "lnx_centos7", + }, + :'p_33470efd-1' => { + :name => "p_33470efd-1", + :if_type => 'patch', + :bridge => ["br2"], + :jacks => ['p_33470efd-0', 'p_33470efd-1'], + :provider => "lnx_centos7", + }, + +} + +describe Puppet::Type.type(:l23_stored_config).provider(:lnx_centos7) do + + let(:input_data) { resources_map} + + let(:resources) do + resources = {} + input_data.each do |name, res| + resources.store name, Puppet::Type.type(:l23_stored_config).new(res) + end + return resources + end + + let(:providers) do + providers = {} + resources.each do |name, resource| + provider = resource.provider + if ENV['SPEC_PUPPET_DEBUG'] + class << provider + def debug(msg) + puts msg + end + end + end + provider.create + providers.store name, provider + end + return providers + end + + before(:each) do + puppet_debug_override() + subject.class.stubs(:script_directory).returns(fixture_path) + file_handle = mock + file_handle.stubs(:write).returns true + File.stubs(:open).yields(file_handle).returns(true) + end + + def fixture_path + File.join(PROJECT_ROOT, 'spec', 'fixtures', 'provider', 'l23_stored_config', 'lnx_centos7__lnx2lnx_patch__spec') + end + + def fixture_file(file) + File.join(fixture_path, file) + end + + def fixture_data(file) + File.read(fixture_file(file)) + end + + context "when formating config files" do + + context 'for LNX bridge br1' do + subject { providers[:'br1'] } + let(:cfg_file) { subject.class.format_file('filepath', [subject]) } + it { expect(cfg_file).to match(/BOOTPROTO=none/) } + it { expect(cfg_file).to match(/IPADDR=192.168.88.2/) } + it { expect(cfg_file).to match(/DEVICE=br1/) } + it { expect(cfg_file).to match(/ONBOOT=yes/) } + it { expect(cfg_file).to match(/TYPE=Bridge/) } + it { expect(cfg_file).to match(/PREFIX=24/) } + it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(6) } + end + + context 'for LNX bridge br2' do + subject { providers[:'br2'] } + let(:cfg_file) { subject.class.format_file('filepath', [subject]) } + it { expect(cfg_file).to match(/BOOTPROTO=none/) } + it { expect(cfg_file).to match(/IPADDR=192.168.99.2/) } + it { expect(cfg_file).to match(/DEVICE=br2/) } + it { expect(cfg_file).to match(/ONBOOT=yes/) } + it { expect(cfg_file).to match(/TYPE=Bridge/) } + it { expect(cfg_file).to match(/PREFIX=24/) } + it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(6) } + end + + context 'for lnx2lnx patchcord p_33470efd-0' do + subject { providers[:'p_33470efd-0'] } + let(:cfg_file) { subject.class.format_file('filepath', [subject]) } + it { expect(cfg_file).to match(/BOOTPROTO=none/) } + it { expect(cfg_file).to match(/DEVICE=p_33470efd-0/) } + it { expect(cfg_file).to match(/BRIDGE=br1/) } + it { expect(cfg_file).to match(/ONBOOT=yes/) } + it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(4) } + end + + context 'for lnx2lnx patchcord p_33470efd-1' do + subject { providers[:'p_33470efd-1'] } + let(:cfg_file) { subject.class.format_file('filepath', [subject]) } + it { expect(cfg_file).to match(/BOOTPROTO=none/) } + it { expect(cfg_file).to match(/DEVICE=p_33470efd-1/) } + it { expect(cfg_file).to match(/BRIDGE=br2/) } + it { expect(cfg_file).to match(/ONBOOT=yes/) } + it { expect(cfg_file.split(/\n/).reject{|x| x=~/^\s*$/}.length). to eq(4) } + end + + context 'file writing error for lnx2lnx patchcord p_33470efd-1' do + subject { providers[:'p_33470efd-1'] } + it do + file_handle = mock + file_handle.stubs(:write).raises(IOError) + File.stubs(:open).yields(file_handle).returns(true) + expect{ subject.class.format_file('filepath', [subject]) }.to raise_error(Puppet::Error, %r{.*file\s+.*-ifcfg-p_33470efd-1\s+can\s+not\s+be\s+written!}) + end + end + + end + + context "when parsing config files" do + + context 'for LNX bridge br1' do + let(:res) { subject.class.parse_file('ifcfg-br1', fixture_data('ifcfg-br1'))[0] } + it { expect(res[:method]).to eq 'manual' } + it { expect(res[:onboot]).to eq true } + it { expect(res[:name]).to eq 'br1' } + it { expect(res[:if_type].to_s).to eq 'bridge' } + it { expect(res[:provider].to_s).to eq 'lnx_centos7' } + end + + context 'for LNX bridge br2' do + let(:res) { subject.class.parse_file('ifcfg-br2', fixture_data('ifcfg-br2'))[0] } + it { expect(res[:method]).to eq 'manual' } + it { expect(res[:onboot]).to eq true } + it { expect(res[:name]).to eq 'br2' } + it { expect(res[:if_type].to_s).to eq 'bridge' } + it { expect(res[:provider].to_s).to eq 'lnx_centos7' } + end + + context 'for lnx2lnx patchcord p_33470efd-0' do + let(:res) { subject.class.parse_file('ifcfg-p_33470efd-0', fixture_data('ifcfg-p_33470efd-0'))[0] } + it { expect(res[:method]).to eq 'manual' } + it { expect(res[:onboot]).to eq true } + it { expect(res[:name]).to eq 'p_33470efd-0' } + it { expect(res[:if_type].to_s).to eq 'patch' } + it { expect(res[:provider].to_s).to eq 'lnx_centos7' } + end + + context 'for lnx2lnx patchcord p_33470efd-1' do + let(:res) { subject.class.parse_file('ifcfg-p_33470efd-1', fixture_data('ifcfg-p_33470efd-1'))[0] } + it { expect(res[:method]).to eq 'manual' } + it { expect(res[:onboot]).to eq true } + it { expect(res[:name]).to eq 'p_33470efd-1' } + it { expect(res[:if_type].to_s).to eq 'patch' } + it { expect(res[:provider].to_s).to eq 'lnx_centos7' } + end + + end + +end