From f83970f017673c026c82141761e11b9dc984d1a9 Mon Sep 17 00:00:00 2001 From: Sergey Vasilenko Date: Wed, 17 Dec 2014 19:22:24 +0300 Subject: [PATCH] New L23network implementation. Squized 33 patchsets, all changes detailed described in following blueprint. Can't be merged without corresponded changes in Nailgun part. Fuel-CI: disable Change-Id: I3d7bf070ef6fc42ef82c14f30780672084db5e71 Blueprint: refactor-l23-linux-bridges --- .../puppet/l23network/lib/facter/l23_os.rb | 18 + .../parser/functions/default_provider_for.rb | 19 + .../functions/generate_network_config.rb | 440 +++++-------- .../functions/get_pair_of_jack_names.rb | 15 + .../puppet/parser/functions/get_patch_name.rb | 15 + .../parser/functions/get_provider_for.rb | 24 + .../lib/puppet/provider/k_mod/lnx.rb | 63 ++ .../provider/l23_stored_config/lnx_centos6.rb | 17 + .../provider/l23_stored_config/lnx_ubuntu.rb | 26 + .../provider/l23_stored_config/ovs_centos6.rb | 15 + .../provider/l23_stored_config/ovs_ubuntu.rb | 39 ++ .../puppet/provider/l23_stored_config_base.rb | 65 ++ .../provider/l23_stored_config_centos6.rb | 213 ++++++ .../provider/l23_stored_config_ubuntu.rb | 334 ++++++++++ .../l23network/lib/puppet/provider/l2_base.rb | 621 ++++++++++++++++++ .../lib/puppet/provider/l2_bond/lnx.rb | 199 ++++++ .../lib/puppet/provider/l2_bond/ovs.rb | 112 ++++ .../lib/puppet/provider/l2_bridge/lnx.rb | 97 +++ .../lib/puppet/provider/l2_bridge/ovs.rb | 103 +++ .../lib/puppet/provider/l2_ovs_bond/ovs.rb | 57 -- .../lib/puppet/provider/l2_ovs_bridge/ovs.rb | 55 -- .../lib/puppet/provider/l2_ovs_patch/ovs.rb | 90 --- .../lib/puppet/provider/l2_ovs_port/ovs.rb | 72 -- .../lib/puppet/provider/l2_patch/ovs.rb | 188 ++++++ .../lib/puppet/provider/l2_port/lnx.rb | 189 ++++++ .../lib/puppet/provider/l2_port/ovs.rb | 100 +++ .../lib/puppet/provider/l3_if_downup/ruby.rb | 226 ------- .../provider/l3_if_downup/util/netstat.rb | 71 -- .../lib/puppet/provider/l3_ifconfig/lnx.rb | 232 +++++++ .../lib/puppet/provider/lnx_base.rb | 94 +++ .../lib/puppet/provider/ovs_base.rb | 141 ++++ .../puppet/l23network/lib/puppet/type/cfg.rb | 1 + .../l23network/lib/puppet/type/k_mod.rb | 14 + .../lib/puppet/type/l23_stored_config.rb | 268 ++++++++ .../l23network/lib/puppet/type/l2_bond.rb | 213 ++++++ .../l23network/lib/puppet/type/l2_bridge.rb | 115 ++++ .../l23network/lib/puppet/type/l2_ovs_bond.rb | 89 --- .../lib/puppet/type/l2_ovs_bridge.rb | 26 - .../lib/puppet/type/l2_ovs_patch.rb | 81 --- .../l23network/lib/puppet/type/l2_ovs_port.rb | 94 --- .../l23network/lib/puppet/type/l2_patch.rb | 92 +++ .../l23network/lib/puppet/type/l2_port.rb | 222 +++++++ .../lib/puppet/type/l3_if_downup.rb | 3 +- .../l23network/lib/puppet/type/l3_ifconfig.rb | 148 +++++ .../l23_ethtool_name_commands_mapping.rb | 42 ++ .../l23network/lib/puppetx/l23_utils.rb | 101 +++ .../examples/adv_net_config__bond_lnx.pp | 1 + .../examples/adv_net_config__bond_ovs.pp | 1 + .../l23network/manifests/examples/bond_lnx.pp | 1 + .../manifests/examples/bond_lnx_old_style.pp | 9 +- .../puppet/l23network/manifests/hosts_file.pp | 4 +- .../puppet/l23network/manifests/init.pp | 53 +- deployment/puppet/l23network/manifests/l2.pp | 100 ++- .../puppet/l23network/manifests/l2/bond.pp | 176 +++-- .../l23network/manifests/l2/bond_interface.pp | 39 ++ .../puppet/l23network/manifests/l2/bridge.pp | 62 +- .../manifests/l2/centos_upndown_scripts.pp | 6 +- .../puppet/l23network/manifests/l2/patch.pp | 77 ++- .../puppet/l23network/manifests/l2/port.pp | 127 +++- .../manifests/l3/create_br_iface.pp | 123 ---- .../l23network/manifests/l3/ifconfig.pp | 356 +++------- .../puppet/l23network/manifests/params.pp | 20 + .../classes/adv_net_config__bond_lnx__spec.rb | 191 ------ .../classes/adv_net_config__bond_ovs__spec.rb | 117 ---- .../l23network/spec/classes/bond_lnx__spec.rb | 130 ---- .../spec/classes/bond_lnx_old_style__spec.rb | 126 ---- .../spec/defines/ifconfig__01_dhcp__spec.rb | 145 ---- .../spec/defines/ifconfig__01_manual__spec.rb | 154 ----- .../spec/defines/ifconfig__01_static__spec.rb | 211 ------ .../spec/defines/ifconfig__aliases__spec.rb | 86 --- .../spec/defines/ifconfig__ethtool__spec.rb | 69 -- .../spec/defines/ifconfig__macaddr__spec.rb | 58 -- .../functions/ethtool_convert_hash__spec.rb | 73 -- .../generate_network_config__spec.rb | 189 ------ ...sh_with_defaults_and_deprecations__spec.rb | 115 ---- .../l23network/templates/bonding_Debian.erb | 6 - .../l23network/templates/bonding_RedHat.erb | 4 - .../templates/ipconfig_Debian_bondslave.erb | 10 - .../templates/ipconfig_Debian_dhcp.erb | 12 - .../templates/ipconfig_Debian_manual.erb | 13 - .../templates/ipconfig_Debian_static.erb | 24 - .../templates/ipconfig_RedHat_bondslave.erb | 12 - .../templates/ipconfig_RedHat_dhcp.erb | 24 - .../templates/ipconfig_RedHat_manual.erb | 18 - .../templates/ipconfig_RedHat_static.erb | 32 - .../lib/puppet/provider/l2_nsx_bridge/ovs.rb | 2 +- 86 files changed, 4949 insertions(+), 3486 deletions(-) create mode 100644 deployment/puppet/l23network/lib/facter/l23_os.rb create mode 100644 deployment/puppet/l23network/lib/puppet/parser/functions/default_provider_for.rb create mode 100644 deployment/puppet/l23network/lib/puppet/parser/functions/get_pair_of_jack_names.rb create mode 100644 deployment/puppet/l23network/lib/puppet/parser/functions/get_patch_name.rb create mode 100644 deployment/puppet/l23network/lib/puppet/parser/functions/get_provider_for.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/k_mod/lnx.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_centos6.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_ubuntu.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_centos6.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_ubuntu.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_base.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos6.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_base.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_bond/lnx.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_bond/ovs.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_bridge/lnx.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_bridge/ovs.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bond/ovs.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bridge/ovs.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_ovs_patch/ovs.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_ovs_port/ovs.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_patch/ovs.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_port/lnx.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l2_port/ovs.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/ruby.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/util/netstat.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/l3_ifconfig/lnx.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/lnx_base.rb create mode 100644 deployment/puppet/l23network/lib/puppet/provider/ovs_base.rb create mode 100644 deployment/puppet/l23network/lib/puppet/type/k_mod.rb create mode 100644 deployment/puppet/l23network/lib/puppet/type/l23_stored_config.rb create mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_bond.rb create mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_bridge.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_ovs_bond.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_ovs_bridge.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_ovs_patch.rb delete mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_ovs_port.rb create mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_patch.rb create mode 100644 deployment/puppet/l23network/lib/puppet/type/l2_port.rb create mode 100644 deployment/puppet/l23network/lib/puppet/type/l3_ifconfig.rb create mode 100644 deployment/puppet/l23network/lib/puppetx/l23_ethtool_name_commands_mapping.rb create mode 100644 deployment/puppet/l23network/lib/puppetx/l23_utils.rb create mode 100644 deployment/puppet/l23network/manifests/l2/bond_interface.pp delete mode 100644 deployment/puppet/l23network/manifests/l3/create_br_iface.pp delete mode 100644 deployment/puppet/l23network/spec/classes/adv_net_config__bond_lnx__spec.rb delete mode 100644 deployment/puppet/l23network/spec/classes/adv_net_config__bond_ovs__spec.rb delete mode 100644 deployment/puppet/l23network/spec/classes/bond_lnx__spec.rb delete mode 100644 deployment/puppet/l23network/spec/classes/bond_lnx_old_style__spec.rb delete mode 100644 deployment/puppet/l23network/spec/defines/ifconfig__01_dhcp__spec.rb delete mode 100644 deployment/puppet/l23network/spec/defines/ifconfig__01_manual__spec.rb delete mode 100644 deployment/puppet/l23network/spec/defines/ifconfig__01_static__spec.rb delete mode 100644 deployment/puppet/l23network/spec/defines/ifconfig__aliases__spec.rb delete mode 100644 deployment/puppet/l23network/spec/defines/ifconfig__ethtool__spec.rb delete mode 100644 deployment/puppet/l23network/spec/defines/ifconfig__macaddr__spec.rb delete mode 100644 deployment/puppet/l23network/spec/functions/ethtool_convert_hash__spec.rb delete mode 100644 deployment/puppet/l23network/spec/functions/generate_network_config__spec.rb delete mode 100644 deployment/puppet/l23network/spec/functions/get_hash_with_defaults_and_deprecations__spec.rb delete mode 100644 deployment/puppet/l23network/templates/bonding_Debian.erb delete mode 100644 deployment/puppet/l23network/templates/bonding_RedHat.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_Debian_bondslave.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_Debian_dhcp.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_Debian_manual.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_Debian_static.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_RedHat_bondslave.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_RedHat_dhcp.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_RedHat_manual.erb delete mode 100644 deployment/puppet/l23network/templates/ipconfig_RedHat_static.erb diff --git a/deployment/puppet/l23network/lib/facter/l23_os.rb b/deployment/puppet/l23network/lib/facter/l23_os.rb new file mode 100644 index 0000000000..1b1850d141 --- /dev/null +++ b/deployment/puppet/l23network/lib/facter/l23_os.rb @@ -0,0 +1,18 @@ +# Fact: l23_os +# +# Purpose: Return return os_name for using inside l23 network module +# +Facter.add(:l23_os) do + setcode do + case Facter.value(:osfamily) + when /(?i)darwin/ + 'osx' + when /(?i)debian/ + #todo: separate upstart and systemd based + 'ubuntu' + when /(?i)redhat/ + #todo: separate centos6 and centos7 + 'centos6' + end + end +end \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/parser/functions/default_provider_for.rb b/deployment/puppet/l23network/lib/puppet/parser/functions/default_provider_for.rb new file mode 100644 index 0000000000..e631074d7f --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/parser/functions/default_provider_for.rb @@ -0,0 +1,19 @@ + +module Puppet::Parser::Functions + newfunction(:default_provider_for, :type => :rvalue, :doc => <<-EOS + Get the default provider of a type + EOS + ) do |argv| + type_name = argv[0] + fail('No type name provided!') if ! type_name + Puppet::Type.loadall() + type_name = type_name.capitalize.to_sym + return 'undef' if ! Puppet::Type.const_defined? type_name + type = Puppet::Type.const_get type_name + provider = type.defaultprovider + return 'undef' if ! provider + rv = provider.name.to_s + debug("Default provider for type '#{type_name}' is a '#{rv}'.") + return rv + end +end \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/parser/functions/generate_network_config.rb b/deployment/puppet/l23network/lib/puppet/parser/functions/generate_network_config.rb index f80e466afa..064f2ff002 100644 --- a/deployment/puppet/l23network/lib/puppet/parser/functions/generate_network_config.rb +++ b/deployment/puppet/l23network/lib/puppet/parser/functions/generate_network_config.rb @@ -1,9 +1,11 @@ require 'ipaddr' +require 'yaml' require 'forwardable' require 'puppet/parser' require 'puppet/parser/templatewrapper' require 'puppet/resource/type_collection_helper' require 'puppet/util/methodhelper' +require 'puppetx/l23_utils' begin require 'puppet/parser/functions/lib/l23network_scheme.rb' @@ -18,79 +20,70 @@ end module L23network - def self.sanitize_transformation(trans) - action = trans[:action].downcase() + def self.sanitize_transformation(trans, def_provider=nil) + action = trans[:action].to_s.downcase() # Setup defaults rv = case action when "noop" then { - :name => nil, + :name => nil, + :provider => nil } when "add-br" then { - :name => nil, - #:stp_enable => true, - :skip_existing => true + :name => nil, + :stp => nil, + :bpdu_forward => nil, +# :bridge_id => nil, + :external_ids => nil, +# :interface_properties => nil, + :vendor_specific => nil, + :provider => def_provider } when "add-port" then { - :name => nil, - :bridge => nil, - #:type => "internal", - :vlan_id => 0, - :trunks => [], - :port_properties => [], - :interface_properties => [], - :skip_existing => true + :name => nil, + :bridge => nil, +# :type => "internal", + :mtu => nil, + :ethtool => nil, + :vlan_id => nil, + :vlan_dev => nil, +# :trunks => [], + :vendor_specific => nil, + :provider => def_provider } when "add-bond" then { - :name => nil, - :provider => 'ovs', - :bridge => nil, - :interfaces => [], - :vlan_id => 0, - :trunks => [], - :properties => [], - #:port_properties => [], - #:interface_properties => [], - :skip_existing => true + :name => nil, + :bridge => nil, + :mtu => nil, + :interfaces => [], +# :vlan_id => 0, +# :trunks => [], + :bond_properties => nil, + :interface_properties => nil, + :vendor_specific => nil, + :provider => def_provider } when "add-patch" then { - :name => "unnamed", # calculated later - :peers => [nil, nil], - :bridges => [], - :vlan_ids => [0, 0], - :trunks => [], + :name => "unnamed", # calculated later + :bridges => [], + :mtu => nil, + :vendor_specific => nil, + :provider => def_provider } else raise(Puppet::ParseError, "Unknown transformation: '#{action}'.") end # replace defaults to real parameters + rv.map{|k,v| rv[k] = trans[k] if trans.has_key? k } + # Validate and mahgle highly required properties. Most of properties should be validated in puppet type. rv[:action] = action - rv.each do |k,v| - if trans[k] - rv[k] = trans[k] - end - end - # Check for incorrect parameters if not rv[:name].is_a? String raise(Puppet::ParseError, "Unnamed transformation: '#{action}'.") end - name = rv[:name] - if not rv[:bridge].is_a? String and !["add-patch", "add-br"].index(action) - raise(Puppet::ParseError, "Undefined bridge for transformation '#{action}' with name '#{name}'.") - end if action == "add-patch" - if not rv[:bridges].is_a? Array and rv[:bridges].size() != 2 + if !rv[:bridges].is_a? Array or rv[:bridges].size() != 2 raise(Puppet::ParseError, "Transformation patch have wrong 'bridges' parameter.") end - name = "patch__#{rv[:bridges][0]}__#{rv[:bridges][1]}" - if not rv[:peers].is_a? Array and rv[:peers].size() != 2 - raise(Puppet::ParseError, "Transformation patch '#{name}' have wrong 'peers' parameter.") - end - rv[:name] = name - end - if action == "add-bond" - if not (rv[:interfaces].is_a?(Array) and rv[:interfaces].size() >= 2) - raise(Puppet::ParseError, "Transformation bond '#{name}' have wrong 'interfaces' parameter.") - end + rv[:name] = get_patch_name(rv[:bridges]) # name for patch SHOULD be auto-generated end return rv end @@ -109,80 +102,92 @@ Puppet::Parser::Functions::newfunction(:generate_network_config, :type => :rvalu def create_endpoint() { - :properties => {}, - :IP => [] + :ipaddr => [] + } + end + + def res_factory() + # define internal puppet parameters for creating resources + { + :br => 'l23network::l2::bridge', + :port => 'l23network::l2::port', + :bond => 'l23network::l2::bond', + :patch => 'l23network::l2::patch', + :ifconfig => 'l23network::l3::ifconfig' } end if argv.size != 0 raise(Puppet::ParseError, "generate_network_config(): Wrong number of arguments.") end - config_hash = L23network::Scheme.get_config(lookupvar('l3_fqdn_hostname')) if config_hash.nil? - raise(Puppet::ParseError, "get_network_role_property(...): You must call prepare_network_config(...) first!") + raise(Puppet::ParseError, "generate_network_config(...): You must call prepare_network_config(...) first!") end - # define internal puppet parameters for creating resources - res_factory = { - :br => { :name_of_resource => 'l23network::l2::bridge' }, - :port => { :name_of_resource => 'l23network::l2::port' }, - :bond => { :name_of_resource => 'l23network::l2::bond' }, - :bond_lnx => { :name_of_resource => 'l23network::l3::ifconfig' }, - :patch => { :name_of_resource => 'l23network::l2::patch' }, - :ifconfig => { :name_of_resource => 'l23network::l3::ifconfig' } - } - res_factory.each do |k, v| - if v[:name_of_resource].index('::') - # operate by Define - res_factory[k][:resource] = lookuptype(v[:name_of_resource].downcase()) # may be find_definition(k.downcase()) - res_factory[k][:type_of_resource] = :define - else - # operate by custom Type - res_factory[k][:resource] = Puppet::Type.type(v[:name_of_resource].to_sym()) - res_factory[k][:type_of_resource] = :type - end + # we can't imagine, that user can write in this field, but we try to convert to numeric and compare + if config_hash[:version].to_s.to_f < 1.1 + raise(Puppet::ParseError, "generate_network_config(...): You network_scheme hash has wrong format.\nThis parser can work with v1.1 format, please convert you config.") end + default_provider = config_hash[:provider] || 'lnx' + # collect interfaces and endpoints - endpoints = {} ifconfig_order = [] born_ports = [] + # collect L2::port properties from 'interfaces' section + ports_properties = {} # additional parameters from interfaces was stored here config_hash[:interfaces].each do |int_name, int_properties| int_name = int_name.to_sym() - endpoints[int_name] = create_endpoint() - born_ports.insert(-1, int_name) + #endpoints[int_name] = create_endpoint() + born_ports << int_name # add some of 1st level interface properties to it's config - int_properties.each do |k,v| - next if ! ['macaddr', 'mtu', 'ethtool'].index(k.to_s) - endpoints[int_name][:properties][k.to_sym] = v + ports_properties[int_name] ||= {} + if ! int_properties.nil? + int_properties.each do |k,v| + if v.to_s != '' + k = k.to_s.tr('-','_').to_sym + ports_properties[int_name][k] = v + end + end end end - config_hash[:endpoints].each do |e_name, e_properties| - e_name = e_name.to_sym() - if not endpoints[e_name] + # collect L3::ifconfig properties from 'endpoints' section + endpoints = {} + if config_hash[:endpoints].is_a? Hash and !config_hash[:endpoints].empty? + config_hash[:endpoints].each do |e_name, e_properties| + e_name = e_name.to_sym() endpoints[e_name] = create_endpoint() - end - e_properties.each do |k,v| - if k.to_sym() == :IP - if !(v.is_a?(Array) || ['none','dhcp',nil].include?(v)) - raise(Puppet::ParseError, "generate_network_config(): IP field for endpoint '#{e_name}' must be array of IP addresses, 'dhcp' or 'none'.") - elsif ['none','dhcp',nil].include?(v) - endpoints[e_name][:IP].insert(-1, v ? v : 'none') - else - v.each do |ip| - begin - iip = IPAddr.new(ip) - endpoints[e_name][:IP].insert(-1, ip) - rescue - raise(Puppet::ParseError, "generate_network_config(): IP address '#{ip}' for endpoint '#{e_name}' wrong!.") + if ! (e_properties.nil? or e_properties.empty?) + e_properties.each do |k,v| + k = k.to_s.tr('-','_').to_sym + if k == :IP + if !(v.is_a?(Array) || ['none','dhcp',nil].include?(v)) + raise(Puppet::ParseError, "generate_network_config(): IP field for endpoint '#{e_name}' must be array of IP addresses, 'dhcp' or 'none'.") + elsif ['none','dhcp',''].include?(v.to_s) + # 'none' and 'dhcp' should be passed to resource not as list + endpoints[e_name][:ipaddr] = (v.to_s == 'dhcp' ? 'dhcp' : 'none') + else + v.each do |ip| + begin + iip = IPAddr.new(ip) # validate IP address + endpoints[e_name][:ipaddr] ||= [] + endpoints[e_name][:ipaddr] << ip + rescue + raise(Puppet::ParseError, "generate_network_config(): IP address '#{ip}' for endpoint '#{e_name}' wrong!.") + end + end end + else + endpoints[e_name][k] = v end end else - endpoints[e_name][:properties][k.to_sym()] = v + endpoints[e_name][:ipaddr] = 'none' end end + else + config_hash[:endpoints] = {} end # execute transformations @@ -193,157 +198,53 @@ Puppet::Parser::Functions::newfunction(:generate_network_config, :type => :rvalu action = t[:action].strip() if action.start_with?('add-') action = t[:action][4..-1].to_sym() + action_ensure = nil + elsif action.start_with?('del-') + action = t[:action][4..-1].to_sym() + action_ensure = 'absent' else action = t[:action].to_sym() end # add newly-created interface to ifconfig order if [:noop, :port, :br].index(action) - if ! ifconfig_order.index(t[:name].to_sym()) - ifconfig_order.insert(-1, t[:name].to_sym()) - end - elsif action == :bond - t[:provider] ||= 'ovs' # default provider for Bond - if ! t[:interfaces].is_a? Array - raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has non-empty 'interfaces' list.") - end - if t[:provider] == 'lnx' - if ! t[:properties].is_a? Hash - raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has 'properties' hash for '#{t[:provider]}' provider.") - else - if t[:properties].size < 1 - raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has non-empty 'properties' hash for '#{t[:provider]}' provider.") - end - end - elsif t[:provider] == 'ovs' - if ! t[:properties].is_a? Array - raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has 'properties' array for '#{t[:provider]}' provider.") - else - if t[:properties].size < 1 - raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource should has non-empty 'properties' array for '#{t[:provider]}' provider.") - end - end - else - raise(Puppet::ParseError, "generate_network_config(): 'add-bond' resource has wrong provider '#{t[:provider]}'.") - end - if t[:provider] == 'lnx' - if ! ifconfig_order.index(t[:name].to_sym()) - ifconfig_order.insert(-1, t[:name].to_sym()) - end - end - t[:interfaces].each do |physint| - if ! ifconfig_order.index(physint.to_sym()) - ifconfig_order.insert(-1, physint.to_sym()) - end + if ! ifconfig_order.include? t[:name].to_sym() + ifconfig_order << t[:name].to_sym() end end next if action == :noop - trans = L23network.sanitize_transformation(t) + #debug("TXX: '#{t[:name]}' => '#{t.to_yaml.gsub('!ruby/sym ',':')}'.") + trans = L23network.sanitize_transformation(t, default_provider) + #debug("TTT: '#{trans[:name]}' => '#{trans.to_yaml.gsub('!ruby/sym ',':')}'.") - # create puppet resources - if action == :bond and t[:provider] == 'lnx' - # Add Linux_bond-specific parameters to the ifconfig - e_name = t[:name].to_sym - if ! endpoints[e_name] - endpoints[e_name] = create_endpoint() - end - endpoints[e_name][:properties] ||= { :ipaddr => 'none' } - endpoints[e_name][:properties][:bond_properties] = Hash[t[:properties].map{|k,v| [k.to_s,v]}] - born_ports.insert(-1, e_name) - t[:interfaces].each{ |iface| - if ! endpoints[iface.to_sym] - endpoints[iface.to_sym] = create_endpoint() - end - endpoints[iface.to_sym][:properties] ||= { :ipaddr => 'none' } - endpoints[iface.to_sym][:properties][:bond_master] = t[:name].to_s - } - # add port to the ovs bridge as ordinary port - tt = Marshal.load(Marshal.dump(t)) - tt[:action] = 'add-port' # because lnx-bind is a ordinary port in OVS - port_trans = L23network.sanitize_transformation(tt) - resource = res_factory[:port][:resource] - p_resource = Puppet::Parser::Resource.new( - res_factory[:port][:name_of_resource], - port_trans[:name], - :scope => self, - :source => resource - ) - trans.select{|k,v| ! [:action, :interfaces, :properties].index(k) }.each do |k,v| - p_resource.set_parameter(k,v) - end - req_list = [] - req_list.insert(-1, previous) if previous - req_list.insert(-1, "L3_if_downup[#{tt[:name]}]") - p_resource.set_parameter(:require, req_list) - resource.instantiate_resource(self, p_resource) - compiler.add_resource(self, p_resource) - transformation_success.insert(-1, "bond-lnx_as_port(#{port_trans[:name]})") - born_ports.insert(-1, port_trans[:name].to_sym()) - else - # normal OVS transformation - resource = res_factory[action][:resource] - p_resource = Puppet::Parser::Resource.new( - res_factory[action][:name_of_resource], - trans[:name], - :scope => self, - :source => resource - ) - - # setup trunks and vlan_splinters for phys.NIC - if (action == :port) and config_hash[:interfaces][trans[:name].to_sym] and # does adding phys.interface? - config_hash[:interfaces][trans[:name].to_sym][:L2] and # does this interface have L2 section - config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks] and # does this interface have TRUNKS section - config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks].is_a?(Array) and - config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks].size() > 0 # does trunks section non empty? - Puppet.debug("Configure trunks and vlan_splinters for #{trans[:name]} (value is '#{config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters]}')") - _do_trunks = true - if config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters] - if config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters] == 'on' - trans[:vlan_splinters] = true - elsif config_hash[:interfaces][trans[:name].to_sym][:L2][:vlan_splinters] == 'auto' - sp_nics = lookupvar('l2_ovs_vlan_splinters_need_for') - Puppet.debug("l2_ovs_vlan_splinters_need_for: #{sp_nics}") - if sp_nics and sp_nics != :undefined and sp_nics.split(',').index(trans[:name].to_s) - Puppet.debug("enable vlan_splinters for: #{trans[:name].to_s}") - trans[:vlan_splinters] = true - else - trans[:vlan_splinters] = false - if trans[:trunks] and trans[:trunks].size() >0 - Puppet.debug("disable vlan_splinters for: #{trans[:name].to_s}. Trunks will be set to '#{trans[:trunks].join(',')}'") - config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks] = [] - else - Puppet.debug("disable vlan_splinters for: #{trans[:name].to_s}. Trunks for this interface also disabled.") - _do_trunks = false - end - end - else - trans[:vlan_splinters] = false - end - else - trans[:vlan_splinters] = false - end - # add trunks list to the interface if it given - if _do_trunks - _trunks = [0] + trans[:trunks] + config_hash[:interfaces][trans[:name].to_sym][:L2][:trunks] # zero for pass untagged traffic - _trunks.sort!().uniq!() - trans[:trunks] = _trunks - end - Puppet.debug("Configure trunks and vlan_splinters for #{trans[:name]} done.") - end - - trans.select{|k,v| k != :action}.each do |k,v| - p_resource.set_parameter(k,v) - end - - p_resource.set_parameter(:require, [previous]) if previous - resource.instantiate_resource(self, p_resource) - compiler.add_resource(self, p_resource) - transformation_success.insert(-1, "#{t[:action].strip()}(#{trans[:name]})") - born_ports.insert(-1, trans[:name].to_sym()) if action != :patch - previous = p_resource.to_s + if !ports_properties[trans[:name].to_sym()].nil? + trans.merge! ports_properties[trans[:name].to_sym()] end + + # create puppet resources for transformations + resource = res_factory[action] + resource_properties = { } + debug("generate_network_config(): Transformation '#{trans[:name]}' will be produced as '#{trans.to_yaml.gsub('!ruby/sym ',':')}'.") + + trans.select{|k,v| k != :action}.each do |k,v| + if ['Hash', 'Array'].include? v.class.to_s + resource_properties[k.to_s] = L23network.reccursive_sanitize_hash(v) + elsif ! v.nil? + resource_properties[k.to_s] = v + else + #pass + end + end + + resource_properties['require'] = [previous] if previous + function_create_resources([resource, { + "#{trans[:name]}" => resource_properties + }]) + transformation_success.insert(-1, "#{t[:action].strip()}(#{trans[:name]})") + born_ports.insert(-1, trans[:name].to_sym()) if action != :patch + previous = "#{resource}[#{trans[:name]}]" end # check for all in endpoints are in interfaces or born by transformation @@ -357,48 +258,51 @@ Puppet::Parser::Functions::newfunction(:generate_network_config, :type => :rvalu ifc_delta = endpoints.keys().sort() - ifconfig_order full_ifconfig_order = ifconfig_order + ifc_delta - # execute interfaces and endpoints + # create resources for interfaces and endpoints # in order, defined by transformation full_ifconfig_order.each do |endpoint_name| if endpoints[endpoint_name] - endpoint_body = endpoints[endpoint_name] + resource_properties = { } + # create resource - resource = res_factory[:ifconfig][:resource] - p_resource = Puppet::Parser::Resource.new( - res_factory[:ifconfig][:name_of_resource], - endpoint_name, - :scope => self, - :source => resource - ) - p_resource.set_parameter(:interface, endpoint_name) - # set ipaddresses - if endpoint_body[:IP].empty? - p_resource.set_parameter(:ipaddr, 'none') - elsif ['none','dhcp'].index(endpoint_body[:IP][0]) - p_resource.set_parameter(:ipaddr, endpoint_body[:IP][0]) - else - ipaddrs = [] - endpoint_body[:IP].each do |i| - if i =~ /\/\d+$/ - ipaddrs.insert(-1, i) - else - ipaddrs.insert(-1, "#{i}#{default_netmask()}") - end + resource = res_factory[:ifconfig] + debug("generate_network_config(): Endpoint '#{endpoint_name}' will be created with additional properties '#{endpoints[endpoint_name].to_yaml.gsub('!ruby/sym ',':')}'.") + # collect properties for creating endpoint resource + endpoints[endpoint_name].each_pair do |k,v| + if ['Hash', 'Array'].include? v.class.to_s + resource_properties[k.to_s] = L23network.reccursive_sanitize_hash(v) + elsif ! v.nil? + resource_properties[k.to_s] = v + else + #pass end - p_resource.set_parameter(:ipaddr, ipaddrs) end - #set another (see L23network::l3::ifconfig DOC) parametres - endpoint_body[:properties].each do |k,v| - p_resource.set_parameter(k,v) - end - p_resource.set_parameter(:require, [previous]) if previous - resource.instantiate_resource(self, p_resource) - compiler.add_resource(self, p_resource) + resource_properties['require'] = [previous] if previous + # # set ipaddresses + # #if endpoints[endpoint_name][:IP].empty? + # # p_resource.set_parameter(:ipaddr, 'none') + # #elsif ['none','dhcp'].index(endpoints[endpoint_name][:IP][0]) + # # p_resource.set_parameter(:ipaddr, endpoints[endpoint_name][:IP][0]) + # #else + # # ipaddrs = [] + # # endpoints[endpoint_name][:IP].each do |i| + # # if i =~ /\/\d+$/ + # # ipaddrs.insert(-1, i) + # # else + # # ipaddrs.insert(-1, "#{i}#{default_netmask()}") + # # end + # # end + # # p_resource.set_parameter(:ipaddr, ipaddrs) + # #end + # #set another (see L23network::l3::ifconfig DOC) parametres + function_create_resources([resource, { + "#{endpoint_name}" => resource_properties + }]) transformation_success.insert(-1, "endpoint(#{endpoint_name})") - previous = p_resource.to_s + previous = "#{resource}[#{endpoint_name}]" end end return transformation_success.join(" -> ") end -# vim: set ts=2 sw=2 et : +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/parser/functions/get_pair_of_jack_names.rb b/deployment/puppet/l23network/lib/puppet/parser/functions/get_pair_of_jack_names.rb new file mode 100644 index 0000000000..7c3d36c4dc --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/parser/functions/get_pair_of_jack_names.rb @@ -0,0 +1,15 @@ +require 'puppetx/l23_utils' +# +module Puppet::Parser::Functions + newfunction(:get_pair_of_jack_names, :type => :rvalue) do |arguments| + if !arguments.is_a? Array or arguments.size != 1 or arguments[0].size != 2 + raise(Puppet::ParseError, "get_pair_of_jack_names(): Wrong arguments given. " + + "Should be array of two bridge names.") + end + + bridges = arguments[0] + # name shouldn't depend from bridge order + L23network.get_pair_of_jack_names(bridges) + end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/parser/functions/get_patch_name.rb b/deployment/puppet/l23network/lib/puppet/parser/functions/get_patch_name.rb new file mode 100644 index 0000000000..338b968660 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/parser/functions/get_patch_name.rb @@ -0,0 +1,15 @@ +require 'puppetx/l23_utils' +# +module Puppet::Parser::Functions + newfunction(:get_patch_name, :type => :rvalue) do |arguments| + if !arguments.is_a? Array or arguments.size != 1 or arguments[0].size != 2 + raise(Puppet::ParseError, "get_patch_name(): Wrong arguments given. " + + "Should be array of two bridge names.") + end + + bridges = arguments[0] + # name shouldn't depend from bridge order + L23network.get_patch_name(bridges) + end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/parser/functions/get_provider_for.rb b/deployment/puppet/l23network/lib/puppet/parser/functions/get_provider_for.rb new file mode 100644 index 0000000000..2fb117ba47 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/parser/functions/get_provider_for.rb @@ -0,0 +1,24 @@ + +module Puppet::Parser::Functions + newfunction(:get_provider_for, :type => :rvalue, :doc => <<-EOS + Get the default provider of a type + EOS + ) do |argv| + type_name = argv[0] + res_name = argv[1] + fail('No type name provided!') if ! type_name + Puppet::Type.loadall() + type_name = type_name.capitalize.to_sym + return 'undef' if ! Puppet::Type.const_defined? type_name + type = Puppet::Type.const_get type_name +# require 'pry' +# binding.pry + type.loadall() + rv = type.instances.select{|i| i.name.to_s.downcase == res_name.to_s.downcase}.map{|j| j[:provider].to_s} +# require 'pry' +# binding.pry + rv = rv[0] + debug("Provider for '#{type_name}[#{res_name}]' is a '#{rv}'.") + return rv + end +end \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/k_mod/lnx.rb b/deployment/puppet/l23network/lib/puppet/provider/k_mod/lnx.rb new file mode 100644 index 0000000000..46c076378a --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/k_mod/lnx.rb @@ -0,0 +1,63 @@ +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base') + +Puppet::Type.type(:k_mod).provide(:lnx) do + defaultfor :osfamily => :linux + commands :mod_load => 'modprobe', + :ls_mod => 'lsmod', + :mod_unload => 'rmmod' + + + def self.prefetch(resources) + interfaces = instances + resources.keys.each do |name| + if provider = interfaces.find{ |ii| ii.name == name } + resources[name].provider = provider + end + end + end + + def self.instances + rv = [] + ls_mod.split(/\n+/).sort.each do |line| + name = line.split(/\s+/)[0] + rv << new({ + :ensure => :present, + :name => name, + }) + end + rv + end + + def exists? + @property_hash[:ensure] == :present + end + + def create + mod_load(@resource[:module]) + end + + def destroy + mod_unload(@resource[:module]) + end + + def initialize(value={}) + super(value) + @property_flush = {} + @old_property_hash = {} + @old_property_hash.merge! @property_hash + end + + # def flush + # if @property_flush + # debug("FLUSH properties: #{@property_flush}") + # # + # # FLUSH changed properties + # # if ! @property_flush[:mtu].nil? + # # File.open("/sys/class/net/#{@resource[:interface]}/mtu", "w") { |f| f.write(@property_flush[:mtu]) } + # # end + # @property_hash = resource.to_hash + # end + # end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_centos6.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_centos6.rb new file mode 100644 index 0000000000..1549b12bc8 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_centos6.rb @@ -0,0 +1,17 @@ +require 'puppetx/filemapper' +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_centos6') + +Puppet::Type.type(:l23_stored_config).provide(:lnx_centos6, :parent => Puppet::Provider::L23_stored_config_centos6) do + + include PuppetX::FileMapper + + confine :l23_os => :centos6 + defaultfor :l23_os => :centos6 + + has_feature :provider_options + #has_feature :hotpluggable + + self.unlink_empty_files = true + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_ubuntu.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_ubuntu.rb new file mode 100644 index 0000000000..d704e28c37 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/lnx_ubuntu.rb @@ -0,0 +1,26 @@ +require 'puppetx/filemapper' +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_ubuntu') + +Puppet::Type.type(:l23_stored_config).provide(:lnx_ubuntu, :parent => Puppet::Provider::L23_stored_config_ubuntu) do + + include PuppetX::FileMapper + + defaultfor :l23_os => :ubuntu + + has_feature :provider_options + #has_feature :hotpluggable + + self.unlink_empty_files = true + + def self.check_if_provider(if_data) + if if_data[:if_provider] == 'auto' + if_data[:if_provider] = :lnx + true + else + if_data[:if_provider] = nil + false + end + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_centos6.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_centos6.rb new file mode 100644 index 0000000000..0114fe6fdf --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_centos6.rb @@ -0,0 +1,15 @@ +require 'puppetx/filemapper' +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_centos6') + +Puppet::Type.type(:l23_stored_config).provide(:ovs_centos6, :parent => Puppet::Provider::L23_stored_config_centos6) do + + include PuppetX::FileMapper + + confine :l23_os => :centos6 + + has_feature :provider_options + + self.unlink_empty_files = true + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_ubuntu.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_ubuntu.rb new file mode 100644 index 0000000000..bf73d23859 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config/ovs_ubuntu.rb @@ -0,0 +1,39 @@ +require 'puppetx/filemapper' +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/l23_stored_config_ubuntu') + +Puppet::Type.type(:l23_stored_config).provide(:ovs_ubuntu, :parent => Puppet::Provider::L23_stored_config_ubuntu) do + + include PuppetX::FileMapper + + has_feature :provider_options + + self.unlink_empty_files = true + + def self.property_mappings + rv = super + rv.merge!({ + :onboot => 'allow-ovs' + }) + return rv + end + + def self.check_if_provider(if_data) + #((if_data[:if_provider] == 'allow-ovs') ? true : false) + if if_data[:if_provider] == 'allow-ovs' + if_data[:if_provider] = :ovs + true + else + if_data[:if_provider] = nil + false + end + end + + def self.mangle__type(val) + :ethernet + end + def self.unmangle__type(val) + nil + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_base.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_base.rb new file mode 100644 index 0000000000..d4164371cd --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_base.rb @@ -0,0 +1,65 @@ +# type for managing persistent interface config options +# Inspired by puppet-network module. Adrien, thanks. + +require 'puppetx/l23_utils' + +class Puppet::Provider::L23_stored_config_base < Puppet::Provider + + COMMENT_CHAR = '#' + + # The valid vlan ID range is 0-4095; 4096 is out of range + VLAN_RANGE_REGEX = %r[\d{1,3}|40[0-9][0-5]] + + # @return [Regexp] The regular expression for interface scripts + SCRIPT_REGEX = %r[\Aifcfg-[a-z]+[\w\d-]+(?::\d+|\.#{VLAN_RANGE_REGEX})?\Z] + + def self.script_directory + raise "Should be implemented in more specific class." + end + + class MalformedInterfacesError < Puppet::Error + def initialize(msg = nil) + msg = "Malformed config file; cannot instantiate stored_config resources for interface #{name}" if msg.nil? + super + end + end + + def self.raise_malformed + @failed = true + raise MalformedInterfacesError + end + + # Map provider instances to files based on their name + # + # @return [String] The path of the file for the given interface resource + # + # @example + # prov = RedhatProvider.new(:name => 'eth1') + # prov.select_file # => '/etc/sysconfig/network-scripts/ifcfg-eth1' + # + def select_file + "#{self.class.script_directory}/ifcfg-#{name}" + end + + # Scan all files in the networking directory for interfaces + # + # @param script_dir [String] The path to the networking scripts, defaults to + # {#SCRIPT_DIRECTORY} + # + # @return [Array] All network-script config files on this machine. + # + # @example + # RedhatProvider.target_files + # # => ['/etc/sysconfig/network-scripts/ifcfg-eth0', '/etc/sysconfig/network-scripts/ifcfg-eth1'] + def self.target_files(script_dir = nil) + script_dir ||= script_directory + entries = Dir.entries(script_dir).select {|entry| entry.match SCRIPT_REGEX} + entries.map {|entry| File.join(script_directory, entry)} + end + + def self.post_flush_hook(filename) + File.chmod(0644, filename) if File.exist? filename + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos6.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos6.rb new file mode 100644 index 0000000000..7c915b77de --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_centos6.rb @@ -0,0 +1,213 @@ +require File.join(File.dirname(__FILE__), 'l23_stored_config_base') + +class Puppet::Provider::L23_stored_config_centos6 < Puppet::Provider::L23_stored_config_base + + # @return [String] The path to network-script directory on redhat systems + def self.script_directory + "/etc/sysconfig/network-scripts" + end + + NAME_MAPPINGS = { + :method => 'BOOTPROTO', + :name => 'DEVICE', + :onboot => 'ONBOOT', + :mtu => 'MTU', + :vlan_id => 'VLAN', + :vlan_dev => 'PHYSDEV', + :vlan_mode => 'VLAN_NAME_TYPE', + :if_type => 'TYPE' + } + + # In the interface config files those fields should be written as boolean + BOOLEAN_FIELDS = [ + :vlan_id, + :hotplug, + :onboot + ] + + # This is a hook method that will be called by PuppetX::Filemapper + # + # @param [String] filename The path of the interfaces file being parsed + # @param [String] contents The contents of the given file + # + # @return [Array>] A single element array containing + # the key/value pairs of properties parsed from the file. + # + # @example + # RedhatProvider.parse_file('/etc/sysconfig/network-scripts/ifcfg-eth0', #) + # # => [ + # # { + # # :name => 'eth0', + # # :ipaddress => '169.254.0.1', + # # :netmask => '255.255.0.0', + # # }, + # # ] + def self.parse_file(filename, contents) + # Split up the file into lines + lines = contents.split("\n") + # Strip out all comments + lines.map! { |line| line.sub(/#.*$/, '') } + # Remove all blank lines + lines.reject! { |line| line.match(/^\s*$/) } + + pair_regex = %r/^\s*(.+?)\s*=\s*(.*)\s*$/ + + # Convert the data into key/value pairs + pairs = lines.inject({}) do |hash, line| + if (m = line.match pair_regex) + key = m[1].strip + val = m[2].strip + hash[key] = val + else + raise Puppet::Error, %{#{filename} is malformed; "#{line}" did not match "#{pair_regex.to_s}"} + end + hash + end + + props = self.munge(pairs) + props.merge!({:family => :inet}) + + debug("Resource hash for '#{props[:name]}' is '#{props}'") + # The FileMapper mixin expects an array of providers, so we return the + # single interface wrapped in an array + [props] + end + + + def self.munge(pairs) + props = {} + + # Unquote all values + pairs.each_pair do |key, val| + if (munged = val.to_s.gsub(/['"]/, '')) + pairs[key] = munged + end + end + + # For each interface attribute that we recognize it, add the value to the + # hash with our expected label + NAME_MAPPINGS.merge({:nnname => 'NAME'}).each_pair do |type_name, redhat_name| + if (val = pairs[redhat_name]) + # We've recognized a value that maps to an actual type property, delete + # it from the pairs and copy it as an actual property + pairs.delete(redhat_name) + case type_name + when /if_type/ + props[type_name] = val.downcase + else + props[type_name] = val + end + end + end + + # use :name if no :device given + if !props[:name] and props[:nnname] + props[:name] = props[:nnname] + end + props.delete(:nnname) + + #!# # For all of the remaining values, blindly toss them into the options hash. + #!# props[:options] = pairs if ! pairs.empty? + + BOOLEAN_FIELDS.each do |bool_property| + if props[bool_property] + props[bool_property] = ! (props[bool_property] =~ /yes/i).nil? + end + end + + + + #todo(sv): Calculate Method + # if ! ['bootp', 'dhcp'].include? props[:method] + # props[:method] = 'static' + # end + + props + end + + def self.mangle__vlan_mode(val) + if val.to_s.upcase == 'VLAN_PLUS_VID_NO_PAD' + 'vlan' + else + 'eth' + end + end + + + ### + # Hash to file + + def self.format_file(filename, providers) + if providers.length == 0 + return "" + elsif providers.length > 1 + raise Puppet::DevError, "Unable to support multiple interfaces [#{providers.map(&:name).join(',')}] in a single file #{filename}" + end + + provider = providers[0] + props = {} + + # Map everything to a flat hash + #props = (provider.options || {}) + + NAME_MAPPINGS.keys.each do |type_name| + val = provider.send(type_name) + if val and val.to_s != 'absent' + props[type_name] = val + end + end + + pairs = self.unmunge(props) + + content = pairs.inject('') do |str, (key, val)| + str << %{#{key}=#{val}\n} + end + + content + end + + + + def self.unmunge(props) + + pairs = {} + + BOOLEAN_FIELDS.each do |bool_property| + if props[bool_property] + props[bool_property] = ((props[bool_property] == true) ? 'yes' : 'no') + end + end + + NAME_MAPPINGS.each_pair do |type_name, redhat_name| + if (val = props[type_name]) + props.delete(type_name) + case type_name + when /if_type/ + pairs[redhat_name] = val.capitalize + else + pairs[redhat_name] = val + end + end + end + + pairs.merge! props + + pairs.each_pair do |key, val| + if val.is_a? String and val.match(/\s+/) + pairs[key] = %{"#{val}"} + end + end + + pairs + end + + def self.unmangle__vlan_mode(val) + if val.to_s == 'vlan' + 'VLAN_PLUS_VID_NO_PAD' + else + nil + end + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb new file mode 100644 index 0000000000..71ca931b73 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l23_stored_config_ubuntu.rb @@ -0,0 +1,334 @@ +require File.join(File.dirname(__FILE__), 'l23_stored_config_base') + +class Puppet::Provider::L23_stored_config_ubuntu < Puppet::Provider::L23_stored_config_base + + # @return [String] The path to network-script directory on redhat systems + def self.script_directory + '/etc/network/interfaces.d' + end + + def self.property_mappings + { + :if_type => 'if_type', # pseudo field, not found in config, but calculated + :if_provider => 'if_provider', # pseudo field, not found in config, but calculated + :method => 'method', + :name => 'iface', + :onboot => 'auto', + :mtu => 'mtu', + :bridge_ports => 'bridge_ports', # ports, members of bridge, fake property + :bridge_stp => 'bridge_stp', + :vlan_dev => 'vlan-raw-device', + :ipaddr => 'address', + # :netmask => 'netmask', + :gateway => 'gateway', + :gateway_metric => 'metric', # todo: rename to 'metric' + # :dhcp_hostname => 'hostname' + :bond_master => 'bond-master', + :bond_slaves => 'bond-slaves', + :bond_mode => 'bond-mode', + :bond_miimon => 'bond-miimon', + } + end + def property_mappings + self.class.property_mappings + end + + # In the interface config files those fields should be written as boolean + def self.boolean_properties + [ + :hotplug, + :onboot, + :bridge_stp + ] + end + def boolean_properties + self.class.boolean_properties + end + + def self.properties_fake + [ + :onboot, + :name, + :family, + :method, + :if_type, + :if_provider + ] + end + def properties_fake + self.class.properties_fake + end + + # This is a hook method that will be called by PuppetX::Filemapper + # + # @param [String] filename The path of the interfaces file being parsed + # @param [String] contents The contents of the given file + # + # @return [Array>] A single element array containing + # the key/value pairs of properties parsed from the file. + # + # @example + # RedhatProvider.parse_file('/etc/sysconfig/network-scripts/ifcfg-eth0', #) + # # => [ + # # { + # # :name => 'eth0', + # # :ipaddress => '169.254.0.1', + # # :netmask => '255.255.0.0', + # # }, + # # ] + + def self.parse_file(filename, contents) + # WARNING!!! + # this implementation can parce only one interface per file file format + + # Split up the file into lines + lines = contents.split("\n") + # Strip out all comments + lines.map! { |line| line.sub(/#.*$/, '') } + # Remove all blank lines + lines.reject! { |line| line.match(/^\s*$/) } + + # initialize hash as predictible values + hash = {} + hash['auto'] = false + hash['if_provider'] = 'none' + hash['if_type'] = :ethernet + dirty_iface_name = nil + if (m = filename.match(%r/ifcfg-(\S+)$/)) + # save iface name from file name. One will be used if iface name not defined inside config. + dirty_iface_name = m[1].strip + end + + # Convert the data into key/value pairs + pair_regex = %r/^\s*([\w+\-]+)\s+(.*)\s*$/ + lines.each do |line| + if (m = line.match(pair_regex)) + key = m[1].strip + val = m[2].strip + case key + # Ubuntu has non-linear config format. Some options should be calculated evristically + when /(auto|allow-ovs)/ + hash[$1] = true + hash['if_provider'] = $1 # temporary store additional data for self.check_if_provider + if ! hash.has_key?('iface') + # setup iface name if it not given in iface directive + mm = val.split(/\s+/) + hash['iface'] = mm[0] + end + when /iface/ + mm = val.split(/\s+/) + hash['iface'] = mm[0] + hash['method'] = mm[2] + # if hash['iface'] =~ /^br.*/i + # # todo(sv): Make more powerful methodology for recognizind Bridges. + # hash['if_type'] = :bridge + # end + when /bridge-ports/ + hash['if_type'] = :bridge + hash[key] = val + when /bond-(slaves|mode)/ + hash['if_type'] = :bond + hash[key] = val + else + hash[key] = val + end + else + raise Puppet::Error, %{#{filename} is malformed; "#{line}" did not match "#{pair_regex.to_s}"} + end + hash + end + # set mostly low-priority interface name if not given in config file + hash['iface'] ||= dirty_iface_name + + props = self.mangle_properties(hash) + props.merge!({:family => :inet}) + + # The FileMapper mixin expects an array of providers, so we return the + # single interface wrapped in an array + rv = (self.check_if_provider(props) ? [props] : []) + debug("parse_file('#{filename}'): #{props.inspect}") + rv + end + + def self.check_if_provider(if_data) + raise Puppet::Error, "self.check_if_provider(if_data) Should be implemented in more specific class." + end + + def self.mangle_properties(pairs) + props = {} + + # Unquote all values + pairs.each_pair do |key, val| + next if ! (val.is_a? String or val.is_a? Symbol) + if (munged = val.to_s.gsub(/['"]/, '')) + pairs[key] = munged + end + end + + # For each interface attribute that we recognize it, add the value to the + # hash with our expected label + property_mappings.each_pair do |type_name, in_config_name| + if (val = pairs[in_config_name]) + # We've recognized a value that maps to an actual type property, delete + # it from the pairs and copy it as an actual property + pairs.delete(in_config_name) + mangle_method_name="mangle__#{type_name}" + if self.respond_to?(mangle_method_name) + rv = self.send(mangle_method_name, val) + else + rv = val + end + props[type_name] = rv if ! [nil, :absent].include? rv + end + end + + #!# # For all of the remaining values, blindly toss them into the options hash. + #!# props[:options] = pairs if ! pairs.empty? + + boolean_properties.each do |bool_property| + if props[bool_property] + props[bool_property] = ! (props[bool_property] =~ /^\s*(yes|on)\s*$/i).nil? + else + props[bool_property] = :absent + end + end + + props + end + + def self.mangle__method(val) + val.to_sym + end + + def self.mangle__if_type(val) + val.downcase.to_sym + end + + def self.mangle__gateway_metric(val) + (val.to_i == 0 ? :absent : val.to_i) + end + + def self.mangle__bridge_ports(val) + val.split(/[\s,]+/).sort + end + + def self.mangle__bond_slaves(val) + val.split(/[\s,]+/).sort + end + + ### + # Hash to file + + def self.format_file(filename, providers) + if providers.length == 0 + return "" + elsif providers.length > 1 + raise Puppet::DevError, "Unable to support multiple interfaces [#{providers.map(&:name).join(',')}] in a single file #{filename}" + end + + content = [] + provider = providers[0] + + # Add onboot interfaces + if provider.onboot + content << "#{property_mappings[:onboot]} #{provider.name}" + end + + # Add iface header + content << "iface #{provider.name} inet #{provider.method}" + + # Map everything to a flat hash + #props = (provider.options || {}) + props = {} + + property_mappings.keys.select{|v| ! properties_fake.include?(v)}.each do |type_name| + #binding.pry + #debug("ZZZZZZZ: #{property_mappings}") + val = provider.send(type_name) + if val and val.to_s != 'absent' + props[type_name] = val + end + end + + debug("format_file('#{filename}')::properties: #{props.inspect}") + pairs = self.unmangle_properties(props) + + pairs.each_pair do |key, val| + content << "#{key} #{val}" if ! val.nil? + end + + debug("format_file('#{filename}')::content: #{content.inspect}") + content << '' + content.join("\n") + end + + + def self.unmangle_properties(props) + pairs = {} + + boolean_properties.each do |bool_property| + if ! props[bool_property].nil? + props[bool_property] = ((props[bool_property].to_s.to_sym == :true) ? 'yes' : 'no') + end + end + + property_mappings.each_pair do |type_name, in_config_name| + if (val = props[type_name]) + props.delete(type_name) + mangle_method_name="unmangle__#{type_name}" + if self.respond_to?(mangle_method_name) + rv = self.send(mangle_method_name, val) + else + rv = val + end + pairs[in_config_name] = rv if ! [nil, :absent].include? rv + end + end + + #pairs.merge! props + + # pairs.each_pair do |key, val| + # if val.is_a? String and val.match(/\s+/) + # debug("==[#{key.to_sym}]==[\"#{val}\"]==") + # pairs[key.to_sym] = "\"#{val}\"" + # end + # end + + pairs + end + + def self.unmangle__if_type(val) + # in Debian family interface config file don't contains declaration of interface type + nil + end + + def self.unmangle__gateway_metric(val) + (val.to_i == 0 ? :absent : val.to_i) + end + + def self.unmangle__bridge_ports(val) + if val.size < 1 or [:absent, :undef].include? Array(val)[0].to_sym + nil + else + val.sort.join(' ') + end + end + + def self.unmangle__bond_master(val) + if [:none, :absent, :undef].include? val.to_sym + nil + else + val + end + end + + def self.unmangle__bond_slaves(val) + if val.size < 1 or [:absent, :undef].include? Array(val)[0].to_sym + nil + else + val.sort.join(' ') + end + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_base.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_base.rb new file mode 100644 index 0000000000..fc8b1c92b8 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_base.rb @@ -0,0 +1,621 @@ +require 'puppetx/l23_utils' +require 'puppetx/l23_ethtool_name_commands_mapping' +require 'yaml' + +class Puppet::Provider::L2_base < Puppet::Provider + + def self.prefetch(resources) + interfaces = instances + resources.keys.each do |name| + if provider = interfaces.find{ |ii| ii.name == name } + resources[name].provider = provider + end + end + end + + # --------------------------------------------------------------------------- + + def self.iface_exist?(iface) + File.exist? "/sys/class/net/#{iface}" + end + + def self.get_lnx_vlan_interfaces + # returns hash, that contains ports (interfaces) configuration. + # i.e { + # eth0.101 => { :vlan_dev => 'eth0', :vlan_id => 101, vlan_mode => 'eth' }, + # vlan102 => { :vlan_dev => 'eth0', :vlan_id => 102, vlan_mode => 'vlan' }, + # } + # + vlan_ifaces = {} + rc_c = /([\w+\.\-]+)\s*\|\s*(\d+)\s*\|\s*([\w+\-]+)/ + File.open("/proc/net/vlan/config", "r").each do |line| + if (rv=line.match(rc_c)) + vlan_ifaces[rv[1]] = { + :vlan_dev => rv[3], + :vlan_id => rv[2], + :vlan_mode => (rv[1].match('\.').nil? ? 'vlan' : 'eth' ) + } + end + end + return vlan_ifaces + end + + def self.get_lnx_ports + # returns hash, that contains ports (interfaces) configuration. + # i.e { + # eth0 => { :mtu => 1500, :if_type => :ethernet, port_type => lnx:eth:unremovable }, + # } + # + # 'unremovable' flag for port_type means, that this port is a more complicated thing, + # than just a port and can't be removed just as port. For example you can't remove bond + # as port. You should remove it as bond. + # + port = {} + # + # parse 802.1q vlan interfaces from /proc + vlan_ifaces = self.get_lnx_vlan_interfaces() + # Fetch information about interfaces, visible in network namespace from /sys/class/net + interfaces = Dir['/sys/class/net/*'].select{ |f| File.symlink? f} + interfaces.each do |if_dir| + if_name = if_dir.split('/')[-1] + port[if_name] = { + :name => if_name, + :port_type => [], + :onboot => self.get_iface_state(if_name), + :ethtool => nil, + :mtu => File.open("#{if_dir}/mtu").read.chomp.to_i, + :provider => (if_name == 'ovs-system') ? 'ovs' : 'lnx' , + } + # determine port_type for this iface + if File.directory? "#{if_dir}/bonding" + # This interface is a baster of bond, get bonding properties + port[if_name][:slaves] = File.open("#{if_dir}/bonding/slaves").read.chomp.strip.split(/\s+/).sort + port[if_name][:port_type] << 'bond' << 'unremovable' + elsif File.directory? "#{if_dir}/bridge" and File.directory? "#{if_dir}/brif" + # this interface is a bridge, get bridge properties + port[if_name][:slaves] = Dir["#{if_dir}/brif/*"].map{|f| f.split('/')[-1]}.sort + port[if_name][:port_type] << 'bridge' << 'unremovable' + else + #pass + end + # Check, whether this interface is a slave of anything + if File.symlink?("#{if_dir}/master") + port[if_name][:has_master] = File.readlink("#{if_dir}/master").split('/')[-1] + end + # Check, whether this interface is a subinterface + if vlan_ifaces.has_key? if_name + # this interface is a 802.1q subinterface + port[if_name].merge! vlan_ifaces[if_name] + port[if_name][:port_type] << 'vlan' + end + end + # Check, whether port is a slave of anything another + port.keys.each do |p_name| + if port[p_name].has_key? :has_master + master = port[p_name][:has_master] + #debug("m='#{master}', name='#{p_name}', props=#{port[p_name]}") + master_flags = port[master][:port_type] + if master_flags.include? 'bond' + # this port is a bond_member + port[p_name][:bond_master] = master + port[p_name][:port_type] << 'bond-slave' + elsif master_flags.include? 'bridge' + # this port is a member of bridge + port[p_name][:bridge] = master + port[p_name][:port_type] << 'bridge-slave' + elsif master == 'ovs-system' + port[p_name][:port_type] << 'ovs-affected' + else + #pass + end + port[p_name].delete(:has_master) + end + end + return port + end + + # --------------------------------------------------------------------------- + def self.ovs_parse_opthash(hh) + #if !(hh=~/^['"]/ and hh=~/['"]$/) + rv = {} + if hh =~ /^\{(.*)\}$/ + $1.split(/\s*\,\s*/).each do |pair| + k,v = pair.split('=') + #debug("===#{k}===#{v}===") + rv[k.tr("'\"",'').to_sym] = v.nil? ? nil : v.tr("'\"",'') + end + end + return rv + end + + def self.get_ovs_bridges + # return OVS interfaces hash if it possible + begin + vsctl_list_bridges = vsctl('list', 'Bridge').split("\n") + vsctl_list_bridges << :EOF # last section of output should be processsed anyway. + rescue + debug("Can't find OVS ports, because error while 'ovs-vsctl list Bridge' execution") + return {} + end + # + buff = {} + rv = {} + # parse ovs-vsctl output and find OVS and OVS-affected interfaces + vsctl_list_bridges.each do |line| + if line =~ /(\w+)\s*\:\s*(.*)\s*$/ + key = $1.tr("'\"",'') + val = $2.tr("'\"",'') + buff[key] = (val == '[]' ? '' : val) + elsif line =~ /^\s*$/ or line == :EOF + stp_enable = buff['stp_enable'] || '' + rv[buff['name']] = { + :stp => stp_enable.downcase == 'true', + :vendor_specific => { + :external_ids => ovs_parse_opthash(buff['external_ids']), + :other_config => ovs_parse_opthash(buff['other_config']), + :status => ovs_parse_opthash(buff['status']), + } + } + debug("Found OVS br: '#{buff['name']}' with properties: #{rv[buff['name']]}") + buff = {} + else + debug("Output of 'ovs-vsctl list Bridge' contain misformated line: '#{line}'") + end + end + return rv + end + + def self.get_ovs_ports + # return OVS interfaces hash if it possible + begin + vsctl_list_ports = vsctl('list', 'Port').split("\n") + vsctl_list_ports << :EOF # last section of output should be processsed anyway. + rescue + debug("Can't find OVS ports, because error while 'ovs-vsctl list Port' execution") + return {} + end + # + buff = {} + rv = {} + # parse ovs-vsctl output and find OVS and OVS-affected interfaces + vsctl_list_ports.each do |line| + if line =~ /(\w+)\s*\:\s*(.*)\s*$/ + key = $1.tr("'\"",'') + val = $2.tr("'\"",'') + buff[key] = val == '[]' ? '' : val + elsif line =~ /^\s*$/ or line == :EOF + rv[buff['name']] = { + :vendor_specific => { + :other_config => ovs_parse_opthash(buff['other_config']), + :status => ovs_parse_opthash(buff['status']), + } + } + rv[buff['name']][:vlan_id] = buff['tag'] if ! (buff['tag'].nil? or buff['tag'].empty?) + rv[buff['name']][:trunks] = buff['trunks'].tr("[]",'').split(/[\,\s]+/) if ! (buff['trunks'].nil? or buff['trunks'].empty?) + debug("Found OVS port '#{buff['name']}' with properties: #{rv[buff['name']]}") + buff = {} + else + debug("Output of 'ovs-vsctl list Port' contain misformated line: '#{line}'") + end + end + return rv + end + + def self.get_ovs_interfaces + # return OVS interfaces hash if it possible + begin + vsctl_list_interfaces = vsctl('list', 'Interface').split("\n") + vsctl_list_interfaces << :EOF # last section of output should be processsed anyway. + rescue + debug("Can't find OVS interfaces, because error while 'ovs-vsctl list Interface' execution") + return {} + end + # + buff = {} + rv = {} + # parse ovs-vsctl output and find OVS and OVS-affected interfaces + vsctl_list_interfaces.each do |line| + if line =~ /(\w+)\s*\:\s*(.*)\s*$/ + key = $1.tr("'\"",'') + val = $2.tr("'\"",'') + buff[key] = val == '[]' ? '' : val + elsif line =~ /^\s*$/ or line == :EOF + rv[buff['name']] = { + :mtu => buff['mtu'], + :port_type => (buff['type'].nil? or buff['type'].empty?) ? [] : [buff['type']], + :vendor_specific => { + :status => ovs_parse_opthash(buff['status']), + } + } + driver = rv[buff['name']][:vendor_specific][:status][:driver_name] + if driver.nil? or driver.empty? or driver == 'openvswitch' + rv[buff['name']][:provider] = 'ovs' + else + rv[buff['name']][:provider] = nil + end + debug("Found OVS interface '#{buff['name']}' with properties: #{rv[buff['name']]}") + buff = {} + else + debug("Output of 'ovs-vsctl list Interface' contain misformated line: '#{line}'") + end + end + return rv + end + + def self.ovs_vsctl_show + begin + #content = vsctl('show') + content = `ovs-vsctl show` + rescue + debug("Can't get OVS configuration, because error while 'ovs-vsctl show' execution") + return {} + end + bridges = get_ovs_bridges() + ports = get_ovs_ports() + interfaces = get_ovs_interfaces() + ovs_config = { + :port => {}, + :interface => {}, + #:bond => {}, # bond in ovs is a internal only port !!! + :bridge => {}, + :jack => {} # jack of ovs patchcord (patchcord is a pair of ports with type 'patch') + } + _br = nil + _po = nil + _if = nil + #_ift = nil + content.split("\n").each do |line| + line.rstrip! + case line + when /^\s+Bridge\s+"?([\w\-\.]+)\"?$/ + _br = $1 + _po = nil + _if = nil + ovs_config[:bridge][_br] = { + :port_type => ['bridge'], + :br_type => 'ovs', + :provider => 'ovs' + } + if bridges.has_key? _br + ovs_config[:bridge][_br].merge! bridges[_br] + end + when /^\s+Port\s+"?([\w\-\.]+)\"?$/ + next if _br.nil? + _po = $1 + _if = nil + ovs_config[:port][_po] = { + :bridge => _br, + :port_type => [], + #:provider => 'ovs' + } + if ports.has_key? _po + ovs_config[:port][_po].merge! ports[_po] + end + if _po == _br + ovs_config[:port][_po][:port_type] << 'bridge' + end + when /^\s+Interface\s+"?([\w\-\.]+)\"?$/ + _if = $1 + ovs_config[:interface][_if] = { + :port => _po, + } + if interfaces.has_key? _if + ovs_config[:interface][_if].merge! interfaces[_if] + end + #todo(sv): Check interface driver from Interfaces table + ovs_config[:port][_po][:provider] = ovs_config[:interface][_if][:provider] + when /^\s+type:\s+"?([\w\-\.]+)\"?$/ + ovs_config[:interface][_if].merge!({ + :type => $1 + }) + when /^\s+options:\s+\{(.+)\}\s*$/ + opts = $1.split(/[\s\,]+/).map{|o| o.split('=')}.reduce({}){|h,p| h.merge(p[0] => p[1].tr('"',''))} + ovs_config[:interface][_if].merge!({ + :options => opts + }) + else + #debug("Misformated line for br='#{_br}', po='#{_po}', if='#{_if}' => '#{line}'") + end + end + ovs_config[:port].keys.each do |p_name| + # didn't use .select{...} here for backward compatibility with ruby 1.8 + ifaces = ovs_config[:interface].reject{|k,v| v[:port]!=p_name} + iface = ifaces[ifaces.keys[0]] + if ifaces.size > 1 + # Bond found + #ovs_config[:bond][p_name] = ovs_config[:port][p_name] + #ovs_config[:port].delete(p_name) + ovs_config[:port][p_name][:port_type] << 'bond' + ovs_config[:port][p_name][:provider] = 'ovs' + elsif iface[:type] == 'patch' + ovs_config[:port][p_name][:port_type] << 'jack' + elsif iface[:type] == 'internal' + ovs_config[:port][p_name][:port_type] << 'internal' + else + # ordinary interface found + # pass + end + # get mtu value (from one of interfaces if bond) and up it to port layer + k = ifaces.keys + if k.size > 0 + ovs_config[:port][p_name][:mtu] = ifaces[k[0]][:mtu] + end + # fix port-type=vlan for tagged ports + if !ovs_config[:port][p_name][:vlan_id].nil? + ovs_config[:port][p_name][:port_type] << 'vlan' + end + end + debug("VSCTL-SHOW: #{ovs_config.to_yaml.gsub('!ruby/sym ',':')}") + return ovs_config + end + # --------------------------------------------------------------------------- + + def self.get_bridge_list + # search all (LXN and OVS) bridges on the host, and return hash with mapping + # bridge_name => { bridge options } + # + bridges = {} + # obtain OVS bridges list + re_c = /^\s*([\w\-]+)/ + begin + vsctl('list-br').split(/\n+/).select{|l| l.match(re_c)}.collect{|a| $1 if a.match(re_c)}.each do |br_name| + br_name.strip! + bridges[br_name] = { + :br_type => :ovs + } + end + rescue + debug("No OVS bridges found, because error while 'ovs-vsctl list-br' execution") + end + # obtain LNX bridges list + re_c = /([\w\-]+)\s+\d+/ + begin + # todo(sv): using port_list instead fork subprocess + brctl('show').split(/\n+/).select{|l| l.match(re_c)}.collect{|a| $1 if a.match(re_c)}.each do |br_name| + br_name.strip! + bridges[br_name] = { + :stp => (File.open("/sys/class/net/#{br_name}/bridge/stp_state").read.strip.to_i == 1), + :external_ids => :absent, + :vendor_specific => {}, + :br_type => :lnx + } + end + rescue + debug("No LNX bridges found, because error while 'brctl show' execution") + end + return bridges + end + + def self.get_ovs_port_bridges_pairs + # returns hash, which map ports to it's bridge. + # i.e { + # qg37f65 => { :bridge => 'br-ex', :br_type => :ovs }, + # } + # + port_mappings = {} + begin + ovs_bridges = vsctl('list-br').split(/\n+/).select{|l| l.match(/^\s*[\w\-]+/)} + rescue + debug("No OVS bridges found, because error while 'ovs-vsctl list-br' execution") + return {} + end + ovs_bridges.each do |br_name| + br_name.strip! + ovs_portlist = vsctl('list-ports', br_name).split(/\n+/).select{|l| l.match(/^\s*[\w\-]+\s*/)} + #todo: handle error + ovs_portlist.each do |port_name| + port_name.strip! + port_mappings[port_name] = { + :bridge => br_name, + :br_type => :ovs + } + end + # bridge also a port, but it don't show itself by list-ports, adding it manually + port_mappings[br_name] = { + :bridge => br_name, + :br_type => :ovs + } + end + return port_mappings + end + + def self.get_lnx_port_bridges_pairs + # returns hash, which map ports to it's bridge. + # i.e { + # 'eth0' => { :bridge => 'br0', :br_type => :lnx }, + # } + # This function returns all visible in default namespace ports + # (lnx and ovs (with type internal)) included to the lnx bridge + # + begin + brctl_show = brctl('show').split(/\n+/).select{|l| l.match(/^[\w\-]+\s+\d+/) or l.match(/^\s+[\w\.\-]+/)} + rescue + debug("No LNX bridges found, because error while 'brctl show' execution") + return {} + end + port_mappings = {} + br_name = nil + brctl_show.each do |line| + line.rstrip! + case line + when /^([\w\-]+)\s+[\d\.abcdef]+\s+(yes|no)\s+([\w\-\.]+$)/i + br_name = $1 + port_name = $3 + when /^\s+([\w\.\-]+)$/ + #br_name using from previous turn + port_name = $1 + else + next + end + if br_name + port_mappings[port_name] = { + :bridge => br_name, + :br_type => :lnx + } + end + end + debug("LNX ports to bridges mapping: #{port_mappings.to_yaml.gsub('!ruby/sym ',':')}") + return port_mappings + end + + def self.get_port_bridges_pairs + # returns hash, which map ports to it's bridge. + # i.e { + # eth0 => { :bridge => 'br0', :br_type => :lnx }, + # qg37f65 => { :bridge => 'br-ex', :br_type => :ovs }, + # } + # This function returns all visible in default namespace ports + # (lnx and ovs (with type internal)) included to the lnx bridge + # + # If port included to both bridges (ovs and lnx at one time), + # i.e. using as patchcord between bridges -- this port will be + # assigned to lnx-type bridge + # + port_bridges_hash = self.get_ovs_port_bridges_pairs() # LNX bridges should overwrite OVS + port_bridges_hash.merge! self.get_lnx_port_bridges_pairs() # because by design! + end + + def self.get_bridges_order_for_patch(bridges) + # if given two OVS bridges -- we should sort it by name + # if given OVS and LNX bridges -- OVS should be first. + br_type = [] + [0,1].each do |i| + br_type << (File.directory?("/sys/class/net/#{bridges[i]}/bridge") ? 'lnx' : 'ovs' ) + end + if br_type[0] == br_type[1] + rv = bridges.sort() + elsif br_type[0] == 'ovs' + rv = [bridges[0],bridges[1]] + else + rv = [bridges[1],bridges[0]] + end + return rv + end + + # --------------------------------------------------------------------------- + + def self.get_lnx_bonds + # search all LXN bonds on the host, and return hash with + # bond_name => { bond options } + # + bond = {} + bondlist = File.open("/sys/class/net/bonding_masters").read.chomp.split(/\s+/).sort + bondlist.each do |bond_name| + mode = File.open("/sys/class/net/#{bond_name}/bonding/mode").read.split(/\s+/)[0] + bond[bond_name] = { + :mtu => File.open("/sys/class/net/#{bond_name}/mtu").read.chomp.to_i, + :slaves => File.open("/sys/class/net/#{bond_name}/bonding/slaves").read.chomp.split(/\s+/).sort, + :bond_properties => { + :mode => mode, + :miimon => File.open("/sys/class/net/#{bond_name}/bonding/miimon").read.chomp, + } + } + if ['802.3ad', 'balance-xor', 'balance-tlb', 'balance-alb'].include? mode + xmit_hash_policy = File.open("/sys/class/net/#{bond_name}/bonding/xmit_hash_policy").read.split(/\s+/)[0] + bond[bond_name][:bond_properties][:xmit_hash_policy] = xmit_hash_policy + end + if mode=='802.3ad' + lacp_rate = File.open("/sys/class/net/#{bond_name}/bonding/lacp_rate").read.split(/\s+/)[0] + bond[bond_name][:bond_properties][:lacp_rate] = lacp_rate + end + bond[bond_name][:onboot] = !self.get_iface_state(bond_name).nil? + end + return bond + end + + def self.lnx_bond_allowed_properties + { + :active_slave => {}, + :ad_select => {}, + :all_slaves_active => {}, + :arp_interval => {}, + :arp_ip_target => {}, + :arp_validate => {}, + :arp_all_targets => {}, + :downdelay => {}, + :updelay => {}, + :fail_over_mac => {}, + :lacp_rate => {:need_reassemble => true}, + :miimon => {}, + :min_links => {}, + :mode => {:need_reassemble => true}, + :num_grat_arp => {}, + :num_unsol_na => {}, + :packets_per_slave => {}, + :primary => {}, + :primary_reselect => {}, + :tlb_dynamic_lb => {}, + :use_carrier => {}, + :xmit_hash_policy => {}, + :resend_igmp => {}, + :lp_interval => {} + } + end + def self.lnx_bond_allowed_properties_list + self.lnx_bond_allowed_properties.keys.sort + end + + def self.ovs_bond_allowed_properties + { + :downdelay => {:property => 'bond_downdelay'}, + :updelay => {:property => 'bond_updelay'}, + :use_carrier => {:property => 'other_config:bond-detect-mode', + :override_integer => ['miimon', 'carrier'] }, + :mode => {:property => 'bond_mode', + :allow => ['balance-slb', 'active-backup', 'balance-tcp', 'stable'] }, + :lacp => {:property => 'lacp', + :allow => ['off', 'active', 'passive'] }, + :lacp_rate => {:property => 'other_config:lacp_time'}, + :miimon => {:property => 'other_config:bond-miimon-interval'}, + :slb_rebalance_interval => {:property => 'other_config:bond-rebalance-interval'}, + } + end + def self.ovs_bond_allowed_properties_list + self.ovs_bond_allowed_properties.keys.sort + end + + + def self.get_iface_state(iface) + # returns: + # true -- interface in UP state + # false -- interface in UP state, but no-carrier + # nil -- interface in DOWN state + begin + 1 == File.open("/sys/class/net/#{iface}/carrier").read.chomp.to_i + rescue + # if interface is down, this file can't be read + nil + end + end + + # --------------------------------------------------------------------------- + + def self.get_ethtool_name_commands_mapping + L23network.ethtool_name_commands_mapping + end + + def self.get_iface_ethtool_hash(if_name, empty_return = {}) + tmp = {} + #todo(sv): wrap to begin--resque + ethtool_k = ethtool_cmd('-k', if_name) + ethtool_k.split(/\n+/).select{|l| !l.match(/(^\s+|\[fixed\]|^Features)/)}.map{|x| x.split(/[\s\:]+/)}.each do |p| + tmp[p[0]] = (p[1] == 'on') + end + return { + 'offload' => tmp || empty_return + } + end + + # --------------------------------------------------------------------------- + + def self.set_mtu(iface, mtu=1500) + if File.symlink?("/sys/class/net/#{iface}") + debug("Set MTU to '#{mtu}' for interface '#{iface}'") + File.open("/sys/class/net/#{iface}/mtu", "a") { |f| f.write(mtu) } + end + end + +end + + +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_bond/lnx.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_bond/lnx.rb new file mode 100644 index 0000000000..dda7159f03 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_bond/lnx.rb @@ -0,0 +1,199 @@ +# Native linux bonding implementation +# INspired by: https://www.kernel.org/doc/Documentation/networking/bonding.txt +# + +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base') + +Puppet::Type.type(:l2_bond).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do + defaultfor :osfamily => :linux + commands :iproute => 'ip', + :ethtool_cmd => 'ethtool', + :brctl => 'brctl', + :vsctl => 'ovs-vsctl' + + + def self.prefetch(resources) + interfaces = instances + resources.keys.each do |name| + if provider = interfaces.find{ |ii| ii.name == name } + resources[name].provider = provider + end + end + end + + def self.instances + bonds ||= self.get_lnx_bonds() + debug("bonds found: #{bonds.keys}") + rv = [] + bonds.each_pair do |bond_name, bond_props| + props = { + :ensure => :present, + :name => bond_name, + :vendor_specific => {} + } + props.merge! bond_props + # # get bridge if port included to it + # if ! port_bridges_hash[if_name].nil? + # props[:bridge] = port_bridges_hash[if_name][:bridge] + # end + # # calculate port_type field + # if !bridges[if_name].nil? + # case bridges[if_name][:br_type] + # when :ovs + # props[:port_type] = 'ovs:br:unremovable' + # when :lnx + # props[:port_type] = 'lnx:br:unremovable' + # else + # # pass + # end + # end + debug("PREFETCHED properties for '#{bond_name}': #{props}") + rv << new(props) + end + rv + end + + def create + debug("CREATE resource: #{@resource}") + @old_property_hash = {} + @property_flush = {}.merge! @resource + open('/sys/class/net/bonding_masters', 'a') do |f| + f << "+#{@resource[:name]}" + end + end + + def destroy + debug("DESTROY resource: #{@resource}") + open('/sys/class/net/bonding_masters', 'a') do |f| + f << "-#{@resource[:name]}" + end + end + + def flush + if @property_flush + debug("FLUSH properties: #{@property_flush}") + # + # FLUSH changed properties + if @property_flush.has_key? :slaves + runtime_slave_ports = File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "r").read.split(/\s+/) + if @property_flush[:slaves].nil? or @property_flush[:slaves] == :absent + debug("Remove all slave ports from bond '#{@resource[:bond]}'") + rm_slave_list = runtime_slave_ports + else + rm_slave_list = runtime_slave_ports - @property_flush[:slaves] + debug("Remove '#{rm_slave_list.join(',')}' ports from bond '#{@resource[:bond]}'") + rm_slave_list.each do |slave| + iproute('link', 'set', 'dev', slave, 'down') # need by kernel requirements by design. undocumented :( + File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "a") {|f| f << "-#{slave}"} + end + end + # We shouldn't add ports here, because bond configures early, than ports. + # corresponded ports may be unconfigured at this time. + # corresponded ports will be add himself to bond while configuration + end + if @property_flush.has_key? :bond_properties + # change bond_properties + need_reassemble = [:mode, :lacp_rate] + #todo(sv): inplement re-assembling only if it need + #todo(sv): re-set only delta between reality and requested + runtime_bond_state = !self.class.get_iface_state(@resource[:bond]).nil? + runtime_slave_ports = File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "r").read.split(/\s+/) + runtime_slave_ports.each do |eth| + # for most bond options we should disassemble bond before re-configuration. In the kernel module documentation + # says, that bond interface should be downed, but it's not enouth. + File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "a") {|f| f << "-#{eth}"} + end + iproute('link', 'set', 'dev', @resource[:bond], 'down') + @property_flush[:bond_properties].each_pair do |prop, val| + if self.class.lnx_bond_allowed_properties_list.include? prop.to_sym + act_val = val.to_s + else + debug("Unsupported property '#{prop}' for bond '#{@resource[:bond]}'") + act_val = nil + end + if act_val + debug("Set property '#{prop}' to '#{act_val}' for bond '#{@resource[:bond]}'") + File.open("/sys/class/net/#{@resource[:bond]}/bonding/#{prop}", 'a') {|f| f << "#{act_val.to_s}"} + end + end + # re-assemble bond after configuration + iproute('link', 'set', 'dev', @resource[:bond], 'up') if runtime_bond_state + runtime_slave_ports.each do |eth| + File.open("/sys/class/net/#{@resource[:bond]}/bonding/slaves", "a") {|f| f << "+#{eth}"} + end + end + if @property_flush.has_key? :bridge + # get actual bridge-list. We should do it here, + # because bridge may be not existing at prefetch stage. + @bridges ||= self.class.get_bridge_list() + debug("Actual-bridge-list: #{@bridges}") + port_bridges_hash = self.class.get_port_bridges_pairs() + debug("Actual-port-bridge-mapping: '#{port_bridges_hash}'") # it should removed from LNX + # + # remove interface from old bridge + runtime_bond_state = !self.class.get_iface_state(@resource[:bond]).nil? + iproute('--force', 'link', 'set', 'dev', @resource[:bond], 'down') + if ! port_bridges_hash[@resource[:bond]].nil? + br_name = port_bridges_hash[@resource[:bond]][:bridge] + if br_name != @resource[:bond] + # do not remove bridge-based interface from his bridge + case port_bridges_hash[@resource[:bond]][:br_type] + when :ovs + vsctl('del-port', br_name, @resource[:bond]) + # todo catch exception + when :lnx + brctl('delif', br_name, @resource[:bond]) + # todo catch exception + else + #pass + end + end + end + # add port to the new bridge + if !@property_flush[:bridge].nil? and @property_flush[:bridge].to_sym != :absent + case @bridges[@property_flush[:bridge]][:br_type] + when :ovs + vsctl('add-port', @property_flush[:bridge], @resource[:bond]) + when :lnx + brctl('addif', @property_flush[:bridge], @resource[:bond]) + else + #pass + end + end + iproute('link', 'set', 'dev', @resource[:bond], 'up') if runtime_bond_state + debug("Change bridge") + end + if @property_flush[:onboot] + iproute('link', 'set', 'dev', @resource[:bond], 'up') + end + if !['', 'absent'].include? @property_flush[:mtu].to_s + self.class.set_mtu(@resource[:bond], @property_flush[:mtu]) + end + @property_hash = resource.to_hash + end + end + + #----------------------------------------------------------------- + def slaves + @property_hash[:slaves] || :absent + end + def slaves=(val) + @property_flush[:slaves] = val + end + + def bond_properties + @property_hash[:bond_properties] || :absent + end + def bond_properties=(val) + @property_flush[:bond_properties] = val + end + + def interface_properties + @property_hash[:interface_properties] || :absent + end + def interface_properties=(val) + @property_flush[:interface_properties] = val + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_bond/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_bond/ovs.rb new file mode 100644 index 0000000000..341344dff1 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_bond/ovs.rb @@ -0,0 +1,112 @@ +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base') + +Puppet::Type.type(:l2_bond).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do + commands :vsctl => 'ovs-vsctl', + :ethtool_cmd => 'ethtool', + :iproute => 'ip' + + + # def self.add_unremovable_flag(port_props) + # # calculate 'unremovable' flag. Should be re-defined in chield providers + # if port_props[:port_type].include? 'bridge' or port_props[:port_type].include? 'bond' + # port_props[:port_type] << 'unremovable' + # end + # end + + def self.get_instances(big_hash) + # didn't use .select{...} here for backward compatibility with ruby 1.8 + big_hash[:port].reject{|k,v| !v[:port_type].include?('bond')} + end + + #----------------------------------------------------------------- + + def create + debug("CREATE resource: #{@resource}") + @old_property_hash = {} + @property_flush = {}.merge! @resource + # + cmd = ["add-bond", @resource[:bridge], @resource[:bond], @resource[:interface]] + begin + vsctl(cmd) + rescue Puppet::ExecutionFailure => error + raise Puppet::ExecutionFailure, "Can't add bond '#{@resource[:bond]}'\n#{error}" + end + # # set interface properties + # if @resource[:interface_properties] + # for option in @resource[:interface_properties] + # begin + # vsctl('--', "set", "Interface", @resource[:interface], option.to_s) + # rescue Puppet::ExecutionFailure => error + # raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't set option '#{option}':\n#{error}" + # end + # end + # end + end + + def destroy + vsctl("del-port", @resource[:bridge], @resource[:interface]) + end + + def flush + if @property_flush + debug("FLUSH properties: #{@property_flush}") + if @property_flush.has_key? :slaves + warn("Do nothing, OVS don't allow change bond slaves for existing bond ('#{@resource[:bond]}').") + # But we can implement this undocumented hack later + # ovs-vsctl add-port br3 ee2 + # ovs-vsctl list interface ee2 # get uuid for port + # ovs-vsctl -- set port bond3 'interfaces=[0e6a0107-d0c7-49a6-93c7-41fe23e61c2c, 2c21e847-05ea-4b11-bde2-bb19e2d0ca56]' + # ovs-vsctl show + # ovs-vsctl del-port ee2 # ignore error + # ovs-vsctl show + end + if @property_flush.has_key? :bond_properties + # change bond_properties + allowed_properties = self.class.ovs_bond_allowed_properties() + @property_flush[:bond_properties].each_pair do |prop, val| + if self.class.ovs_bond_allowed_properties_list.include? prop.to_sym + act_val = val.to_s + else + warn("Unsupported property '#{prop}' for bond '#{@resource[:bond]}'") + act_val = nil + end + if act_val + debug("Set property '#{prop}' to '#{act_val}' for bond '#{@resource[:bond]}'") + if allowed_properties[prop.to_sym][:property] + # just setup property in OVSDB + if allowed_properties[prop.to_sym][:allow] and ! allowed_properties[prop.to_sym][:allow].include? val + warn("Unsupported value '#{val}' for property '#{prop}' for bond '#{@resource[:bond]}'.\nAllowed modes: #{allowed_properties[prop.to_sym][:allow]}") + val = nil + end + if allowed_properties[prop.to_sym][:override_integer] + # override property if it should be given as string for ovs and as integer for native linux + val = allowed_properties[prop.to_sym][:override_integer][val.to_i] || allowed_properties[prop.to_sym][:override_integer][0] + end + vsctl('--', "set", "Port", @resource[:bond], "#{allowed_properties[prop.to_sym][:property]}=#{val}") if ! val.nil? + end + end + end + end + # + if @property_flush.has_key? :mtu + debug("Do nothing, because for OVS bonds MTU can be changed only for slave interfaces.") + end + end + end + + #----------------------------------------------------------------- + def bond_properties + @property_hash[:bond_properties] || :absent + end + def bond_properties=(val) + @property_flush[:bond_properties] = val + end + + def interface_properties + @property_hash[:interface_properties] || :absent + end + def interface_properties=(val) + @property_flush[:interface_properties] = val + end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_bridge/lnx.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_bridge/lnx.rb new file mode 100644 index 0000000000..35b04d3584 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_bridge/lnx.rb @@ -0,0 +1,97 @@ +# Native linux bridging implementation +# Inspired by: +# * https://www.kernel.org/doc/Documentation/networking/bridge.txt +# * http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge +# + +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base') + +Puppet::Type.type(:l2_bridge).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do + defaultfor :osfamily => :linux + commands :brctl => 'brctl', + :ethtool_cmd => 'ethtool', + :vsctl => 'ovs-vsctl', + :iproute => 'ip' + + def self.instances + rv = [] + get_bridge_list().each_pair do |bridge, props| + debug("prefetching '#{bridge}'") + br_props = { + :ensure => :present, + :name => bridge, + } + br_props.merge! props + if props[:br_type] == :lnx + #br_props[:provider] = 'lnx' + #props[:port_type] = props[:port_type].insert(0, 'ovs').join(':') + rv << new(br_props) + debug("PREFETCH properties for '#{bridge}': #{br_props}") + else + debug("SKIP properties for '#{bridge}': #{br_props}") + end + end + rv + end + + def create + debug("CREATE resource: #{@resource}") + @old_property_hash = {} + @property_flush = {}.merge! @resource + begin + brctl('addbr', @resource[:bridge]) + rescue + # Some time interface may be created by OS init scripts. It's a normal for Ubuntu. + raise if ! self.class.iface_exist? @resource[:bridge] + notice("'#{@resource[:bridge]}' already created by ghost event.") + end + iproute('link', 'set', 'up', 'dev', @resource[:bridge]) + end + + def destroy + iproute('link', 'set', 'down', 'dev', @resource[:bridge]) + brctl('delbr', @resource[:bridge]) + end + + def flush + if @property_flush + debug("FLUSH properties: #{@property_flush}") + # + # FLUSH changed properties + if @property_flush.has_key? :stp + effective_stp = (@property_flush[:stp].to_s == 'true' ? 1 : 0) + File.open("/sys/class/net/#{@resource[:bridge]}/bridge/stp_state", "a") {|f| f << effective_stp} + end + @property_hash = resource.to_hash + end + end + + #----------------------------------------------------------------- + def br_type + @property_hash[:br_type] || :absent + end + def br_type=(val) + @property_flush[:br_type] = val + end + + # external IDs not supported + def external_ids + :absent + end + def external_ids=(value) + {} + end + + def stp + # puppet has internal transformation, and we shouldn't use boolean values. Use symbols -- it works stable!!! + @property_hash[:stp].to_s.to_sym + end + def stp=(val) + @property_flush[:stp] = (val.to_s.downcase.to_sym==:true) + end + + #----------------------------------------------------------------- + + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_bridge/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_bridge/ovs.rb new file mode 100644 index 0000000000..c47b5dd0b0 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_bridge/ovs.rb @@ -0,0 +1,103 @@ +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base') + +Puppet::Type.type(:l2_bridge).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do + commands :vsctl => 'ovs-vsctl', + :ethtool_cmd => 'ethtool', + :brctl => 'brctl', + :iproute => 'ip' + + def self.skip_port_for?(port_props) + port_props[:br_type] != 'ovs' + end + + def self.get_instances(big_hash) + big_hash[:bridge] + end + + # def self.instances + # rv = super + # #debug("#{rv.inspect}") + # end + + #----------------------------------------------------------------- + + def create + debug("CREATE resource: #{@resource}") + @old_property_hash = {} + @property_flush = {}.merge! @resource + # + vsctl('add-br', @resource[:bridge]) + iproute('link', 'set', 'up', 'dev', @resource[:bridge]) + notice("bridge '#{@resource[:bridge]}' created.") + end + + def destroy + iproute('link', 'set', 'down', 'dev', @resource[:bridge]) + vsctl("del-br", @resource[:bridge]) + end + + def flush + if @property_flush + debug("FLUSH properties: #{@property_flush}") + # + # FLUSH changed properties + if @property_flush.has_key? :stp + vsctl('set', 'Bridge', @resource[:bridge], "stp_enable=#{@property_flush[:stp]}") + end + if @property_flush.has_key? :external_ids + old_ids = (@old_property_hash[:external_ids] || {}) + new_ids = @property_flush[:external_ids] + #todo(sv): calculate deltas and remove unnided. + new_ids.each_pair do |k,v| + if ! old_ids.has_key?(k) + vsctl("br-set-external-id", @resource[:bridge], k, v) + end + end + end + # + @property_hash = resource.to_hash + end + end + + + #----------------------------------------------------------------- + def br_type + @property_hash[:br_type] || :absent + end + def br_type=(val) + @property_flush[:br_type] = val + end + + def external_ids + # result = vsctl("br-get-external-id", @resource[:bridge]) + vs = (@property_hash[:vendor_specific] || {}) + result = (vs[:external_ids] || '') + return result #.split("\n").join(",") + end + def external_ids=(val) + @property_flush[:external_ids] = val + end + + def vendor_specific + @property_hash[:vendor_specific] || :absent + end + def vendor_specific=(val) + @property_flush[:vendor_specific] = val + end + + def stp + # puppet has internal trancformation, and we shouldn't use boolean values. it works unstable!!! + @property_hash[:stp].to_s.to_sym + end + def stp=(val) + @property_flush[:stp] = (val.to_s.downcase.to_sym==:true) + end + + #----------------------------------------------------------------- + + def _split(string, splitter=",") + return Hash[string.split(splitter).map{|i| i.split("=")}] + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bond/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bond/ovs.rb deleted file mode 100644 index 2b2062893e..0000000000 --- a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bond/ovs.rb +++ /dev/null @@ -1,57 +0,0 @@ -Puppet::Type.type(:l2_ovs_bond).provide(:ovs) do - optional_commands( - :vsctl => "/usr/bin/ovs-vsctl", - :appctl => "/usr/bin/ovs-appctl" - ) - - def _exists?(bond) - begin - appctl('bond/show', bond) - true - rescue Puppet::ExecutionFailure - false - end - end - - def exists? - _exists?(@resource[:bond]) - end - - def create - if _exists?(@resource[:bond]) - msg = "Bond '#{@resource[:bond]}' already exists" - if @resource[:skip_existing] - notice("#{msg}, skip creating.") - else - fail("#{msg}.") - end - end - - bond_properties = Array(@resource[:properties]) - if @resource[:vlan_id] > 0 - bond_properties.insert(-1, "tag=#{@resource[:vlan_id]}") - end - if not @resource[:trunks].empty? - bond_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]") - end - - bond_create_cmd = ['add-bond', @resource[:bridge], @resource[:bond]] + @resource[:interfaces] - if ! bond_properties.empty? - bond_create_cmd += bond_properties - end - begin - vsctl(bond_create_cmd) - rescue Puppet::ExecutionFailure => error - fail("Can't create bond '#{@resource[:bond]}' (interfaces: #{@resource[:interfaces].join(',')}) for bridge '#{@resource[:bridge]}'.\n#{error}") - end - end - - def destroy - begin - vsctl("del-port", @resource[:bridge], @resource[:bond]) - rescue Puppet::ExecutionFailure => error - fail("Can't remove bond '#{@resource[:bond]}' from bridge '#{@resource[:bridge]}'.\n#{error}") - end - end - -end diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bridge/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bridge/ovs.rb deleted file mode 100644 index a6380ca26d..0000000000 --- a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_bridge/ovs.rb +++ /dev/null @@ -1,55 +0,0 @@ -Puppet::Type.type(:l2_ovs_bridge).provide(:ovs) do - optional_commands :vsctl => "/usr/bin/ovs-vsctl" - - def exists? - vsctl("br-exists", @resource[:bridge]) - rescue Puppet::ExecutionFailure - return false - end - - def create - begin - vsctl('br-exists', @resource[:bridge]) - if @resource[:skip_existing] - notice("Bridge '#{@resource[:bridge]}' already exists, skip creating.") - #external_ids = @resource[:external_ids] if @resource[:external_ids] - return true - else - raise Puppet::ExecutionFailure, "Bridge '#{@resource[:bridge]}' already exists." - end - rescue Puppet::ExecutionFailure - # pass - notice("Bridge '#{@resource[:bridge]}' not exists, creating...") - end - vsctl('add-br', @resource[:bridge]) - notice("bridge '#{@resource[:bridge]}' created.") - # We do self.attr_setter=(value) instead of attr=value because this doesn't - # work in Puppet (our guess). - # TODO (adanin): Fix other places like this one. See bug #1366009 - self.external_ids=(@resource[:external_ids]) if @resource[:external_ids] - end - - def destroy - vsctl("del-br", @resource[:bridge]) - end - - def _split(string, splitter=",") - return Hash[string.split(splitter).map{|i| i.split("=")}] - end - - def external_ids - result = vsctl("br-get-external-id", @resource[:bridge]) - 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[:bridge], k, v) - end - end - end -end diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_patch/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_patch/ovs.rb deleted file mode 100644 index 15e58a6064..0000000000 --- a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_patch/ovs.rb +++ /dev/null @@ -1,90 +0,0 @@ -Puppet::Type.type(:l2_ovs_patch).provide(:ovs) do - optional_commands( - :vsctl => "/usr/bin/ovs-vsctl", - :appctl => "/usr/bin/ovs-appctl" - ) - - def get_names() - # result always contains array of two elements - # get_names()[i-1] always returns neighbor's name - # - rv = [] - i = 0 - for peer in @resource[:peers] - if peer == nil - rv.insert(-1, "#{@resource[:bridges][i]}--#{@resource[:bridges][i-1]}") - else - rv.insert(-1, peer) - end - i += 1 - end - #todo: check tags, trunks and bridge names - return rv - end - - def _exists?(interface) - rv = true - begin - result = vsctl('get', 'interface', "#{interface}", 'type') - rv = false if result.strip() != 'patch' - rescue Puppet::ExecutionFailure - rv = false - end - return rv - end - - def exists? - for name in get_names() - return false if not _exists?(name) - end - return true - end - - def create() - names = get_names() - i = 0 - for name in names - # tag and trunks for port - port_properties = [] #@resource[:port_properties] - tag = @resource[:vlan_ids][i] - if tag > 0 - port_properties.insert(-1, "tag=#{tag}") - end - if not @resource[:trunks].empty? - port_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]") - end - #todo: kill before create if need - cmd = ['add-port', @resource[:bridges][i], name] - cmd.concat(port_properties) - cmd.concat(['--', 'set', 'interface', name, 'type=patch']) - begin - vsctl(cmd) - rescue Puppet::ExecutionFailure => errmsg - raise Puppet::ExecutionFailure, "Can't create patch '#{name}':\n#{errmsg}" - end - i += 1 - end - i = 0 - for name in names - begin - vsctl('set', 'interface', name, "options:peer=#{names[i-1]}") - rescue Puppet::ExecutionFailure => errmsg - raise Puppet::ExecutionFailure, "Can't connect patch '#{name}' to '#{names[i-1]}':\n#{errmsg}" - end - i += 1 - end - end - - def destroy() - names = get_names() - i = 0 - for name in names - begin - vsctl('del-port', @resource[:bridges][i], name) - rescue Puppet::ExecutionFailure => error - raise Puppet::ExecutionFailure, "Can't remove patch '#{name}' from bridge '#{@resource[:bridges][i]}':\n#{error}" - end - i += 1 - end - end -end diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_port/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_port/ovs.rb deleted file mode 100644 index 06f1838c13..0000000000 --- a/deployment/puppet/l23network/lib/puppet/provider/l2_ovs_port/ovs.rb +++ /dev/null @@ -1,72 +0,0 @@ -Puppet::Type.type(:l2_ovs_port).provide(:ovs) do - optional_commands :vsctl => "/usr/bin/ovs-vsctl" - - def exists? - vsctl("list-ports", @resource[:bridge]).split(/\n+/).include? @resource[:interface] - end - - def create - begin - vsctl('port-to-br', @resource[:interface]) - if @resource[:skip_existing] - return true - else - raise Puppet::ExecutionFailure, "Port '#{@resource[:interface]}' already exists." - end - rescue Puppet::ExecutionFailure - # pass - end - # tag and trunks for port - port_properties = @resource[:port_properties] - if @resource[:vlan_id] > 0 - port_properties.insert(-1, "tag=#{@resource[:vlan_id]}") - end - if not @resource[:trunks].empty? - port_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]") - end - # Port create begins from definition brodge and port - cmd = [@resource[:bridge], @resource[:interface]] - # add port properties (k/w) to command line - if not port_properties.empty? - for option in port_properties - cmd.insert(-1, option) - end - end - # set interface type - if @resource[:type] and @resource[:type].to_s != '' - tt = "type=" + @resource[:type].to_s - cmd += ['--', "set", "Interface", @resource[:interface], tt] - end - # executing OVS add-port command - cmd = ["add-port"] + cmd - begin - vsctl(cmd) - rescue Puppet::ExecutionFailure => error - raise Puppet::ExecutionFailure, "Can't add port '#{@resource[:interface]}'\n#{error}" - end - # set interface properties - if @resource[:interface_properties] - for option in @resource[:interface_properties] - begin - vsctl('--', "set", "Interface", @resource[:interface], option.to_s) - rescue Puppet::ExecutionFailure => error - raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't set option '#{option}':\n#{error}" - end - end - end - # enable vlan_splinters if need - if @resource[:vlan_splinters].to_s() == 'true' # puppet send non-boolean value instead true/false - Puppet.debug("Interface '#{@resource[:interface]}' vlan_splinters is '#{@resource[:vlan_splinters]}' [#{@resource[:vlan_splinters].class}]") - begin - vsctl('--', "set", "Port", @resource[:interface], "vlan_mode=trunk") - vsctl('--', "set", "Interface", @resource[:interface], "other-config:enable-vlan-splinters=true") - rescue Puppet::ExecutionFailure => error - raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't setup vlan_splinters:\n#{error}" - end - end - end - - def destroy - vsctl("del-port", @resource[:bridge], @resource[:interface]) - end -end diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_patch/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_patch/ovs.rb new file mode 100644 index 0000000000..85f331eab7 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_patch/ovs.rb @@ -0,0 +1,188 @@ +require 'puppetx/l23_utils' +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base') + +Puppet::Type.type(:l2_patch).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do + commands :vsctl => 'ovs-vsctl', + :ethtool_cmd => 'ethtool', + :brctl => 'brctl', + :iproute => 'ip' + + + def self.instances + vsctl_show = ovs_vsctl_show() + lnx_port_br_mapping = get_lnx_port_bridges_pairs() + jacks = [] + # didn't use .select{...} here for backward compatibility with ruby 1.8 + vsctl_show[:port].reject{|k,v| !(v[:port_type] & ['jack','internal']).any?}.each_pair do |p_name, p_props| + props = { + :name => p_name, + } + props.merge! p_props + if props[:port_type].include? 'jack' + debug("found jack '#{p_name}'") + # get 'peer' property and copy to jack + # didn't use .select{...} here for backward compatibility with ruby 1.8 + ifaces = vsctl_show[:interface].reject{|k,v| v[:port]!=p_name} + iface = ifaces[ifaces.keys[0]] + props[:peer] = (iface.has_key?(:options) ? iface[:options]['peer'] : nil) + elsif props[:port_type].include? 'internal' + debug("found 'internal' ovs port '#{p_name}'") + props[:cross] = true + else + #pass + end + jacks << props + end + # search pairs of jacks and make patchcord resources + patches = [] + skip = [] + mtu = nil + jacks.each do |jack| + next if skip.include? jack[:name] + if jack[:cross] + # process 'cross' patch between OVS and LNX bridge + peer = lnx_port_br_mapping[jack[:name]] + next if peer.nil? + _bridges = [jack[:bridge], peer[:bridge]] # no sort here!!! architecture limitation -- ovs brodge always first! + _tails = [jack[:name], jack[:name]] + mtu = File.open("/sys/class/net/#{jack[:name]}/mtu").read.chomp.to_i + else + # process patch between two OVS bridges + next if jack[:peer].nil? + found_peer = jacks.select{|j| j[:name]==jack[:peer]} + next if found_peer.empty? + peer = found_peer[0] + _bridges = [jack[:bridge], peer[:bridge]].sort + _tails = ([jack[:bridge], peer[:bridge]] == _bridges ? [jack[:name], peer[:name]] : [peer[:name], jack[:name]]) + end + props = { + :ensure => :present, + :name => L23network.get_patch_name([jack[:bridge],peer[:bridge]]), + :bridges => _bridges, + :jacks => _tails, + :mtu => mtu, + :cross => jack[:cross], + :provider => 'ovs' + } + debug("PREFETCH properties for '#{props[:name]}': #{props}") + patches << new(props) + skip << peer[:name] + end + return patches #.map{|x| new(x)} + end + + #----------------------------------------------------------------- + + def create + debug("CREATE resource: #{@resource}") + @old_property_hash = {} + @property_flush = {}.merge! @resource + bridges = self.class.get_bridges_order_for_patch(@resource[:bridges]) + @property_flush[:bridges] = bridges + # + debug("Bridges: '#{bridges.join(', ')}.") + if File.directory?("/sys/class/net/#{bridges[1]}/bridge") + # creating 'cross' OVS-to-lnx patchcord + lnx_port_br_mapping = self.class.get_lnx_port_bridges_pairs() + jack = L23network.get_lnx_jack_name(bridges[0]) + vsctl('--may-exist', 'add-port', bridges[0], jack, '--', 'set', 'Interface', jack, 'type=internal') + if lnx_port_br_mapping.has_key? jack and lnx_port_br_mapping[jack][:bridge] != bridges[1] + # eject lnx-side jack from bridge, if jack aldeady a member + brctl('delif', lnx_port_br_mapping[jack][:bridge], jack) + lnx_port_br_mapping.delete(jack) + end + if !lnx_port_br_mapping.has_key? jack + begin + brctl('addif', bridges[1], jack) + rescue Exception => e + if e.to_s =~ /device\s+#{jack}\s+is\s+already\s+a\s+member\s+of\s+a\s+bridge/ + notice("'#{jack}' already addeded to '#{bridges[1]}' by ghost event.") + else + raise + end + end + end + else + # creating OVS-to-OVS patchcord + jacks = [] + jacks << L23network.get_ovs_jack_name(bridges[1]) + jacks << L23network.get_ovs_jack_name(bridges[0]) + #todo(sv): make type and peer change in flush + cmds = [] + cmds << ['--may-exist', 'add-port', bridges[0], jacks[0], '--', 'set', 'Interface', jacks[0], 'type=patch', "option:peer=#{jacks[1]}"] + cmds << ['--may-exist', 'add-port', bridges[1], jacks[1], '--', 'set', 'Interface', jacks[1], 'type=patch', "option:peer=#{jacks[0]}"] + cmds.each do |cmd| + begin + vsctl(cmd) + rescue Puppet::ExecutionFailure => error + raise Puppet::ExecutionFailure, "Can't add jack for patchcord '#{@resource[:name]}'\n#{error}" + end + end + end + end + + def destroy + if File.directory?("/sys/class/net/#{@resource[:bridges][1]}/bridge") + # removing 'cross' OVS-to-lnx patchcord + jack = L23network.get_lnx_jack_name(@resource[:bridges][0]) + if File.symlink?("/sys/class/net/#{@resource[:bridges][1]}/brif/#{jack}") + brctl('delif', @resource[:bridges][1], jack) + end + vsctl('del-port', @resource[:bridges][0], jack) + else + # removing OVS-to-OVS patchcord + bridges = @resource[:bridges].sort + jacks = [] + jacks << L23network.get_ovs_jack_name(bridges[1]) + jacks << L23network.get_ovs_jack_name(bridges[0]) + cmds = [] + cmds << ['del-port', bridges[0], jacks[0]] + cmds << ['del-port', bridges[1], jacks[1]] + cmds.each do |cmd| + begin + vsctl(cmd) + rescue Puppet::ExecutionFailure => error + raise Puppet::ExecutionFailure, "Can't remove jack for patchcord '#{@resource[:name]}'\n#{error}" + end + end + end + end + + def flush + if !@property_flush.empty? + 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 + end + @property_hash = resource.to_hash + end + end + + #----------------------------------------------------------------- + + def bridges + self.class.get_bridges_order_for_patch(@property_hash[:bridges]) + end + def bridges=(val) + @property_flush[:bridges] = self.class.get_bridges_order_for_patch(val) + end + + def jacks + @property_hash[:jacks] + end + def jacks=(val) + nil + end + + def cross + @property_hash[:cross] + end + def cross=(val) + nil + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_port/lnx.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_port/lnx.rb new file mode 100644 index 0000000000..2122022eb6 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_port/lnx.rb @@ -0,0 +1,189 @@ +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/lnx_base') + +Puppet::Type.type(:l2_port).provide(:lnx, :parent => Puppet::Provider::Lnx_base) do + defaultfor :osfamily => :linux + commands :iproute => 'ip', + :ethtool_cmd => 'ethtool', + :brctl => 'brctl', + :vsctl => 'ovs-vsctl' + + + def self.instances + rv = [] + #todo: what do with OVS ports, inserted in LNX bridge? i.e. port located in two bridges. + ports = get_lnx_ports() + ovs_interfaces = get_ovs_interfaces() + ports.each_pair do |if_name, if_props| + props = { + :ensure => :present, + :name => if_name, + :vendor_specific => {} + } + debug("prefetching interface '#{if_name}'") + props.merge! if_props + props[:ethtool] = get_iface_ethtool_hash(if_name, nil) + # add PROVIDER prefix to port type flags and convert port_type to string + if ovs_interfaces.has_key? if_name and ovs_interfaces[if_name][:port_type].is_a? Array and ovs_interfaces[if_name][:port_type].include? 'internal' + if_provider = ovs_interfaces[if_name][:provider] + props[:port_type] = ovs_interfaces[if_name][:port_type] + props[:provider] = ovs_interfaces[if_name][:provider] + else + if_provider = props[:provider] + end + props[:port_type] = props[:port_type].insert(0, if_provider).join(':') + if if_provider == 'lnx' + rv << new(props) + debug("PREFETCH properties for '#{if_name}': #{props}") + else + debug("SKIP properties for '#{if_name}': #{props}") + end + end + return rv + end + + def create + debug("CREATE resource: #{@resource}") + @old_property_hash = {} + @property_flush = {}.merge! @resource + # todo: divide simple creating interface and vlan + begin + iproute('link', 'add', 'link', @resource[:vlan_dev], 'name', @resource[:interface], 'type', 'vlan', 'id', @resource[:vlan_id]) + rescue + # Some time interface may be created by OS init scripts. It's a normal for Ubuntu. + raise if ! self.class.iface_exist? @resource[:interface] + notice("'#{@resource[:interface]}' already created by ghost event.") + end + end + + def destroy + debug("DESTROY resource: #{@resource}") + # todo: Destroing of L2 resource -- is a putting interface to the DOWN state. + # Or remove, if ove a vlan interface + #iproute('--force', 'addr', 'flush', 'dev', @resource[:interface]) + end + + def flush + if @property_flush + debug("FLUSH properties: #{@property_flush}") + # + # FLUSH changed properties + if @property_flush.has_key? :bond_master + bond = @old_property_hash[:bond_master] + # putting interface to the down-state, because add/remove upped interface impossible. undocumented kern.behavior. + iproute('--force', 'link', 'set', 'dev', @resource[:interface], 'down') + if bond and bond != :absent + # remove interface from bond, if one included to it + debug("Remove interface '#{@resource[:interface]}' from bond '#{bond}'.") + File.open("/sys/class/net/#{@resource[:interface]}/master/bonding/slaves", "a") {|f| f << "-#{@resource[:interface]}"} + end + if ! @property_flush[:bond_master].nil? and @property_flush[:bond_master] != :absent + # add interface as slave to bond + debug("Add interface '#{@resource[:interface]}' to bond '#{@property_flush[:bond_master]}'.") + File.open("/sys/class/net/#{@property_flush[:bond_master]}/bonding/slaves", "a") {|f| f << "+#{@resource[:interface]}"} + else + # port no more member of any bonds + @property_flush[:port_type] = nil + end + end + if @property_flush.has_key? :bridge + # get actual bridge-list. We should do it here, + # because bridge may be not existing at prefetch stage. + @bridges ||= self.class.get_bridge_list # resource port can't change bridge list + debug("Actual-bridge-list: #{@bridges}") + port_bridges_hash = self.class.get_port_bridges_pairs() + debug("Actual-port-bridge-mapping: '#{port_bridges_hash}'") # it should removed from LNX + # + iproute('--force', 'link', 'set', 'dev', @resource[:interface], 'down') + # remove interface from old bridge + if ! port_bridges_hash[@resource[:interface]].nil? + br_name = port_bridges_hash[@resource[:interface]][:bridge] + br_type = port_bridges_hash[@resource[:interface]][:br_type] + if br_name != @resource[:interface] + # do not remove bridge-based interface from his bridge + case br_type + when :ovs + vsctl('del-port', br_name, @resource[:interface]) + when :lnx + brctl('delif', br_name, @resource[:interface]) + else + #pass + end + end + end + # add port to the new bridge + if !@property_flush[:bridge].nil? and @property_flush[:bridge].to_sym != :absent + case @bridges[@property_flush[:bridge]][:br_type] + when :ovs + vsctl('add-port', @property_flush[:bridge], @resource[:interface]) + when :lnx + brctl('addif', @property_flush[:bridge], @resource[:interface]) + else + #pass + end + end + iproute('link', 'set', 'dev', @resource[:interface], 'up') if @resource[:onboot] + debug("Change bridge") + end + if @property_flush.has_key? :ethtool and @property_flush[:ethtool].is_a? Hash + @property_flush[:ethtool].each_pair do |section, pairs| + debug("Setup '#{section}' by ethtool for interface '#{@resource[:interface]}'.") + optmaps = self.class.get_ethtool_name_commands_mapping[section] + if optmaps + pairs.each_pair do |k,v| + if optmaps.has_key? k + _cmd = [optmaps['__section_key_set__'], @resource[:interface], optmaps[k], v ? 'on':'off'] + begin + ethtool_cmd(_cmd) + rescue Exception => e + warn("Non-fatal error: #{e.to_s}") + end + end + end + else + warn("No mapping for ethtool section '#{section}' for interface '#{@resource[:interface]}'.") + end + end + end + if ! @property_flush[:onboot].nil? + # Should be after bond, because interface may auto-upped while added to the bond + debug("Setup UP state for interface '#{@resource[:interface]}'.") + iproute('link', 'set', 'dev', @resource[:interface], 'up') + end + if !['', 'absent'].include? @property_flush[:mtu].to_s + self.class.set_mtu(@resource[:interface], @property_flush[:mtu]) + end + @property_hash = resource.to_hash + end + end + + #----------------------------------------------------------------- + def vlan_dev + @property_hash[:vlan_dev] || :absent + end + def vlan_dev=(val) + @property_flush[:vlan_dev] = val + end + + def vlan_id + @property_hash[:vlan_id] || :absent + end + def vlan_id=(val) + @property_flush[:vlan_id] = val + end + + def vlan_mode + @property_hash[:vlan_mode] || :absent + end + def vlan_mode=(val) + @property_flush[:vlan_mode] = val + end + + def bond_master + @property_hash[:bond_master] || :absent + end + def bond_master=(val) + @property_flush[:bond_master] = val + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l2_port/ovs.rb b/deployment/puppet/l23network/lib/puppet/provider/l2_port/ovs.rb new file mode 100644 index 0000000000..d52a798a07 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l2_port/ovs.rb @@ -0,0 +1,100 @@ +require File.join(File.dirname(__FILE__), '..','..','..','puppet/provider/ovs_base') + +Puppet::Type.type(:l2_port).provide(:ovs, :parent => Puppet::Provider::Ovs_base) do + commands :vsctl => 'ovs-vsctl', + :ethtool_cmd => 'ethtool', + :iproute => 'ip' + + + def self.add_unremovable_flag(port_props) + # calculate 'unremovable' flag. Should be re-defined in chield providers + if port_props[:port_type].include? 'bridge' or port_props[:port_type].include? 'bond' + port_props[:port_type] << 'unremovable' + end + end + + def self.get_instances(big_hash) + big_hash[:port] + end + + #----------------------------------------------------------------- + + def create + debug("CREATE resource: #{@resource}") + @old_property_hash = {} + @property_flush = {}.merge! @resource + # + cmd = ["add-port", @resource[:bridge], @resource[:interface]] + # # tag and trunks for port + # port_properties = @resource[:port_properties] + # if ![nil, :absent].include? @resource[:vlan_id] and @resource[:vlan_id] > 0 + # port_properties << "tag=#{@resource[:vlan_id]}" + # end + # if ![nil, :absent].include? @resource[:trunks] and !@resource[:trunks].empty? + # port_properties.insert(-1, "trunks=[#{@resource[:trunks].join(',')}]") + # end + # Port create begins from definition brodge and port + # # add port properties (k/w) to command line + # if not port_properties.empty? + # for option in port_properties + # cmd.insert(-1, option) + # end + # end + # set interface type + if @resource[:type] and (@resource[:type].to_s != '' or @resource[:type].to_s != :absent) + tt = "type=" + @resource[:type].to_s + else + tt = "type=internal" + end + cmd += ['--', "set", "Interface", @resource[:interface], tt] + # executing OVS add-port command + begin + vsctl(cmd) + rescue Puppet::ExecutionFailure => error + raise Puppet::ExecutionFailure, "Can't add port '#{@resource[:interface]}'\n#{error}" + end + # # set interface properties + # if @resource[:interface_properties] + # for option in @resource[:interface_properties] + # begin + # vsctl('--', "set", "Interface", @resource[:interface], option.to_s) + # rescue Puppet::ExecutionFailure => error + # raise Puppet::ExecutionFailure, "Interface '#{@resource[:interface]}' can't set option '#{option}':\n#{error}" + # end + # end + # end + end + + def destroy + vsctl("del-port", @resource[:bridge], @resource[:interface]) + end + + def flush + if @property_flush + debug("FLUSH properties: #{@property_flush}") + if !['', 'absent'].include? @property_flush[:mtu].to_s + self.class.set_mtu(@resource[:interface], @property_flush[:mtu]) + end + if @property_flush.has_key? :vlan_id + if !@property_flush[:vlan_id].nil? and @property_flush[:vlan_id] != :absent + vsctl('set', 'Port', @resource[:interface], "tag=#{@property_flush[:vlan_id].to_i}") + else + # remove 802.1q tag + vsctl('set', 'Port', @resource[:interface], "tag='[]'") + end + end + @property_hash = resource.to_hash + end + end + + #----------------------------------------------------------------- + + def ethtool + @property_hash[:ethtool] || nil + end + def ethtool=(val) + @property_flush[:ethtool] = val + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/ruby.rb b/deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/ruby.rb deleted file mode 100644 index 4b773310ed..0000000000 --- a/deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/ruby.rb +++ /dev/null @@ -1,226 +0,0 @@ -require 'timeout' -require 'ipaddr' - -begin - require 'util/netstat.rb' -rescue LoadError => e - # puppet apply does not add module lib directories to the $LOAD_PATH (See - # #4248). It should (in the future) but for the time being we need to be - # defensive which is what this rescue block is doing. - rb_file = File.join(File.dirname(__FILE__), 'util', 'netstat.rb') - load rb_file if File.exists?(rb_file) or raise e -end - -def get_gateway() - Facter::Util::NetStat.get_route_value('default', 'gw') || Facter::Util::NetStat.get_route_value('0.0.0.0', 'gw') -end - -def find_gateway(interface, if_file) - rv = nil - def_route = get_gateway() - if def_route and if_file - ifile = /\[(\S+)\]/.match(if_file.to_s()) - if ifile - #notice("RT-def-route: '#{def_route}' int_file: '#{ifile}'") ################ - ifile = ifile[1] - begin - File.open(ifile, 'r').each() do |line| - gate = /gateway\s+(\d+\.\d+\.\d+\.\d+)/.match(line.to_s()) || /GATEWAY\s*=\s*(\d+\.\d+\.\d+\.\d+)/.match(line.to_s()) - if gate - gate = gate[1] - #notice("IN-FILE-GATE: '#{gate}'") - if gate == def_route - rv = gate - #notice("IN-FILE-GATE: '#{gate}' rv = gate") - end - end - end - rescue - notice("Can't open file '#{ifile}'") - end - end - else - notice("Default route: UNKNOWN") - end - return rv -end - -Puppet::Type.type(:l3_if_downup).provide(:ruby) do - confine :osfamily => [:debian, :redhat] - optional_commands( - :ifup => 'ifup', - :ifdn => 'ifdown', - :ip => "ip", - :kill => "kill", - :ps => "ps", - :ping => "ping" - ) - - def ping_ip(ipaddr,timeout) - end_time = Time.now.to_i + timeout - rv = false - loop do - begin - ping(['-n', '-c1', ipaddr]) - rv = true - break - rescue Puppet::ExecutionFailure => e - current_time = Time.now.to_i - if current_time > end_time - break - else - wa = end_time - current_time - notice("Host #{ipaddr} not answered. Wait up to #{wa} sec.") - #notice e.message - end - sleep(0.5) # do not remove!!! It's a positive brake! - end - end - return rv - end - - def get_interface_carrier() - begin - return File.open("/sys/class/net/#{@resource[:interface]}/carrier", 'r'){ |file| file.read().to_i } - rescue - return -1 - end - end - - def restart() - #Check the current state of the interface first - if get_interface_carrier != 1 - notice("Carrier is DOWN, '#{@resource[:interface]}' skipping carrier test") - poll_for_carrier = false - else - poll_for_carrier = true - end - - begin # downing inteface - # add force for debian-based OS ([PRD-2132]) - if Facter.value(:osfamily) == 'Debian' - ifdn(['--force',@resource[:interface]]) - else - ifdn(@resource[:interface]) - end - notice("Interface '#{@resource[:interface]}' down.") - sleep @resource[:sleep_time] - rescue Puppet::ExecutionFailure - notice("Can't put interface '#{@resource[:interface]}' to DOWN state.") - end - if @resource[:kill_dhclient] and Facter.value(:osfamily) == 'Debian' - # kill forgotten dhclient in Ubuntu - dhclient = @resource[:dhclient_name] - iface = @resource[:interface] - ps('axf').each_line do |line| - rg = line.match("^\s*([0-9]+)\s+.*#{dhclient}\s+.*(\s#{iface})") - if rg - begin - kill(['-9',rg[1]]) - notice("Killed forgotten #{dhclient} with PID=#{rg[1]} succeffuly...") - sleep @resource[:sleep_time] - rescue Puppet::ExecutionFailure - notice("Can't kill #{dhclient} with PID=#{rg[1]}") - end - end - end - end - if @resource[:flush] # Flushing IP addresses from interface - begin - ip(['addr', 'flush', @resource[:interface]]) - notice("Interface '#{@resource[:interface]}' flush.") - sleep @resource[:sleep_time] - rescue Puppet::ExecutionFailure - notice("Can't flush interface '#{@resource[:interface]}'.") - end - end - return true if @resource[:onlydown] - begin # Put interface to UP state - if Facter.value(:osfamily) == 'Debian' - # add force for debian-based OS ([PRD-2132]) - ifup(['--force', @resource[:interface]]) - else - ifup(@resource[:interface]) - end - notice("Interface '#{@resource[:interface]}' up.") - # checking and waiting carrier for PHYS. interface - if (@resource[:interface] =~ /^eth\d+$/) and @resource[:wait_carrier_after_ifup] and poll_for_carrier - begin - Timeout::timeout(@resource[:wait_carrier_after_ifup_timeout]) do - _w = 10 - loop do - carrier = get_interface_carrier - if carrier == 1 - break - elsif carrier == -1 - notice("Seems that the interface '#{@resource[:interface]}' was brought down administratively. Further deployment actions may fail!") - sleep(10) - else - if _w == 0 - notice("Interface '#{@resource[:interface]}' waiting for carrier...") - _w = 10 - end - sleep(1) - _w -= 1 - end - end - end - rescue Timeout::Error - notice("Interface '#{@resource[:interface]}' has no carrier. :(") - else - notice("Interface '#{@resource[:interface]}' has good carrier.") - end - end - if @resource[:check_by_ping] == 'gateway' - # find gateway for interface and ping it - ip_to_ping = find_gateway(@resource[:interface], @resource[:subscribe]) - if ip_to_ping - notice("Interface '#{@resource[:interface]}' Gateway #{ip_to_ping} will be pinged. Wait up to #{@resource[:check_by_ping_timeout]} sec.") - rv = self.ping_ip(ip_to_ping, @resource[:check_by_ping_timeout].to_i) - if rv - notice("Interface '#{@resource[:interface]}' #{ip_to_ping} is OK") - else - notice("Interface '#{@resource[:interface]}' #{ip_to_ping} no answer :(") - end - end - elsif @resource[:check_by_ping] == 'none' - #pass - notice("Interface '#{@resource[:interface]}' Don't checked.") - else - # IP address given - notice("Interface '#{@resource[:interface]}' IP #{@resource[:check_by_ping]} will be pinged. Wait up to #{@resource[:check_by_ping_timeout]} sec.") - rv = self.ping_ip(@resource[:check_by_ping], @resource[:check_by_ping_timeout].to_i) - if rv - notice("Interface '#{@resource[:interface]}' #{@resource[:check_by_ping]} is OK") - else - notice("Interface '#{@resource[:interface]}' #{@resource[:check_by_ping]} no answer :(") - end - end - notice("Interface '#{@resource[:interface]}' done.") - rescue Puppet::ExecutionFailure - notice("Can't put interface '#{@resource[:interface]}' to UP state.") - end - end - - def create() - if ! @resource[:refreshonly] - restart() - end - end - - def destroy() - end - - # def self.instances - # if_list = [] - # File.open("/proc/net/dev", "r") do |raw_iflist| - # while (line = raw_iflist.gets) - # rg = line.match('^\s*([0-9A-Za-z\.\-\_]+):') - # if rg - # if_list.push(rg[1].to_sym) - # end - # end - # end - # return if_list - # end -end diff --git a/deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/util/netstat.rb b/deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/util/netstat.rb deleted file mode 100644 index 782bfb7e13..0000000000 --- a/deployment/puppet/l23network/lib/puppet/provider/l3_if_downup/util/netstat.rb +++ /dev/null @@ -1,71 +0,0 @@ -module Facter::Util::NetStat - def self.column_map - { - :bsd => { - :aliases => [:sunos, :freebsd, :netbsd, :darwin], - :dest => 0, - :gw => 1, - :iface => 5 - }, - :linux => { - :dest => 0, - :gw => 1, - :iface => 7 - }, - :openbsd => { - :dest => 0, - :gw => 1, - :iface => 6 - } - } - end - - def self.supported_platforms - column_map.inject([]) do |result, tmp| - key, map = tmp - if map[:aliases] - result += map[:aliases] - else - result << key - end - result - end - end - - def self.get_ipv4_output - output = "" - case Facter.value(:kernel) - when 'SunOS', 'FreeBSD', 'NetBSD', 'OpenBSD' - output = %x{/usr/bin/netstat -rn -f inet} - when 'Darwin' - output = %x{/usr/sbin/netstat -rn -f inet} - when 'Linux' - output = %x{/bin/netstat -rn -A inet} - end - output - end - - def self.get_route_value(route, label) - tmp1 = [] - - kernel = Facter.value(:kernel).downcase.to_sym - - # If it's not directly in the map or aliased in the map, then we don't know how to deal with it. - unless map = column_map[kernel] || column_map.values.find { |tmp| tmp[:aliases] and tmp[:aliases].include?(kernel) } - return nil - end - - c1 = map[:dest] - c2 = map[label.to_sym] - - get_ipv4_output.split("\n").map { |s| s.split}.each { |a| - if a[c1] == route - tmp1 << a[c2] - end - } - - if tmp1 - return tmp1.shift - end - end -end diff --git a/deployment/puppet/l23network/lib/puppet/provider/l3_ifconfig/lnx.rb b/deployment/puppet/l23network/lib/puppet/provider/l3_ifconfig/lnx.rb new file mode 100644 index 0000000000..9ccc360668 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/l3_ifconfig/lnx.rb @@ -0,0 +1,232 @@ +Puppet::Type.type(:l3_ifconfig).provide(:lnx) do + defaultfor :osfamily => :linux + commands :iproute => 'ip' + + + def self.prefetch(resources) + interfaces = instances + resources.keys.each do |name| + if provider = interfaces.find{ |ii| ii.name == name } + resources[name].provider = provider + end + end + end + + def self.instances + insts = [] + rou_list = self.get_if_defroutes_mappings() + # parse all system interfaces + self.get_if_addr_mappings().each_pair do |if_name, pro| + props = { + :ensure => :present, + :name => if_name, + :ipaddr => pro[:ipaddr], + } + if !rou_list[if_name].nil? + props.merge! rou_list[if_name] + else + props.merge!({ + :gateway => :absent, + :gateway_metric => :absent + }) + end + debug("PREFETCHED properties for '#{if_name}': #{props}") + insts << new(props) + end + return insts + end + + def exists? + @property_hash[:ensure] == :present + end + + def create + debug("CREATE resource: #{@resource}") # with hash: '#{m}'") + @old_property_hash = {} + @property_flush = {}.merge! @resource + #p @property_flush + #p @property_hash + #p @resource.inspect + end + + def destroy + debug("DESTROY resource: #{@resource}") + # todo: Destroing of L3 resource -- is a removing any IP addresses. + # DO NOT!!! put intedafce to Down state. + iproute('--force', 'addr', 'flush', 'dev', @resource[:interface]) + @property_hash.clear + end + + def initialize(value={}) + super(value) + @property_flush = {} + @old_property_hash = {} + @old_property_hash.merge! @property_hash + end + + def flush + if @property_flush + debug("FLUSH properties: #{@property_flush}") + # + # FLUSH changed properties + if ! @property_flush[:ipaddr].nil? + if @property_flush[:ipaddr].include?(:absent) + # flush all ip addresses from interface + iproute('--force', 'addr', 'flush', 'dev', @resource[:interface]) + elsif @property_flush[:ipaddr].include?(:dhcp) + # start dhclient on interface + iproute('--force', 'addr', 'flush', 'dev', @resource[:interface]) + #todo: start dhclient + else + # add-remove static IP addresses + if !@old_property_hash.nil? and !@old_property_hash[:ipaddr].nil? + (@old_property_hash[:ipaddr] - @property_flush[:ipaddr]).each do |ipaddr| + iproute('--force', 'addr', 'del', ipaddr, 'dev', @resource[:interface]) + end + adding_addresses = @property_flush[:ipaddr] - @old_property_hash[:ipaddr] + else + adding_addresses = @property_flush[:ipaddr] + end + if adding_addresses.include? :none + iproute('--force', 'link', 'set', 'dev', @resource[:interface], 'up') + elsif adding_addresses.include? :dhcp + debug("!!! DHCP runtime configuration not implemented now !!!") + else + # add IP addresses + adding_addresses.each do |ipaddr| + iproute('addr', 'add', ipaddr, 'dev', @resource[:interface]) + end + end + end + end + + if !@property_flush[:gateway].nil? or !@property_flush[:gateway_metric].nil? + # clean all default gateways for this interface with any metrics + cmdline = ['route', 'del', 'default', 'dev', @resource[:interface]] + rc = 0 + while rc == 0 + # we should remove route repeatedly for prevent situation + # when has multiple default routes through the same router, + # but with different metrics + begin + iproute(cmdline) + rescue + rc = 1 + end + end + # add new route + if @resource[:gateway] != :absent + cmdline = ['route', 'add', 'default', 'via', @resource[:gateway], 'dev', @resource[:interface]] + if ![nil, :absent].include?(@property_flush[:gateway_metric]) and @property_flush[:gateway_metric].to_i > 0 + cmdline << ['metric', @property_flush[:gateway_metric]] + end + begin + rv = iproute(cmdline) + rescue + warn("!!! Iproute can't setup new gateway.\n!!! May be you already have default gateway with same metric:") + rv = iproute('-f', 'inet', 'route', 'show') + warn("#{rv}\n\n") + end + end + end + + # if ! @property_flush[:onboot].nil? + # iproute('link', 'set', 'dev', @resource[:interface], 'up') + # end + @property_hash = resource.to_hash + end + end + + #----------------------------------------------------------------- + # def bridge + # @property_hash[:bridge] || :absent + # end + # def bridge=(val) + # @property_flush[:bridge] = val + # end + + # def name + # @property_hash[:name] + # end + + def port_type + @property_hash[:port_type] || :absent + end + def port_type=(val) + @property_flush[:port_type] = val + end + + def onboot + @property_hash[:onboot] || :absent + end + def onboot=(val) + @property_flush[:onboot] = val + end + + def ipaddr + @property_hash[:ipaddr] || :absent + end + def ipaddr=(val) + if (@old_property_hash[:ipaddr] - val) != (val - @old_property_hash[:ipaddr]) + @property_flush[:ipaddr] = val + end + end + + def gateway + @property_hash[:gateway] || :absent + end + def gateway=(val) + @property_flush[:gateway] = val + end + + def gateway_metric + @property_hash[:gateway_metric] || :absent + end + def gateway_metric=(val) + @property_flush[:gateway_metric] = val + end + + def dhcp_hostname + @property_hash[:dhcp_hostname] || :absent + end + def dhcp_hostname=(val) + @property_flush[:dhcp_hostname] = val + end + + #----------------------------------------------------------------- + + def self.get_if_addr_mappings + if_list = {} + ip_a = iproute('-f', 'inet', 'addr', 'show').split(/\n+/) + if_name = nil + ip_a.each do |line| + line.rstrip! + case line + when /^\s*\d+\:\s+([\w\-\.]+)[\:\@]/i + if_name = $1 + if_list[if_name] = { :ipaddr => [] } + when /^\s+inet\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2})/ + next if if_name.nil? + if_list[if_name][:ipaddr] << $1 + else + next + end + end + return if_list + end + + def self.get_if_defroutes_mappings + rou_list = {} + ip_a = iproute('-f', 'inet', 'route', 'show').split(/\n+/) + ip_a.each do |line| + line.rstrip! + next if !line.match(/^\s*default\s+via\s+([\d\.]+)\s+dev\s+([\w\-\.]+)(\s+metric\s+(\d+))?/) + metric = $4.nil? ? :absent : $4.to_i + rou_list[$2] = { :gateway => $1, :gateway_metric => metric } if rou_list[$2].nil? # do not replace to gateway with highest metric + end + return rou_list + end + + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/lnx_base.rb b/deployment/puppet/l23network/lib/puppet/provider/lnx_base.rb new file mode 100644 index 0000000000..fb02a28bbb --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/lnx_base.rb @@ -0,0 +1,94 @@ +require File.join(File.dirname(__FILE__), 'l2_base') + +class Puppet::Provider::Lnx_base < Puppet::Provider::L2_base + + #todo(sv): adapt this to LNX resources + # def self.instances + # rv = [] + # get_instances(ovs_vsctl_show()).each_pair do |p_name, p_props| + # props = { + # :ensure => :present, + # :name => p_name, + # :vendor_specific => {} + # } + # debug("prefetching '#{p_name}'") + # props.merge! p_props + # next if skip_port_for? props + # add_unremovable_flag(props) + # ##add PROVIDER prefix to port type flags and create puppet resource + # if props[:provider] == 'ovs' + # props[:port_type] = props[:port_type].insert(0, 'ovs').join(':') + # rv << new(props) + # debug("PREFETCH properties for '#{p_name}': #{props}") + # else + # debug("SKIP properties for '#{p_name}': #{props}") + # end + # end + # return rv + # end + + + def initialize(value={}) + super(value) + @property_flush = {} + @old_property_hash = {} + @old_property_hash.merge! @property_hash + end + + def exists? + @property_hash[:ensure] == :present + end + + #----------------------------------------------------------------- + def vendor_specific + @property_hash[:vendor_specific] || :absent + end + def vendor_specific=(val) + nil + end + + def mtu + @property_hash[:mtu] || :absent + end + def mtu=(val) + # for MTU :absent is sinonym of 'do not change' + @property_flush[:mtu] = val.to_i if !['', 'absent'].include? val.to_s + end + + def onboot + @property_hash[:onboot] || :absent + end + def onboot=(val) + @property_flush[:onboot] = val + end + + def bridge + @property_hash[:bridge] || :absent + end + def bridge=(val) + @property_flush[:bridge] = val + end + + def ethtool + @property_hash[:ethtool] || nil + end + def ethtool=(val) + @property_flush[:ethtool] = val + end + + def port_type + @property_hash[:port_type] || :absent + end + def port_type=(val) + @property_flush[:port_type] = val + end + + def type + :absent + end + def type=(value) + debug("Resource '#{@resource[:name]}': Doesn't support interface type change.") + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/provider/ovs_base.rb b/deployment/puppet/l23network/lib/puppet/provider/ovs_base.rb new file mode 100644 index 0000000000..a4121984aa --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/provider/ovs_base.rb @@ -0,0 +1,141 @@ +require File.join(File.dirname(__FILE__), 'l2_base') + +class Puppet::Provider::Ovs_base < Puppet::Provider::L2_base + + def self.skip_port_for?(port_props) + # calculate whether this port should be skipped. + # Should be re-defined in chield providers + false + end + + def self.add_unremovable_flag(port_props) + # calculate 'unremovable' flag. Should be re-defined in chield providers + true + end + + def self.get_instances(big_hash) + # calculate hash of hashes from given big hash + # Should be re-defined in chield providers + {} + end + + def self.instances + rv = [] + get_instances(ovs_vsctl_show()).each_pair do |p_name, p_props| + props = { + :ensure => :present, + :name => p_name, + :vendor_specific => {} + } + debug("prefetching '#{p_name}'") + props.merge! p_props + next if skip_port_for? props + add_unremovable_flag(props) + ##add PROVIDER prefix to port type flags and create puppet resource + if props[:provider] == 'ovs' + props[:port_type] = props[:port_type].insert(0, 'ovs').join(':') + rv << new(props) + debug("PREFETCH properties for '#{p_name}': #{props}") + else + debug("SKIP properties for '#{p_name}': #{props}") + end + end + return rv + end + + + def initialize(value={}) + super(value) + @property_flush = {} + @old_property_hash = {} + @old_property_hash.merge! @property_hash + end + + def exists? + @property_hash[:ensure] == :present + end + + #----------------------------------------------------------------- + #----------------------------------------------------------------- + def bridge + @property_hash[:bridge] || :absent + end + def bridge=(val) + @property_flush[:bridge] = val + end + + def vlan_dev + :absent + end + def vlan_dev=(val) + nil + end + + def vlan_id + @property_hash[:vlan_id] || :absent + end + def vlan_id=(val) + @property_flush[:vlan_id] = val + end + + def port_type + @property_hash[:port_type] || :absent + end + def port_type=(val) + @property_flush[:port_type] = val + end + + def vlan_mode + 'vlan' + end + def vlan_mode=(val) + nil + end + + def bond_master + :absent + end + def bond_master=(val) + nil + end + + def slaves + @property_hash[:slaves] || :absent + end + def slaves=(val) + nil + end + + def mtu + @property_hash[:mtu] || :absent + end + def mtu=(val) + # for MTU :absent is sinonym of 'do not change' + @property_flush[:mtu] = val.to_i if !['', 'absent'].include? val.to_s + end + + def onboot + @property_hash[:onboot] || :absent + end + def onboot=(val) + @property_flush[:onboot] = val + end + + def vendor_specific + @property_hash[:vendor_specific] || :absent + end + def vendor_specific=(val) + @property_flush[:vendor_specific] = val + end + + def type + @property_hash[:type] || :absent + end + def type=(value) + @property_flush[:type] = val + end + + #----------------------------------------------------------------- + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/cfg.rb b/deployment/puppet/l23network/lib/puppet/type/cfg.rb index e2374c29ec..e956a339e3 100644 --- a/deployment/puppet/l23network/lib/puppet/type/cfg.rb +++ b/deployment/puppet/l23network/lib/puppet/type/cfg.rb @@ -39,3 +39,4 @@ Puppet::Type.newtype(:cfg) do end end end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/k_mod.rb b/deployment/puppet/l23network/lib/puppet/type/k_mod.rb new file mode 100644 index 0000000000..50efa4b792 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/type/k_mod.rb @@ -0,0 +1,14 @@ +Puppet::Type.newtype(:k_mod) do + @doc = "Check and load kernel module, if need" + desc @doc + + ensurable + + MAX_BR_NAME_LENGTH = 15 + + newparam(:module) do + isnamevar + desc "Module name" + end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/l23_stored_config.rb b/deployment/puppet/l23network/lib/puppet/type/l23_stored_config.rb new file mode 100644 index 0000000000..b23f2e4a34 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/type/l23_stored_config.rb @@ -0,0 +1,268 @@ +# type for managing persistent interface config options +# Inspired by puppet-network module. Adrien, thanks. + +Puppet::Type.newtype(:l23_stored_config) do + @doc = "Manage lines in interface config file" + desc @doc + + feature :provider_options, <<-EOD + The provider can accept a hash of arbitrary options. The semantics of + these options will depend on the provider. + EOD + + ensurable + + newparam(:name) do + isnamevar + desc "The name of the physical or logical network device" + end + + newproperty(:method) do + desc "The method for determining an IP address for the interface" + # static -- assign IP address in config + # manual -- UP interface without IP address + newvalues(:static, :absent, :manual, :dhcp, :loopback, :none, :undef, :nil) + aliasvalue(:none, :manual) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :manual + end + + # newproperty(:port_type) do + # desc "port_type fake RO property" + # end + + newproperty(:if_type) do + desc "Device type. Service property, shouldn't be setting by puppet" + newvalues(:ethernet, :bridge, :bond) + end + + newproperty(:bridge, :array_matching => :all) do + # Array_matching for this property required for very complicated cases + # ex. patchcord for connectind two bridges or bridge and network namesspace + desc "Name of bridge, including this port" + newvalues(/^[\w+\-]+$/, :none, :undef, :nil, :absent) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + end + + newproperty(:jacks, :array_matching => :all) do + desc "Name of jacks for patchcord" + newvalues(/^[\w+\-]+$/) + end + + newproperty(:bridge_ports, :array_matching => :all) do + desc "Ports, member of bridge, service property, do not use directly." + end + + newproperty(:bridge_stp) do + desc "Whether stp enable" + newvalues(:true, :absent, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :absent + end + + newproperty(:onboot) do + desc "Whether to bring the interface up on boot" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + newproperty(:mtu) do + desc "The Maximum Transmission Unit size to use for the interface" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + aliasvalue(0, :absent) + defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces) + validate do |value| # inherits it from a parent interface + # Intel 82598 & 82599 chips support MTUs up to 16110; is there any + # hardware in the wild that supports larger frames? + # + # It appears loopback devices routinely have large MTU values; Eg. 65536 + # + # Frames small than 64bytes are discarded as runts. Smallest valid MTU + # is 42 with a 802.1q header and 46 without. + min_mtu = 42 + max_mtu = 65536 + if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i)) + raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})" + end + end + munge do |val| + ((val == :absent) ? :absent : val.to_i) + end + end + + newproperty(:vlan_dev) do + desc "802.1q vlan base device" + end + + newproperty(:vlan_id) do + desc "802.1q vlan ID" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + aliasvalue(0, :absent) + defaultto :absent + validate do |val| + min_vid = 1 + max_vid = 4094 + if ! (val.to_s == 'absent' or (min_vid .. max_vid).include?(val.to_i)) + raise ArgumentError, "'#{val}' is not a valid 802.1q NALN_ID (must be a integer value in range (#{min_vid} .. #{max_vid})" + end + end + munge do |val| + ((val == :absent) ? :absent : val.to_i) + end + end + + newproperty(:vlan_mode) do + desc "802.1q vlan interface naming model" + #newvalues(:ethernet, :bridge, :bond) + #defaultto :ethernet + end + + + newproperty(:ipaddr) do + desc "Primary IP address for interface" + newvalues(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}$/, :absent, :none, :undef, :nil, :dhcp) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + end + + newproperty(:gateway) do + desc "Default gateway" + newvalues(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + end + + newproperty(:gateway_metric) do + desc "Default gateway metric" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + aliasvalue(0, :absent) + defaultto :absent + validate do |val| + min_metric = 0 + max_metric = 65535 + if ! (val.to_s == 'absent' or (min_metric .. max_metric).include?(val.to_i)) + raise ArgumentError, "'#{val}' is not a valid metric (must be a integer value in range (#{min_metric} .. #{max_metric})" + end + end + munge do |val| + ((val == :absent) ? :absent : val.to_i) + end + end + + newproperty(:bond_master) do + desc "bond name for bonded interface" + newvalues(/^[\w+\-]+$/, :none, :undef, :nil, :absent) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + end + + newproperty(:bond_slaves, :array_matching => :all) do + desc "slave ports for bond interface" + newvalues(/^[\w+\-]+$/, :false, :none, :undef, :nil, :absent) + #aliasvalue(:absent, :none) # none is a valid config value + aliasvalue(:false, :none) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + end + + newproperty(:bond_mode) + newproperty(:bond_miimon) + newproperty(:bond_lacp_rate) + + # # `:options` provides an arbitrary passthrough for provider properties, so + # # that provider specific behavior doesn't clutter up the main type but still + # # allows for more powerful actions to be taken. + # newproperty(:options, :required_features => :provider_options) do + # desc "Provider specific options to be passed to the provider" + + # def is_to_s(hash = @is) + # hash.keys.sort.map {|key| "#{key} => #{hash[key]}"}.join(", ") + # end + + # def should_to_s(hash = @should) + # hash.keys.sort.map {|key| "#{key} => #{hash[key]}"}.join(", ") + # end + + # defaultto {} + + # validate do |value| + # raise ArgumentError, "#{self.class} requires a hash for the options property" unless value.is_a? Hash + # #provider.validate + # end + # end + + newproperty(:vendor_specific) do + desc "Hash of vendor specific properties" + #defaultto {} # no default value should be!!! + # provider-specific properties, can be validating only by provider. + validate do |val| + if ! val.is_a? Hash + fail("Vendor_specific should be a hash!") + end + end + + munge do |value| + L23network.reccursive_sanitize_hash(value) + end + + def should_to_s(value) + "\n#{value.to_yaml}\n" + end + + def is_to_s(value) + "\n#{value.to_yaml}\n" + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + + def generate + return if ! (!([:absent, :none, :nil, :undef] & self[:bridge]).any? \ + and [:ethernet, :bond].include? self[:if_type] + ) + self[:bridge].each do |bridge| + br = self.catalog.resource('L23_stored_config', bridge) + fail("Stored_config resource for bridge '#{bridge}' not found for port '#{self[:name]}'!") if ! br + br[:bridge_ports] ||= [] + ports = br[:bridge_ports] + return if ! ports.is_a? Array + if ! ports.include? self[:name] + ports << self[:name].to_s + br[:bridge_ports] = ports.reject{|a| a=='none'}.sort + end + end + nil + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_bond.rb b/deployment/puppet/l23network/lib/puppet/type/l2_bond.rb new file mode 100644 index 0000000000..b7ba8af7b6 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/type/l2_bond.rb @@ -0,0 +1,213 @@ +# type for managing runtime bond of NICs states. + +Puppet::Type.newtype(:l2_bond) do + @doc = "Manage a network port abctraction." + desc @doc + + ensurable + + newparam(:bond) do + isnamevar + desc "The bond name" + # + validate do |val| + if not val =~ /^[a-z_][\w\.\-]*[0-9a-z]$/ + fail("Invalid bond name: '#{val}'") + end + end + end + + newparam(:use_ovs) do + desc "Whether using OVS comandline tools" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + newproperty(:port_type) do + desc "Internal read-only property" + validate do |value| + raise ArgumentError, "You shouldn't change port_type -- it's a internal RO property!" + end + end + + + newproperty(:onboot) do + desc "Whether to bring the interface up" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + newproperty(:bridge) do + desc "What bridge to use" + newvalues(/^[a-z][0-9a-z\-\_]*[0-9a-z]$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + end + + newproperty(:slaves, :array_matching => :all) do + desc "What bridge to use" + newvalues(/^[a-z][0-9a-z\-\_]*[0-9a-z]$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + # provider-specific list. may be empty. + def should_to_s(value) + value == :absent ? value : value.sort.join(',') + end + def is_to_s(value) + should_to_s(value) + end + def insync?(value) + should_to_s(value) == should_to_s(should) + end + + end + + newparam(:trunks, :array_matching => :all) do + desc "Array of trunks id, for configure patch's ends as ports in trunk mode" + end + + newproperty(:interface_properties) do + desc "Hash of bonded interfaces properties" + #defaultto {} + # provider-specific hash, validating only by type. + validate do |val| + if ! val.is_a? Hash + fail("Interface_properties should be a hash!") + end + end + + def should_to_s(value) + return :absent if value == :absent + rv = [] + value.keys.sort.each do |key| + rv << "(#{key.to_s}=#{value[key]})" + end + rv.join(', ') + end + + def is_to_s(value) + should_to_s(value) + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + newproperty(:bond_properties) do + desc "Hash of bond properties" + #defaultto {} + # provider-specific hash, validating only by type. + validate do |val| + #puts "l2_bond validate got '#{val.inspect}'" + if ! val.is_a? Hash + fail("Interface_properties should be a hash!") + end + end + + munge do |val| + # it's a workaround, because puppet double some values inside his internal logic + val.keys.each do |k| + if k.is_a? String + if ! val.has_key? k.to_sym + val[k.to_sym] = val[k] + end + val.delete(k) + end + end + val + end + + def should_to_s(value) + return '' if [:absent, 'absent', nil, {}].include? value + value.keys.sort.map{|k| "(#{k.to_s}=#{value[k]})"}.join(', ') + end + + def is_to_s(value) + should_to_s(value) + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + newproperty(:mtu) do + desc "The Maximum Transmission Unit size to use for the interface" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + aliasvalue(0, :absent) + defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces) + validate do |value| # inherits it from a parent interface + # Intel 82598 & 82599 chips support MTUs up to 16110; is there any + # hardware in the wild that supports larger frames? + # + # It appears loopback devices routinely have large MTU values; Eg. 65536 + # + # Frames small than 64bytes are discarded as runts. Smallest valid MTU + # is 42 with a 802.1q header and 46 without. + min_mtu = 42 + max_mtu = 65536 + if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i)) + raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})" + end + end + munge do |val| + ((val == :absent) ? :absent : val.to_i) + end + end + + newproperty(:vendor_specific) do + desc "Hash of vendor specific properties" + #defaultto {} # no default value should be!!! + # provider-specific properties, can be validating only by provider. + validate do |val| + if ! val.is_a? Hash + fail("Vendor_specific should be a hash!") + end + end + + munge do |value| + L23network.reccursive_sanitize_hash(value) + end + + def should_to_s(value) + "\n#{value.to_yaml}\n" + end + + def is_to_s(value) + "\n#{value.to_yaml}\n" + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + + autorequire(:l2_bridge) do + [self[:bridge]] + end + + # def validate + # if self[:name].to_s == 'bond23' + # require 'pry' + # binding.pry + # end + # end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_bridge.rb b/deployment/puppet/l23network/lib/puppet/type/l2_bridge.rb new file mode 100644 index 0000000000..b453bb0f56 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/type/l2_bridge.rb @@ -0,0 +1,115 @@ +# +Puppet::Type.newtype(:l2_bridge) do + @doc = "Manage a native linux and open vSwitch bridges (virtual switches)" + desc @doc + + ensurable + + MAX_BR_NAME_LENGTH = 15 + + newparam(:bridge) do + isnamevar + desc "The bridge to configure" + # + validate do |val| + if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/ + fail("Wrong bridge name: '#{val}'") + end + end + end + + newparam(:use_ovs) do + desc "Whether using OVS comandline tools" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + newproperty(:external_ids) do + desc "External IDs for the bridge" + #defaultto {} # do not use defaultto here!!! + + validate do |val| + if ! val.is_a? Hash + fail("External_ids should be a hash!") + end + end + def should_to_s(value) + return [] if value == :absent + rv = [] + value.keys.sort.each do |key| + rv << "(#{key.to_s}=#{value[key]})" + end + rv.join(', ') + end + + def is_to_s(value) + should_to_s(value) + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + newproperty(:br_type) do + desc "Internal read-only property" + validate do |value| + raise ArgumentError, "You shouldn't change br_type -- it's a internal RO property!" + end + end + + newproperty(:stp) do + desc "Whether stp enable" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :false + end + + newproperty(:vendor_specific) do + desc "Hash of vendor specific properties" + #defaultto {} # no default value should be!!! + # provider-specific properties, can be validating only by provider. + validate do |val| + if ! val.is_a? Hash + fail("Vendor_specific should be a hash!") + end + end + + munge do |value| + L23network.reccursive_sanitize_hash(value) + end + + def should_to_s(value) + "\n#{value.to_yaml}\n" + end + + def is_to_s(value) + "\n#{value.to_yaml}\n" + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + + # global validator + def validate + # require 'pry' + # binding.pry + if provider.class.name != :ovs and self[:name].length > MAX_BR_NAME_LENGTH + # validate name for differetn providers may only in global validator, because + # 'provider' option don't accessible while validating name + fail("Wrong bridge name '#{self[:name]}'.\n For provider '#{provider.class.name}' bridge name shouldn't has length more, than #{MAX_BR_NAME_LENGTH}.") + end + end + +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_bond.rb b/deployment/puppet/l23network/lib/puppet/type/l2_ovs_bond.rb deleted file mode 100644 index b067575f26..0000000000 --- a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_bond.rb +++ /dev/null @@ -1,89 +0,0 @@ -Puppet::Type.newtype(:l2_ovs_bond) do - @doc = "Manage a Open vSwitch port" - desc @doc - - ensurable - - newparam(:bond) do - isnamevar - desc "The bond name" - # - validate do |val| - if not (val =~ /^[a-zA-Z][0-9a-zA-Z\.\-\_]*[0-9a-zA-Z]$/) - fail("Invalid bond name: '#{val}'") - end - end - end - - newparam(:interfaces) do - desc "List of interfaces that will be added to the bond" - # - validate do |val| - if not (val.is_a?(Array) and val.size() >= 2) - fail("Interfaces parameter must be an array of two or more interface names.") - end - for ii in val - if not (ii =~ /^[a-zA-Z][0-9a-zA-Z\.\-\_]*[0-9a-zA-Z]$/) - fail("Invalid port name: '#{ii}'") - end - end - end - end - - newparam(:skip_existing) do - defaultto(false) - desc "Allow to skip existing bond" - end - - newparam(:properties) do - defaultto([]) - desc "Array of bond properties" - munge do |val| - Array(val) - end - end - - newparam(:bridge) do - desc "What bridge to use" - # - validate do |val| - if not (val =~ /^[a-zA-Z][0-9a-zA-Z\.\-\_]*[0-9a-zA-Z]$/) - fail("Invalid bridge name: '#{val}'") - end - end - end - - newparam(:vlan_id) do - defaultto(0) - desc "802.1q tag" - validate do |val| - if !val.is_a?(Integer) or (val < 0 or val > 4094) - fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval") - end - end - munge do |val| - val.to_i - end - end - - newparam(:trunks, :array_matching => :all) do - defaultto([]) - desc "Array of trunks id, for configure patch's ends as ports in trunk mode" - # - validate do |val| - val = Array(val) # prevents puppet conversion array of one Int to Int - for i in val - if !i.is_a?(Integer) or (i < 0 or i > 4094) - fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval") - end - end - end - munge do |val| - Array(val) - end - end - - autorequire(:l2_ovs_bridge) do - [self[:bridge]] - end -end diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_bridge.rb b/deployment/puppet/l23network/lib/puppet/type/l2_ovs_bridge.rb deleted file mode 100644 index 9632f3c9be..0000000000 --- a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_bridge.rb +++ /dev/null @@ -1,26 +0,0 @@ -Puppet::Type.newtype(:l2_ovs_bridge) do - @doc = "Manage a Open vSwitch bridge (virtual switch)" - desc @doc - - ensurable - - newparam(:bridge) do - isnamevar - desc "The bridge to configure" - # - validate do |val| - if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/ - fail("Invalid bridge name: '#{val}'") - end - end - end - - newparam(:skip_existing) do - defaultto(false) - desc "Allow to skip existing bridge" - end - - newproperty(:external_ids) do - desc "External IDs for the bridge" - end -end diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_patch.rb b/deployment/puppet/l23network/lib/puppet/type/l2_ovs_patch.rb deleted file mode 100644 index ded3a32a90..0000000000 --- a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_patch.rb +++ /dev/null @@ -1,81 +0,0 @@ -Puppet::Type.newtype(:l2_ovs_patch) do - @doc = "Manage a Open vSwitch patch between two bridges" - desc @doc - - ensurable - - newparam(:name) # workarround for following error: - # Error 400 on SERVER: Could not render to pson: undefined method `merge' for []:Array - # http://projects.puppetlabs.com/issues/5220 - - newparam(:bridges, :array_matching => :all) do - desc "Array of bridges that will be connected" - # - validate do |val| - if !val.is_a?(Array) or val.size() != 2 - fail("Must be an array of two bridge names") - end - if not (val[0].is_a?(String) and val[1].is_a?(String)) - fail("Bridge names must have be a string.") - end - end - end - - newparam(:peers, :array_matching => :all) do - defaultto([nil,nil]) - desc "List of names that will be used for naming patches at it's ends." - # - validate do |val| - if !val.is_a?(Array) or val.size() != 2 - fail("Must be an array of two bridge names") - end - for i in val - if not (i.is_a?(String) or i == nil) - fail("Peer names must have be a string.") - end - end - end - end - - # newparam(:skip_existing) do - # defaultto(false) - # desc "Allow to skip existing bond" - # end - - newparam(:vlan_ids, :array_matching => :all) do - defaultto([0,0]) - desc "Array of 802.1q tag for ends." - # - validate do |val| - if !val.is_a?(Array) or val.size() != 2 - fail("Must be an array of two integers") - end - for i in val - if !i.is_a?(Integer) or (i < 0 or i > 4094) - fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval") - end - end - end - end - - newparam(:trunks, :array_matching => :all) do - defaultto([]) - desc "Array of trunks id, for configure patch's ends as ports in trunk mode" - # - validate do |val| - val = Array(val) # prevents puppet conversion array of one Int to Int - for i in val - if !i.is_a?(Integer) or (i < 0 or i > 4094) - fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval") - end - end - end - munge do |val| - Array(val) - end - end - - autorequire(:l2_ovs_bridge) do - self[:bridges] - end -end diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_port.rb b/deployment/puppet/l23network/lib/puppet/type/l2_ovs_port.rb deleted file mode 100644 index 65741aac91..0000000000 --- a/deployment/puppet/l23network/lib/puppet/type/l2_ovs_port.rb +++ /dev/null @@ -1,94 +0,0 @@ -Puppet::Type.newtype(:l2_ovs_port) do - @doc = "Manage a Open vSwitch port" - desc @doc - - ensurable - - newparam(:interface) do - isnamevar - desc "The interface to attach to the bridge" - # - validate do |val| - if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/ - fail("Invalid interface name: '#{val}'") - end - end - end - - newparam(:type) do - newvalues('', :system, :internal, :tap, :gre, :ipsec_gre, :capwap, :patch, :null) - defaultto('') - desc "Ovs port type" - end - - newparam(:skip_existing) do - defaultto(false) - desc "Allow to skip existing port" - end - - newparam(:bridge) do - desc "What bridge to use" - # - validate do |val| - if not val =~ /^[a-z][0-9a-z\.\-\_]*[0-9a-z]$/ - fail("Invalid bridge name: '#{val}'") - end - end - end - - newparam(:port_properties, :array_matching => :all) do - defaultto([]) - desc "Array of port properties" - munge do |val| - Array(val) - end - end - - newparam(:interface_properties) do - defaultto([]) - desc "Array of port interface properties" - munge do |val| - Array(val) - end - end - - newparam(:vlan_id) do - defaultto(0) - desc "802.1q tag" - validate do |val| - if !val.is_a?(Integer) or (val < 0 or val > 4094) - fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval") - end - end - munge do |val| - val.to_i - end - end - - newparam(:trunks, :array_matching => :all) do - defaultto([]) - desc "Array of trunks id, for configure patch's ends as ports in trunk mode" - # - validate do |val| - val = Array(val) # prevents puppet conversion array of one Int to Int - for i in val - if !i.is_a?(Integer) or (i < 0 or i > 4094) - fail("Wrong 802.1q tag. Tag must be an integer in 2..4094 interval") - end - end - end - munge do |val| - Array(val) - end - end - - newparam(:vlan_splinters) do - newvalues(true, false) - defaultto(false) - desc "Enable vlan splinters (if it's a phys. interface)" - end - - autorequire(:l2_ovs_bridge) do - [self[:bridge]] - end -end diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_patch.rb b/deployment/puppet/l23network/lib/puppet/type/l2_patch.rb new file mode 100644 index 0000000000..b1bad632e8 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/type/l2_patch.rb @@ -0,0 +1,92 @@ +Puppet::Type.newtype(:l2_patch) do + @doc = "Manage a patchcords between two bridges" + desc @doc + + ensurable + + newparam(:name) # workarround for following error: + # Error 400 on SERVER: Could not render to pson: undefined method `merge' for []:Array + # http://projects.puppetlabs.com/issues/5220 + + newparam(:use_ovs) do + desc "Whether using OVS comandline tools" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + newproperty(:bridges, :array_matching => :all) do + desc "Array of bridges that will be connected" + newvalues(/^[a-z][0-9a-z\-\_]*[0-9a-z]$/) + end + + newproperty(:jacks, :array_matching => :all) do + desc "Patchcord jacks. Read-only. for debug purpose." + end + + newproperty(:cross) do + desc "Cross-system patch. Read-only. for debug purpose." + end + + newproperty(:mtu) do + desc "The Maximum Transmission Unit size to use for the interface" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + aliasvalue(0, :absent) + defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces) + validate do |value| # inherits it from a parent interface + # Intel 82598 & 82599 chips support MTUs up to 16110; is there any + # hardware in the wild that supports larger frames? + # + # It appears loopback devices routinely have large MTU values; Eg. 65536 + # + # Frames small than 64bytes are discarded as runts. Smallest valid MTU + # is 42 with a 802.1q header and 46 without. + min_mtu = 42 + max_mtu = 65536 + if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i)) + raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})" + end + end + munge do |val| + ((val == :absent) ? :absent : val.to_i) + end + end + + newproperty(:vendor_specific) do + desc "Hash of vendor specific properties" + #defaultto {} # no default value should be!!! + # provider-specific properties, can be validating only by provider. + validate do |val| + if ! val.is_a? Hash + fail("Vendor_specific should be a hash!") + end + end + + munge do |value| + L23network.reccursive_sanitize_hash(value) + end + + def should_to_s(value) + "\n#{value.to_yaml}\n" + end + + def is_to_s(value) + "\n#{value.to_yaml}\n" + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + autorequire(:l2_bridge) do + self[:bridges] + end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/l2_port.rb b/deployment/puppet/l23network/lib/puppet/type/l2_port.rb new file mode 100644 index 0000000000..800f70a9a0 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/type/l2_port.rb @@ -0,0 +1,222 @@ +# type for managing runtime NIC states. + +require 'yaml' +require 'puppetx/l23_utils' + +Puppet::Type.newtype(:l2_port) do + @doc = "Manage a network port abctraction." + desc @doc + + ensurable + + newparam(:interface) do + isnamevar + desc "The interface name" + # + validate do |val| + if not val =~ /^[a-z_][\w\.\-]*[0-9a-z]$/ + fail("Invalid interface name: '#{val}'") + end + end + end + + newparam(:use_ovs) do + desc "Whether using OVS comandline tools" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + #todo(sv): move to provider_specific hash + newproperty(:type) do + newvalues(:system, :internal, :tap, :gre, :ipsec_gre, :capwap, :patch, :null, :undef, :nil, :none) + aliasvalue(:none, :internal) + aliasvalue(:undef, :internal) + aliasvalue(:nil, :internal) + aliasvalue(:null, :internal) + #defaultto :internal + desc "Port type (for openvswitch only)" + end + + newproperty(:port_type) do + desc "Internal read-only property" + validate do |value| + raise ArgumentError, "You shouldn't change port_type -- it's a internal RO property!" + end + end + + newproperty(:onboot) do + desc "Whether to bring the interface up" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + newproperty(:bridge) do + desc "What bridge to use" + # + validate do |val| + if not val =~ /^[a-z][0-9a-z\-\_]*[0-9a-z]$/ + fail("Invalid bridge name: '#{val}'") + end + end + munge do |val| + if ['nil', 'undef', 'none', 'absent', ''].include?(val.to_s) + :absent + else + val + end + end + end + + newparam(:port_properties, :array_matching => :all) do + desc "Array of port properties" + defaultto [] + end + + newparam(:interface_properties, :array_matching => :all) do + desc "Array of port interface properties" + defaultto [] + end + + newproperty(:vlan_dev) do + desc "802.1q vlan base device" + end + + newproperty(:vlan_id) do + desc "802.1q vlan ID" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + aliasvalue(0, :absent) + defaultto :absent + validate do |value| + min_vid = 1 + max_vid = 4094 + if ! (value.to_s == 'absent' or (min_vid .. max_vid).include?(value.to_i)) + raise ArgumentError, "'#{value}' is not a valid 802.1q NALN_ID (must be a integer value in range (#{min_vid} .. #{max_vid})" + end + end + munge do |val| + ((val == :absent) ? :absent : val.to_i) + end + + end + + newproperty(:vlan_mode) do + desc "802.1q vlan interface naming model" + end + + newproperty(:bond_master) do + desc "Bond name, if interface is a part of bond" + newvalues(/^[a-z][\w\-]*$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + end + + newparam(:trunks, :array_matching => :all) do + desc "Array of trunks id, for configure patch's ends as ports in trunk mode" + end + + newproperty(:mtu) do + desc "The Maximum Transmission Unit size to use for the interface" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + aliasvalue(0, :absent) + defaultto :absent # MTU value should be undefined by default, because some network resources (bridges, subinterfaces) + validate do |value| # inherits it from a parent interface + # Intel 82598 & 82599 chips support MTUs up to 16110; is there any + # hardware in the wild that supports larger frames? + # + # It appears loopback devices routinely have large MTU values; Eg. 65536 + # + # Frames small than 64bytes are discarded as runts. Smallest valid MTU + # is 42 with a 802.1q header and 46 without. + min_mtu = 42 + max_mtu = 65536 + if ! (value.to_s == 'absent' or (min_mtu .. max_mtu).include?(value.to_i)) + raise ArgumentError, "'#{value}' is not a valid mtu (must be a positive integer in range (#{min_mtu} .. #{max_mtu})" + end + end + munge do |val| + ((val == :absent) ? :absent : val.to_i) + end + + end + + newproperty(:ethtool) do + desc "Hash of ethtool properties" + #defaultto {} + # provider-specific hash, validating only by type. + validate do |val| + if ! val.is_a? Hash + fail("Ethtool should be a hash!") + end + end + munge do |value| + L23network.reccursive_sanitize_hash(value) + end + + def should_to_s(value) + "\n#{value.to_yaml}\n" + end + + def is_to_s(value) + "\n#{value.to_yaml}\n" + end + + def insync?(value) + new_should = {} + (value.keys + should.keys).uniq.map{|k| new_should[k] = {}} + # debug("\nV: #{value.to_yaml}\n") + # debug("\nS: #{should.to_yaml}\n") + # debug("\nN: #{new_should.to_yaml}\n") + new_should.keys.map{|key| new_should[key] = value[key].merge should[key] } + #debug("\nZ: #{new_should.to_yaml}\n") + (L23network.reccursive_sanitize_hash(value) == L23network.reccursive_sanitize_hash(new_should)) + end + end + + newproperty(:vendor_specific) do + desc "Hash of vendor specific properties" + #defaultto {} # no default value should be!!! + # provider-specific properties, can be validating only by provider. + validate do |val| + if ! val.is_a? Hash + fail("Vendor_specific should be a hash!") + end + end + + munge do |value| + L23network.reccursive_sanitize_hash(value) + end + + def should_to_s(value) + "\n#{value.to_yaml}\n" + end + + def is_to_s(value) + "\n#{value.to_yaml}\n" + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + autorequire(:l2_bridge) do + [self[:bridge]] + end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/l3_if_downup.rb b/deployment/puppet/l23network/lib/puppet/type/l3_if_downup.rb index ad991cce6a..749d224614 100644 --- a/deployment/puppet/l23network/lib/puppet/type/l3_if_downup.rb +++ b/deployment/puppet/l23network/lib/puppet/type/l3_if_downup.rb @@ -82,7 +82,8 @@ Puppet::Type.newtype(:l3_if_downup) do provider.restart() end - # autorequire(:l2_ovs_bridge) do + # autorequire(:l2_bridge) do # [self[:bridge]] # end end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppet/type/l3_ifconfig.rb b/deployment/puppet/l23network/lib/puppet/type/l3_ifconfig.rb new file mode 100644 index 0000000000..9f1a95ac5a --- /dev/null +++ b/deployment/puppet/l23network/lib/puppet/type/l3_ifconfig.rb @@ -0,0 +1,148 @@ +# type for managing runtime IP addresses and another L3 stuff. + +Puppet::Type.newtype(:l3_ifconfig) do + @doc = "Manage a network port abctraction." + desc @doc + + ensurable + + newparam(:interface) do + isnamevar + desc "The interface name" + # + validate do |val| + if not val =~ /^[a-z_][0-9a-z\.\-\_]*[0-9a-z]$/ + fail("Invalid interface name: '#{val}'") + end + end + end + + newparam(:use_ovs) do + desc "Whether using OVS comandline tools" + newvalues(:true, :yes, :on, :false, :no, :off) + aliasvalue(:yes, :true) + aliasvalue(:on, :true) + aliasvalue(:no, :false) + aliasvalue(:off, :false) + defaultto :true + end + + newproperty(:port_type) do + desc "Internal read-only property" + validate do |value| + raise ArgumentError, "You shouldn't change port_type -- it's a internal RO property!" + end + end + + newproperty(:ipaddr, :array_matching => :all) do + desc "List of IP address for this interface" + newvalues(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(\/(\d{1,2}))?$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + validate do |val| + return true if [:dhcp, :none, :undef, :nil, :absent].include?(val.downcase.to_sym) + val.strip! + raise ArgumentError, "Invalid IP address in list: '#{val}'" if \ + not val.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(\/(\d{1,2}))?$/) \ + or not ($1.to_i >= 0 and $1.to_i <= 255) \ + or not ($2.to_i >= 0 and $2.to_i <= 255) \ + or not ($3.to_i >= 0 and $3.to_i <= 255) \ + or not ($4.to_i >= 0 and $4.to_i <= 255) \ + or not ($6.to_i >= 0 and $6.to_i <= 32) + end + def should_to_s(value) + value.inspect + end + def is_to_s(value) + value.inspect + end + end + + newproperty(:gateway) do + desc "Default gateway" + newvalues(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + validate do |val| + if val != :absent + val.strip! + raise ArgumentError, "Invalid gateway: '#{val}'" if \ + not val.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) \ + or not ($1.to_i >= 0 and $1.to_i <= 255) \ + or not ($2.to_i >= 0 and $2.to_i <= 255) \ + or not ($3.to_i >= 0 and $3.to_i <= 255) \ + or not ($4.to_i >= 0 and $4.to_i <= 255) + end + end + end + newproperty(:gateway_metric) do + desc "Default gateway metric" + newvalues(/^\d+$/, :absent, :none, :undef, :nil) + aliasvalue(:none, :absent) + aliasvalue(:undef, :absent) + aliasvalue(:nil, :absent) + defaultto :absent + validate do |val| + min_metric = 0 + max_metric = 65535 + if ! (val.to_s == 'absent' or (min_metric .. max_metric).include?(val.to_i)) + raise ArgumentError, "'#{val}' is not a valid metric (must be a integer value in range (#{min_metric} .. #{max_metric})" + end + end + munge do |val| + if val == :absent + :absent + else + begin + val.to_i + rescue + :absent + end + end + end + end + + newproperty(:dhcp_hostname) do + desc "DHCP hostname" + end + + # newproperty(:onboot, :parent => Puppet::Property::Boolean) do + # desc "Whether to bring the interface up" + # defaultto :true + # end + + newproperty(:vendor_specific) do + desc "Hash of vendor specific properties" + #defaultto {} # no default value should be!!! + # provider-specific properties, can be validating only by provider. + validate do |val| + if ! val.is_a? Hash + fail("Vendor_specific should be a hash!") + end + end + + munge do |value| + L23network.reccursive_sanitize_hash(value) + end + + def should_to_s(value) + "\n#{value.to_yaml}\n" + end + + def is_to_s(value) + "\n#{value.to_yaml}\n" + end + + def insync?(value) + should_to_s(value) == should_to_s(should) + end + end + + autorequire(:l2_port) do + [self[:interface]] + end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppetx/l23_ethtool_name_commands_mapping.rb b/deployment/puppet/l23network/lib/puppetx/l23_ethtool_name_commands_mapping.rb new file mode 100644 index 0000000000..137682341b --- /dev/null +++ b/deployment/puppet/l23network/lib/puppetx/l23_ethtool_name_commands_mapping.rb @@ -0,0 +1,42 @@ +module L23network + + def self.ethtool_name_commands_mapping() + { + 'offload' => { + '__section_key_set__' => '-K', + '__section_key_get__' => '-k', + 'rx-checksumming' => 'rx', + 'tx-checksumming' => 'tx', + 'scatter-gather' => 'sg', + 'tcp-segmentation-offload' => 'tso', + 'udp-fragmentation-offload' => 'ufo', + 'generic-segmentation-offload' => 'gso', + 'generic-receive-offload' => 'gro', + 'large-receive-offload' => 'lro', + 'rx-vlan-offload' => 'rxvlan', + 'tx-vlan-offload' => 'txvlan', + 'ntuple-filters' => 'ntuple', + 'receive-hashing' => 'rxhash', + 'rx-fcs' => 'rx-fcs', + 'rx-all' => 'rx-all', + 'highdma' => 'highdma', + 'rx-vlan-filter' => 'rx-vlan-filter', + 'fcoe-mtu' => 'fcoe-mtu', + 'l2-fwd-offload' => 'l2-fwd-offload', + 'loopback' => 'loopback', + 'tx-nocache-copy' => 'tx-nocache-copy', + 'tx-gso-robust' => 'tx-gso-robust', + 'tx-fcoe-segmentation' => 'tx-fcoe-segmentation', + 'tx-gre-segmentation' => 'tx-gre-segmentation', + 'tx-ipip-segmentation' => 'tx-ipip-segmentation', + 'tx-sit-segmentation' => 'tx-sit-segmentation', + 'tx-udp_tnl-segmentation' => 'tx-udp_tnl-segmentation', + 'tx-mpls-segmentation' => 'tx-mpls-segmentation', + 'tx-vlan-stag-hw-insert' => 'tx-vlan-stag-hw-insert', + 'rx-vlan-stag-hw-parse' => 'rx-vlan-stag-hw-parse', + 'rx-vlan-stag-filter' => 'rx-vlan-stag-filter', + } + } + end + +end \ No newline at end of file diff --git a/deployment/puppet/l23network/lib/puppetx/l23_utils.rb b/deployment/puppet/l23network/lib/puppetx/l23_utils.rb new file mode 100644 index 0000000000..e8bdbd93c7 --- /dev/null +++ b/deployment/puppet/l23network/lib/puppetx/l23_utils.rb @@ -0,0 +1,101 @@ +module L23network + def self.reccursive_sanitize_hash(data) + if data.is_a? Hash + new_data = {} + data.each do |key, value| + new_data.store(reccursive_sanitize_hash(key), reccursive_sanitize_hash(value)) + end + new_data + elsif data.is_a? Array + data.map do |element| + reccursive_sanitize_hash(element) + end + elsif ['true', 'on', 'yes'].include? data.to_s.downcase + true + elsif ['false', 'off', 'no'].include? data.to_s.downcase + false + elsif data.nil? + nil + else + data.to_s + end + end + + def self.get_patch_name(bridges) + # bridges should be an array of two string + "patch__#{bridges.map{|s| s.to_s}.sort.join('--')}" + end + + def self.ovs_jack_name_len + 13 + end + + def self.get_ovs_jack_name(bridge) + # bridges should be an array of two string + tail = bridge[0..ovs_jack_name_len-1] + "p_#{tail}" + end + + def self.lnx_jack_name_len + 11 + end + + def self.get_lnx_jack_name(bridge, num=0) + # bridges should be an array of two string + tail = bridge[0..lnx_jack_name_len-1] + "p_#{tail}-#{num}" + end + + def self.get_pair_of_jack_names(bridges) + if bridges.is_a? String + j1 = get_lnx_jack_name(bridges,0) + j2 = get_lnx_jack_name(bridges,1) + elsif bridges.is_a? Array and bridges.length==1 + j1 = get_lnx_jack_name(bridges[0],0) + j2 = get_lnx_jack_name(bridges[0],1) + else + j1 = get_lnx_jack_name(bridges[0],0) + j2 = get_lnx_jack_name(bridges[1],1) + end + return [j1, j2] + end + +# def self.reccursive_merge_hash(a,b) +# rv = {} + +# a.keys.each do |key| +# if data.is_a? Hash +# new_data = {} +# data.each do |key, value| +# new_data.store(reccursive_sanitize_hash(key), reccursive_sanitize_hash(value)) +# end +# new_data +# else +# data.to_s +# end +# end + +# if data.is_a? Hash +# new_data = {} +# data.each do |key, value| +# new_data.store(reccursive_sanitize_hash(key), reccursive_sanitize_hash(value)) +# end +# new_data +# elsif data.is_a? Array +# data.map do |element| +# reccursive_sanitize_hash(element) +# end +# elsif ['true', 'on', 'yes'].include? data.to_s.downcase +# true +# elsif ['false', 'off', 'no'].include? data.to_s.downcase +# false +# elsif data.nil? +# nil +# else +# data.to_s +# end + +# return rv +# end +end +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_lnx.pp b/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_lnx.pp index 173bbccac2..08ebfafe74 100644 --- a/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_lnx.pp +++ b/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_lnx.pp @@ -1,3 +1,4 @@ +# xxx class l23network::examples::adv_net_config__bond_lnx ( $fuel_settings, ) { diff --git a/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_ovs.pp b/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_ovs.pp index b07791ba07..90fc1afe4d 100644 --- a/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_ovs.pp +++ b/deployment/puppet/l23network/manifests/examples/adv_net_config__bond_ovs.pp @@ -1,3 +1,4 @@ +# xxx class l23network::examples::adv_net_config__bond_ovs ( $fuel_settings, ) { diff --git a/deployment/puppet/l23network/manifests/examples/bond_lnx.pp b/deployment/puppet/l23network/manifests/examples/bond_lnx.pp index bf5736cc30..cb5018a3ba 100644 --- a/deployment/puppet/l23network/manifests/examples/bond_lnx.pp +++ b/deployment/puppet/l23network/manifests/examples/bond_lnx.pp @@ -1,3 +1,4 @@ +# xxx class l23network::examples::bond_lnx ( $bond = $name, $interfaces = ['eth4','eth5'], diff --git a/deployment/puppet/l23network/manifests/examples/bond_lnx_old_style.pp b/deployment/puppet/l23network/manifests/examples/bond_lnx_old_style.pp index eb1b950da6..c13908d042 100644 --- a/deployment/puppet/l23network/manifests/examples/bond_lnx_old_style.pp +++ b/deployment/puppet/l23network/manifests/examples/bond_lnx_old_style.pp @@ -1,3 +1,4 @@ +# xxx class l23network::examples::bond_lnx_old_style ( $bond = $name, $interfaces = ['eth4','eth5'], @@ -8,10 +9,10 @@ class l23network::examples::bond_lnx_old_style ( $bond_lacp_rate = 1, ) { l23network::l3::ifconfig {$bond: - ipaddr => $ipaddr, - bond_mode => $bond_mode, - bond_miimon => $bond_miimon, - bond_lacp_rate => $bond_lacp_rate, + ipaddr => $ipaddr, + bond_mode => $bond_mode, + bond_miimon => $bond_miimon, + bond_lacp_rate => $bond_lacp_rate, } -> l23network::l3::ifconfig {$interfaces[0]: ipaddr=>'none', bond_master=>$bond} -> l23network::l3::ifconfig {$interfaces[1]: ipaddr=>'none', bond_master=>$bond} diff --git a/deployment/puppet/l23network/manifests/hosts_file.pp b/deployment/puppet/l23network/manifests/hosts_file.pp index 2295e3f9a4..fc8a9adb3d 100644 --- a/deployment/puppet/l23network/manifests/hosts_file.pp +++ b/deployment/puppet/l23network/manifests/hosts_file.pp @@ -1,6 +1,8 @@ +# manage /etc/hosts +# class l23network::hosts_file ( $nodes, - $hosts_file = "/etc/hosts" + $hosts_file = '/etc/hosts' ) { #Move original hosts file diff --git a/deployment/puppet/l23network/manifests/init.pp b/deployment/puppet/l23network/manifests/init.pp index 07e2c86a4b..2eb98eb792 100644 --- a/deployment/puppet/l23network/manifests/init.pp +++ b/deployment/puppet/l23network/manifests/init.pp @@ -4,13 +4,56 @@ # Requirements, packages and services. # class l23network ( - $use_ovs = true, - $use_lnxbr = true, + $use_ovs = true, + $use_lnx = true, + $install_ovs = $use_ovs, + $install_brtool = $use_lnx, + $install_ethtool = $use_lnx, + $install_bondtool = $use_lnx, + $install_vlantool = $use_lnx, ){ - class {'l23network::l2': - use_ovs => $use_ovs, - use_lnxbr => $use_lnxbr, + + include ::l23network::params + + class { 'l23network::l2': + use_ovs => $use_ovs, + use_lnx => $use_lnx, + install_ovs => $install_ovs, + install_brtool => $install_brtool, + install_ethtool => $install_ethtool, + install_bondtool => $install_bondtool, + install_vlantool => $install_vlantool, } + + if $::l23network::params::interfaces_file { + if ! defined(File["${::l23network::params::interfaces_file}"]) { + file {"${::l23network::params::interfaces_file}": + ensure => present, + content => template('l23network/interfaces.erb'), + } + } + File<| title == "${::l23network::params::interfaces_file}" |> -> File<| title == "${::l23network::params::interfaces_dir}" |> + } + + if ! defined(File["${::l23network::params::interfaces_dir}"]) { + file {"${::l23network::params::interfaces_dir}": + ensure => directory, + owner => 'root', + mode => '0755', + } -> Anchor['l23network::init'] + } + Class['l23network::l2'] -> File<| title == "${::l23network::params::interfaces_dir}" |> + Class['l23network::l2'] -> File<| title == "${::l23network::params::interfaces_file}" |> + + # Centos interface up-n-down scripts + if $::osfamily =~ /(?i)redhat/ { + class{'::l23network::l2::centos_upndown_scripts': } -> Anchor['l23network::init'] + Anchor <| title == 'l23network::l2::centos_upndown_scripts' |> -> Anchor['l23network::init'] + } + + Anchor['l23network::l2::init'] -> Anchor['l23network::init'] + anchor { 'l23network::init': } + } # ### diff --git a/deployment/puppet/l23network/manifests/l2.pp b/deployment/puppet/l23network/manifests/l2.pp index 55af538fc9..4877797e56 100644 --- a/deployment/puppet/l23network/manifests/l2.pp +++ b/deployment/puppet/l23network/manifests/l2.pp @@ -4,54 +4,88 @@ # Requirements, packages and services. # class l23network::l2 ( - $use_ovs = true, - $use_lnxbr = true, + $use_ovs = true, + $use_lnx = true, + $install_ovs = $use_ovs, + $install_brtool = $use_lnx, + $install_ethtool = $use_lnx, + $install_bondtool = $use_lnx, + $install_vlantool = $use_lnx, + $ovs_modname = 'openvswitch' ){ include ::l23network::params if $use_ovs { - if $::l23network::params::ovs_datapath_package_name { - package { 'openvswitch-datapath': - name => $::l23network::params::ovs_datapath_package_name + $ovs_mod_ensure = present + if $install_ovs { + if $::l23network::params::ovs_datapath_package_name { + package { 'openvswitch-datapath': + name => $::l23network::params::ovs_datapath_package_name + } + } + package { 'openvswitch-common': + name => $::l23network::params::ovs_common_package_name } - } - package { 'openvswitch-common': - name => $::l23network::params::ovs_common_package_name - } - Package<| title=='openvswitch-datapath' |> -> Package['openvswitch-common'] - Package['openvswitch-common'] ~> Service['openvswitch-service'] - service {'openvswitch-service': - ensure => running, - name => $::l23network::params::ovs_service_name, - enable => true, - hasstatus => true, - status => $::l23network::params::ovs_status_cmd, - } - Service['openvswitch-service'] -> L23network::L3::Ifconfig<||> - if !defined(Service['openvswitch-service']) { - notify{ "Module ${module_name} cannot notify service openvswitch-service on packages update": } + Package<| title=='openvswitch-datapath' |> -> Package['openvswitch-common'] + Package['openvswitch-common'] ~> Service['openvswitch-service'] } + $ovs_service_ensure = 'running' + } else { + $ovs_mod_ensure = absent + $ovs_service_ensure = 'stopped' + } + service {'openvswitch-service': + ensure => $ovs_service_ensure, + name => $::l23network::params::ovs_service_name, + enable => $ovs_service_ensure == 'running', + hasstatus => true, + } + Service['openvswitch-service'] -> Anchor['l23network::l2::init'] + + @k_mod{$ovs_modname: + ensure => $ovs_mod_ensure } - if $::osfamily =~ /(?i)debian/ { - if !defined(Package["$l23network::params::lnx_bond_tools"]) { - package {"$l23network::params::lnx_bond_tools": } - } + if $use_lnx { + $mod_8021q_ensure = present + $mod_bonding_ensure = present + $mod_bridge_ensure = present + } else { + $mod_8021q_ensure = absent + $mod_bonding_ensure = absent + $mod_bridge_ensure = absent } - if !defined(Package["$l23network::params::lnx_vlan_tools"]) { - package {"$l23network::params::lnx_vlan_tools": } + if $install_vlantool and $::l23network::params::lnx_vlan_tools { + ensure_packages($::l23network::params::lnx_vlan_tools) + Package[$::l23network::params::lnx_vlan_tools] -> Anchor['l23network::l2::init'] + } + @k_mod{'8021q': + ensure => $mod_8021q_ensure } - if !defined(Package["$l23network::params::lnx_ethernet_tools"]) { - package {"$l23network::params::lnx_ethernet_tools": } + if $install_bondtool and $::l23network::params::lnx_bond_tools { + ensure_packages($::l23network::params::lnx_bond_tools) + Package[$::l23network::params::lnx_bond_tools] -> Anchor['l23network::l2::init'] + } + @k_mod{'bonding': + ensure => $mod_bonding_ensure } - if $::osfamily =~ /(?i)debian/ { - Package["$l23network::params::lnx_bond_tools"] -> L23network::L3::Ifconfig<||> + if $install_brtool and $::l23network::params::lnx_bridge_tools { + ensure_packages($::l23network::params::lnx_bridge_tools) + #Package[$::l23network::params::lnx_bridge_tools] -> Anchor['l23network::l2::init'] } - Package["$l23network::params::lnx_vlan_tools"] -> L23network::L3::Ifconfig<||> - Package["$l23network::params::lnx_ethernet_tools"] -> L23network::L3::Ifconfig<||> + @k_mod{'bridge': + ensure => $mod_bridge_ensure + } + + if $install_ethtool and $::l23network::params::lnx_ethernet_tools { + ensure_packages($::l23network::params::lnx_ethernet_tools) + Package[$::l23network::params::lnx_ethernet_tools] -> Anchor['l23network::l2::init'] + } + + anchor { 'l23network::l2::init': } } diff --git a/deployment/puppet/l23network/manifests/l2/bond.pp b/deployment/puppet/l23network/manifests/l2/bond.pp index aba5b7e07f..e4702cdb69 100644 --- a/deployment/puppet/l23network/manifests/l2/bond.pp +++ b/deployment/puppet/l23network/manifests/l2/bond.pp @@ -12,52 +12,148 @@ # # [*interfaces*] # List of interfaces in this bond. -# -# [*vlan_id*] -# Specify 802.1q tag for result bond. If need. -# -# [*trunks*] -# Specify array of 802.1q tags if need configure bond in trunk mode. -# Define trunks => [0] if you need pass only untagged traffic. -# -# [*skip_existing*] -# If this bond already exists it will be ignored without any errors. -# Must be true or false. -# + define l23network::l2::bond ( - $bridge, - $interfaces = undef, - $ports = undef, # deprecated, must be used interfaces - $bond = $name, - $properties = [], - $vlan_id = 0, - $trunks = [], - $provider = 'ovs', - $ensure = present, - $skip_existing = false + $ensure = present, + $bond = $name, + $use_ovs = $::l23network::use_ovs, + $interfaces = undef, + $bridge = undef, + $mtu = undef, + $onboot = undef, +# $ethtool = undef, + $bond_properties = undef, # bond configuration options + $interface_properties = undef, # configuration options for included interfaces (mtu, ethtool, etc...) + $vendor_specific = undef, + $monolith_bond_providers = undef, + $provider = undef, + # deprecated parameters, in the future ones will be moved to the vendor_specific hash +# $skip_existing = undef, ) { - if ! $::l23network::l2::use_ovs { - fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.') + include ::stdlib + include ::l23network::params + + $actual_monolith_bond_providers = $monolith_bond_providers ? { + undef => $l23network::params::monolith_bond_providers, + default => $monolith_bond_providers, } + $bond_modes = [ + 'balance-rr', + 'active-backup', + 'balance-xor', + 'broadcast', + '802.3ad', + 'balance-tlb', + 'balance-alb' + ] + + $lacp_rates = [ + 'slow', + 'fast' + ] + + # calculate string representation for bond_mode + if ! $bond_properties[mode] { + # default value by design https://www.kernel.org/doc/Documentation/networking/bonding.txt + $bond_mode = $bond_modes[0] + } elsif is_integer($bond_properties[mode]) and $bond_properties[mode] < size($bond_modes) { + $bond_mode = $bond_modes[$bond_properties[mode]] + } else { + $bond_mode = $bond_properties[mode] + } + + # calculate string representation for lacp_rate + if ! $bond_properties[lacp_rate] { + # default value by design https://www.kernel.org/doc/Documentation/networking/bonding.txt + $lacp_rate = $lacp_rates[0] + } elsif is_integer($bond_properties[lacp_rate]) and $bond_properties[lacp_rate] < size($lacp_rates) { + $lacp_rate = $lacp_rates[$bond_properties[lacp_rate]] + } else { + $lacp_rate = $bond_properties[lacp_rate] + } + + # calculate default miimon + if is_integer($bond_properties[miimon]) and $bond_properties[miimon] >= 0 { + $miimon = $bond_properties[miimon] + } else { + # recommended default value https://www.kernel.org/doc/Documentation/networking/bonding.txt + $miimon = 100 + } + + # default bond properties + $default_bond_properties = { + mode => $bond_mode, + miimon => $miimon, + lacp_rate => $lacp_rate, + } + + $real_bond_properties = merge($bond_properties, $default_bond_properties) + if $interfaces { - $r_interfaces = $interfaces - } elsif $ports { - $r_interfaces = $ports - } else { - fail("You must specify 'interfaces' property for this bond.") + validate_array($interfaces) } - if ! defined (L2_ovs_bond["$bond"]) { - l2_ovs_bond { "$bond" : - ensure => $ensure, - interfaces => $r_interfaces, - bridge => $bridge, - vlan_id => $vlan_id, - trunks => $trunks, - properties => $properties, - skip_existing => $skip_existing, - } - Service<| title == 'openvswitch-service' |> -> L2_ovs_bond["$bond"] + # Use $monolith_bond_providers list for prevent creating ports for monolith bonds + $actual_provider_for_bond_interface = $provider ? { + undef => default_provider_for('L2_port'), + default => $provider } + $eee = default_provider_for('L2_port') + + if ! member($actual_monolith_bond_providers, $actual_provider_for_bond_interface) { + l23network::l2::bond_interface{ $interfaces: + bond => $bond, + mtu => $mtu, + interface_properties => $interface_properties, + ensure => $ensure, + provider => $actual_provider_for_bond_interface + } + } + + if ! defined(L2_bond[$bond]) { + if $provider { + $config_provider = "${provider}_${::l23_os}" + } else { + $config_provider = undef + } + + if ! defined(L23_stored_config[$bond]) { + l23_stored_config { $bond: } + } + L23_stored_config <| title == $bond |> { + ensure => $ensure, + if_type => 'bond', + bridge => $bridge, + mtu => $mtu, + onboot => $onboot, + bond_mode => $real_bond_properties[mode], + bond_master => undef, + bond_slaves => $interfaces, + bond_miimon => $real_bond_properties[miimon], + bond_lacp_rate => $real_bond_properties[lacp_rate], + vendor_specific => $vendor_specific, + provider => $config_provider + } + + l2_bond { $bond : + ensure => $ensure, + bridge => $bridge, + use_ovs => $use_ovs, + onboot => $onboot, + slaves => $interfaces, + mtu => $mtu, + interface_properties => $interface_properties, + bond_properties => $real_bond_properties, + vendor_specific => $vendor_specific, + provider => $provider + } + + # this need for creating L2_port resource by ifup, if it allowed by OS + L23_stored_config[$bond] -> L2_bond[$bond] + + K_mod<||> -> L2_bond<||> + + } + } diff --git a/deployment/puppet/l23network/manifests/l2/bond_interface.pp b/deployment/puppet/l23network/manifests/l2/bond_interface.pp new file mode 100644 index 0000000000..e506a08ee4 --- /dev/null +++ b/deployment/puppet/l23network/manifests/l2/bond_interface.pp @@ -0,0 +1,39 @@ +# +define l23network::l2::bond_interface ( + $bond, + $use_ovs = $::l23network::use_ovs, + $ensure = present, + $mtu = undef, + $interface_properties = {}, + $provider = undef, +) { + include ::l23network::params + include ::stdlib + + if ! defined(L23network::L2::Port[$name]) { + $additional_properties = { + use_ovs => $use_ovs, + mtu => is_integer($interface_properties[mtu]) ? {false=>$mtu, default=>$interface_properties[mtu]}, + master => $bond, + slave => true, + provider => $provider + } + + create_resources(l23network::l2::port, { + "${name}" => merge($interface_properties, $additional_properties) + }) + } else { + L23network::L2::Port<| title == $name |> { + use_ovs => $use_ovs, + master => $bond, + slave => true + } + } + if $provider == 'ovs' { + # OVS can't create bond if slave port don't exists. + L2_port[$name] -> L2_bond[$bond] + } else { + L2_bond[$bond] -> L2_port[$name] + } +} +### \ No newline at end of file diff --git a/deployment/puppet/l23network/manifests/l2/bridge.pp b/deployment/puppet/l23network/manifests/l2/bridge.pp index d84be4d28c..bace2be430 100644 --- a/deployment/puppet/l23network/manifests/l2/bridge.pp +++ b/deployment/puppet/l23network/manifests/l2/bridge.pp @@ -7,30 +7,58 @@ # [*name*] # Bridge name. # -# [*skip_existing*] -# If this bridge already exists it will be ignored without any errors. -# Must be true or false. -# # [*external_ids*] # See open vSwitch documentation. # http://openvswitch.org/cgi-bin/ovsman.cgi?page=utilities%2Fovs-vsctl.8 # define l23network::l2::bridge ( - $external_ids = "bridge-id=${name}", - $provider = 'ovs', - $ensure = present, - $skip_existing = false + $ensure = present, + $use_ovs = $::l23network::use_ovs, + $mtu = undef, + $stp = undef, + $bpdu_forward = true, +# $bridge_id = undef, # will be implemented later + $external_ids = { 'bridge-id' => "${name}" }, + $vendor_specific = undef, + $provider = undef, ) { - if ! $::l23network::l2::use_ovs { - fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.') - } - if ! defined (L2_ovs_bridge[$name]) { - l2_ovs_bridge {$name: - ensure => $ensure, - external_ids => $external_ids, - skip_existing=> $skip_existing, + include l23network::params + + if ! defined (L2_bridge[$name]) { + if $provider { + $config_provider = "${provider}_${::l23_os}" + } else { + $config_provider = undef } - Service<| title == 'openvswitch-service' |> -> L2_ovs_bridge[$name] + + if ! defined (L23_stored_config[$name]) { + l23_stored_config { $name: } + } + + L23_stored_config <| title == $name |> { + ensure => $ensure, + #bpdu_forward => $bpdu_forward, + if_type => 'bridge', + bridge_stp => $stp, + bridge_ports => ['none'], # this property will be fulled by l2_port + vendor_specific => $vendor_specific, + provider => $config_provider + } + + l2_bridge {$name: + ensure => $ensure, + use_ovs => $use_ovs, + external_ids => $external_ids, + stp => $stp, + #bpdu_forward => $bpdu_forward, + vendor_specific => $vendor_specific, + provider => $provider + } + + # this need for creating L2_bridge resource by ifup, if it allowed by OS + L23_stored_config[$name] -> L2_bridge[$name] + + K_mod<||> -> L2_bridge<||> } } diff --git a/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp b/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp index 1006c9ab24..9babb2f948 100644 --- a/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp +++ b/deployment/puppet/l23network/manifests/l2/centos_upndown_scripts.pp @@ -4,15 +4,13 @@ class l23network::l2::centos_upndown_scripts { ensure => present, owner => 'root', mode => '0755', - recurse => true, - content => template("l23network/centos_ifup-local.erb"), + content => template('l23network/centos_ifup-local.erb'), } -> file {'/sbin/ifdown-local': ensure => present, owner => 'root', mode => '0755', - recurse => true, - content => template("l23network/centos_ifdown-local.erb"), + content => template('l23network/centos_ifdown-local.erb'), } -> anchor { 'l23network::l2::centos_upndown_scripts': } } diff --git a/deployment/puppet/l23network/manifests/l2/patch.pp b/deployment/puppet/l23network/manifests/l2/patch.pp index abe8a316bf..d0ccfcadf6 100644 --- a/deployment/puppet/l23network/manifests/l2/patch.pp +++ b/deployment/puppet/l23network/manifests/l2/patch.pp @@ -9,45 +9,58 @@ # [*peers*] # Patch port names for both bridges. must be array of two strings. # -# [*vlan_ids*] -# Specify 802.1q tag for each end of patchcord. Must be array of 2 integers. -# Default [0,0] -- untagged -# -# [*trunks*] -# Specify array of 802.1q tags (identical for both ends) if need configure patch in trunk mode. -# Define trunks => [0] if you need pass only untagged traffic. -# by default -- undefined. -# -# [*skip_existing*] -# If this patch already exists it will be ignored without any errors. -# Must be true or false. -# define l23network::l2::patch ( $bridges, - $peers = [undef,undef], - $vlan_ids = [0, 0], - $trunks = [], - $provider = 'ovs', - $ensure = present, - $skip_existing = false + $use_ovs = $::l23network::use_ovs, + $ensure = present, + $mtu = undef, + $vendor_specific = undef, + $provider = undef, ) { - if ! $::l23network::l2::use_ovs { - fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.') - } + + #$provider_1 = get_provider_for('L2_bridge', bridges[0]) # this didn't work, because parser functions + #$provider_2 = get_provider_for('L2_bridge', bridges[1]) # executed before resources prefetch # Architecture limitation. # We can't create more one patch between same bridges. - #$patch = "${bridges[0]}_${vlan_ids[0]}--${bridges[1]}_${vlan_ids[1]}" - $patch = "${bridges[0]}--${bridges[1]}" + $patch_name = get_patch_name($bridges) + $patch_jacks_names = get_pair_of_jack_names($bridges) - if ! defined (L2_ovs_patch["$patch"]) { - l2_ovs_patch { "$patch" : - bridges => $bridges, - peers => $peers, - vlan_ids => $vlan_ids, - trunks => $trunks, - ensure => $ensure + if ! defined(L2_patch[$patch_name]) { + if $provider { + $config_provider = "${provider}_${::l23_os}" + } else { + $config_provider = undef } - Service<| title == 'openvswitch-service' |> -> L2_ovs_patch["$patch"] + + if ! defined(L23_stored_config[$patch_jacks_names[0]]) { + # we use only one (last) patch jack name here and later, + # because a both jacks for patch + # creates by one command. This command stores in one config file. + l23_stored_config { $patch_jacks_names[0]: } + } + L23_stored_config <| title == $patch_jacks_names[0] |> { + ensure => $ensure, + if_type => 'ethernet', + bridge => $bridges, + jacks => $patch_jacks_names, + mtu => $mtu, + onboot => true, + vendor_specific => $vendor_specific, + provider => $config_provider + } + L23_stored_config[$patch_jacks_names[0]] -> L2_patch[$patch_name] + + l2_patch{ $patch_name : + ensure => $ensure, + bridges => $bridges, + use_ovs => $use_ovs, + mtu => $mtu, + vendor_specific => $vendor_specific, + provider => $provider + } + + K_mod<||> -> L2_patch<||> } } +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/manifests/l2/port.pp b/deployment/puppet/l23network/manifests/l2/port.pp index 238fdb412d..feae4057fd 100644 --- a/deployment/puppet/l23network/manifests/l2/port.pp +++ b/deployment/puppet/l23network/manifests/l2/port.pp @@ -29,34 +29,113 @@ # Must be true or false. # define l23network::l2::port ( - $bridge, - $port = $name, - $type = '', - $port_properties = [], - $interface_properties = [], - $vlan_id = 0, - $trunks = [], - $vlan_splinters = false, - $provider = 'ovs', $ensure = present, - $skip_existing = false + $use_ovs = $::l23network::use_ovs, + $port = $name, + $bridge = undef, + $onboot = undef, + $vlan_id = undef, # actually only for OVS workflow + $vlan_dev = undef, + $mtu = undef, + $ethtool = undef, + $master = undef, # used for bonds automatically + $slave = undef, # used for bonds automatically +# $type = undef, # was '', + $vendor_specific = undef, + $provider = undef, + # deprecated parameters, in the future ones will be moved to the vendor_specific hash +# $skip_existing = undef, +# $port_properties = [], +# $interface_properties = [], +# $trunks = [], ) { - if ! $::l23network::l2::use_ovs { - fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.') + # Detect VLAN mode configuration + case $port { + /^vlan(\d+)/: { + $port_name = $port + $port_vlan_mode = 'vlan' + if $vlan_id { + $port_vlan_id = $vlan_id + } else { + $port_vlan_id = $1 + } + if $vlan_dev { + $port_vlan_dev = $vlan_dev + } else { + if $provider != 'ovs' { + fail("Can't configure vlan interface ${port} without definition vlandev=>ethXX.") + } + } + } + /^([\w\-]+\d+)\.(\d+)/: { + $port_vlan_mode = 'eth' + $port_vlan_id = $2 + $port_vlan_dev = $1 + $port_name = "${1}.${2}" + } + default: { + $port_vlan_mode = undef + $port_vlan_id = undef + $port_vlan_dev = undef + $port_name = $port + } } - if ! defined (L2_ovs_port[$port]) { - l2_ovs_port { $port : - ensure => $ensure, - bridge => $bridge, - type => $type, - vlan_id => $vlan_id, - trunks => $trunks, - vlan_splinters => $vlan_splinters, - port_properties => $port_properties, - interface_properties => $interface_properties, - skip_existing => $skip_existing + # # implicitly create bridge, if it given and not exists + # if $bridge { + # if !defined(L2_bridge[$bridge]) { + # l2_bridge { $bridge: } + # } + # # or do this from autorequire ?????? + # L2_bridge[$bridge] -> L2_port[$port_name] + # } + + if ! defined(L2_port[$port_name]) { + if $provider { + $config_provider = "${provider}_${::l23_os}" + } else { + $config_provider = undef } - Service<| title == 'openvswitch-service' |> -> L2_ovs_port[$port] + + if ! defined(L23_stored_config[$port_name]) { + l23_stored_config { $port_name: } + } + L23_stored_config <| title == $port_name |> { + ensure => $ensure, + if_type => 'ethernet', + bridge => $bridge, + vlan_id => $port_vlan_id, + vlan_dev => $port_vlan_dev, + vlan_mode => $port_vlan_mode, + bond_master => $master, + mtu => $mtu, + onboot => $onboot, + #ethtool => $ethtool, + vendor_specific => $vendor_specific, + provider => $config_provider + } + + l2_port { $port_name : + ensure => $ensure, + use_ovs => $use_ovs, + bridge => $bridge, + vlan_id => $port_vlan_id, + vlan_dev => $port_vlan_dev, + vlan_mode => $port_vlan_mode, + bond_master => $master, + mtu => $mtu, + onboot => $onboot, + #type => $type, + #trunks => $trunks, + ethtool => $ethtool, + vendor_specific => $vendor_specific, + provider => $provider + } + + # this need for creating L2_port resource by ifup, if it allowed by OS + L23_stored_config[$port_name] -> L2_port[$port_name] + + K_mod<||> -> L2_port<||> } } +# vim: set ts=2 sw=2 et : \ No newline at end of file diff --git a/deployment/puppet/l23network/manifests/l3/create_br_iface.pp b/deployment/puppet/l23network/manifests/l3/create_br_iface.pp deleted file mode 100644 index 0c5fae1a49..0000000000 --- a/deployment/puppet/l23network/manifests/l3/create_br_iface.pp +++ /dev/null @@ -1,123 +0,0 @@ -# == Define: l23network::l3::create_br_iface -# -# Create L2 ovs bridge, clean IPs from interface and add IP address to this -# bridge -# -# === Parameters -# -# [*bridge*] -# Bridge name -# -# [*interface*] -# Interface that will be added to the bridge. -# If you set the interface parameter as an array of interface names -# then Open vSwitch will create bond with given interfaces. -# In this case you must set ovs_bond_name and ovs_bond_properties parameters. -# -# [*ipaddr*] -# IP address for port in bridge. -# -# [*netmask*] -# Network mask. -# -# [*gateway*] -# You can specify default gateway IP address, or 'save' for save default route -# if it lies through this interface now. -# -# [*dns_nameservers*] -# Dns nameservers to use -# -# [*dns_domain*] -# Describe DNS domain -# -# [*dns_search*] -# DNS domain to search for -# -# [*save_default_gateway*] -# If current network configuration contains a gateway parameter -# this option will try to save it. -# DEPRECATED!!! use gateway=>'save' -# -define l23network::l3::create_br_iface ( - $interface, - $ipaddr, - $bridge = $name, - $netmask = '255.255.255.0', - $gateway = undef, - $se = true, - $external_ids = '', - $dns_nameservers = undef, - $dns_domain = undef, - $dns_search = undef, - $save_default_gateway = false, - $lnx_interface_vlandev = undef, - $lnx_interface_bond_mode = undef, - $lnx_interface_bond_miimon = 100, - $lnx_interface_bond_lacp_rate = 1, - $ovs_bond_name = 'bond0', - $ovs_bond_properties = [], - $interface_order_prefix = false, -){ - if ! $::l23network::l2::use_ovs { - fail('You must enable Open vSwitch by setting the l23network::l2::use_ovs to true.') - } - - if ! $external_ids { - $ext_ids = "bridge-id=${bridge}" - } - # - if $gateway { - $gateway_ip_address_for_newly_created_interface = $gateway - } elsif ($save_default_gateway or $gateway == 'save') and $::l3_default_route_interface == $interface { - $gateway_ip_address_for_newly_created_interface = 'save' - } else { - $gateway_ip_address_for_newly_created_interface = undef - } - # Build ovs bridge - l23network::l2::bridge {"$bridge": - skip_existing => $se, - external_ids => $ext_ids, - } - if is_array($interface) { - # Build an ovs bridge containing ovs bond with given interfaces - l23network::l2::bond {"$ovs_bond_name": - bridge => $bridge, - ports => $interface, - properties => $ovs_bond_properties, - skip_existing => $se, - require => L23network::L2::Bridge["$bridge"] - } -> - l23network::l3::ifconfig {$interface: # no quotes here, $interface _may_be_ array!!! - ipaddr => 'none', - ifname_order_prefix => '0', - require => L23network::L2::Bond["$ovs_bond_name"], - before => L23network::L3::Ifconfig["$bridge"] - } - } else { - # Build an ovs bridge containing one interface - l23network::l2::port {$interface: - bridge => $bridge, - skip_existing => $se, - require => L23network::L2::Bridge["$bridge"] - } -> - l23network::l3::ifconfig {"${interface}": - ipaddr => 'none', - vlandev => $lnx_interface_vlandev, - bond_mode => $lnx_interface_bond_mode, - bond_miimon => $lnx_interface_bond_miimon, - bond_lacp_rate => $lnx_interface_bond_lacp_rate, - ifname_order_prefix => $interface_order_prefix, - require => L23network::L2::Port["${interface}"], - before => L23network::L3::Ifconfig["${bridge}"] - } - } - l23network::l3::ifconfig {"${bridge}": - ipaddr => $ipaddr, - netmask => $netmask, - gateway => $gateway_ip_address_for_newly_created_interface, - dns_nameservers => $dns_nameservers, - dns_domain => $dns_domain, - dns_search => $dns_search, - ifname_order_prefix => 'ovs', - } -} diff --git a/deployment/puppet/l23network/manifests/l3/ifconfig.pp b/deployment/puppet/l23network/manifests/l3/ifconfig.pp index e5da4a7eb3..d474e81d3a 100644 --- a/deployment/puppet/l23network/manifests/l3/ifconfig.pp +++ b/deployment/puppet/l23network/manifests/l3/ifconfig.pp @@ -16,47 +16,21 @@ # [*netmask*] # Specify network mask. Default is '255.255.255.0'. # -# [*macaddr*] -# Specify macaddr if need change. -# -# [*vlandev*] -# If you configure 802.1q vlan interface with name like 'vlanXXX' -# you must specify a parent interface in this option -# -# [*bond_master*] -# This parameter sets the bond_master interface and says that this interface -# is a slave for bondX interface. -# -# [*bond_properties*] -# This parameter specifies a bond properties for interfaces like bondNN. -# It's a property hash, that should contains native linux bonding options, ex: -# bond_properties => { -# mode => 1, # mode is a obligatory option -# miimon => 100, -# .... -# } -# -# bond_properties will be ignored for bond-slave interfaces -# Full set of properties we can see here: https://www.kernel.org/doc/Documentation/networking/bonding.txt -# -# [*ifname_order_prefix*] -# Sets the interface startup order -# # [*gateway*] # Specify default gateway if need. # You can specify IP address, or 'save' for save default route # if it lies through this interface now. # -# [*default_gateway*] -# Specify if this nic and gateway should become the default route. -# requires that gateway is also set. -# -# [*other_nets*] -# Optional. Defines additional networks that this inteface can reach in CIDR -# format. -# It will be used to add additional routes to this interface. -# other_nets => ['10.10.2.0/24', '10.10.4.0/24'] -# +## [*default_gateway*] +## Specify if this nic and gateway should become the default route. +## requires that gateway is also set. +## +## [*other_nets*] +## Optional. Defines additional networks that this inteface can reach in CIDR +## format. +## It will be used to add additional routes to this interface. +## other_nets => ['10.10.2.0/24', '10.10.4.0/24'] +## # [*dns_nameservers*] # Specify a pair of nameservers if need. Must be an array, for example: # nameservers => ['8.8.8.8', '8.8.4.4'] @@ -84,88 +58,35 @@ # [*check_by_ping_timeout*] # Timeout for check_by_ping # -# [*ethtool*] -# You can specify k/w hash with ethtool key/value pairs. -# If this hash not empty, this ethtool with this parameters will be executed -# at each boot -# -# If you configure 802.1q vlan interfaces then you must declare relationships -# between them in site.pp. -# Ex: L23network:L3:Ifconfig['eth2'] -> L23network:L3:Ifconfig['eth2.128'] -# + define l23network::l3::ifconfig ( - $ipaddr, + $ensure = present, $interface = $name, - $netmask = '255.255.255.0', + $ipaddr = undef, +# $netmask = '255.255.255.0', # I hardly want deprecate this address notation $gateway = undef, - $default_gateway = false, - $other_nets = undef, - $vlandev = undef, - $bond_master = undef, - $bond_properties = {}, - $bond_mode = undef, # deprecated, should be used $bond_properties hash - $bond_miimon = undef, # deprecated, should be used $bond_properties hash - $bond_lacp_rate = undef, # deprecated, should be used $bond_properties hash - $mtu = undef, - $macaddr = undef, - $ethtool = undef, + $gateway_metric = undef, +# $default_gateway = false, +# $other_nets = undef, $dns_nameservers = undef, $dns_search = undef, $dns_domain = undef, $dhcp_hostname = undef, - $dhcp_nowait = false, - $ifname_order_prefix = false, +# $dhcp_nowait = false, $check_by_ping = 'gateway', $check_by_ping_timeout = 30, #todo: label => "XXX", # -- "ip addr add..... label XXX" -){ + $vendor_specific = undef, + $provider = undef +) { include ::l23network::params - $bond_properties_defaults = { - mode => 0, - miimon => 100, - lacp_rate => 1, - } - - $bond_modes = [ - 'balance-rr', - 'active-backup', - 'balance-xor', - 'broadcast', - '802.3ad', - 'balance-tlb', - 'balance-alb' - ] - - if $bond_properties[mode] or $bond_mode { - $actual_bond_properties = get_hash_with_defaults_and_deprecations( - $bond_properties, - $bond_properties_defaults, - { - mode => $bond_mode, - miimon => $bond_miimon, - lacp_rate => $bond_lacp_rate, - } - ) - } else { - $actual_bond_properties = { mode => undef, } - } - - if $macaddr and $macaddr !~ /^([0-9a-fA-F]{2}\:){5}[0-9a-fA-F]{2}$/ { - fail("Invalid MAC address '${macaddr}' for interface '${interface}'") - } - - if $mtu and !is_integer("${mtu}") { # is_integer() fails if integer given :) - fail("Invalid MTU '${mtu}' for interface '${interface}'") - } - # setup configure method for inteface - if $bond_master { - $method = 'bondslave' - } elsif is_array($ipaddr) { + if is_array($ipaddr) { # getting array of IP addresses for one interface $method = 'static' check_cidrs($ipaddr) + $ipaddr_list = $ipaddr $effective_ipaddr = cidr_to_ipaddr($ipaddr[0]) $effective_netmask = cidr_to_netmask($ipaddr[0]) $ipaddr_aliases = array_part($ipaddr,1,0) @@ -177,11 +98,13 @@ define l23network::l3::ifconfig ( $method = 'dhcp' $effective_ipaddr = 'dhcp' $effective_netmask = undef + $ipaddr_list = ['dhcp'] } 'none': { $method = 'manual' $effective_ipaddr = 'none' $effective_netmask = undef + $ipaddr_list = ['none'] } default: { $method = 'static' @@ -189,39 +112,18 @@ define l23network::l3::ifconfig ( # ipaddr can be cidr-notated $effective_ipaddr = cidr_to_ipaddr($ipaddr) $effective_netmask = cidr_to_netmask($ipaddr) + $ipaddr_list = [$ipaddr] } else { # or classic pair of ipaddr+netmask $effective_ipaddr = $ipaddr $effective_netmask = $netmask + $cidr_notated_effective_netmask = netmask_to_cidr($netmask) + $ipaddr_list = ["${ipaddr}/${cidr_notated_effective_netmask}"] } } } } else { - fail("Ipaddr must be a string or array of strings") - } - - # OS dependent constants and packages - case $::osfamily { - /(?i)debian/: { - $if_files_dir = '/etc/network/interfaces.d' - $interfaces = '/etc/network/interfaces' - } - /(?i)redhat/: { - $if_files_dir = '/etc/sysconfig/network-scripts' - $interfaces = false - if ! defined(Class[L23network::L2::Centos_upndown_scripts]) { - if defined(Stage[netconfig]) { - class{'l23network::l2::centos_upndown_scripts': stage=>'netconfig' } - } else { - class{'l23network::l2::centos_upndown_scripts': } - } - } - Anchor <| title == 'l23network::l2::centos_upndown_scripts' |> - -> L23network::L3::Ifconfig <| interface == "${interface}" |> - } - default: { - fail("Unsupported OS: ${::osfamily}/${::operatingsystem}") - } + fail('Ipaddr must be a single IPaddr or list of IPaddrs in CIDR notation.') } # DNS nameservers, search and domain options @@ -235,7 +137,7 @@ define l23network::l3::ifconfig ( if $dns_search_list { $dns_search_string = join($dns_search_list, ' ') } else { - fail("dns_search option must be array or string") + fail('dns_search option must be array or string') } } if $dns_domain { @@ -243,148 +145,96 @@ define l23network::l3::ifconfig ( if $dns_domain_list { $dns_domain_string = $dns_domain_list[0] } else { - fail("dns_domain option must be array or string") + fail('dns_domain option must be array or string') } } - # Detect VLAN and bond mode configuration - case $interface { - /^vlan(\d+)/: { - $vlan_mode = 'vlan' - $vlan_id = $1 - if $vlandev { - $vlan_dev = $vlandev - } else { - fail("Can't configure vlan interface ${interface} without definition (ex: vlandev=>ethXX).") - } - } - /^(eth\d+)\.(\d+)/: { # TODO: bond0.123 -- also vlan - $vlan_mode = 'eth' - $vlan_id = $2 - $vlan_dev = $1 - } - /^(bond\d+)/: { - if ! $actual_bond_properties[mode] { - fail('To configure the interface bonding you should the mode properties for bond is required and must be between 0..6.') - } - if $actual_bond_properties[mode] <0 or $actual_bond_properties[mode] >6 { - fail("For interface bonding the bond mode should be between 0..6, not '${actual_bond_properties[mode]}'.") - } - $vlan_mode = undef - } - default: { - $vlan_mode = undef - } - } - - # Specify interface file name prefix - if $ifname_order_prefix { - $interface_file= "${if_files_dir}/ifcfg-${ifname_order_prefix}-${interface}" - } else { - $interface_file= "${if_files_dir}/ifcfg-${interface}" - } + # # Specify interface file name prefix + # if $ifname_order_prefix { + # $interface_file= "${::l23network::params::interfaces_dir}/ifcfg-${ifname_order_prefix}-${interface}" + # } else { + # $interface_file= "${::l23network::params::interfaces_dir}/ifcfg-${interface}" + # } + # File<| title == "${::l23network::params::interfaces_dir}" |> -> File<| title == "${interface_file}" |> if $method == 'static' { - if $gateway and $gateway != 'save' and $default_gateway { + if $gateway and $gateway != 'save' { $def_gateway = $gateway + } elsif $gateway == 'save' and $::l3_default_route and $::l3_default_route_interface == $interface { + $def_gateway = $::l3_default_route } else { - # recognizing default gateway - if $gateway == 'save' and $::l3_default_route and $::l3_default_route_interface == $interface { - $def_gateway = $::l3_default_route - } else { - $def_gateway = undef - } - } - if (($::osfamily == 'RedHat' or $::osfamily == 'Debian') and - $def_gateway and - !defined(L23network::L3::Defaultroute[$def_gateway]) - ) { - L3_if_downup[$interface] -> - l23network::l3::defaultroute { $def_gateway: } + $def_gateway = undef } + # # todo: move routing to separated resource with his own provider + # if ($def_gateway and !defined(L23network::L3::Defaultroute[$def_gateway])) { + # Anchor['l23network::init'] -> + # L3_ifconfig[$interface] + # -> + # l23network::l3::defaultroute { $def_gateway: } + # } } else { $def_gateway = undef } - if $other_nets { - if $::osfamily =~ /(?i)redhat/ and $other_nets { - file {"${if_files_dir}/route-${interface}": - ensure => present, - owner => 'root', - mode => '0755', - recurse => true, - content => template("l23network/route_${::osfamily}.erb"), - } -> - File <| title == $interface_file |> - } - } + # todo: re-implement later + # if $::osfamily =~ /(?i)redhat/ and ($ipaddr_aliases or $ethtool_lines) { + # Anchor['l23network::init'] -> + # file {"${::l23network::params::interfaces_dir}/interface-up-script-${interface}": + # ensure => present, + # owner => 'root', + # mode => '0755', + # recurse => true, + # content => template("l23network/ipconfig_${::osfamily}_ifup-script.erb"), + # } -> + # file {"${::l23network::params::interfaces_dir}/interface-dn-script-${interface}": + # ensure => present, + # owner => 'root', + # mode => '0755', + # recurse => true, + # content => template("l23network/ipconfig_${::osfamily}_ifdn-script.erb"), + # } -> + # File <| title == $interface_file |> + # } - if $interfaces { - if ! defined(File["${interfaces}"]) { - file {"${interfaces}": - ensure => present, - content => template('l23network/interfaces.erb'), + if ! defined (L3_ifconfig[$interface]) { + if $provider { + $config_provider = "${provider}_${::l23_os}" + } else { + $config_provider = undef + } + + + if ! defined (L23_stored_config[$interface]) { + l23_stored_config { $interface: + provider => $config_provider } } - File<| title == "${interfaces}" |> -> File<| title == "${if_files_dir}" |> - } + L23_stored_config <| title == $interface |> { + method => $method, + ipaddr => $ipaddr_list[0], + gateway => $def_gateway, + gateway_metric => $gateway_metric, + vendor_specific => $vendor_specific, + #provider => $config_provider # do not enable, provider should be set while port define + } - if ! defined(File["${if_files_dir}"]) { - file {"${if_files_dir}": - ensure => directory, - owner => 'root', - mode => '0755', - recurse => true, + # configure runtime + l3_ifconfig { $interface : + ensure => $ensure, + ipaddr => $ipaddr_list, + gateway => $def_gateway, + gateway_metric => $gateway_metric, +## $default_gateway = false, +## $other_nets = undef, +# dns_nameservers => $dns_nameservers, +# dns_search => $dns_search_string, +# dns_domain => $dns_domain_string, +# dhcp_hostname => $dhcp_hostname, +# check_by_ping => $check_by_ping, +# check_by_ping_timeout => $check_by_ping_timeout, + vendor_specific => $vendor_specific, + provider => $provider # For L3 features provider independed from OVS } } - File<| title == "${if_files_dir}" |> -> File<| title == "${interface_file}" |> - if $ethtool { - $ethtool_lines=ethtool_convert_hash($ethtool) - } - - if $::osfamily =~ /(?i)redhat/ and ($ipaddr_aliases or $ethtool_lines) { - file {"${if_files_dir}/interface-up-script-${interface}": - ensure => present, - owner => 'root', - mode => '0755', - recurse => true, - content => template("l23network/ipconfig_${::osfamily}_ifup-script.erb"), - } -> - file {"${if_files_dir}/interface-dn-script-${interface}": - ensure => present, - owner => 'root', - mode => '0755', - recurse => true, - content => template("l23network/ipconfig_${::osfamily}_ifdn-script.erb"), - } -> - File <| title == $interface_file |> - } - - file {"${interface_file}": - ensure => present, - owner => 'root', - mode => '0644', - content => template("l23network/ipconfig_${::osfamily}_${method}.erb"), - } - - # bond master interface should be upped only after including at least one slave interface to one - if $interface =~ /^(bond\d+)/ { - $l3_if_downup__subscribe = undef - File["${interface_file}"] -> L3_if_downup["${interface}"] # do not remove!!! we using L3_if_downup["bondXX"] in advanced_netconfig - # todo(sv): filter and notify L3_if_downup["$interface"] if need. - # in Centos it works properly without it. - # May be because slaves of bond automaticaly ups master-bond - # L3_if_downup<| $bond_master == $interface |> ~> L3_if_downup["$interface"] - } else { - $l3_if_downup__subscribe = File["${interface_file}"] - } - notify {"ifconfig_${interface}": message=>"Interface:${interface} IP:${effective_ipaddr}/${effective_netmask}", withpath=>false} -> - l3_if_downup {"${interface}": - check_by_ping => $check_by_ping, - check_by_ping_timeout => $check_by_ping_timeout, - #require => File["$interface_file"], ## do not enable it!!! It affect requirements interface from interface in some cases. - subscribe => $l3_if_downup__subscribe, - refreshonly => true, - } } diff --git a/deployment/puppet/l23network/manifests/params.pp b/deployment/puppet/l23network/manifests/params.pp index 0c9a60997c..49d987ec1b 100644 --- a/deployment/puppet/l23network/manifests/params.pp +++ b/deployment/puppet/l23network/manifests/params.pp @@ -1,13 +1,19 @@ +# L23network OS-aware constants +# class l23network::params { $need_datapath_module = !str2bool($::kern_has_ovs_datapath) + $monolith_bond_providers = ['ovs'] case $::osfamily { /(?i)debian/: { + $interfaces_dir = '/etc/network/interfaces.d' + $interfaces_file = '/etc/network/interfaces' $ovs_service_name = 'openvswitch-switch' $ovs_status_cmd = '/etc/init.d/openvswitch-switch status' $lnx_vlan_tools = 'vlan' $lnx_bond_tools = 'ifenslave' $lnx_ethernet_tools = 'ethtool' + $lnx_bridge_tools = 'bridge-utils' $ovs_datapath_package_name = $need_datapath_module ? { true => 'openvswitch-datapath-lts-saucy-dkms', default => false @@ -15,14 +21,28 @@ class l23network::params { $ovs_common_package_name = 'openvswitch-switch' } /(?i)redhat/: { + $interfaces_dir = '/etc/sysconfig/network-scripts' + $interfaces_file = undef $ovs_service_name = 'openvswitch' $ovs_status_cmd = '/etc/init.d/openvswitch status' $lnx_vlan_tools = 'vconfig' $lnx_bond_tools = undef $lnx_ethernet_tools = 'ethtool' + $lnx_bridge_tools = 'bridge-utils' $ovs_datapath_package_name = 'kmod-openvswitch' $ovs_common_package_name = 'openvswitch' } + /(?i)darwin/: { + $interfaces_dir = '/tmp/1' + $interfaces_file = undef + $ovs_service_name = undef + $lnx_vlan_tools = undef + $lnx_bond_tools = undef + $lnx_ethernet_tools = undef + $lnx_bridge_tools = undef + $ovs_datapath_package_name = undef + $ovs_common_package_name = undef + } default: { fail("Unsupported OS: ${::osfamily}/${::operatingsystem}") } diff --git a/deployment/puppet/l23network/spec/classes/adv_net_config__bond_lnx__spec.rb b/deployment/puppet/l23network/spec/classes/adv_net_config__bond_lnx__spec.rb deleted file mode 100644 index a3be646dff..0000000000 --- a/deployment/puppet/l23network/spec/classes/adv_net_config__bond_lnx__spec.rb +++ /dev/null @@ -1,191 +0,0 @@ -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' -require 'yaml' - -#fuel_settings = YAML::load(<<-EOM) -c_ipaddr = '10.0.0.1' -c_masklen = '24' -c_mode = 2 -c_bondname = 'bond0' -c_interfaces = ['eth1','eth2'] -c_lacp_rate = 2 -c_miimon = 150 -bond_modes = [ - 'balance-rr', - 'active-backup', - 'balance-xor', - 'broadcast', - '802.3ad', - 'balance-tlb', - 'balance-alb' -] -fuel_settings = YAML::load(<<-EOM) -network_scheme: - version: '1.0' - provider: ovs - interfaces: - eth2: - L2: - vlan_splinters: 'off' - eth1: - L2: - vlan_splinters: 'off' - transformations: - - action: add-br - name: br-#{c_bondname} - - action: add-bond - bridge: br-#{c_bondname} - name: #{c_bondname} - provider: lnx - interfaces: - - eth1 - - eth2 - properties: - mode: #{c_mode} - miimon: #{c_miimon} - lacp_rate: #{c_lacp_rate} - endpoints: - #{c_bondname}: - IP: - - #{c_ipaddr}/#{c_masklen} - # eth1: - # IP: none - # eth2: - # IP: none -EOM - -#p fuel_settings - -# Ubintu, static -describe 'l23network::examples::adv_net_config__bond_lnx', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :fuel_settings => fuel_settings - } } - let(:facts) { { - :l3_fqdn_hostname => 'qweqweqwe', - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Should contains interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{c_bondname}") - should rv.with_content(/auto\s+#{c_bondname}/) - should rv.with_content(/iface\s+#{c_bondname}/) - should rv.with_content(/address\s+#{c_ipaddr}/) - should rv.with_content(/netmask\s+255.255.255.0/) - end - - it 'Should contains bond-specific parameters' do - rv = contain_file("#{interface_file_start}#{c_bondname}") - should rv.with_content(/slaves\s+none/) - should rv.with_content(/bond-mode\s+#{c_mode}/) - should rv.with_content(/bond-miimon\s+#{c_miimon}/) - should rv.with_content(/bond-lacp-rate\s+#{c_lacp_rate}/) - end - - it 'Should contains interface files for bond-slave interfaces' do - c_interfaces.each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/auto\s+#{iface}/) - should rv.with_content(/iface\s+#{iface}/) - should rv.with_content(/bond-master\s+#{c_bondname}/) - end - end - - it 'ALL: Should contains l23network::l2::bridge resource' do - rv = contain_l23network__l2__bridge("br-#{c_bondname}") - should rv.with( - 'ensure' => 'present' - ) - end - - it 'ALL: Should contains l23network::l2::port resource' do - rv = contain_l23network__l2__port("#{c_bondname}") - should rv.with( - 'bridge' => "br-#{c_bondname}", - 'ensure' => 'present' - ) - end - - it 'ALL: Should contains relationship beetwen l23network::l2::bridge and l23network::l2::port' do - bridge = contain_l23network__l2__bridge("br-#{c_bondname}") - should bridge.that_comes_before("L23network::L2::Port[#{c_bondname}]") - end - -end - -# Centos, static -describe 'l23network::examples::adv_net_config__bond_lnx', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :fuel_settings => fuel_settings - } } - let(:facts) { { - :l3_fqdn_hostname => 'qweqweqwe', - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - let(:bond_modes) { [ - 'balance-rr', - 'active-backup', - 'balance-xor', - 'broadcast', - '802.3ad', - 'balance-tlb', - 'balance-alb' - ] } - - it 'Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{c_bondname}") - should rv.with_content(/DEVICE=#{c_bondname}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - should rv.with_content(/IPADDR=#{c_ipaddr}/) - should rv.with_content(/NETMASK=255.255.255.0/) - end - - it 'Should contains interface files for bond-slave interfaces' do - c_interfaces.each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/DEVICE=#{iface}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - should rv.with_content(/MASTER=#{c_bondname}/) - should rv.with_content(/SLAVE=yes/) - end - end - - it 'Should contains Bonding-opts line' do - rv = contain_file("#{interface_file_start}#{c_bondname}") - should rv.with_content(/DEVICE=#{c_bondname}/) - should rv.with_content(/BONDING_OPTS="mode=/) - end - - it 'Should contains Bond mode' do - rv = contain_file("#{interface_file_start}#{c_bondname}") - should rv.with_content(/BONDING_OPTS.*mode=#{bond_modes[c_mode]}/) - end - - it 'Should contains miimon' do - rv = contain_file("#{interface_file_start}#{c_bondname}") - should rv.with_content(/BONDING_OPTS.*miimon=#{c_miimon}/) - end - - it 'Should contains lacp_rate' do - rv = contain_file("#{interface_file_start}#{c_bondname}") - should rv.with_content(/BONDING_OPTS.*lacp_rate=#{c_lacp_rate}/) - end -end diff --git a/deployment/puppet/l23network/spec/classes/adv_net_config__bond_ovs__spec.rb b/deployment/puppet/l23network/spec/classes/adv_net_config__bond_ovs__spec.rb deleted file mode 100644 index 40002c3f7f..0000000000 --- a/deployment/puppet/l23network/spec/classes/adv_net_config__bond_ovs__spec.rb +++ /dev/null @@ -1,117 +0,0 @@ -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' -require 'yaml' - -#fuel_settings = YAML::load(<<-EOM) -c_bondname = 'bond0' -c_interfaces = ['eth1','eth2'] -c_lacp_rate = 2 -c_miimon = 150 -fuel_settings = YAML::load(<<-EOM) -network_scheme: - version: '1.0' - provider: ovs - interfaces: - eth2: - L2: - vlan_splinters: 'off' - eth1: - L2: - vlan_splinters: 'off' - eth5: - fake: - interface: eth5 - transformations: - - action: add-br - name: br-#{c_bondname} - - action: add-bond - bridge: br-#{c_bondname} - name: #{c_bondname} - interfaces: - - eth1 - - eth2 - properties: - - bond_mode=active-backup - endpoints: - eth5: - IP: none -EOM - -# Ubintu -describe 'l23network::examples::adv_net_config__bond_ovs', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :fuel_settings => fuel_settings - } } - let(:facts) { { - :l3_fqdn_hostname => 'qweqweqwe', - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "UBUNTU: Should contains interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'UBUNTU: Should contains interface files for bond-slave interfaces' do - c_interfaces.each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/auto\s+#{iface}/) - should rv.with_content(/iface\s+#{iface}/) - should rv.with_content(/up\s+ip\s+l\s+set\s+#{iface}\s+up/) - should rv.with_content(/down\s+ip\s+l\s+set\s+#{iface}\s+down/) - end - end - - it 'ALL: Should contains l23network::l2::bridge resource' do - rv = contain_l23network__l2__bridge("br-#{c_bondname}") - should rv.with( - 'ensure' => 'present' - ) - end - - it 'ALL: Should contains l23network::l2::bond resource' do - rv = contain_l23network__l2__bond("#{c_bondname}") - should rv.with( - 'bridge' => "br-#{c_bondname}", - 'interfaces' => c_interfaces, - 'ensure' => 'present' - ) - end - - it 'ALL: Should contains relationship beetwen l23network::l2::bridge and l23network::l2::bond' do - bridge = contain_l23network__l2__bridge("br-#{c_bondname}") - should bridge.that_comes_before("L23network::L2::Bond[#{c_bondname}]") - end - -end - -# Centos -describe 'l23network::examples::adv_net_config__bond_ovs', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :fuel_settings => fuel_settings - } } - let(:facts) { { - :l3_fqdn_hostname => 'qweqweqwe', - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - - it 'CENTOS: Should contains interface files for bond-slave interfaces' do - c_interfaces.each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/DEVICE=#{iface}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - end - end - -end diff --git a/deployment/puppet/l23network/spec/classes/bond_lnx__spec.rb b/deployment/puppet/l23network/spec/classes/bond_lnx__spec.rb deleted file mode 100644 index ee4d53db2e..0000000000 --- a/deployment/puppet/l23network/spec/classes/bond_lnx__spec.rb +++ /dev/null @@ -1,130 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, static -describe 'l23network::examples::bond_lnx', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :bond => 'bond0', - :ipaddr => '1.1.1.1/27', - :interfaces => ['eth4','eth5'], - :bond_properties => { - 'mode' => 2, - 'miimon' => 150, - 'lacp_rate' => 0, - }, - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Should contains interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/auto\s+#{params[:bond]}/) - should rv.with_content(/iface\s+#{params[:bond]}/) - should rv.with_content(/address\s+1.1.1.1/) - should rv.with_content(/netmask\s+255.255.255.224/) - end - - it 'Should contains bond-specific parameters' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/slaves\s+none/) - should rv.with_content(/bond-mode\s+#{params[:bond_properties]['mode']}/) - should rv.with_content(/bond-miimon\s+#{params[:bond_properties]['miimon']}/) - should rv.with_content(/bond-lacp-rate\s+#{params[:bond_properties]['lacp_rate']}/) - end - - it 'Should contains interface files for bond-slave interfaces' do - params[:interfaces].each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/auto\s+#{iface}/) - should rv.with_content(/iface\s+#{iface}/) - should rv.with_content(/bond-master\s+#{params[:bond]}/) - end - end - -end - -# Centos, static -describe 'l23network::examples::bond_lnx', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :bond => 'bond0', - :ipaddr => '1.1.1.1/27', - :interfaces => ['eth4','eth5'], - :bond_properties => { - 'mode' => 2, - 'miimon' => 150, - 'lacp_rate' => 0, - }, - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - let(:bond_modes) { [ - 'balance-rr', - 'active-backup', - 'balance-xor', - 'broadcast', - '802.3ad', - 'balance-tlb', - 'balance-alb' - ] } - - it 'Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/DEVICE=#{params[:bond]}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - should rv.with_content(/IPADDR=1.1.1.1/) - should rv.with_content(/NETMASK=255.255.255.224/) - end - - it 'Should contains interface files for bond-slave interfaces' do - params[:interfaces].each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/DEVICE=#{iface}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - should rv.with_content(/MASTER=#{params[:bond]}/) - should rv.with_content(/SLAVE=yes/) - end - end - - it 'Should contains Bonding-opts line' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/DEVICE=#{params[:bond]}/) - should rv.with_content(/BONDING_OPTS="mode=/) - end - - it 'Should contains Bond mode' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/BONDING_OPTS.*mode=#{bond_modes[params[:bond_properties]['mode']]}/) - end - - it 'Should contains miimon' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/BONDING_OPTS.*miimon=#{params[:bond_properties]['miimon']}/) - end - - it 'Should contains lacp_rate' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/BONDING_OPTS.*lacp_rate=#{params[:bond_properties]['lacp_rate']}/) - end -end diff --git a/deployment/puppet/l23network/spec/classes/bond_lnx_old_style__spec.rb b/deployment/puppet/l23network/spec/classes/bond_lnx_old_style__spec.rb deleted file mode 100644 index 281bee581b..0000000000 --- a/deployment/puppet/l23network/spec/classes/bond_lnx_old_style__spec.rb +++ /dev/null @@ -1,126 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, static -describe 'l23network::examples::bond_lnx_old_style', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :bond => 'bond0', - :ipaddr => '1.1.1.1/27', - :interfaces => ['eth4','eth5'], - :bond_mode => 2, - :bond_miimon => 200, - :bond_lacp_rate => 2, - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Should contains interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/auto\s+#{params[:bond]}/) - should rv.with_content(/iface\s+#{params[:bond]}/) - should rv.with_content(/address\s+1.1.1.1/) - should rv.with_content(/netmask\s+255.255.255.224/) - end - - it 'Should contains bond-specific parameters' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/slaves\s+none/) - should rv.with_content(/bond-mode\s+#{params[:bond_mode]}/) - should rv.with_content(/bond-miimon\s+#{params[:bond_miimon]}/) - should rv.with_content(/bond-lacp-rate\s+#{params[:bond_lacp_rate]}/) - end - - it 'Should contains interface files for bond-slave interfaces' do - params[:interfaces].each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/auto\s+#{iface}/) - should rv.with_content(/iface\s+#{iface}/) - should rv.with_content(/bond-master\s+#{params[:bond]}/) - end - end - -end - -# Centos, static -describe 'l23network::examples::bond_lnx_old_style', :type => :class do - let(:module_path) { '../' } - #let(:title) { 'bond0' } - let(:params) { { - :bond => 'bond0', - :ipaddr => '1.1.1.1/27', - :interfaces => ['eth4','eth5'], - :bond_mode => 2, - :bond_miimon => 200, - :bond_lacp_rate => 0, - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - let(:bond_modes) { [ - 'balance-rr', - 'active-backup', - 'balance-xor', - 'broadcast', - '802.3ad', - 'balance-tlb', - 'balance-alb' - ] } - - it 'Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/DEVICE=#{params[:bond]}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - should rv.with_content(/IPADDR=1.1.1.1/) - should rv.with_content(/NETMASK=255.255.255.224/) - end - - it 'Should contains interface files for bond-slave interfaces' do - params[:interfaces].each do |iface| - rv = contain_file("#{interface_file_start}#{iface}") - should rv.with_content(/DEVICE=#{iface}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - should rv.with_content(/MASTER=#{params[:bond]}/) - should rv.with_content(/SLAVE=yes/) - end - end - - it 'Should contains Bonding-opts line' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/DEVICE=#{params[:bond]}/) - should rv.with_content(/BONDING_OPTS="mode=/) - end - - it 'Should contains Bond mode' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/BONDING_OPTS.*mode=#{bond_modes[params[:bond_mode]]}/) - end - - it 'Should contains miimon' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/BONDING_OPTS.*miimon=#{params[:miimon]}/) - end - - it 'Should contains lacp_rate' do - rv = contain_file("#{interface_file_start}#{params[:bond]}") - should rv.with_content(/BONDING_OPTS.*lacp_rate=#{params[:lacp_rate]}/) - end -end diff --git a/deployment/puppet/l23network/spec/defines/ifconfig__01_dhcp__spec.rb b/deployment/puppet/l23network/spec/defines/ifconfig__01_dhcp__spec.rb deleted file mode 100644 index 441870ee89..0000000000 --- a/deployment/puppet/l23network/spec/defines/ifconfig__01_dhcp__spec.rb +++ /dev/null @@ -1,145 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, dhcp -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'dhcp' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Ubintu/dhcp: Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Ubintu/dhcp: interface file should contain DHCP ipaddr and netmask' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/auto\s+#{params[:interface]}/) - should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+dhcp/) - end - - it "Ubintu/dhcp: interface file shouldn't contain ipaddr and netmask" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/address/) - should rv.without_content(/netmask/) - end - - it "Ubintu/dhcp: interface file shouldn't contains bond-master options" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/bond-mode/) - should rv.without_content(/slaves/) - end - -end - -# Ubintu, dhcp, ordered iface -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'dhcp', - :ifname_order_prefix => 'zzz' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Ubintu/dhcp: ordered.ifaces: Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it "Ubintu/dhcp: ordered.ifaces: interface file shouldn't contain ipaddr and netmask" do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.without_content(/address/) - should rv.without_content(/netmask/) - end - - it "Ubintu/dhcp: ordered.ifaces: interface file should contain ifup/ifdn commands" do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.without_content(/address/) - should rv.without_content(/netmask/) - end - - it "Ubintu/dhcp: ordered.ifaces: interface file shouldn't contains bond-master options" do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.without_content(/bond-mode/) - should rv.without_content(/slaves/) - end -end - -# Centos, dhcp -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'dhcp' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - - it 'Centos/dhcp: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/DEVICE=#{params[:interface]}/) - should rv.with_content(/BOOTPROTO=dhcp/) - should rv.with_content(/ONBOOT=yes/) - end - - it "Centos/dhcp: Shouldn't contains interface_file with IP-addr" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/IPADDR=/) - should rv.without_content(/NETMASK=/) - end -end - -# Centos, dhcp, ordered iface -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'dhcp', - :ifname_order_prefix => 'zzz' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - - it 'Centos/dhcp: ordered.ifaces: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.with_content(/DEVICE=#{params[:interface]}/) - should rv.with_content(/BOOTPROTO=dhcp/) - should rv.with_content(/ONBOOT=yes/) - end - - it 'Centos/dhcp: ordered.ifaces: Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.without_content(/IPADDR=/) - should rv.without_content(/NETMASK=/) - end -end -### \ No newline at end of file diff --git a/deployment/puppet/l23network/spec/defines/ifconfig__01_manual__spec.rb b/deployment/puppet/l23network/spec/defines/ifconfig__01_manual__spec.rb deleted file mode 100644 index c0ba97ffc6..0000000000 --- a/deployment/puppet/l23network/spec/defines/ifconfig__01_manual__spec.rb +++ /dev/null @@ -1,154 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, manual -- no IP addresses, but interface in UP state -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'none' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Ubintu/manual: Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Ubintu/manual: interface file should contain DHCP ipaddr and netmask' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/auto\s+#{params[:interface]}/) - should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+manual/) - end - - it "Ubintu/manual: interface file shouldn't contain ipaddr and netmask" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/address/) - should rv.without_content(/netmask/) - end - - it "Ubintu/manual: interface file should contain ifup/ifdn commands" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/up\s+ip\s+l\s+set\s+#{params[:interface]}\s+up/) - should rv.with_content(/down\s+ip\s+l\s+set\s+#{params[:interface]}\s+down/) - end - - it "Ubintu/manual: interface file shouldn't contains bond-master options" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/bond-mode/) - should rv.without_content(/slaves/) - end -end - -# Ubintu, manual, ordered iface -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'none', - :ifname_order_prefix => 'zzz' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Ubintu/manual: ordered.ifaces:Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it "Ubintu/manual: interface file shouldn't contain ipaddr and netmask" do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.without_content(/address/) - should rv.without_content(/netmask/) - end - - it "Ubintu/manual: ordered.ifaces:interface file should contain ifup/ifdn commands" do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.with_content(/up\s+ip\s+l\s+set\s+#{params[:interface]}\s+up/) - should rv.with_content(/down\s+ip\s+l\s+set\s+#{params[:interface]}\s+down/) - end - - it "Ubintu/manual: ordered.ifaces:interface file shouldn't contains bond-master options" do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.without_content(/bond-mode/) - should rv.without_content(/slaves/) - end -end - - - -# Centos, manual -- no IP addresses, but interface in UP state -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'none' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - - it 'Centos/manual: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/DEVICE=#{params[:interface]}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - end - - it "Centos/manual: Shouldn't contains interface_file with IP-addr" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/IPADDR=/) - should rv.without_content(/NETMASK=/) - end -end - -# Centos, manual, ordered iface -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => 'none', - :ifname_order_prefix => 'zzz' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - - it 'Centos/manual: ordered.ifaces: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.with_content(/DEVICE=#{params[:interface]}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - end - - it 'Centos/manual: ordered.ifaces: Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.without_content(/IPADDR=/) - should rv.without_content(/NETMASK=/) - end - -end - -### \ No newline at end of file diff --git a/deployment/puppet/l23network/spec/defines/ifconfig__01_static__spec.rb b/deployment/puppet/l23network/spec/defines/ifconfig__01_static__spec.rb deleted file mode 100644 index d200b972b6..0000000000 --- a/deployment/puppet/l23network/spec/defines/ifconfig__01_static__spec.rb +++ /dev/null @@ -1,211 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => '1.2.3.4/16' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Ubintu/static: Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Ubintu/static: interface file should contain ipaddr and netmask' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/auto\s+#{params[:interface]}/) - should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+static/) - end - - it 'Ubintu/static: interface file should contain ipaddr and netmask' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/address\s+1.2.3.4/) - should rv.with_content(/netmask\s+255.255.0.0/) - end - - it "Ubintu/static: interface file shouldn't contain bond-master options" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/bond-mode/) - should rv.without_content(/slaves/) - end -end - -# Ubintu, static, netmask as additional parameter -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => '1.2.3.4', - :netmask => '255.255.0.0' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Ubintu/static: old.netmask: Should contains interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Ubintu/static: old.netmask: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/auto\s+#{params[:interface]}/) - should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+static/) - end - - it 'Ubintu/static: old.netmask: interface file should contains ipaddr and netmask' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/address\s+#{params[:ipaddr]}/) - should rv.with_content(/netmask\s+#{params[:netmask]}/) - end - - it "Ubintu/static: old.netmask: interface file shouldn't contains bond-master options" do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.without_content(/bond-mode/) - should rv.without_content(/slaves/) - end -end - -# Ubintu, static, ordered iface -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => '1.2.3.4/16', - :ifname_order_prefix => 'zzz' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/network/interfaces.d/ifcfg-' } - - it "Ubintu/static: ordered.ifaces: Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Ubintu/static: ordered.ifaces: interface file should contain ipaddr and netmask' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.with_content(/auto\s+#{params[:interface]}/) - should rv.with_content(/iface\s+#{params[:interface]}\s+inet\s+static/) - end - - it 'Ubintu/static: ordered.ifaces: interface file should contain ipaddr and netmask' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.with_content(/address\s+1.2.3.4/) - should rv.with_content(/netmask\s+255.255.0.0/) - end -end - - - -# Centos, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => '1.2.3.4/16' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - - it 'Centos/static: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/DEVICE=#{params[:interface]}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - end - - it 'Centos/static: Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/IPADDR=1.2.3.4/) - should rv.with_content(/NETMASK=255.255.0.0/) - end - -end - -# Centos, static, netmask as additional parameter -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => '1.2.3.4', - :netmask => '255.255.0.0' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - - it 'Centos/static: old.netmask: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/DEVICE=#{params[:interface]}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - end - - it 'Centos/static: old.netmask: Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:interface]}") - should rv.with_content(/IPADDR=#{params[:ipaddr]}/) - should rv.with_content(/NETMASK=#{params[:netmask]}/) - end -end - -# Centos, static, ordered iface -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'ifconfig simple test' } - let(:params) { { - :interface => 'eth4', - :ipaddr => '1.2.3.4/16', - :ifname_order_prefix => 'zzz' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file_start) { '/etc/sysconfig/network-scripts/ifcfg-' } - let(:interface_up_file_start) { '/etc/sysconfig/network-scripts/interface-up-script-' } - - it 'Centos/static: ordered.ifaces: interface file should contains true header' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.with_content(/DEVICE=#{params[:interface]}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - end - - it 'Centos/static: ordered.ifaces: Should contains interface_file with IP-addr' do - rv = contain_file("#{interface_file_start}#{params[:ifname_order_prefix]}-#{params[:interface]}") - should rv.with_content(/IPADDR=1.2.3.4/) - should rv.with_content(/NETMASK=255.255.0.0/) - end - -end \ No newline at end of file diff --git a/deployment/puppet/l23network/spec/defines/ifconfig__aliases__spec.rb b/deployment/puppet/l23network/spec/defines/ifconfig__aliases__spec.rb deleted file mode 100644 index 4f316eb7dd..0000000000 --- a/deployment/puppet/l23network/spec/defines/ifconfig__aliases__spec.rb +++ /dev/null @@ -1,86 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'eth4' } - let(:params) { { - :ipaddr => ['1.1.1.1/16','2.2.2.2/25','3.3.3.3/26'] - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file) { '/etc/network/interfaces.d/ifcfg-eth4' } - - it "Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Should contain interface_file /etc/network/interfaces.d/ifcfg-eth4' do - rv = contain_file("#{interface_file}") - should rv.with_content(/auto\s+#{title}/) - should rv.with_content(/iface\s+#{title}\s+inet\s+static/) - should rv.with_content(/address\s+1.1.1.1/) - end - - it 'Should contain main ipaddr' do - rv = contain_file("#{interface_file}") - should rv.with_content(/address\s+1.1.1.1/) - should rv.with_content(/netmask\s+255.255.0.0/) - end - - it 'Should contains post-up directives for apply IP aliases' do - rv = contain_file("#{interface_file}") - params[:ipaddr][1..-1].each do |addr| - should rv.with_content(/post-up\s+ip\s+addr\s+add\s+#{addr}\s+dev\s+#{title}/) - should rv.with_content(/pre-down\s+ip\s+addr\s+del\s+#{addr}\s+dev\s+#{title}/) - end - end -end - -# Centos, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'eth4' } - let(:params) { { - :ipaddr => ['1.1.1.1/16','2.2.2.2/25','3.3.3.3/26'] - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file) { '/etc/sysconfig/network-scripts/ifcfg-eth4' } - let(:interface_up_file) { '/etc/sysconfig/network-scripts/interface-up-script-eth4' } - - it 'Should contain interface_file /etc/sysconfig/network-scripts/ifcfg-eth4' do - rv = contain_file("#{interface_file}") - should rv.with_content(/DEVICE=#{title}/) - should rv.with_content(/BOOTPROTO=none/) - should rv.with_content(/ONBOOT=yes/) - end - - it 'Should contains common ifup script file /sbin/ifup-local' do - should contain_file("/sbin/ifup-local") - end - - it 'Should contain main ipaddr' do - rv = contain_file("#{interface_file}") - should rv.with_content(/IPADDR=1.1.1.1/) - should rv.with_content(/NETMASK=255.255.0.0/) - end - - it 'Should contains post-up directives for apply IP aliases' do - rv = contain_file("#{interface_up_file}") - params[:ipaddr][1..-1].each do |addr| - should rv.with_content(/ip\s+addr\s+add\s+#{addr}\s+dev\s+#{title}/) - end - end - -end diff --git a/deployment/puppet/l23network/spec/defines/ifconfig__ethtool__spec.rb b/deployment/puppet/l23network/spec/defines/ifconfig__ethtool__spec.rb deleted file mode 100644 index 08621bd751..0000000000 --- a/deployment/puppet/l23network/spec/defines/ifconfig__ethtool__spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'eth4' } - let(:params) { { - :ipaddr => '1.2.3.4/24', - :ethtool => { - '-K' => 'gso off gro off', - '--set-channels' => 'rx 1 tx 2 other 3' - } - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file) { '/etc/network/interfaces.d/ifcfg-eth4' } - - it "Should contains interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Should contains post-up directives' do - rv = contain_file("#{interface_file}") - params[:ethtool].each do |k, v| - # "--#{k}"" -- workaround for rspec-pupppet bug. - should rv.with_content(/post-up\s+ethtool\s+--#{k}\s+#{title}\s+#{v}/) - end - end -end - -# Centos, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'eth4' } - let(:params) { { - :ipaddr => '1.2.3.4/24', - :ethtool => { - '-K' => 'gso off gro off', - '--set-channels' => 'rx 1 tx 2 other 3' - } - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file) { '/etc/sysconfig/network-scripts/ifcfg-eth4' } - let(:interface_up_file) { '/etc/sysconfig/network-scripts/interface-up-script-eth4' } - - it 'Should contains common ifup script file /sbin/ifup-local' do - should contain_file("/sbin/ifup-local") - end - - it 'Should contain interface post-up script' do - rv = contain_file("#{interface_up_file}") - params[:ethtool].each do |k, v| - # "--#{k}"" -- workaround for rspec-pupppet bug. - should rv.with_content(/ethtool\s+--#{k}\s+#{title}\s+#{v}/) - end - end - -end diff --git a/deployment/puppet/l23network/spec/defines/ifconfig__macaddr__spec.rb b/deployment/puppet/l23network/spec/defines/ifconfig__macaddr__spec.rb deleted file mode 100644 index e2ed44cdf7..0000000000 --- a/deployment/puppet/l23network/spec/defines/ifconfig__macaddr__spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -# require 'puppet' -# require 'rspec' -require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -# Ubintu, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'eth4' } - let(:params) { { - :ipaddr => '1.2.3.4/24', - :macaddr => 'AA:BB:CC:33:22:11' - } } - let(:facts) { { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu', - :kernel => 'Linux' - } } - let(:interface_file) { '/etc/network/interfaces.d/ifcfg-eth4' } - - it "Should contain interface_file" do - should contain_file('/etc/network/interfaces').with_content(/\*/) - end - - it 'Should contain interface_file /etc/network/interfaces.d/ifcfg-eth4' do - rv = contain_file("#{interface_file}") - should rv.with_content(/hwaddress\s+ether\s+#{params[:macaddr].downcase()}/) - should rv.with_content(/address\s+1.2.3.4/) - should rv.with_content(/auto\s+#{title}/) - should rv.with_content(/iface\s+#{title}/) - end - -end - -# Centos, static -describe 'l23network::l3::ifconfig', :type => :define do - let(:module_path) { '../' } - let(:title) { 'eth4' } - let(:params) { { - :ipaddr => '1.2.3.4/24', - :macaddr => 'AA:BB:CC:33:22:11' - } } - let(:facts) { { - :osfamily => 'RedHat', - :operatingsystem => 'Centos', - :kernel => 'Linux' - } } - let(:interface_file) { '/etc/sysconfig/network-scripts/ifcfg-eth4' } - - it 'Should contain interface_file /etc/sysconfig/network-scripts/ifcfg-eth4' do - rv = contain_file("#{interface_file}") - should rv.with_content(/MACADDR=#{params[:macaddr].upcase()}/) - should rv.with_content(/IPADDR=1.2.3.4/) - should rv.with_content(/DEVICE=#{title}/) - end - -end diff --git a/deployment/puppet/l23network/spec/functions/ethtool_convert_hash__spec.rb b/deployment/puppet/l23network/spec/functions/ethtool_convert_hash__spec.rb deleted file mode 100644 index c9830203a4..0000000000 --- a/deployment/puppet/l23network/spec/functions/ethtool_convert_hash__spec.rb +++ /dev/null @@ -1,73 +0,0 @@ -# require 'puppet' -# require 'rspec' -# require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -describe 'ethtool_convert_hash' do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it 'should exist' do - expect(Puppet::Parser::Functions.function('ethtool_convert_hash')).to eq 'function_ethtool_convert_hash' - end - - it 'should throw an error on invalid arguments number #1' do - expect { - scope.function_ethtool_convert_hash([]) - }.to raise_error(Puppet::ParseError) - end - - it 'should throw an error on invalid arguments number #2' do - expect { - scope.function_ethtool_convert_hash([{},{},{}]) - }.to raise_error(Puppet::ParseError) - end - - it 'should throw an error on invalid argument type' do - expect { - scope.function_ethtool_convert_hash(['qweqwe']) - }.to raise_error(Puppet::ParseError) - end - - it 'should return hash with two sort of options' do - rv = scope.function_ethtool_convert_hash([{ - :K => [ - 'gso off', - 'gro off' - ], - :"set-channels" => [ - 'rx 1', - 'tx 2', - 'other 3', - ] - }]) - expect(rv).to eq({ - '-K' => 'gso off gro off', - '--set-channels' => 'rx 1 tx 2 other 3' - }) - end - - it 'should return hash with three sort of options with different case' do - rv = scope.function_ethtool_convert_hash([{ - :s => [ - 'xxx off', - 'yyy off' - ], - :K => [ - 'gso off', - 'gro off' - ], - :"set-channels" => [ - 'rx 1', - 'tx 2', - 'other 3', - ] - }]) - expect(rv).to eq({ - '-s' => 'xxx off yyy off', - '-K' => 'gso off gro off', - '--set-channels' => 'rx 1 tx 2 other 3' - }) - - end -end diff --git a/deployment/puppet/l23network/spec/functions/generate_network_config__spec.rb b/deployment/puppet/l23network/spec/functions/generate_network_config__spec.rb deleted file mode 100644 index 1d0c446f69..0000000000 --- a/deployment/puppet/l23network/spec/functions/generate_network_config__spec.rb +++ /dev/null @@ -1,189 +0,0 @@ -# require 'puppet' -# require 'rspec' -# require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' -begin - require 'puppet/parser/functions/lib/l23network_scheme.rb' -rescue LoadError => e - # puppet apply does not add module lib directories to the $LOAD_PATH (See - # #4248). It should (in the future) but for the time being we need to be - # defensive which is what this rescue block is doing. - rb_file = File.join(File.dirname(__FILE__),'lib','l23network_scheme.rb') - load rb_file if File.exists?(rb_file) or raise e -end - - -describe 'generate_network_config' do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - # before(:each) do - # L23network::Scheme.set = { - # :endpoints => { - # :eth0 => {:IP => 'dhcp'}, - # :"br-ex" => { - # :gateway => '10.1.3.1', - # :IP => ['10.1.3.11/24'], - # }, - # :"br-mgmt" => { :IP => ['10.20.1.11/25'] }, - # :"br-storage" => { :IP => ['192.168.1.2/24'] }, - # :"br-prv" => { :IP => 'none' }, - # }, - # :roles => { - # :management => 'br-mgmt', - # :private => 'br-prv', - # :ex => 'br-ex', - # :storage => 'br-storage', - # :admin => 'eth0', - # }, - # } - # end - - it 'should exist' do - Puppet::Parser::Functions.function('generate_network_config').should == 'function_generate_network_config' - end - - # it 'should convert string-boolean values to boolean' do - # should run.with_params({ - # :s_true => 'true', - # :s_false => 'false', - # :s_none => 'none', - # :s_null => 'null', - # :s_nil => 'nil', - # :s_nill => 'nill', - # }).and_return({ - # :s_true => true, - # :s_false => false, - # :s_none => nil, - # :s_null => nil, - # :s_nil => nil, - # :s_nill => nil, - # }) - # end - - # it 'should convert UP-sace string-boolean values to boolean' do - # should run.with_params({ - # :s_true => 'TRUE', - # :s_false => 'FALSE', - # :s_none => 'NONE', - # :s_null => 'NULL', - # :s_nil => 'NIL', - # :s_nill => 'NILL', - # }).and_return({ - # :s_true => true, - # :s_false => false, - # :s_none => nil, - # :s_null => nil, - # :s_nil => nil, - # :s_nill => nil, - # }) - # end - - # it 'should convert reccursive hashes' do - # should run.with_params({ - # :bool_hash => { - # :str => 'aaa', - # :int => 123, - # :array => [111,222,333], - # :hash => { - # :str => 'aaa', - # :int => 123, - # :array => [111,222,333], - # :a_sbool => ['true', 'nil', 'false'], - # :a_bool => [true, nil, false], - # :hash => { - # :str => 'aaa', - # :int => 123, - # :array => [111,222,333], - # :a_sbool => ['true', 'nil', 'false'], - # :a_bool => [true, nil, false], - # }, - # }, - # :a_sbool => ['true', 'nil', 'false'], - # :a_bool => [true, nil, false], - # }, - # :bool_hash => { - # :t => true, - # :f => false, - # :n => nil - # }, - # }).and_return({ - # :bool_hash => { - # :str => 'aaa', - # :int => 123, - # :array => [111,222,333], - # :hash => { - # :str => 'aaa', - # :int => 123, - # :array => [111,222,333], - # :a_sbool => [true, nil, false], - # :a_bool => [true, nil, false], - # :hash => { - # :str => 'aaa', - # :int => 123, - # :array => [111,222,333], - # :a_sbool => [true, nil, false], - # :a_bool => [true, nil, false], - # }, - # }, - # :a_sbool => [true, nil, false], - # :a_bool => [true, nil, false], - # }, - # :bool_hash => { - # :t => true, - # :f => false, - # :n => nil - # }, - # }) - # end - - # it 'should convert array of hashes' do - # should run.with_params({ :array => [ - # {:aaa=>1,"aaa"=>11, :bbb=>2,'bbb'=>12, :ccc=>3,'ccc'=>3}, - # {:t=>'true','tt'=>'true', :f=>'false','ff'=>'false', :n=>'nil','nn'=>'nil'}, - # { - # :s_true => 'true', - # :s_false => 'false', - # :s_none => 'none', - # :s_null => 'null', - # :s_nil => 'nil', - # :s_nill => 'nill', - # }, - # { - # :s_true => 'TRUE', - # :s_false => 'FALSE', - # :s_none => 'NONE', - # :s_null => 'NULL', - # :s_nil => 'NIL', - # :s_nill => 'NILL', - # }, - # ]}).and_return({ :array => [ - # {:aaa=>1,"aaa"=>11, :bbb=>2,'bbb'=>12, :ccc=>3,'ccc'=>3}, - # {:t=>true,'tt'=>true, :f=>false,'ff'=>false, :n=>nil,'nn'=>nil}, - # { - # :s_true => true, - # :s_false => false, - # :s_none => nil, - # :s_null => nil, - # :s_nil => nil, - # :s_nill => nil, - # }, - # { - # :s_true => true, - # :s_false => false, - # :s_none => nil, - # :s_null => nil, - # :s_nil => nil, - # :s_nill => nil, - # }, - # ]}) - # end - - # it 'should throw an error' do - # lambda { - # scope.function_concat(['xxx']) - # }.should(raise_error(Puppet::ParseError)) - # end - -end - -# vim: set ts=2 sw=2 et : diff --git a/deployment/puppet/l23network/spec/functions/get_hash_with_defaults_and_deprecations__spec.rb b/deployment/puppet/l23network/spec/functions/get_hash_with_defaults_and_deprecations__spec.rb deleted file mode 100644 index 325702c7a2..0000000000 --- a/deployment/puppet/l23network/spec/functions/get_hash_with_defaults_and_deprecations__spec.rb +++ /dev/null @@ -1,115 +0,0 @@ -# require 'puppet' -# require 'rspec' -# require 'rspec-puppet' -require 'spec_helper' -require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals' - -describe 'get_hash_with_defaults_and_deprecations' do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it 'should exist' do - expect(Puppet::Parser::Functions.function('get_hash_with_defaults_and_deprecations')).to eq 'function_get_hash_with_defaults_and_deprecations' - end - - it 'should throw an error on invalid arguments number #1' do - expect { - scope.function_get_hash_with_defaults_and_deprecations([]) - }.to raise_error(Puppet::ParseError) - end - - it 'should throw an error on invalid arguments number #2' do - expect { - scope.function_get_hash_with_defaults_and_deprecations([{},{}]) - }.to raise_error(Puppet::ParseError) - end - - it 'should throw an error on invalid arguments number #3' do - expect { - scope.function_get_hash_with_defaults_and_deprecations([{},{},{},{}]) - }.to raise_error(Puppet::ParseError) - end - - it 'should throw an error on invalid argument type' do - expect { - scope.function_get_hash_with_defaults_and_deprecations(['qweqwe']) - }.to raise_error(Puppet::ParseError) - end - - it 'should return hash with sum of two hashes' do - rv = scope.function_get_hash_with_defaults_and_deprecations([{ - 'aaa' => 1, - 'bbb' => 2, - }, { - 'ccc' => 3, - 'ddd' => 4, - }, {}]) - expect(rv).to eq({ - 'aaa' => 1, - 'bbb' => 2, - 'ccc' => 3, - 'ddd' => 4, - }) - end - - it 'should return hash with sum of two hashes, add defaults if need' do - rv = scope.function_get_hash_with_defaults_and_deprecations([{ - 'aaa' => 1, - 'bbb' => 2, - }, { - 'bbb' => -1, - 'ccc' => 3, - 'ddd' => 4, - }, {}]) - expect(rv).to eq({ - 'aaa' => 1, - 'bbb' => 2, - 'ccc' => 3, - 'ddd' => 4, - }) - end - - it 'should return hash with sum of three hashes' do - rv = scope.function_get_hash_with_defaults_and_deprecations([{ - 'aaa' => 1, - 'bbb' => 2, - }, { - 'bbb' => -1, - 'ccc' => 3, - 'ddd' => 4, - }, { - 'eee' => 5, - }]) - expect(rv).to eq({ - 'aaa' => 1, - 'bbb' => 2, - 'ccc' => 3, - 'ddd' => 4, - 'eee' => 5, - }) - end - - - # it 'should return hash with three sort of options with different case' do - # rv = scope.function_get_hash_with_defaults_and_deprecations([{ - # :s => [ - # 'xxx off', - # 'yyy off' - # ], - # :K => [ - # 'gso off', - # 'gro off' - # ], - # :"set-channels" => [ - # 'rx 1', - # 'tx 2', - # 'other 3', - # ] - # }]) - # expect(rv).to eq({ - # '-s' => 'xxx off yyy off', - # '-K' => 'gso off gro off', - # '--set-channels' => 'rx 1 tx 2 other 3' - # }) - - # end -end diff --git a/deployment/puppet/l23network/templates/bonding_Debian.erb b/deployment/puppet/l23network/templates/bonding_Debian.erb deleted file mode 100644 index 3a215fa0d8..0000000000 --- a/deployment/puppet/l23network/templates/bonding_Debian.erb +++ /dev/null @@ -1,6 +0,0 @@ -<%- if @actual_bond_properties['mode'].to_s != 'undef' -%> -slaves none -<%- @actual_bond_properties.each do |key, val| -%> -bond-<%= key.tr('_','-') %> <%= val %> -<%- end -%> -<%- end -%> diff --git a/deployment/puppet/l23network/templates/bonding_RedHat.erb b/deployment/puppet/l23network/templates/bonding_RedHat.erb deleted file mode 100644 index 0f2af4f54e..0000000000 --- a/deployment/puppet/l23network/templates/bonding_RedHat.erb +++ /dev/null @@ -1,4 +0,0 @@ -<%- if @actual_bond_properties['mode'].to_s != 'undef' -%> -BONDING_OPTS="mode=<%= @bond_modes[@actual_bond_properties['mode'].to_i] -%> -<%- @actual_bond_properties.select{|k,v| k!='mode'}.each do |key, val| -%> <%= key %>=<%= val %><%- end -%>" -<% end %> diff --git a/deployment/puppet/l23network/templates/ipconfig_Debian_bondslave.erb b/deployment/puppet/l23network/templates/ipconfig_Debian_bondslave.erb deleted file mode 100644 index 2eb7fe1931..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_Debian_bondslave.erb +++ /dev/null @@ -1,10 +0,0 @@ -auto <%= @interface %> -iface <%= @interface %> inet manual -bond-master <%= @bond_master %> -<% if @macaddr -%> -hwaddress ether <%= @macaddr.downcase %> -<% end -%> -<% if @mtu -%> -mtu <%= @mtu %> -<% end -%> -<%= scope.function_template(['l23network/ethtool_Debian.erb']) %> diff --git a/deployment/puppet/l23network/templates/ipconfig_Debian_dhcp.erb b/deployment/puppet/l23network/templates/ipconfig_Debian_dhcp.erb deleted file mode 100644 index f6ca86d3ea..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_Debian_dhcp.erb +++ /dev/null @@ -1,12 +0,0 @@ -auto <%= @interface %> -iface <%= @interface %> inet dhcp -<% if @macaddr -%> -hwaddress ether <%= @macaddr.downcase %> -<% end -%> -<% if @dhcp_hostname %>hostname <%= @dhcp_hostname %><% end %> -<% if @vlan_mode %>vlan_raw_device <%= @vlan_dev %><% end %> -<% if @mtu -%> -mtu <%= @mtu %> -<% end -%> -<%= scope.function_template(['l23network/bonding_Debian.erb']) %> -<%= scope.function_template(['l23network/ethtool_Debian.erb']) %> diff --git a/deployment/puppet/l23network/templates/ipconfig_Debian_manual.erb b/deployment/puppet/l23network/templates/ipconfig_Debian_manual.erb deleted file mode 100644 index 1a63ecb8e6..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_Debian_manual.erb +++ /dev/null @@ -1,13 +0,0 @@ -auto <%= @interface %> -iface <%= @interface %> inet manual -<% if @macaddr -%> -hwaddress ether <%= @macaddr.downcase %> -<% end -%> -<% if @mtu -%> -mtu <%= @mtu %> -<% end -%> -<% if @vlan_mode %>vlan_raw_device <%= @vlan_dev %><% end %> -up ip l set <%= @interface %> up -down ip l set <%= @interface %> down -<%= scope.function_template(['l23network/bonding_Debian.erb']) %> -<%= scope.function_template(['l23network/ethtool_Debian.erb']) %> diff --git a/deployment/puppet/l23network/templates/ipconfig_Debian_static.erb b/deployment/puppet/l23network/templates/ipconfig_Debian_static.erb deleted file mode 100644 index 453c220c5b..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_Debian_static.erb +++ /dev/null @@ -1,24 +0,0 @@ -auto <%= @interface %> -iface <%= @interface %> inet static -<% if @macaddr -%> -hwaddress ether <%= @macaddr.downcase %> -<% end -%> -<% if @mtu -%> -mtu <%= @mtu %> -<% end -%> -<% if @vlan_mode %>vlan_raw_device <%= @vlan_dev %><% end %> -address <%= @effective_ipaddr %> -netmask <%= @effective_netmask %> -<% if @def_gateway %>gateway <%= @def_gateway %><% end %> -<% if @dns_nameservers_1 or @dns_nameservers_2 %>dns-nameservers <% if @dns_nameservers_1 %><%= @dns_nameservers_1 %><% end %> <% if @dns_nameservers_2 %><%= @dns_nameservers_2 %><% end %><% end %> -<% if @dns_search_string %>dns-search <%= @dns_search_string %><% end %> -<% if @dns_domain_string %>dns-domain <%= @dns_domain_string %><% end %> -<%- if @other_nets -%> -<%= scope.function_template(['l23network/ip_route_Debian.erb']) %> -<%- end -%> -<%- if @ipaddr_aliases -%><%- @ipaddr_aliases.each do |addr| -%> -post-up ip addr add <%= addr %> dev <%= @interface %> -pre-down ip addr del <%= addr %> dev <%= @interface %> -<%- end -%><%- end -%> -<%= scope.function_template(['l23network/bonding_Debian.erb']) %> -<%= scope.function_template(['l23network/ethtool_Debian.erb']) %> diff --git a/deployment/puppet/l23network/templates/ipconfig_RedHat_bondslave.erb b/deployment/puppet/l23network/templates/ipconfig_RedHat_bondslave.erb deleted file mode 100644 index 5ffb34a26e..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_RedHat_bondslave.erb +++ /dev/null @@ -1,12 +0,0 @@ -DEVICE=<%= @interface %> -BOOTPROTO=none -ONBOOT=yes -USERCTL=no -MASTER=<%= @bond_master %> -SLAVE=yes -<% if @macaddr -%> -MACADDR=<%= @macaddr.upcase %> -<% end -%> -<% if @mtu -%> -MTU=<%= @mtu %> -<% end -%> diff --git a/deployment/puppet/l23network/templates/ipconfig_RedHat_dhcp.erb b/deployment/puppet/l23network/templates/ipconfig_RedHat_dhcp.erb deleted file mode 100644 index 6d3d26c777..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_RedHat_dhcp.erb +++ /dev/null @@ -1,24 +0,0 @@ -DEVICE=<%= @interface %> -BOOTPROTO=dhcp -ONBOOT=yes -USERCTL=no -<% if @dhcp_hostname -%> -DHCP_HOSTNAME=<%= @dhcp_hostname %> -<% end -%> -<% if @vlan_mode -%> -VLAN=yes -<% end -%> -<% if @vlan_mode == 'vlan' -%> -VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD -PHYSDEV=<%= @vlan_dev %> -<% end -%> -<% if @mtu -%> -MTU=<%= @mtu %> -<% end -%> -<% if @macaddr -%> -MACADDR=<%= @macaddr.upcase %> -<% end -%> -<% if @mtu -%> -MTU=<%= @mtu %> -<% end -%> -<%= scope.function_template(['l23network/bonding_RedHat.erb']) %> diff --git a/deployment/puppet/l23network/templates/ipconfig_RedHat_manual.erb b/deployment/puppet/l23network/templates/ipconfig_RedHat_manual.erb deleted file mode 100644 index 97a94e0875..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_RedHat_manual.erb +++ /dev/null @@ -1,18 +0,0 @@ -DEVICE=<%= @interface %> -BOOTPROTO=none -ONBOOT=yes -USERCTL=no -<% if @vlan_mode -%> -VLAN=yes -<% end -%> -<% if @vlan_mode == 'vlan' -%> -VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD -PHYSDEV=<%= @vlan_dev %> -<% end -%> -<% if @mtu -%> -MTU=<%= @mtu %> -<% end -%> -<% if @macaddr -%> -MACADDR=<%= @macaddr.upcase %> -<% end -%> -<%= scope.function_template(['l23network/bonding_RedHat.erb']) %> diff --git a/deployment/puppet/l23network/templates/ipconfig_RedHat_static.erb b/deployment/puppet/l23network/templates/ipconfig_RedHat_static.erb deleted file mode 100644 index f1b033d0de..0000000000 --- a/deployment/puppet/l23network/templates/ipconfig_RedHat_static.erb +++ /dev/null @@ -1,32 +0,0 @@ -DEVICE=<%= @interface %> -IPADDR=<%= @effective_ipaddr %> -NETMASK=<%= @effective_netmask %> -BOOTPROTO=none -ONBOOT=yes -USERCTL=no -<% if @macaddr -%> -MACADDR=<%= @macaddr.upcase %> -<% end -%> -<% if @vlan_mode -%> -VLAN=yes -<% end -%> -<% if @vlan_mode == 'vlan' -%> -VLAN_NAME_TYPE=VLAN_PLUS_VID_NO_PAD -PHYSDEV=<%= @vlan_dev %> -<% end -%> -<% if @def_gateway -%> -GATEWAY=<%= @def_gateway %> -<% end -%> -<% if @dns_nameservers_1 -%> -DNS1=<%= @dns_nameservers_1 %> -<% end -%> -<% if @dns_nameservers_2 -%> -DNS2=<%= @dns_nameservers_2 %> -<% end -%> -<% if @dns_search_string -%> -SEARCH=<%= @dns_search_string %> -<% end -%> -<% if @mtu -%> -MTU=<%= @mtu %> -<% end -%> -<%= scope.function_template(['l23network/bonding_RedHat.erb']) %> diff --git a/deployment/puppet/plugin_neutronnsx/lib/puppet/provider/l2_nsx_bridge/ovs.rb b/deployment/puppet/plugin_neutronnsx/lib/puppet/provider/l2_nsx_bridge/ovs.rb index 08d618af24..a76725d954 100644 --- a/deployment/puppet/plugin_neutronnsx/lib/puppet/provider/l2_nsx_bridge/ovs.rb +++ b/deployment/puppet/plugin_neutronnsx/lib/puppet/provider/l2_nsx_bridge/ovs.rb @@ -1,6 +1,6 @@ Puppet::Type.type(:l2_nsx_bridge).provide( :ovs, - :parent => Puppet::Type.type(:l2_ovs_bridge).provider(:ovs) + :parent => Puppet::Type.type(:l2_bridge).provider(:ovs) ) do optional_commands :vsctl => "/usr/bin/ovs-vsctl"