From ac2d7693e02a11d80879ccd80dc33a4f213295e6 Mon Sep 17 00:00:00 2001 From: Feng Pan Date: Sun, 19 Feb 2017 15:14:40 -0500 Subject: Add support for inline config changes This patch changes VPP configuration from file template to inline change directly. This prevents issue with overwriting existing VPP config. Change-Id: I4133be8ebe689d9288e3a8e64cca43afd7e42e64 Signed-off-by: Feng Pan --- lib/puppet/provider/vpp_config/vpp.rb | 118 +++++++++++++++++++++++++++++++++ lib/puppet/provider/vpp_service/vpp.rb | 113 ------------------------------- lib/puppet/type/vpp_config.rb | 14 ++++ lib/puppet/type/vpp_service.rb | 46 ------------- 4 files changed, 132 insertions(+), 159 deletions(-) create mode 100644 lib/puppet/provider/vpp_config/vpp.rb delete mode 100644 lib/puppet/provider/vpp_service/vpp.rb create mode 100644 lib/puppet/type/vpp_config.rb delete mode 100644 lib/puppet/type/vpp_service.rb (limited to 'lib') diff --git a/lib/puppet/provider/vpp_config/vpp.rb b/lib/puppet/provider/vpp_config/vpp.rb new file mode 100644 index 0000000..2574d4c --- /dev/null +++ b/lib/puppet/provider/vpp_config/vpp.rb @@ -0,0 +1,118 @@ +Puppet::Type.type(:vpp_config).provide(:vpp) do + + def file_path + '/etc/vpp/startup.conf' + end + + def initialize(value={}) + super(value) + settings_arr = @resource[:setting].split('/') + @section = settings_arr[0] + @real_setting = settings_arr[1] + @dev = settings_arr[2] + + if @section.nil? || @real_setting.nil? + fail("#{@resource[:setting]} is not a valid setting string") + end + + if @dev + @search_regex = /^\s*dev\s+#{@dev}\s*({[^}]*})?/ + else + @search_regex = /^\s*#{@real_setting}\s+(\S+)?/ + end + + end + + def write_config(config) + if File.read(file_path) != config + File.open(file_path, 'w') do |fh| + fh.puts(config) + end + end + end + + def get_sections + vpp_config = File.read(file_path) + scanner = StringScanner.new vpp_config + + #first skip to section beginning + string = scanner.scan_until(/#{@section}\s*{\s*/) + + #if we can't find the section, add it to the end + return vpp_config+"\n#{@section} {", "", "}\n" unless string + + level = 1 + before = string + after = '' + section_config = '' + + while current_char = scanner.getch + case current_char + when '{' + level += 1 + section_config << current_char + when '}' + level -= 1 + if level == 0 + after = current_char + scanner.post_match + break + else + section_config << current_char + end + else + section_config << current_char + end + end + + fail("Failed to parse VPP config: #{vpp_config}") unless level == 0 + return before, section_config, after + end + + def add_setting(value) + before, section_config, after = get_sections + + if @dev + if value.to_s.empty? + setting_string = "#{@real_setting} #{@dev}" + else + setting_string = "#{@real_setting} #{@dev} {#{value}}" + end + else + setting_string = "#{@real_setting} #{value}" + end + + if section_config =~ @search_regex + section_config.sub!(@search_regex, " #{setting_string}") + else + section_config.rstrip! + section_config << "\n #{setting_string}\n" + end + + write_config(before+section_config+after) + end + + def create + add_setting(@resource[:value]) + end + + def destroy + before, section_config, after = get_sections + section_config.sub!(@search_regex, "") + write_config(before+section_config+after) + end + + def exists? + before, section_config, after = get_sections + @search_regex.match(section_config) + end + + def value + before, section_config, after = get_sections + @search_regex.match(section_config) { |m| m[1] } + end + + def value=(value) + add_setting(value) + end + +end diff --git a/lib/puppet/provider/vpp_service/vpp.rb b/lib/puppet/provider/vpp_service/vpp.rb deleted file mode 100644 index a887404..0000000 --- a/lib/puppet/provider/vpp_service/vpp.rb +++ /dev/null @@ -1,113 +0,0 @@ -Puppet::Type.type(:vpp_service).provide :vpp do - - commands :vppctlcmd => "vppctl" - commands :systemctlcmd => "systemctl" - - def get_int_prefix(name) - if %r{([[:alpha:]]*#{name})\s+} =~ `vppctl show int` - return $1 - else - raise Puppet::Error.new("Cannot find vpp interface matching: #{name}") - end - end - - def convert_pci_addr(pci_dev) - if pci_dev =~ /\p{XDigit}+:(\p{XDigit}+):(\p{XDigit}+)\.(\p{XDigit}+)/ - return "%x/%x/%x" % ["0x#{$1}".hex, "0x#{$2}".hex, "0x#{$3}".hex] - else - raise Puppet::Error.new("Incorrect pci dev format: #{pci_dev}") - end - end - - def vpp_pre_config - @resource[:pci_devs].each do |pci_dev| - Facter.value(:interfaces).split(',').each do |kernel_nic| - if pci_dev == `ethtool -i #{kernel_nic} | grep bus-info | awk '{print $2}'`.strip - unless system("ip link set dev #{kernel_nic} down") - raise Puppet::Error.new("Failed to shut down kernel nic #{kernel_nic}") - end - - #Disable NIC on boot - file_data = "" - onboot_exists = false - if File.exist?("/etc/sysconfig/network-scripts/ifcfg-#{kernel_nic}") - IO.foreach("/etc/sysconfig/network-scripts/ifcfg-#{kernel_nic}") do |line| - if /ONBOOT/.match(line) - onboot_exists = true - file_data += "ONBOOT=no\n" - else - file_data += line - end - end - unless onboot_exists - file_data += "ONBOOT=no" - end - File.open("/etc/sysconfig/network-scripts/ifcfg-#{kernel_nic}", "w") {|file| file.puts file_data} - end - - if Facter.value("ipaddress_#{kernel_nic}") - @int_ip_mapping[pci_dev] = Facter.value("ipaddress_#{kernel_nic}") + "/" + Facter.value("netmask_#{kernel_nic}") - end - end - end - end - end - - def configure_vpp_interfaces - @resource[:pci_devs].each do |pci_dev| - vpp_int_name= get_int_prefix(convert_pci_addr(pci_dev)) - vppctlcmd "set int state", vpp_int_name, @resource[:state] - if @resource[:copy_kernel_nic_ip] && @int_ip_mapping.has_key?(pci_dev) - vppctlcmd "set int ip address", vpp_int_name, @int_ip_mapping[pci_dev] - end - end - end - - def create - @int_ip_mapping = {} - vpp_pre_config - - #Bring up VPP service - systemctlcmd "restart", "vpp" - systemctlcmd "enable", "vpp" - sleep 10 - - #Configure VPP interfaces - configure_vpp_interfaces - end - - def destroy - systemctlcmd "stop", "vpp" - systemctlcmd "disable", "vpp" - end - - def exists? - if system("systemctl is-active vpp --quiet") - @resource[:pci_devs].each do |pci_dev| - int_name_str = convert_pci_addr(pci_dev) - if %r{([[:alpha:]]*#{int_name_str})\s+} !~ `vppctl show int` - return false - end - end - else - return false - end - return true - end - - def state - @resource[:pci_devs].each do |pci_dev| - vpp_int_output = `vppctl show int #{get_int_prefix(convert_pci_addr(pci_dev))}` - if ! /\s+up\s+/.match(vpp_int_output) - return "down" - end - end - return "up" - end - - def state=(value) - @resource[:pci_devs].each do |pci_dev| - vppctlcmd "set int state", get_int_prefix(convert_pci_addr(pci_dev)), value - end - end -end \ No newline at end of file diff --git a/lib/puppet/type/vpp_config.rb b/lib/puppet/type/vpp_config.rb new file mode 100644 index 0000000..17c910f --- /dev/null +++ b/lib/puppet/type/vpp_config.rb @@ -0,0 +1,14 @@ +Puppet::Type.newtype(:vpp_config) do + + ensurable + + newparam(:setting, :namevar => true) do + end + + newproperty(:value) do + munge do |value| + value.strip if value.is_a? String + end + end + +end diff --git a/lib/puppet/type/vpp_service.rb b/lib/puppet/type/vpp_service.rb deleted file mode 100644 index c1c818f..0000000 --- a/lib/puppet/type/vpp_service.rb +++ /dev/null @@ -1,46 +0,0 @@ -Puppet::Type.newtype(:vpp_service) do - - ensurable - - newparam(:name) do - end - - newparam(:pci_devs, :array_matching => :all) do - desc "PCI dev addresses to be bound to VPP" - def insync?(is) - is.sort == should.sort - end - - validate do |values| - values = [values] unless values.is_a?(Array) - values.map! do |value| - if value =~ /\p{XDigit}+:(\p{XDigit}+):(\p{XDigit}+)\.(\p{XDigit}+)/ - value - else - raise(Puppet::Error, "Incorrect PCI dev address #{value}") - end - end - end - - munge do |values| - if values.is_a?(Array) - values - else - [values] - end - end - end - - newproperty(:state) do - desc "VPP interface state" - defaultto :up - newvalues(:up, :down) - end - - newparam(:copy_kernel_nic_ip) do - desc "Whether to configure VPP interface with kernel NIC's IP settings" - defaultto :true - newvalues(:true, :false) - end - -end -- cgit 1.2.3-korg